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