github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/mmr/util.go (about) 1 package mmr 2 3 import ( 4 "math/bits" 5 ) 6 7 // minPeakHeight equals position of the lowest 1 bit 8 // zero based height 9 func minPeakHeight(size uint64) int { 10 return bits.TrailingZeros64(size) 11 } 12 13 func maxPeakHeight(size uint64) int { 14 highBit := 64 - bits.LeadingZeros64(size) 15 return highBit - 1 16 } 17 18 // peakCount equals the number of 1 bit 19 func peakCount(size uint64) int { 20 return bits.OnesCount64(size) 21 } 22 23 func bagPeaks(hasher Hasher, peaks []HashType) HashType { 24 l := len(peaks) 25 accum := peaks[l-1] 26 27 for i := l - 2; i >= 0; i-- { 28 accum = hasher.Node(peaks[i], accum) 29 } 30 return accum 31 } 32 33 // leftPeak returns left peak 34 // 1 based index 35 // precondition: size >= 1 36 func leftPeak(size uint64) uint64 { 37 highBit := 64 - bits.LeadingZeros64(size) 38 return uint64(1<<highBit) - 1 39 } 40 41 // leftPeakLeaf returns the leaf of left peak 42 func leftPeakLeaf(size uint64) uint64 { 43 highBit := 64 - bits.LeadingZeros64(size) 44 return 1 << (highBit - 1) 45 } 46 47 // getMoutainSizes returns moutain sizes from left to right 48 func getMoutainSizes(size uint64) []uint64 { 49 nPeaks := bits.OnesCount64(size) 50 51 moutainSizes := make([]uint64, nPeaks, nPeaks) 52 for i, id := nPeaks-1, uint64(1); size != 0; size = size >> 1 { 53 id = id * 2 54 if size%2 == 1 { 55 moutainSizes[i] = id - 1 56 i-- 57 } 58 } 59 60 return moutainSizes 61 } 62 63 // getMoutainPeaks returns moutain peaks from left to right 64 // 1 based index 65 func getMoutainPeaks(size uint64) []uint64 { 66 nPeaks := bits.OnesCount64(size) 67 peakPos := make([]uint64, nPeaks, nPeaks) 68 for i, id := nPeaks-1, uint64(1); size != 0; size = size >> 1 { 69 id = id * 2 70 if size%2 == 1 { 71 peakPos[i] = id - 1 72 i-- 73 } 74 } 75 76 for i := 1; i < nPeaks; i++ { 77 peakPos[i] += peakPos[i-1] 78 } 79 80 return peakPos 81 } 82 83 func proofLength(index, size uint64) int { 84 length := 0 85 lastNode := size - 1 86 for lastNode > 0 { 87 if index%2 == 1 || index < lastNode { 88 length += 1 89 } 90 index /= 2 91 lastNode /= 2 92 } 93 return length 94 } 95 96 var defaultHasher = NewHasher([]byte{0}, []byte{1}) 97 98 // ComputeRoot ... 99 func ComputeRoot(hashes []HashType) (root HashType) { 100 if len(hashes) == 0 { 101 return 102 } 103 104 mmr := NewMMR(0, nil, defaultHasher, nil) 105 for _, hash := range hashes { 106 mmr.PushHash(hash, false) 107 } 108 109 root = mmr.Root() 110 111 return 112 }