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 }