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