github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/hasherstore.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  	"context"
    29  	"fmt"
    30  	"sync"
    31  
    32  	"github.com/ethereum/go-ethereum/crypto/sha3"
    33  	"github.com/ethereum/go-ethereum/swarm/chunk"
    34  	"github.com/ethereum/go-ethereum/swarm/storage/encryption"
    35  )
    36  
    37  type chunkEncryption struct {
    38  	spanEncryption encryption.Encryption
    39  	dataEncryption encryption.Encryption
    40  }
    41  
    42  type hasherStore struct {
    43  	store           ChunkStore
    44  	hashFunc        SwarmHasher
    45  	chunkEncryption *chunkEncryption
    46  hashSize        int   //
    47  refSize         int64 //
    48  	wg              *sync.WaitGroup
    49  	closed          chan struct{}
    50  }
    51  
    52  func newChunkEncryption(chunkSize, refSize int64) *chunkEncryption {
    53  	return &chunkEncryption{
    54  		spanEncryption: encryption.New(0, uint32(chunkSize/refSize), sha3.NewKeccak256),
    55  		dataEncryption: encryption.New(int(chunkSize), 0, sha3.NewKeccak256),
    56  	}
    57  }
    58  
    59  //
    60  //
    61  //
    62  func NewHasherStore(chunkStore ChunkStore, hashFunc SwarmHasher, toEncrypt bool) *hasherStore {
    63  	var chunkEncryption *chunkEncryption
    64  
    65  	hashSize := hashFunc().Size()
    66  	refSize := int64(hashSize)
    67  	if toEncrypt {
    68  		refSize += encryption.KeyLength
    69  		chunkEncryption = newChunkEncryption(chunk.DefaultSize, refSize)
    70  	}
    71  
    72  	return &hasherStore{
    73  		store:           chunkStore,
    74  		hashFunc:        hashFunc,
    75  		chunkEncryption: chunkEncryption,
    76  		hashSize:        hashSize,
    77  		refSize:         refSize,
    78  		wg:              &sync.WaitGroup{},
    79  		closed:          make(chan struct{}),
    80  	}
    81  }
    82  
    83  //
    84  //
    85  //
    86  func (h *hasherStore) Put(ctx context.Context, chunkData ChunkData) (Reference, error) {
    87  	c := chunkData
    88  	size := chunkData.Size()
    89  	var encryptionKey encryption.Key
    90  	if h.chunkEncryption != nil {
    91  		var err error
    92  		c, encryptionKey, err = h.encryptChunkData(chunkData)
    93  		if err != nil {
    94  			return nil, err
    95  		}
    96  	}
    97  	chunk := h.createChunk(c, size)
    98  
    99  	h.storeChunk(ctx, chunk)
   100  
   101  	return Reference(append(chunk.Addr, encryptionKey...)), nil
   102  }
   103  
   104  //
   105  //
   106  //
   107  func (h *hasherStore) Get(ctx context.Context, ref Reference) (ChunkData, error) {
   108  	key, encryptionKey, err := parseReference(ref, h.hashSize)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	toDecrypt := (encryptionKey != nil)
   113  
   114  	chunk, err := h.store.Get(ctx, key)
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  
   119  	chunkData := chunk.SData
   120  	if toDecrypt {
   121  		var err error
   122  		chunkData, err = h.decryptChunkData(chunkData, encryptionKey)
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  	}
   127  	return chunkData, nil
   128  }
   129  
   130  //
   131  //
   132  func (h *hasherStore) Close() {
   133  	close(h.closed)
   134  }
   135  
   136  //
   137  //
   138  //
   139  func (h *hasherStore) Wait(ctx context.Context) error {
   140  	<-h.closed
   141  	h.wg.Wait()
   142  	return nil
   143  }
   144  
   145  func (h *hasherStore) createHash(chunkData ChunkData) Address {
   146  	hasher := h.hashFunc()
   147  hasher.ResetWithLength(chunkData[:8]) //
   148  hasher.Write(chunkData[8:])           //
   149  	return hasher.Sum(nil)
   150  }
   151  
   152  func (h *hasherStore) createChunk(chunkData ChunkData, chunkSize int64) *Chunk {
   153  	hash := h.createHash(chunkData)
   154  	chunk := NewChunk(hash, nil)
   155  	chunk.SData = chunkData
   156  	chunk.Size = chunkSize
   157  
   158  	return chunk
   159  }
   160  
   161  func (h *hasherStore) encryptChunkData(chunkData ChunkData) (ChunkData, encryption.Key, error) {
   162  	if len(chunkData) < 8 {
   163  		return nil, nil, fmt.Errorf("Invalid ChunkData, min length 8 got %v", len(chunkData))
   164  	}
   165  
   166  	encryptionKey, err := encryption.GenerateRandomKey()
   167  	if err != nil {
   168  		return nil, nil, err
   169  	}
   170  
   171  	encryptedSpan, err := h.chunkEncryption.spanEncryption.Encrypt(chunkData[:8], encryptionKey)
   172  	if err != nil {
   173  		return nil, nil, err
   174  	}
   175  	encryptedData, err := h.chunkEncryption.dataEncryption.Encrypt(chunkData[8:], encryptionKey)
   176  	if err != nil {
   177  		return nil, nil, err
   178  	}
   179  	c := make(ChunkData, len(encryptedSpan)+len(encryptedData))
   180  	copy(c[:8], encryptedSpan)
   181  	copy(c[8:], encryptedData)
   182  	return c, encryptionKey, nil
   183  }
   184  
   185  func (h *hasherStore) decryptChunkData(chunkData ChunkData, encryptionKey encryption.Key) (ChunkData, error) {
   186  	if len(chunkData) < 8 {
   187  		return nil, fmt.Errorf("Invalid ChunkData, min length 8 got %v", len(chunkData))
   188  	}
   189  
   190  	decryptedSpan, err := h.chunkEncryption.spanEncryption.Decrypt(chunkData[:8], encryptionKey)
   191  	if err != nil {
   192  		return nil, err
   193  	}
   194  
   195  	decryptedData, err := h.chunkEncryption.dataEncryption.Decrypt(chunkData[8:], encryptionKey)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  //
   201  	length := ChunkData(decryptedSpan).Size()
   202  	for length > chunk.DefaultSize {
   203  		length = length + (chunk.DefaultSize - 1)
   204  		length = length / chunk.DefaultSize
   205  		length *= h.refSize
   206  	}
   207  
   208  	c := make(ChunkData, length+8)
   209  	copy(c[:8], decryptedSpan)
   210  	copy(c[8:], decryptedData[:length])
   211  
   212  	return c[:length+8], nil
   213  }
   214  
   215  func (h *hasherStore) RefSize() int64 {
   216  	return h.refSize
   217  }
   218  
   219  func (h *hasherStore) storeChunk(ctx context.Context, chunk *Chunk) {
   220  	h.wg.Add(1)
   221  	go func() {
   222  		<-chunk.dbStoredC
   223  		h.wg.Done()
   224  	}()
   225  	h.store.Put(ctx, chunk)
   226  }
   227  
   228  func parseReference(ref Reference, hashSize int) (Address, encryption.Key, error) {
   229  	encryptedKeyLength := hashSize + encryption.KeyLength
   230  	switch len(ref) {
   231  	case KeyLength:
   232  		return Address(ref), nil, nil
   233  	case encryptedKeyLength:
   234  		encKeyIdx := len(ref) - encryption.KeyLength
   235  		return Address(ref[:encKeyIdx]), encryption.Key(ref[encKeyIdx:]), nil
   236  	default:
   237  		return nil, nil, fmt.Errorf("Invalid reference length, expected %v or %v got %v", hashSize, encryptedKeyLength, len(ref))
   238  	}
   239  
   240  }