github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/storage/mru/request.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 //</624342683355189248> 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 "encoding/json" 33 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/common/hexutil" 36 "github.com/ethereum/go-ethereum/swarm/storage" 37 ) 38 39 // 40 type updateRequestJSON struct { 41 Name string `json:"name,omitempty"` 42 Frequency uint64 `json:"frequency,omitempty"` 43 StartTime uint64 `json:"startTime,omitempty"` 44 Owner string `json:"ownerAddr,omitempty"` 45 RootAddr string `json:"rootAddr,omitempty"` 46 MetaHash string `json:"metaHash,omitempty"` 47 Version uint32 `json:"version,omitempty"` 48 Period uint32 `json:"period,omitempty"` 49 Data string `json:"data,omitempty"` 50 Multihash bool `json:"multiHash"` 51 Signature string `json:"signature,omitempty"` 52 } 53 54 // 55 type Request struct { 56 SignedResourceUpdate 57 metadata ResourceMetadata 58 isNew bool 59 } 60 61 var zeroAddr = common.Address{} 62 63 // 64 func NewCreateUpdateRequest(metadata *ResourceMetadata) (*Request, error) { 65 66 request, err := NewCreateRequest(metadata) 67 if err != nil { 68 return nil, err 69 } 70 71 // 72 now := TimestampProvider.Now().Time 73 74 request.version = 1 75 request.period, err = getNextPeriod(metadata.StartTime.Time, now, metadata.Frequency) 76 if err != nil { 77 return nil, err 78 } 79 return request, nil 80 } 81 82 // 83 func NewCreateRequest(metadata *ResourceMetadata) (request *Request, err error) { 84 if metadata.StartTime.Time == 0 { // 85 metadata.StartTime = TimestampProvider.Now() 86 } 87 88 if metadata.Owner == zeroAddr { 89 return nil, NewError(ErrInvalidValue, "OwnerAddr is not set") 90 } 91 92 request = &Request{ 93 metadata: *metadata, 94 } 95 request.rootAddr, request.metaHash, _, err = request.metadata.serializeAndHash() 96 request.isNew = true 97 return request, nil 98 } 99 100 // 101 func (r *Request) Frequency() uint64 { 102 return r.metadata.Frequency 103 } 104 105 // 106 func (r *Request) Name() string { 107 return r.metadata.Name 108 } 109 110 // 111 func (r *Request) Multihash() bool { 112 return r.multihash 113 } 114 115 // 116 func (r *Request) Period() uint32 { 117 return r.period 118 } 119 120 // 121 func (r *Request) Version() uint32 { 122 return r.version 123 } 124 125 // 126 func (r *Request) RootAddr() storage.Address { 127 return r.rootAddr 128 } 129 130 // 131 func (r *Request) StartTime() Timestamp { 132 return r.metadata.StartTime 133 } 134 135 // 136 func (r *Request) Owner() common.Address { 137 return r.metadata.Owner 138 } 139 140 // 141 func (r *Request) Sign(signer Signer) error { 142 if r.metadata.Owner != zeroAddr && r.metadata.Owner != signer.Address() { 143 return NewError(ErrInvalidSignature, "Signer does not match current owner of the resource") 144 } 145 146 if err := r.SignedResourceUpdate.Sign(signer); err != nil { 147 return err 148 } 149 r.metadata.Owner = signer.Address() 150 return nil 151 } 152 153 // 154 func (r *Request) SetData(data []byte, multihash bool) { 155 r.data = data 156 r.multihash = multihash 157 r.signature = nil 158 if !r.isNew { 159 r.metadata.Frequency = 0 // 160 } 161 } 162 163 func (r *Request) IsNew() bool { 164 return r.metadata.Frequency > 0 && (r.period <= 1 || r.version <= 1) 165 } 166 167 func (r *Request) IsUpdate() bool { 168 return r.signature != nil 169 } 170 171 // 172 func (r *Request) fromJSON(j *updateRequestJSON) error { 173 174 r.version = j.Version 175 r.period = j.Period 176 r.multihash = j.Multihash 177 r.metadata.Name = j.Name 178 r.metadata.Frequency = j.Frequency 179 r.metadata.StartTime.Time = j.StartTime 180 181 if err := decodeHexArray(r.metadata.Owner[:], j.Owner, "ownerAddr"); err != nil { 182 return err 183 } 184 185 var err error 186 if j.Data != "" { 187 r.data, err = hexutil.Decode(j.Data) 188 if err != nil { 189 return NewError(ErrInvalidValue, "Cannot decode data") 190 } 191 } 192 193 var declaredRootAddr storage.Address 194 var declaredMetaHash []byte 195 196 declaredRootAddr, err = decodeHexSlice(j.RootAddr, storage.KeyLength, "rootAddr") 197 if err != nil { 198 return err 199 } 200 declaredMetaHash, err = decodeHexSlice(j.MetaHash, 32, "metaHash") 201 if err != nil { 202 return err 203 } 204 205 if r.IsNew() { 206 // 207 // 208 // 209 210 r.rootAddr, r.metaHash, _, err = r.metadata.serializeAndHash() 211 if err != nil { 212 return err 213 } 214 if j.RootAddr != "" && !bytes.Equal(declaredRootAddr, r.rootAddr) { 215 return NewError(ErrInvalidValue, "rootAddr does not match resource metadata") 216 } 217 if j.MetaHash != "" && !bytes.Equal(declaredMetaHash, r.metaHash) { 218 return NewError(ErrInvalidValue, "metaHash does not match resource metadata") 219 } 220 221 } else { 222 // 223 r.rootAddr = declaredRootAddr 224 r.metaHash = declaredMetaHash 225 } 226 227 if j.Signature != "" { 228 sigBytes, err := hexutil.Decode(j.Signature) 229 if err != nil || len(sigBytes) != signatureLength { 230 return NewError(ErrInvalidSignature, "Cannot decode signature") 231 } 232 r.signature = new(Signature) 233 r.updateAddr = r.UpdateAddr() 234 copy(r.signature[:], sigBytes) 235 } 236 return nil 237 } 238 239 func decodeHexArray(dst []byte, src, name string) error { 240 bytes, err := decodeHexSlice(src, len(dst), name) 241 if err != nil { 242 return err 243 } 244 if bytes != nil { 245 copy(dst, bytes) 246 } 247 return nil 248 } 249 250 func decodeHexSlice(src string, expectedLength int, name string) (bytes []byte, err error) { 251 if src != "" { 252 bytes, err = hexutil.Decode(src) 253 if err != nil || len(bytes) != expectedLength { 254 return nil, NewErrorf(ErrInvalidValue, "Cannot decode %s", name) 255 } 256 } 257 return bytes, nil 258 } 259 260 // 261 // 262 func (r *Request) UnmarshalJSON(rawData []byte) error { 263 var requestJSON updateRequestJSON 264 if err := json.Unmarshal(rawData, &requestJSON); err != nil { 265 return err 266 } 267 return r.fromJSON(&requestJSON) 268 } 269 270 // 271 // 272 func (r *Request) MarshalJSON() (rawData []byte, err error) { 273 var signatureString, dataHashString, rootAddrString, metaHashString string 274 if r.signature != nil { 275 signatureString = hexutil.Encode(r.signature[:]) 276 } 277 if r.data != nil { 278 dataHashString = hexutil.Encode(r.data) 279 } 280 if r.rootAddr != nil { 281 rootAddrString = hexutil.Encode(r.rootAddr) 282 } 283 if r.metaHash != nil { 284 metaHashString = hexutil.Encode(r.metaHash) 285 } 286 var ownerAddrString string 287 if r.metadata.Frequency == 0 { 288 ownerAddrString = "" 289 } else { 290 ownerAddrString = hexutil.Encode(r.metadata.Owner[:]) 291 } 292 293 requestJSON := &updateRequestJSON{ 294 Name: r.metadata.Name, 295 Frequency: r.metadata.Frequency, 296 StartTime: r.metadata.StartTime.Time, 297 Version: r.version, 298 Period: r.period, 299 Owner: ownerAddrString, 300 Data: dataHashString, 301 Multihash: r.multihash, 302 Signature: signatureString, 303 RootAddr: rootAddrString, 304 MetaHash: metaHashString, 305 } 306 307 return json.Marshal(requestJSON) 308 } 309