github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/mru/signedupdate.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  package mru
    26  
    27  import (
    28  	"bytes"
    29  	"hash"
    30  
    31  	"github.com/ethereum/go-ethereum/common"
    32  	"github.com/ethereum/go-ethereum/crypto"
    33  	"github.com/ethereum/go-ethereum/swarm/storage"
    34  )
    35  
    36  //
    37  type SignedResourceUpdate struct {
    38  resourceUpdate //
    39  	signature      *Signature
    40  updateAddr     storage.Address //
    41  binaryData     []byte          //
    42  }
    43  
    44  //
    45  func (r *SignedResourceUpdate) Verify() (err error) {
    46  	if len(r.data) == 0 {
    47  		return NewError(ErrInvalidValue, "Update does not contain data")
    48  	}
    49  	if r.signature == nil {
    50  		return NewError(ErrInvalidSignature, "Missing signature field")
    51  	}
    52  
    53  	digest, err := r.GetDigest()
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  //
    59  	ownerAddr, err := getOwner(digest, *r.signature)
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	if !bytes.Equal(r.updateAddr, r.UpdateAddr()) {
    65  		return NewError(ErrInvalidSignature, "Signature address does not match with ownerAddr")
    66  	}
    67  
    68  //
    69  	if !verifyOwner(ownerAddr, r.metaHash, r.rootAddr) {
    70  		return NewErrorf(ErrUnauthorized, "signature is valid but signer does not own the resource: %v", err)
    71  	}
    72  
    73  	return nil
    74  }
    75  
    76  //
    77  func (r *SignedResourceUpdate) Sign(signer Signer) error {
    78  
    79  r.binaryData = nil           //
    80  digest, err := r.GetDigest() //
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	signature, err := signer.Sign(digest)
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  //
    91  //
    92  	ownerAddress, err := getOwner(digest, signature)
    93  	if err != nil {
    94  		return NewError(ErrInvalidSignature, "Error verifying signature")
    95  	}
    96  
    97  if ownerAddress != signer.Address() { //
    98  		return NewError(ErrInvalidSignature, "Signer address does not match ownerAddr")
    99  	}
   100  
   101  	r.signature = &signature
   102  	r.updateAddr = r.UpdateAddr()
   103  	return nil
   104  }
   105  
   106  //
   107  func (r *SignedResourceUpdate) toChunk() (*storage.Chunk, error) {
   108  
   109  //
   110  //
   111  //
   112  	if r.signature == nil || r.binaryData == nil {
   113  		return nil, NewError(ErrInvalidSignature, "newUpdateChunk called without a valid signature or payload data. Call .Sign() first.")
   114  	}
   115  
   116  	chunk := storage.NewChunk(r.updateAddr, nil)
   117  	resourceUpdateLength := r.resourceUpdate.binaryLength()
   118  	chunk.SData = r.binaryData
   119  
   120  //
   121  	copy(chunk.SData[resourceUpdateLength:], r.signature[:])
   122  
   123  	chunk.Size = int64(len(chunk.SData))
   124  	return chunk, nil
   125  }
   126  
   127  //
   128  func (r *SignedResourceUpdate) fromChunk(updateAddr storage.Address, chunkdata []byte) error {
   129  //
   130  
   131  //
   132  	if err := r.resourceUpdate.binaryGet(chunkdata); err != nil {
   133  		return err
   134  	}
   135  
   136  //
   137  	var signature *Signature
   138  	cursor := r.resourceUpdate.binaryLength()
   139  	sigdata := chunkdata[cursor : cursor+signatureLength]
   140  	if len(sigdata) > 0 {
   141  		signature = &Signature{}
   142  		copy(signature[:], sigdata)
   143  	}
   144  
   145  	r.signature = signature
   146  	r.updateAddr = updateAddr
   147  	r.binaryData = chunkdata
   148  
   149  	return nil
   150  
   151  }
   152  
   153  //
   154  //
   155  func (r *SignedResourceUpdate) GetDigest() (result common.Hash, err error) {
   156  	hasher := hashPool.Get().(hash.Hash)
   157  	defer hashPool.Put(hasher)
   158  	hasher.Reset()
   159  	dataLength := r.resourceUpdate.binaryLength()
   160  	if r.binaryData == nil {
   161  		r.binaryData = make([]byte, dataLength+signatureLength)
   162  		if err := r.resourceUpdate.binaryPut(r.binaryData[:dataLength]); err != nil {
   163  			return result, err
   164  		}
   165  	}
   166  hasher.Write(r.binaryData[:dataLength]) //
   167  
   168  	return common.BytesToHash(hasher.Sum(nil)), nil
   169  }
   170  
   171  //
   172  func getOwner(digest common.Hash, signature Signature) (common.Address, error) {
   173  	pub, err := crypto.SigToPub(digest.Bytes(), signature[:])
   174  	if err != nil {
   175  		return common.Address{}, err
   176  	}
   177  	return crypto.PubkeyToAddress(*pub), nil
   178  }
   179  
   180  //
   181  //
   182  //
   183  //
   184  func verifyOwner(ownerAddr common.Address, metaHash []byte, rootAddr storage.Address) bool {
   185  	hasher := hashPool.Get().(hash.Hash)
   186  	defer hashPool.Put(hasher)
   187  	hasher.Reset()
   188  	hasher.Write(metaHash)
   189  	hasher.Write(ownerAddr.Bytes())
   190  	rootAddr2 := hasher.Sum(nil)
   191  	return bytes.Equal(rootAddr2, rootAddr)
   192  }