github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/core/access_contoller/crypto/hash/merkle.go (about)

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