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  }