github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/bmt/bmt_r.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:43</date>
    10  //</624450112629772288>
    11  
    12  
    13  //包bmt是基于hashsize段的简单非当前引用实现
    14  //任意但固定的最大chunksize上的二进制merkle树哈希
    15  //
    16  //此实现不利用任何并行列表和使用
    17  //内存远比需要的多,但很容易看出它是正确的。
    18  //它可以用于生成用于优化实现的测试用例。
    19  //在bmt_test.go中对引用散列器的正确性进行了额外的检查。
    20  //*TestFisher
    21  //*测试bmthshercorrection函数
    22  package bmt
    23  
    24  import (
    25  	"hash"
    26  )
    27  
    28  //refhasher是BMT的非优化易读参考实现
    29  type RefHasher struct {
    30  maxDataLength int       //c*hashsize,其中c=2^ceil(log2(count)),其中count=ceil(length/hashsize)
    31  sectionLength int       //2*尺寸
    32  hasher        hash.Hash //基哈希函数(keccak256 sha3)
    33  }
    34  
    35  //NewRefHasher返回新的RefHasher
    36  func NewRefHasher(hasher BaseHasherFunc, count int) *RefHasher {
    37  	h := hasher()
    38  	hashsize := h.Size()
    39  	c := 2
    40  	for ; c < count; c *= 2 {
    41  	}
    42  	return &RefHasher{
    43  		sectionLength: 2 * hashsize,
    44  		maxDataLength: c * hashsize,
    45  		hasher:        h,
    46  	}
    47  }
    48  
    49  //hash返回字节片的bmt哈希
    50  //实现swarmhash接口
    51  func (rh *RefHasher) Hash(data []byte) []byte {
    52  //如果数据小于基长度(maxdatalength),我们将提供零填充。
    53  	d := make([]byte, rh.maxDataLength)
    54  	length := len(data)
    55  	if length > rh.maxDataLength {
    56  		length = rh.maxDataLength
    57  	}
    58  	copy(d, data[:length])
    59  	return rh.hash(d, rh.maxDataLength)
    60  }
    61  
    62  //数据的长度maxdatalength=segmentsize*2^k
    63  //哈希在给定切片的两半递归调用自身
    64  //连接结果,并返回该结果的哈希值
    65  //如果d的长度是2*SegmentSize,则只返回该节的哈希值。
    66  func (rh *RefHasher) hash(data []byte, length int) []byte {
    67  	var section []byte
    68  	if length == rh.sectionLength {
    69  //部分包含两个数据段(D)
    70  		section = data
    71  	} else {
    72  //部分包含左右BMT子目录的哈希
    73  //通过在数据的左半部分和右半部分递归调用哈希来计算
    74  		length /= 2
    75  		section = append(rh.hash(data[:length], length), rh.hash(data[length:], length)...)
    76  	}
    77  	rh.hasher.Reset()
    78  	rh.hasher.Write(section)
    79  	return rh.hasher.Sum(nil)
    80  }
    81