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 }