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