github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/mru/handler.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 // 26 // 27 package mru 28 29 import ( 30 "bytes" 31 "context" 32 "sync" 33 "time" 34 "unsafe" 35 36 "github.com/ethereum/go-ethereum/swarm/chunk" 37 "github.com/ethereum/go-ethereum/swarm/log" 38 "github.com/ethereum/go-ethereum/swarm/storage" 39 ) 40 41 type Handler struct { 42 chunkStore *storage.NetStore 43 HashSize int 44 resources map[uint64]*resource 45 resourceLock sync.RWMutex 46 storeTimeout time.Duration 47 queryMaxPeriods uint32 48 } 49 50 // 51 // 52 type HandlerParams struct { 53 QueryMaxPeriods uint32 54 } 55 56 // 57 var hashPool sync.Pool 58 var minimumChunkLength int 59 60 // 61 func init() { 62 hashPool = sync.Pool{ 63 New: func() interface{} { 64 return storage.MakeHashFunc(resourceHashAlgorithm)() 65 }, 66 } 67 if minimumMetadataLength < minimumUpdateDataLength { 68 minimumChunkLength = minimumMetadataLength 69 } else { 70 minimumChunkLength = minimumUpdateDataLength 71 } 72 } 73 74 // 75 func NewHandler(params *HandlerParams) *Handler { 76 rh := &Handler{ 77 resources: make(map[uint64]*resource), 78 storeTimeout: defaultStoreTimeout, 79 queryMaxPeriods: params.QueryMaxPeriods, 80 } 81 82 for i := 0; i < hasherCount; i++ { 83 hashfunc := storage.MakeHashFunc(resourceHashAlgorithm)() 84 if rh.HashSize == 0 { 85 rh.HashSize = hashfunc.Size() 86 } 87 hashPool.Put(hashfunc) 88 } 89 90 return rh 91 } 92 93 // 94 func (h *Handler) SetStore(store *storage.NetStore) { 95 h.chunkStore = store 96 } 97 98 // 99 // 100 // 101 func (h *Handler) Validate(chunkAddr storage.Address, data []byte) bool { 102 dataLength := len(data) 103 if dataLength < minimumChunkLength || dataLength > chunk.DefaultSize+8 { 104 return false 105 } 106 107 // 108 if data[0] == 0 && data[1] == 0 && dataLength >= minimumMetadataLength { 109 // 110 rootAddr, _ := metadataHash(data) 111 valid := bytes.Equal(chunkAddr, rootAddr) 112 if !valid { 113 log.Debug("Invalid root metadata chunk with address", "addr", chunkAddr.Hex()) 114 } 115 return valid 116 } 117 118 // 119 // 120 // 121 122 // 123 var r SignedResourceUpdate 124 if err := r.fromChunk(chunkAddr, data); err != nil { 125 log.Debug("Invalid resource chunk", "addr", chunkAddr.Hex(), "err", err.Error()) 126 return false 127 } 128 129 // 130 // 131 // 132 if !bytes.Equal(chunkAddr, r.updateHeader.UpdateAddr()) { 133 log.Debug("period,version,rootAddr contained in update chunk do not match updateAddr", "addr", chunkAddr.Hex()) 134 return false 135 } 136 137 // 138 // 139 // 140 if err := r.Verify(); err != nil { 141 log.Debug("Invalid signature", "err", err) 142 return false 143 } 144 145 return true 146 } 147 148 // 149 func (h *Handler) GetContent(rootAddr storage.Address) (storage.Address, []byte, error) { 150 rsrc := h.get(rootAddr) 151 if rsrc == nil || !rsrc.isSynced() { 152 return nil, nil, NewError(ErrNotFound, " does not exist or is not synced") 153 } 154 return rsrc.lastKey, rsrc.data, nil 155 } 156 157 // 158 func (h *Handler) GetLastPeriod(rootAddr storage.Address) (uint32, error) { 159 rsrc := h.get(rootAddr) 160 if rsrc == nil { 161 return 0, NewError(ErrNotFound, " does not exist") 162 } else if !rsrc.isSynced() { 163 return 0, NewError(ErrNotSynced, " is not synced") 164 } 165 return rsrc.period, nil 166 } 167 168 // 169 func (h *Handler) GetVersion(rootAddr storage.Address) (uint32, error) { 170 rsrc := h.get(rootAddr) 171 if rsrc == nil { 172 return 0, NewError(ErrNotFound, " does not exist") 173 } else if !rsrc.isSynced() { 174 return 0, NewError(ErrNotSynced, " is not synced") 175 } 176 return rsrc.version, nil 177 } 178 179 // 180 func (h *Handler) New(ctx context.Context, request *Request) error { 181 182 // 183 if request.metadata.Frequency == 0 { 184 return NewError(ErrInvalidValue, "frequency cannot be 0 when creating a resource") 185 } 186 187 // 188 if request.metadata.Owner == zeroAddr { 189 return NewError(ErrInvalidValue, "ownerAddr must be set to create a new metadata chunk") 190 } 191 192 // 193 chunk, metaHash, err := request.metadata.newChunk() 194 if err != nil { 195 return err 196 } 197 if request.metaHash != nil && !bytes.Equal(request.metaHash, metaHash) || 198 request.rootAddr != nil && !bytes.Equal(request.rootAddr, chunk.Addr) { 199 return NewError(ErrInvalidValue, "metaHash in UpdateRequest does not match actual metadata") 200 } 201 202 request.metaHash = metaHash 203 request.rootAddr = chunk.Addr 204 205 h.chunkStore.Put(ctx, chunk) 206 log.Debug("new resource", "name", request.metadata.Name, "startTime", request.metadata.StartTime, "frequency", request.metadata.Frequency, "owner", request.metadata.Owner) 207 208 // 209 rsrc := &resource{ 210 resourceUpdate: resourceUpdate{ 211 updateHeader: updateHeader{ 212 UpdateLookup: UpdateLookup{ 213 rootAddr: chunk.Addr, 214 }, 215 }, 216 }, 217 ResourceMetadata: request.metadata, 218 updated: time.Now(), 219 } 220 h.set(chunk.Addr, rsrc) 221 222 return nil 223 } 224 225 // 226 // 227 // 228 func (h *Handler) NewUpdateRequest(ctx context.Context, rootAddr storage.Address) (updateRequest *Request, err error) { 229 230 if rootAddr == nil { 231 return nil, NewError(ErrInvalidValue, "rootAddr cannot be nil") 232 } 233 234 // 235 rsrc, err := h.Load(ctx, rootAddr) 236 if err != nil { 237 return nil, err 238 } 239 240 now := TimestampProvider.Now() 241 242 updateRequest = new(Request) 243 updateRequest.period, err = getNextPeriod(rsrc.StartTime.Time, now.Time, rsrc.Frequency) 244 if err != nil { 245 return nil, err 246 } 247 248 if _, err = h.lookup(rsrc, LookupLatestVersionInPeriod(rsrc.rootAddr, updateRequest.period)); err != nil { 249 if err.(*Error).code != ErrNotFound { 250 return nil, err 251 } 252 // 253 // 254 } 255 256 updateRequest.multihash = rsrc.multihash 257 updateRequest.rootAddr = rsrc.rootAddr 258 updateRequest.metaHash = rsrc.metaHash 259 updateRequest.metadata = rsrc.ResourceMetadata 260 261 // 262 // 263 if h.hasUpdate(rootAddr, updateRequest.period) { 264 updateRequest.version = rsrc.version + 1 265 } else { 266 updateRequest.version = 1 267 } 268 269 return updateRequest, nil 270 } 271 272 // 273 // 274 // 275 // 276 // 277 // 278 // 279 func (h *Handler) Lookup(ctx context.Context, params *LookupParams) (*resource, error) { 280 281 rsrc := h.get(params.rootAddr) 282 if rsrc == nil { 283 return nil, NewError(ErrNothingToReturn, "resource not loaded") 284 } 285 return h.lookup(rsrc, params) 286 } 287 288 // 289 // 290 // 291 // 292 func (h *Handler) LookupPrevious(ctx context.Context, params *LookupParams) (*resource, error) { 293 rsrc := h.get(params.rootAddr) 294 if rsrc == nil { 295 return nil, NewError(ErrNothingToReturn, "resource not loaded") 296 } 297 if !rsrc.isSynced() { 298 return nil, NewError(ErrNotSynced, "LookupPrevious requires synced resource.") 299 } else if rsrc.period == 0 { 300 return nil, NewError(ErrNothingToReturn, " not found") 301 } 302 var version, period uint32 303 if rsrc.version > 1 { 304 version = rsrc.version - 1 305 period = rsrc.period 306 } else if rsrc.period == 1 { 307 return nil, NewError(ErrNothingToReturn, "Current update is the oldest") 308 } else { 309 version = 0 310 period = rsrc.period - 1 311 } 312 return h.lookup(rsrc, NewLookupParams(rsrc.rootAddr, period, version, params.Limit)) 313 } 314 315 // 316 func (h *Handler) lookup(rsrc *resource, params *LookupParams) (*resource, error) { 317 318 lp := *params 319 // 320 if h.chunkStore == nil { 321 return nil, NewError(ErrInit, "Call Handler.SetStore() before performing lookups") 322 } 323 324 var specificperiod bool 325 if lp.period > 0 { 326 specificperiod = true 327 } else { 328 // 329 now := TimestampProvider.Now() 330 331 var period uint32 332 period, err := getNextPeriod(rsrc.StartTime.Time, now.Time, rsrc.Frequency) 333 if err != nil { 334 return nil, err 335 } 336 lp.period = period 337 } 338 339 // 340 // 341 // 342 var specificversion bool 343 if lp.version > 0 { 344 specificversion = true 345 } else { 346 lp.version = 1 347 } 348 349 var hops uint32 350 if lp.Limit == 0 { 351 lp.Limit = h.queryMaxPeriods 352 } 353 log.Trace("resource lookup", "period", lp.period, "version", lp.version, "limit", lp.Limit) 354 for lp.period > 0 { 355 if lp.Limit != 0 && hops > lp.Limit { 356 return nil, NewErrorf(ErrPeriodDepth, "Lookup exceeded max period hops (%d)", lp.Limit) 357 } 358 updateAddr := lp.UpdateAddr() 359 chunk, err := h.chunkStore.GetWithTimeout(context.TODO(), updateAddr, defaultRetrieveTimeout) 360 if err == nil { 361 if specificversion { 362 return h.updateIndex(rsrc, chunk) 363 } 364 // 365 log.Trace("rsrc update version 1 found, checking for version updates", "period", lp.period, "updateAddr", updateAddr) 366 for { 367 newversion := lp.version + 1 368 updateAddr := lp.UpdateAddr() 369 newchunk, err := h.chunkStore.GetWithTimeout(context.TODO(), updateAddr, defaultRetrieveTimeout) 370 if err != nil { 371 return h.updateIndex(rsrc, chunk) 372 } 373 chunk = newchunk 374 lp.version = newversion 375 log.Trace("version update found, checking next", "version", lp.version, "period", lp.period, "updateAddr", updateAddr) 376 } 377 } 378 if specificperiod { 379 break 380 } 381 log.Trace("rsrc update not found, checking previous period", "period", lp.period, "updateAddr", updateAddr) 382 lp.period-- 383 hops++ 384 } 385 return nil, NewError(ErrNotFound, "no updates found") 386 } 387 388 // 389 // 390 func (h *Handler) Load(ctx context.Context, rootAddr storage.Address) (*resource, error) { 391 chunk, err := h.chunkStore.GetWithTimeout(ctx, rootAddr, defaultRetrieveTimeout) 392 if err != nil { 393 return nil, NewError(ErrNotFound, err.Error()) 394 } 395 396 // 397 rsrc := &resource{} 398 399 if err := rsrc.ResourceMetadata.binaryGet(chunk.SData); err != nil { // 400 return nil, err 401 } 402 403 rsrc.rootAddr, rsrc.metaHash = metadataHash(chunk.SData) 404 if !bytes.Equal(rsrc.rootAddr, rootAddr) { 405 return nil, NewError(ErrCorruptData, "Corrupt metadata chunk") 406 } 407 h.set(rootAddr, rsrc) 408 log.Trace("resource index load", "rootkey", rootAddr, "name", rsrc.ResourceMetadata.Name, "starttime", rsrc.ResourceMetadata.StartTime, "frequency", rsrc.ResourceMetadata.Frequency) 409 return rsrc, nil 410 } 411 412 // 413 func (h *Handler) updateIndex(rsrc *resource, chunk *storage.Chunk) (*resource, error) { 414 415 // 416 var r SignedResourceUpdate 417 if err := r.fromChunk(chunk.Addr, chunk.SData); err != nil { 418 return nil, err 419 } 420 log.Trace("resource index update", "name", rsrc.ResourceMetadata.Name, "updatekey", chunk.Addr, "period", r.period, "version", r.version) 421 422 // 423 rsrc.lastKey = chunk.Addr 424 rsrc.period = r.period 425 rsrc.version = r.version 426 rsrc.updated = time.Now() 427 rsrc.data = make([]byte, len(r.data)) 428 rsrc.multihash = r.multihash 429 copy(rsrc.data, r.data) 430 rsrc.Reader = bytes.NewReader(rsrc.data) 431 log.Debug("resource synced", "name", rsrc.ResourceMetadata.Name, "updateAddr", chunk.Addr, "period", rsrc.period, "version", rsrc.version) 432 h.set(chunk.Addr, rsrc) 433 return rsrc, nil 434 } 435 436 // 437 // 438 // 439 // 440 // 441 // 442 func (h *Handler) Update(ctx context.Context, r *SignedResourceUpdate) (storage.Address, error) { 443 return h.update(ctx, r) 444 } 445 446 // 447 func (h *Handler) update(ctx context.Context, r *SignedResourceUpdate) (updateAddr storage.Address, err error) { 448 449 // 450 if h.chunkStore == nil { 451 return nil, NewError(ErrInit, "Call Handler.SetStore() before updating") 452 } 453 454 rsrc := h.get(r.rootAddr) 455 if rsrc != nil && rsrc.period != 0 && rsrc.version != 0 && // 456 rsrc.period == r.period && rsrc.version >= r.version { // 457 458 return nil, NewError(ErrInvalidValue, "A former update in this period is already known to exist") 459 } 460 461 chunk, err := r.toChunk() // 462 if err != nil { 463 return nil, err 464 } 465 466 // 467 h.chunkStore.Put(ctx, chunk) 468 log.Trace("resource update", "updateAddr", r.updateAddr, "lastperiod", r.period, "version", r.version, "data", chunk.SData, "multihash", r.multihash) 469 470 // 471 if rsrc != nil && (r.period > rsrc.period || (rsrc.period == r.period && r.version > rsrc.version)) { 472 rsrc.period = r.period 473 rsrc.version = r.version 474 rsrc.data = make([]byte, len(r.data)) 475 rsrc.updated = time.Now() 476 rsrc.lastKey = r.updateAddr 477 rsrc.multihash = r.multihash 478 copy(rsrc.data, r.data) 479 rsrc.Reader = bytes.NewReader(rsrc.data) 480 } 481 return r.updateAddr, nil 482 } 483 484 // 485 func (h *Handler) get(rootAddr storage.Address) *resource { 486 if len(rootAddr) < storage.KeyLength { 487 log.Warn("Handler.get with invalid rootAddr") 488 return nil 489 } 490 hashKey := *(*uint64)(unsafe.Pointer(&rootAddr[0])) 491 h.resourceLock.RLock() 492 defer h.resourceLock.RUnlock() 493 rsrc := h.resources[hashKey] 494 return rsrc 495 } 496 497 // 498 func (h *Handler) set(rootAddr storage.Address, rsrc *resource) { 499 if len(rootAddr) < storage.KeyLength { 500 log.Warn("Handler.set with invalid rootAddr") 501 return 502 } 503 hashKey := *(*uint64)(unsafe.Pointer(&rootAddr[0])) 504 h.resourceLock.Lock() 505 defer h.resourceLock.Unlock() 506 h.resources[hashKey] = rsrc 507 } 508 509 // 510 func (h *Handler) hasUpdate(rootAddr storage.Address, period uint32) bool { 511 rsrc := h.get(rootAddr) 512 return rsrc != nil && rsrc.period == period 513 }