github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/swarm/storage/feed/id.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package feed 18 19 import ( 20 "fmt" 21 "hash" 22 "strconv" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/swarm/storage" 26 "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" 27 ) 28 29 // ID uniquely identifies an update on the network. 30 type ID struct { 31 Feed `json:"feed"` 32 lookup.Epoch `json:"epoch"` 33 } 34 35 // ID layout: 36 // Feed feedLength bytes 37 // Epoch EpochLength 38 const idLength = feedLength + lookup.EpochLength 39 40 // Addr calculates the feed update chunk address corresponding to this ID 41 func (u *ID) Addr() (updateAddr storage.Address) { 42 serializedData := make([]byte, idLength) 43 var cursor int 44 u.Feed.binaryPut(serializedData[cursor : cursor+feedLength]) 45 cursor += feedLength 46 47 eid := u.Epoch.ID() 48 copy(serializedData[cursor:cursor+lookup.EpochLength], eid[:]) 49 50 hasher := hashPool.Get().(hash.Hash) 51 defer hashPool.Put(hasher) 52 hasher.Reset() 53 hasher.Write(serializedData) 54 return hasher.Sum(nil) 55 } 56 57 // binaryPut serializes this instance into the provided slice 58 func (u *ID) binaryPut(serializedData []byte) error { 59 if len(serializedData) != idLength { 60 return NewErrorf(ErrInvalidValue, "Incorrect slice size to serialize ID. Expected %d, got %d", idLength, len(serializedData)) 61 } 62 var cursor int 63 if err := u.Feed.binaryPut(serializedData[cursor : cursor+feedLength]); err != nil { 64 return err 65 } 66 cursor += feedLength 67 68 epochBytes, err := u.Epoch.MarshalBinary() 69 if err != nil { 70 return err 71 } 72 copy(serializedData[cursor:cursor+lookup.EpochLength], epochBytes[:]) 73 cursor += lookup.EpochLength 74 75 return nil 76 } 77 78 // binaryLength returns the expected size of this structure when serialized 79 func (u *ID) binaryLength() int { 80 return idLength 81 } 82 83 // binaryGet restores the current instance from the information contained in the passed slice 84 func (u *ID) binaryGet(serializedData []byte) error { 85 if len(serializedData) != idLength { 86 return NewErrorf(ErrInvalidValue, "Incorrect slice size to read ID. Expected %d, got %d", idLength, len(serializedData)) 87 } 88 89 var cursor int 90 if err := u.Feed.binaryGet(serializedData[cursor : cursor+feedLength]); err != nil { 91 return err 92 } 93 cursor += feedLength 94 95 if err := u.Epoch.UnmarshalBinary(serializedData[cursor : cursor+lookup.EpochLength]); err != nil { 96 return err 97 } 98 cursor += lookup.EpochLength 99 100 return nil 101 } 102 103 // FromValues deserializes this instance from a string key-value store 104 // useful to parse query strings 105 func (u *ID) FromValues(values Values) error { 106 level, _ := strconv.ParseUint(values.Get("level"), 10, 32) 107 u.Epoch.Level = uint8(level) 108 u.Epoch.Time, _ = strconv.ParseUint(values.Get("time"), 10, 64) 109 110 if u.Feed.User == (common.Address{}) { 111 return u.Feed.FromValues(values) 112 } 113 return nil 114 } 115 116 // AppendValues serializes this structure into the provided string key-value store 117 // useful to build query strings 118 func (u *ID) AppendValues(values Values) { 119 values.Set("level", fmt.Sprintf("%d", u.Epoch.Level)) 120 values.Set("time", fmt.Sprintf("%d", u.Epoch.Time)) 121 u.Feed.AppendValues(values) 122 }