github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/storage/mru/signedupdate.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:50</date>
    10  //</624342683757842432>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package mru
    29  
    30  import (
    31  	"bytes"
    32  	"hash"
    33  
    34  	"github.com/ethereum/go-ethereum/common"
    35  	"github.com/ethereum/go-ethereum/crypto"
    36  	"github.com/ethereum/go-ethereum/swarm/storage"
    37  )
    38  
    39  //
    40  type SignedResourceUpdate struct {
    41  resourceUpdate //
    42  	signature      *Signature
    43  updateAddr     storage.Address //
    44  binaryData     []byte          //
    45  }
    46  
    47  //
    48  func (r *SignedResourceUpdate) Verify() (err error) {
    49  	if len(r.data) == 0 {
    50  		return NewError(ErrInvalidValue, "Update does not contain data")
    51  	}
    52  	if r.signature == nil {
    53  		return NewError(ErrInvalidSignature, "Missing signature field")
    54  	}
    55  
    56  	digest, err := r.GetDigest()
    57  	if err != nil {
    58  		return err
    59  	}
    60  
    61  //
    62  	ownerAddr, err := getOwner(digest, *r.signature)
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	if !bytes.Equal(r.updateAddr, r.UpdateAddr()) {
    68  		return NewError(ErrInvalidSignature, "Signature address does not match with ownerAddr")
    69  	}
    70  
    71  //
    72  	if !verifyOwner(ownerAddr, r.metaHash, r.rootAddr) {
    73  		return NewErrorf(ErrUnauthorized, "signature is valid but signer does not own the resource: %v", err)
    74  	}
    75  
    76  	return nil
    77  }
    78  
    79  //
    80  func (r *SignedResourceUpdate) Sign(signer Signer) error {
    81  
    82  r.binaryData = nil           //
    83  digest, err := r.GetDigest() //
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	signature, err := signer.Sign(digest)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  //
    94  //
    95  	ownerAddress, err := getOwner(digest, signature)
    96  	if err != nil {
    97  		return NewError(ErrInvalidSignature, "Error verifying signature")
    98  	}
    99  
   100  if ownerAddress != signer.Address() { //
   101  		return NewError(ErrInvalidSignature, "Signer address does not match ownerAddr")
   102  	}
   103  
   104  	r.signature = &signature
   105  	r.updateAddr = r.UpdateAddr()
   106  	return nil
   107  }
   108  
   109  //
   110  func (r *SignedResourceUpdate) toChunk() (*storage.Chunk, error) {
   111  
   112  //
   113  //
   114  //
   115  	if r.signature == nil || r.binaryData == nil {
   116  		return nil, NewError(ErrInvalidSignature, "newUpdateChunk called without a valid signature or payload data. Call .Sign() first.")
   117  	}
   118  
   119  	chunk := storage.NewChunk(r.updateAddr, nil)
   120  	resourceUpdateLength := r.resourceUpdate.binaryLength()
   121  	chunk.SData = r.binaryData
   122  
   123  //
   124  	copy(chunk.SData[resourceUpdateLength:], r.signature[:])
   125  
   126  	chunk.Size = int64(len(chunk.SData))
   127  	return chunk, nil
   128  }
   129  
   130  //
   131  func (r *SignedResourceUpdate) fromChunk(updateAddr storage.Address, chunkdata []byte) error {
   132  //
   133  
   134  //
   135  	if err := r.resourceUpdate.binaryGet(chunkdata); err != nil {
   136  		return err
   137  	}
   138  
   139  //
   140  	var signature *Signature
   141  	cursor := r.resourceUpdate.binaryLength()
   142  	sigdata := chunkdata[cursor : cursor+signatureLength]
   143  	if len(sigdata) > 0 {
   144  		signature = &Signature{}
   145  		copy(signature[:], sigdata)
   146  	}
   147  
   148  	r.signature = signature
   149  	r.updateAddr = updateAddr
   150  	r.binaryData = chunkdata
   151  
   152  	return nil
   153  
   154  }
   155  
   156  //
   157  //
   158  func (r *SignedResourceUpdate) GetDigest() (result common.Hash, err error) {
   159  	hasher := hashPool.Get().(hash.Hash)
   160  	defer hashPool.Put(hasher)
   161  	hasher.Reset()
   162  	dataLength := r.resourceUpdate.binaryLength()
   163  	if r.binaryData == nil {
   164  		r.binaryData = make([]byte, dataLength+signatureLength)
   165  		if err := r.resourceUpdate.binaryPut(r.binaryData[:dataLength]); err != nil {
   166  			return result, err
   167  		}
   168  	}
   169  hasher.Write(r.binaryData[:dataLength]) //
   170  
   171  	return common.BytesToHash(hasher.Sum(nil)), nil
   172  }
   173  
   174  //
   175  func getOwner(digest common.Hash, signature Signature) (common.Address, error) {
   176  	pub, err := crypto.SigToPub(digest.Bytes(), signature[:])
   177  	if err != nil {
   178  		return common.Address{}, err
   179  	}
   180  	return crypto.PubkeyToAddress(*pub), nil
   181  }
   182  
   183  //
   184  //
   185  //
   186  //
   187  func verifyOwner(ownerAddr common.Address, metaHash []byte, rootAddr storage.Address) bool {
   188  	hasher := hashPool.Get().(hash.Hash)
   189  	defer hashPool.Put(hasher)
   190  	hasher.Reset()
   191  	hasher.Write(metaHash)
   192  	hasher.Write(ownerAddr.Bytes())
   193  	rootAddr2 := hasher.Sum(nil)
   194  	return bytes.Equal(rootAddr2, rootAddr)
   195  }
   196