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  }