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  }