gitee.com/lh-her-team/common@v1.5.1/crypto/hash/merkle.go (about)

     1  package hash
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"math"
     6  
     7  	"gitee.com/lh-her-team/common/crypto"
     8  )
     9  
    10  // nolint: deadcode,unused
    11  var h = sha256.New()
    12  
    13  func GetMerkleRoot(hashType string, hashes [][]byte) ([]byte, error) {
    14  	if len(hashes) == 0 {
    15  		return nil, nil
    16  	}
    17  	merkleTree, err := BuildMerkleTree(hashType, hashes)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  	return merkleTree[len(merkleTree)-1], nil
    22  }
    23  
    24  // take leaf node hash array and build merkle tree
    25  func BuildMerkleTree(hashType string, hashes [][]byte) ([][]byte, error) {
    26  	var hasher = Hash{
    27  		hashType: crypto.HashAlgoMap[hashType],
    28  	}
    29  	var err error
    30  	if len(hashes) == 0 {
    31  		return nil, nil
    32  	}
    33  	// use array to store merkle tree entries
    34  	nextPowOfTwo := getNextPowerOfTwo(len(hashes))
    35  	arraySize := nextPowOfTwo*2 - 1
    36  	merkelTree := make([][]byte, arraySize)
    37  	// 1. copy hashes first
    38  	copy(merkelTree[:len(hashes)], hashes[:])
    39  	// 2. compute merkle step by step
    40  	offset := nextPowOfTwo
    41  	for i := 0; i < arraySize-1; i += 2 {
    42  		switch {
    43  		case merkelTree[i] == nil:
    44  			// parent node is nil if left is nil
    45  			merkelTree[offset] = nil
    46  		case merkelTree[i+1] == nil:
    47  			// hash(left, left) if right is nil
    48  			merkelTree[offset], err = hashMerkleBranches(hasher, merkelTree[i], merkelTree[i])
    49  			if err != nil {
    50  				return nil, err
    51  			}
    52  		default:
    53  			// default hash(left||right)
    54  			merkelTree[offset], err = hashMerkleBranches(hasher, merkelTree[i], merkelTree[i+1])
    55  			if err != nil {
    56  				return nil, err
    57  			}
    58  		}
    59  		offset++
    60  	}
    61  	return merkelTree, nil
    62  }
    63  
    64  func GetMerklePath(hashType string, hash []byte, merkleTree [][]byte,
    65  	paths *[][]byte, withRoot bool) (brother []byte, parent []byte) {
    66  	brother, parent = getPath(hashType, hash, merkleTree, withRoot)
    67  	if brother != nil {
    68  		*paths = append(*paths, brother)
    69  		GetMerklePath(hashType, parent, merkleTree, paths, withRoot)
    70  	}
    71  	return brother, parent
    72  }
    73  
    74  func getPath(hashType string, hash []byte, merkleTree [][]byte, withRoot bool) (brother []byte, parent []byte) {
    75  	var hasher = Hash{
    76  		hashType: crypto.HashAlgoMap[hashType],
    77  	}
    78  	for i, bytes := range merkleTree {
    79  		if isEqualStr(bytes, hash) {
    80  			if isEvenNum(i) {
    81  				return getEvenHashMerkleBranches(i, hasher, merkleTree, withRoot)
    82  			}
    83  			parent, _ = hashMerkleBranches(hasher, merkleTree[i-1], hash)
    84  			return merkleTree[i-1], parent
    85  		}
    86  	}
    87  	return nil, nil
    88  }
    89  
    90  func getEvenHashMerkleBranches(i int, hasher Hash, merkleTree [][]byte, withRoot bool) (brother []byte, parent []byte) {
    91  	if i+1 < len(merkleTree) {
    92  		parent, _ = hashMerkleBranches(hasher, merkleTree[i], merkleTree[i+1])
    93  		return merkleTree[i+1], parent
    94  	} else if withRoot { //root
    95  		parent, _ = hashMerkleBranches(hasher, merkleTree[i], merkleTree[i])
    96  		return merkleTree[i], parent
    97  	}
    98  	return brother, parent
    99  }
   100  
   101  func isEvenNum(num int) bool {
   102  	return num&'1' == 0
   103  }
   104  
   105  func isEqualStr(dst, src []byte) bool {
   106  	return string(dst) == string(src)
   107  }
   108  
   109  func getNextPowerOfTwo(n int) int {
   110  	if n&(n-1) == 0 {
   111  		return n
   112  	}
   113  	exponent := uint(math.Log2(float64(n))) + 1
   114  	return 1 << exponent
   115  }
   116  
   117  func hashMerkleBranches(hasher Hash, left []byte, right []byte) ([]byte, error) {
   118  	data := make([]byte, len(left)+len(right))
   119  	copy(data[:len(left)], left)
   120  	copy(data[len(left):], right)
   121  	return hasher.Get(data)
   122  }
   123  
   124  func getNextPowerOfTen(n int) (int, int) {
   125  	if n == 1 {
   126  		return 1, 0
   127  	}
   128  	exponent := int(math.Log10(float64(n-1))) + 1
   129  	rootsSize := 0
   130  	for i := 0; i < exponent; i++ {
   131  		rootsSize += int(math.Pow10(i))
   132  	}
   133  	return int(math.Pow10(exponent)), rootsSize
   134  }