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