github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/storage/types.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 //</624342684512817152> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 package storage 29 30 import ( 31 "bytes" 32 "context" 33 "crypto" 34 "crypto/rand" 35 "encoding/binary" 36 "fmt" 37 "hash" 38 "io" 39 "sync" 40 41 "github.com/ethereum/go-ethereum/common" 42 "github.com/ethereum/go-ethereum/crypto/sha3" 43 "github.com/ethereum/go-ethereum/swarm/bmt" 44 "github.com/ethereum/go-ethereum/swarm/chunk" 45 ) 46 47 const MaxPO = 16 48 const KeyLength = 32 49 50 type Hasher func() hash.Hash 51 type SwarmHasher func() SwarmHash 52 53 // 54 // 55 type Peer interface{} 56 57 type Address []byte 58 59 func (a Address) Size() uint { 60 return uint(len(a)) 61 } 62 63 func (a Address) isEqual(y Address) bool { 64 return bytes.Equal(a, y) 65 } 66 67 func (a Address) bits(i, j uint) uint { 68 ii := i >> 3 69 jj := i & 7 70 if ii >= a.Size() { 71 return 0 72 } 73 74 if jj+j <= 8 { 75 return uint((a[ii] >> jj) & ((1 << j) - 1)) 76 } 77 78 res := uint(a[ii] >> jj) 79 jj = 8 - jj 80 j -= jj 81 for j != 0 { 82 ii++ 83 if j < 8 { 84 res += uint(a[ii]&((1<<j)-1)) << jj 85 return res 86 } 87 res += uint(a[ii]) << jj 88 jj += 8 89 j -= 8 90 } 91 return res 92 } 93 94 func Proximity(one, other []byte) (ret int) { 95 b := (MaxPO-1)/8 + 1 96 if b > len(one) { 97 b = len(one) 98 } 99 m := 8 100 for i := 0; i < b; i++ { 101 oxo := one[i] ^ other[i] 102 if i == b-1 { 103 m = MaxPO % 8 104 } 105 for j := 0; j < m; j++ { 106 if (oxo>>uint8(7-j))&0x01 != 0 { 107 return i*8 + j 108 } 109 } 110 } 111 return MaxPO 112 } 113 114 func IsZeroAddr(addr Address) bool { 115 return len(addr) == 0 || bytes.Equal(addr, ZeroAddr) 116 } 117 118 var ZeroAddr = Address(common.Hash{}.Bytes()) 119 120 func MakeHashFunc(hash string) SwarmHasher { 121 switch hash { 122 case "SHA256": 123 return func() SwarmHash { return &HashWithLength{crypto.SHA256.New()} } 124 case "SHA3": 125 return func() SwarmHash { return &HashWithLength{sha3.NewKeccak256()} } 126 case "BMT": 127 return func() SwarmHash { 128 hasher := sha3.NewKeccak256 129 hasherSize := hasher().Size() 130 segmentCount := chunk.DefaultSize / hasherSize 131 pool := bmt.NewTreePool(hasher, segmentCount, bmt.PoolSize) 132 return bmt.New(pool) 133 } 134 } 135 return nil 136 } 137 138 func (a Address) Hex() string { 139 return fmt.Sprintf("%064x", []byte(a[:])) 140 } 141 142 func (a Address) Log() string { 143 if len(a[:]) < 8 { 144 return fmt.Sprintf("%x", []byte(a[:])) 145 } 146 return fmt.Sprintf("%016x", []byte(a[:8])) 147 } 148 149 func (a Address) String() string { 150 return fmt.Sprintf("%064x", []byte(a)[:]) 151 } 152 153 func (a Address) MarshalJSON() (out []byte, err error) { 154 return []byte(`"` + a.String() + `"`), nil 155 } 156 157 func (a *Address) UnmarshalJSON(value []byte) error { 158 s := string(value) 159 *a = make([]byte, 32) 160 h := common.Hex2Bytes(s[1 : len(s)-1]) 161 copy(*a, h) 162 return nil 163 } 164 165 type AddressCollection []Address 166 167 func NewAddressCollection(l int) AddressCollection { 168 return make(AddressCollection, l) 169 } 170 171 func (c AddressCollection) Len() int { 172 return len(c) 173 } 174 175 func (c AddressCollection) Less(i, j int) bool { 176 return bytes.Compare(c[i], c[j]) == -1 177 } 178 179 func (c AddressCollection) Swap(i, j int) { 180 c[i], c[j] = c[j], c[i] 181 } 182 183 // 184 // 185 // 186 // 187 // 188 type Chunk struct { 189 Addr Address // 190 SData []byte // 191 Size int64 // 192 // 193 C chan bool // 194 ReqC chan bool // 195 dbStoredC chan bool // 196 dbStored bool 197 dbStoredMu *sync.Mutex 198 errored error // 199 erroredMu sync.Mutex 200 } 201 202 func (c *Chunk) SetErrored(err error) { 203 c.erroredMu.Lock() 204 defer c.erroredMu.Unlock() 205 206 c.errored = err 207 } 208 209 func (c *Chunk) GetErrored() error { 210 c.erroredMu.Lock() 211 defer c.erroredMu.Unlock() 212 213 return c.errored 214 } 215 216 func NewChunk(addr Address, reqC chan bool) *Chunk { 217 return &Chunk{ 218 Addr: addr, 219 ReqC: reqC, 220 dbStoredC: make(chan bool), 221 dbStoredMu: &sync.Mutex{}, 222 } 223 } 224 225 func (c *Chunk) markAsStored() { 226 c.dbStoredMu.Lock() 227 defer c.dbStoredMu.Unlock() 228 229 if !c.dbStored { 230 close(c.dbStoredC) 231 c.dbStored = true 232 } 233 } 234 235 func (c *Chunk) WaitToStore() error { 236 <-c.dbStoredC 237 return c.GetErrored() 238 } 239 240 func GenerateRandomChunk(dataSize int64) *Chunk { 241 return GenerateRandomChunks(dataSize, 1)[0] 242 } 243 244 func GenerateRandomChunks(dataSize int64, count int) (chunks []*Chunk) { 245 var i int 246 hasher := MakeHashFunc(DefaultHash)() 247 if dataSize > chunk.DefaultSize { 248 dataSize = chunk.DefaultSize 249 } 250 251 for i = 0; i < count; i++ { 252 chunks = append(chunks, NewChunk(nil, nil)) 253 chunks[i].SData = make([]byte, dataSize+8) 254 rand.Read(chunks[i].SData) 255 binary.LittleEndian.PutUint64(chunks[i].SData[:8], uint64(dataSize)) 256 hasher.ResetWithLength(chunks[i].SData[:8]) 257 hasher.Write(chunks[i].SData[8:]) 258 chunks[i].Addr = make([]byte, 32) 259 copy(chunks[i].Addr, hasher.Sum(nil)) 260 } 261 262 return chunks 263 } 264 265 // 266 type LazySectionReader interface { 267 Context() context.Context 268 Size(context.Context, chan bool) (int64, error) 269 io.Seeker 270 io.Reader 271 io.ReaderAt 272 } 273 274 type LazyTestSectionReader struct { 275 *io.SectionReader 276 } 277 278 func (r *LazyTestSectionReader) Size(context.Context, chan bool) (int64, error) { 279 return r.SectionReader.Size(), nil 280 } 281 282 func (r *LazyTestSectionReader) Context() context.Context { 283 return context.TODO() 284 } 285 286 type StoreParams struct { 287 Hash SwarmHasher `toml:"-"` 288 DbCapacity uint64 289 CacheCapacity uint 290 ChunkRequestsCacheCapacity uint 291 BaseKey []byte 292 } 293 294 func NewDefaultStoreParams() *StoreParams { 295 return NewStoreParams(defaultLDBCapacity, defaultCacheCapacity, defaultChunkRequestsCacheCapacity, nil, nil) 296 } 297 298 func NewStoreParams(ldbCap uint64, cacheCap uint, requestsCap uint, hash SwarmHasher, basekey []byte) *StoreParams { 299 if basekey == nil { 300 basekey = make([]byte, 32) 301 } 302 if hash == nil { 303 hash = MakeHashFunc(DefaultHash) 304 } 305 return &StoreParams{ 306 Hash: hash, 307 DbCapacity: ldbCap, 308 CacheCapacity: cacheCap, 309 ChunkRequestsCacheCapacity: requestsCap, 310 BaseKey: basekey, 311 } 312 } 313 314 type ChunkData []byte 315 316 type Reference []byte 317 318 // 319 type Putter interface { 320 Put(context.Context, ChunkData) (Reference, error) 321 // 322 RefSize() int64 323 // 324 Close() 325 // 326 Wait(context.Context) error 327 } 328 329 // 330 type Getter interface { 331 Get(context.Context, Reference) (ChunkData, error) 332 } 333 334 // 335 func (c ChunkData) Size() int64 { 336 return int64(binary.LittleEndian.Uint64(c[:8])) 337 } 338 339 func (c ChunkData) Data() []byte { 340 return c[8:] 341 } 342 343 type ChunkValidator interface { 344 Validate(addr Address, data []byte) bool 345 } 346 347 // 348 // 349 type ContentAddressValidator struct { 350 Hasher SwarmHasher 351 } 352 353 // 354 func NewContentAddressValidator(hasher SwarmHasher) *ContentAddressValidator { 355 return &ContentAddressValidator{ 356 Hasher: hasher, 357 } 358 } 359 360 // 361 func (v *ContentAddressValidator) Validate(addr Address, data []byte) bool { 362 if l := len(data); l < 9 || l > chunk.DefaultSize+8 { 363 return false 364 } 365 366 hasher := v.Hasher() 367 hasher.ResetWithLength(data[:8]) 368 hasher.Write(data[8:]) 369 hash := hasher.Sum(nil) 370 371 return bytes.Equal(hash, addr[:]) 372 } 373