github.com/gobitfly/go-ethereum@v1.8.12/swarm/storage/types.go (about) 1 // Copyright 2016 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 storage 18 19 import ( 20 "bytes" 21 "crypto" 22 "crypto/rand" 23 "encoding/binary" 24 "fmt" 25 "hash" 26 "io" 27 "sync" 28 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/crypto/sha3" 31 "github.com/ethereum/go-ethereum/swarm/bmt" 32 ) 33 34 const MaxPO = 16 35 const KeyLength = 32 36 37 type Hasher func() hash.Hash 38 type SwarmHasher func() SwarmHash 39 40 // Peer is the recorded as Source on the chunk 41 // should probably not be here? but network should wrap chunk object 42 type Peer interface{} 43 44 type Address []byte 45 46 func (a Address) Size() uint { 47 return uint(len(a)) 48 } 49 50 func (a Address) isEqual(y Address) bool { 51 return bytes.Equal(a, y) 52 } 53 54 func (a Address) bits(i, j uint) uint { 55 ii := i >> 3 56 jj := i & 7 57 if ii >= a.Size() { 58 return 0 59 } 60 61 if jj+j <= 8 { 62 return uint((a[ii] >> jj) & ((1 << j) - 1)) 63 } 64 65 res := uint(a[ii] >> jj) 66 jj = 8 - jj 67 j -= jj 68 for j != 0 { 69 ii++ 70 if j < 8 { 71 res += uint(a[ii]&((1<<j)-1)) << jj 72 return res 73 } 74 res += uint(a[ii]) << jj 75 jj += 8 76 j -= 8 77 } 78 return res 79 } 80 81 func Proximity(one, other []byte) (ret int) { 82 b := (MaxPO-1)/8 + 1 83 if b > len(one) { 84 b = len(one) 85 } 86 m := 8 87 for i := 0; i < b; i++ { 88 oxo := one[i] ^ other[i] 89 if i == b-1 { 90 m = MaxPO % 8 91 } 92 for j := 0; j < m; j++ { 93 if (oxo>>uint8(7-j))&0x01 != 0 { 94 return i*8 + j 95 } 96 } 97 } 98 return MaxPO 99 } 100 101 func IsZeroAddr(addr Address) bool { 102 return len(addr) == 0 || bytes.Equal(addr, ZeroAddr) 103 } 104 105 var ZeroAddr = Address(common.Hash{}.Bytes()) 106 107 func MakeHashFunc(hash string) SwarmHasher { 108 switch hash { 109 case "SHA256": 110 return func() SwarmHash { return &HashWithLength{crypto.SHA256.New()} } 111 case "SHA3": 112 return func() SwarmHash { return &HashWithLength{sha3.NewKeccak256()} } 113 case "BMT": 114 return func() SwarmHash { 115 hasher := sha3.NewKeccak256 116 pool := bmt.NewTreePool(hasher, bmt.SegmentCount, bmt.PoolSize) 117 return bmt.New(pool) 118 } 119 } 120 return nil 121 } 122 123 func (a Address) Hex() string { 124 return fmt.Sprintf("%064x", []byte(a[:])) 125 } 126 127 func (a Address) Log() string { 128 if len(a[:]) < 8 { 129 return fmt.Sprintf("%x", []byte(a[:])) 130 } 131 return fmt.Sprintf("%016x", []byte(a[:8])) 132 } 133 134 func (a Address) String() string { 135 return fmt.Sprintf("%064x", []byte(a)[:]) 136 } 137 138 func (a Address) MarshalJSON() (out []byte, err error) { 139 return []byte(`"` + a.String() + `"`), nil 140 } 141 142 func (a *Address) UnmarshalJSON(value []byte) error { 143 s := string(value) 144 *a = make([]byte, 32) 145 h := common.Hex2Bytes(s[1 : len(s)-1]) 146 copy(*a, h) 147 return nil 148 } 149 150 type AddressCollection []Address 151 152 func NewAddressCollection(l int) AddressCollection { 153 return make(AddressCollection, l) 154 } 155 156 func (c AddressCollection) Len() int { 157 return len(c) 158 } 159 160 func (c AddressCollection) Less(i, j int) bool { 161 return bytes.Compare(c[i], c[j]) == -1 162 } 163 164 func (c AddressCollection) Swap(i, j int) { 165 c[i], c[j] = c[j], c[i] 166 } 167 168 // Chunk also serves as a request object passed to ChunkStores 169 // in case it is a retrieval request, Data is nil and Size is 0 170 // Note that Size is not the size of the data chunk, which is Data.Size() 171 // but the size of the subtree encoded in the chunk 172 // 0 if request, to be supplied by the dpa 173 type Chunk struct { 174 Addr Address // always 175 SData []byte // nil if request, to be supplied by dpa 176 Size int64 // size of the data covered by the subtree encoded in this chunk 177 //Source Peer // peer 178 C chan bool // to signal data delivery by the dpa 179 ReqC chan bool // to signal the request done 180 dbStoredC chan bool // never remove a chunk from memStore before it is written to dbStore 181 dbStored bool 182 dbStoredMu *sync.Mutex 183 errored error // flag which is set when the chunk request has errored or timeouted 184 erroredMu sync.Mutex 185 } 186 187 func (c *Chunk) SetErrored(err error) { 188 c.erroredMu.Lock() 189 defer c.erroredMu.Unlock() 190 191 c.errored = err 192 } 193 194 func (c *Chunk) GetErrored() error { 195 c.erroredMu.Lock() 196 defer c.erroredMu.Unlock() 197 198 return c.errored 199 } 200 201 func NewChunk(addr Address, reqC chan bool) *Chunk { 202 return &Chunk{ 203 Addr: addr, 204 ReqC: reqC, 205 dbStoredC: make(chan bool), 206 dbStoredMu: &sync.Mutex{}, 207 } 208 } 209 210 func (c *Chunk) markAsStored() { 211 c.dbStoredMu.Lock() 212 defer c.dbStoredMu.Unlock() 213 214 if !c.dbStored { 215 close(c.dbStoredC) 216 c.dbStored = true 217 } 218 } 219 220 func (c *Chunk) WaitToStore() error { 221 <-c.dbStoredC 222 return c.GetErrored() 223 } 224 225 func GenerateRandomChunk(dataSize int64) *Chunk { 226 return GenerateRandomChunks(dataSize, 1)[0] 227 } 228 229 func GenerateRandomChunks(dataSize int64, count int) (chunks []*Chunk) { 230 var i int 231 hasher := MakeHashFunc(DefaultHash)() 232 if dataSize > DefaultChunkSize { 233 dataSize = DefaultChunkSize 234 } 235 236 for i = 0; i < count; i++ { 237 chunks = append(chunks, NewChunk(nil, nil)) 238 chunks[i].SData = make([]byte, dataSize+8) 239 rand.Read(chunks[i].SData) 240 binary.LittleEndian.PutUint64(chunks[i].SData[:8], uint64(dataSize)) 241 hasher.ResetWithLength(chunks[i].SData[:8]) 242 hasher.Write(chunks[i].SData[8:]) 243 chunks[i].Addr = make([]byte, 32) 244 copy(chunks[i].Addr, hasher.Sum(nil)) 245 } 246 247 return chunks 248 } 249 250 // Size, Seek, Read, ReadAt 251 type LazySectionReader interface { 252 Size(chan bool) (int64, error) 253 io.Seeker 254 io.Reader 255 io.ReaderAt 256 } 257 258 type LazyTestSectionReader struct { 259 *io.SectionReader 260 } 261 262 func (r *LazyTestSectionReader) Size(chan bool) (int64, error) { 263 return r.SectionReader.Size(), nil 264 } 265 266 type StoreParams struct { 267 Hash SwarmHasher `toml:"-"` 268 DbCapacity uint64 269 CacheCapacity uint 270 ChunkRequestsCacheCapacity uint 271 BaseKey []byte 272 } 273 274 func NewDefaultStoreParams() *StoreParams { 275 return NewStoreParams(defaultLDBCapacity, defaultCacheCapacity, defaultChunkRequestsCacheCapacity, nil, nil) 276 } 277 278 func NewStoreParams(ldbCap uint64, cacheCap uint, requestsCap uint, hash SwarmHasher, basekey []byte) *StoreParams { 279 if basekey == nil { 280 basekey = make([]byte, 32) 281 } 282 if hash == nil { 283 hash = MakeHashFunc(DefaultHash) 284 } 285 return &StoreParams{ 286 Hash: hash, 287 DbCapacity: ldbCap, 288 CacheCapacity: cacheCap, 289 ChunkRequestsCacheCapacity: requestsCap, 290 BaseKey: basekey, 291 } 292 } 293 294 type ChunkData []byte 295 296 type Reference []byte 297 298 // Putter is responsible to store data and create a reference for it 299 type Putter interface { 300 Put(ChunkData) (Reference, error) 301 // RefSize returns the length of the Reference created by this Putter 302 RefSize() int64 303 // Close is to indicate that no more chunk data will be Put on this Putter 304 Close() 305 // Wait returns if all data has been store and the Close() was called. 306 Wait() 307 } 308 309 // Getter is an interface to retrieve a chunk's data by its reference 310 type Getter interface { 311 Get(Reference) (ChunkData, error) 312 } 313 314 // NOTE: this returns invalid data if chunk is encrypted 315 func (c ChunkData) Size() int64 { 316 return int64(binary.LittleEndian.Uint64(c[:8])) 317 } 318 319 func (c ChunkData) Data() []byte { 320 return c[8:] 321 } 322 323 type ChunkValidator interface { 324 Validate(addr Address, data []byte) bool 325 } 326 327 // Provides method for validation of content address in chunks 328 // Holds the corresponding hasher to create the address 329 type ContentAddressValidator struct { 330 Hasher SwarmHasher 331 } 332 333 // Constructor 334 func NewContentAddressValidator(hasher SwarmHasher) *ContentAddressValidator { 335 return &ContentAddressValidator{ 336 Hasher: hasher, 337 } 338 } 339 340 // Validate that the given key is a valid content address for the given data 341 func (v *ContentAddressValidator) Validate(addr Address, data []byte) bool { 342 hasher := v.Hasher() 343 hasher.ResetWithLength(data[:8]) 344 hasher.Write(data[8:]) 345 hash := hasher.Sum(nil) 346 347 return bytes.Equal(hash, addr[:]) 348 }