github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/trie/hasher.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 19:16:45</date>
    10  //</624450122876456960>
    11  
    12  
    13  package trie
    14  
    15  import (
    16  	"hash"
    17  	"sync"
    18  
    19  	"github.com/ethereum/go-ethereum/common"
    20  	"github.com/ethereum/go-ethereum/rlp"
    21  	"golang.org/x/crypto/sha3"
    22  )
    23  
    24  type hasher struct {
    25  	tmp        sliceBuffer
    26  	sha        keccakState
    27  	cachegen   uint16
    28  	cachelimit uint16
    29  	onleaf     LeafCallback
    30  }
    31  
    32  //keccakstate包裹sha3.state。除了通常的哈希方法外,它还支持
    33  //读取以从哈希状态获取可变数量的数据。读取比求和快
    34  //因为它不复制内部状态,而是修改内部状态。
    35  type keccakState interface {
    36  	hash.Hash
    37  	Read([]byte) (int, error)
    38  }
    39  
    40  type sliceBuffer []byte
    41  
    42  func (b *sliceBuffer) Write(data []byte) (n int, err error) {
    43  	*b = append(*b, data...)
    44  	return len(data), nil
    45  }
    46  
    47  func (b *sliceBuffer) Reset() {
    48  	*b = (*b)[:0]
    49  }
    50  
    51  //哈希存在于全局数据库中。
    52  var hasherPool = sync.Pool{
    53  	New: func() interface{} {
    54  		return &hasher{
    55  tmp: make(sliceBuffer, 0, 550), //cap和完整的fullnode一样大。
    56  			sha: sha3.NewLegacyKeccak256().(keccakState),
    57  		}
    58  	},
    59  }
    60  
    61  func newHasher(cachegen, cachelimit uint16, onleaf LeafCallback) *hasher {
    62  	h := hasherPool.Get().(*hasher)
    63  	h.cachegen, h.cachelimit, h.onleaf = cachegen, cachelimit, onleaf
    64  	return h
    65  }
    66  
    67  func returnHasherToPool(h *hasher) {
    68  	hasherPool.Put(h)
    69  }
    70  
    71  //哈希将节点向下折叠为哈希节点,同时返回
    72  //原始节点初始化为计算哈希以替换原始节点。
    73  func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) {
    74  //如果我们不存储节点,只需要散列,使用可用的缓存数据
    75  	if hash, dirty := n.cache(); hash != nil {
    76  		if db == nil {
    77  			return hash, n, nil
    78  		}
    79  		if n.canUnload(h.cachegen, h.cachelimit) {
    80  //从缓存中卸载节点。其所有子节点都将具有一个较低或相等的
    81  //缓存生成编号。
    82  			cacheUnloadCounter.Inc(1)
    83  			return hash, hash, nil
    84  		}
    85  		if !dirty {
    86  			return hash, n, nil
    87  		}
    88  	}
    89  //尚未处理或需要存储,请带孩子走
    90  	collapsed, cached, err := h.hashChildren(n, db)
    91  	if err != nil {
    92  		return hashNode{}, n, err
    93  	}
    94  	hashed, err := h.store(collapsed, db, force)
    95  	if err != nil {
    96  		return hashNode{}, n, err
    97  	}
    98  //缓存节点的哈希以便稍后重用和删除
    99  //提交模式下的脏标志。可以直接指定这些值
   100  //不首先复制节点,因为hashchildren会复制它。
   101  	cachedHash, _ := hashed.(hashNode)
   102  	switch cn := cached.(type) {
   103  	case *shortNode:
   104  		cn.flags.hash = cachedHash
   105  		if db != nil {
   106  			cn.flags.dirty = false
   107  		}
   108  	case *fullNode:
   109  		cn.flags.hash = cachedHash
   110  		if db != nil {
   111  			cn.flags.dirty = false
   112  		}
   113  	}
   114  	return hashed, cached, nil
   115  }
   116  
   117  //hashchildren将节点的子节点替换为其哈希,如果
   118  //子节点的大小大于哈希,同时返回折叠的节点
   119  //用缓存的子哈希替换原始节点。
   120  func (h *hasher) hashChildren(original node, db *Database) (node, node, error) {
   121  	var err error
   122  
   123  	switch n := original.(type) {
   124  	case *shortNode:
   125  //散列短节点的子节点,缓存新散列的子树
   126  		collapsed, cached := n.copy(), n.copy()
   127  		collapsed.Key = hexToCompact(n.Key)
   128  		cached.Key = common.CopyBytes(n.Key)
   129  
   130  		if _, ok := n.Val.(valueNode); !ok {
   131  			collapsed.Val, cached.Val, err = h.hash(n.Val, db, false)
   132  			if err != nil {
   133  				return original, original, err
   134  			}
   135  		}
   136  		return collapsed, cached, nil
   137  
   138  	case *fullNode:
   139  //散列完整节点的子节点,缓存新散列的子树
   140  		collapsed, cached := n.copy(), n.copy()
   141  
   142  		for i := 0; i < 16; i++ {
   143  			if n.Children[i] != nil {
   144  				collapsed.Children[i], cached.Children[i], err = h.hash(n.Children[i], db, false)
   145  				if err != nil {
   146  					return original, original, err
   147  				}
   148  			}
   149  		}
   150  		cached.Children[16] = n.Children[16]
   151  		return collapsed, cached, nil
   152  
   153  	default:
   154  //值和哈希节点没有子节点,因此它们保持原样
   155  		return n, original, nil
   156  	}
   157  }
   158  
   159  //store散列节点n,如果指定了存储层,它将写入
   160  //它的键/值对并跟踪任何节点->子引用以及任何
   161  //节点->外部trie引用。
   162  func (h *hasher) store(n node, db *Database, force bool) (node, error) {
   163  //不要存储哈希或空节点。
   164  	if _, isHash := n.(hashNode); n == nil || isHash {
   165  		return n, nil
   166  	}
   167  //生成节点的rlp编码
   168  	h.tmp.Reset()
   169  	if err := rlp.Encode(&h.tmp, n); err != nil {
   170  		panic("encode error: " + err.Error())
   171  	}
   172  	if len(h.tmp) < 32 && !force {
   173  return n, nil //小于32字节的节点存储在其父节点中
   174  	}
   175  //较大的节点被其散列替换并存储在数据库中。
   176  	hash, _ := n.cache()
   177  	if hash == nil {
   178  		hash = h.makeHashNode(h.tmp)
   179  	}
   180  
   181  	if db != nil {
   182  //我们正在将trie节点合并到中间内存缓存中
   183  		hash := common.BytesToHash(hash)
   184  
   185  		db.lock.Lock()
   186  		db.insert(hash, h.tmp, n)
   187  		db.lock.Unlock()
   188  
   189  //从“帐户”->“存储检索”跟踪外部引用
   190  		if h.onleaf != nil {
   191  			switch n := n.(type) {
   192  			case *shortNode:
   193  				if child, ok := n.Val.(valueNode); ok {
   194  					h.onleaf(child, hash)
   195  				}
   196  			case *fullNode:
   197  				for i := 0; i < 16; i++ {
   198  					if child, ok := n.Children[i].(valueNode); ok {
   199  						h.onleaf(child, hash)
   200  					}
   201  				}
   202  			}
   203  		}
   204  	}
   205  	return hash, nil
   206  }
   207  
   208  func (h *hasher) makeHashNode(data []byte) hashNode {
   209  	n := make(hashNode, h.sha.Size())
   210  	h.sha.Reset()
   211  	h.sha.Write(data)
   212  	h.sha.Read(n)
   213  	return n
   214  }
   215