git.gammaspectra.live/P2Pool/consensus@v0.0.0-20240403173234-a039820b20c9/monero/crypto/merkle.go (about) 1 package crypto 2 3 import ( 4 "git.gammaspectra.live/P2Pool/consensus/types" 5 "git.gammaspectra.live/P2Pool/consensus/utils" 6 "git.gammaspectra.live/P2Pool/sha3" 7 ) 8 9 type BinaryTreeHash []types.Hash 10 11 func (t BinaryTreeHash) leafHash(hasher *sha3.HasherState) (rootHash types.Hash) { 12 switch len(t) { 13 case 0: 14 panic("unsupported length") 15 case 1: 16 return t[0] 17 default: 18 //only hash the next two items 19 hasher.Reset() 20 _, _ = hasher.Write(t[0][:]) 21 _, _ = hasher.Write(t[1][:]) 22 HashFastSum(hasher, rootHash[:]) 23 return rootHash 24 } 25 } 26 27 func (t BinaryTreeHash) RootHash() (rootHash types.Hash) { 28 29 hasher := GetKeccak256Hasher() 30 defer PutKeccak256Hasher(hasher) 31 count := len(t) 32 if count <= 2 { 33 return t.leafHash(hasher) 34 } 35 36 pow2cnt := utils.PreviousPowerOfTwo(uint64(count)) 37 offset := pow2cnt*2 - count 38 39 temporaryTree := make(BinaryTreeHash, pow2cnt) 40 copy(temporaryTree, t[:offset]) 41 42 offsetTree := temporaryTree[offset:] 43 for i := range offsetTree { 44 offsetTree[i] = t[offset+i*2:].leafHash(hasher) 45 } 46 47 for pow2cnt >>= 1; pow2cnt > 1; pow2cnt >>= 1 { 48 for i := range temporaryTree[:pow2cnt] { 49 temporaryTree[i] = temporaryTree[i*2:].leafHash(hasher) 50 } 51 } 52 53 rootHash = temporaryTree.leafHash(hasher) 54 55 return 56 } 57 58 func (t BinaryTreeHash) MainBranch() (mainBranch []types.Hash) { 59 60 hasher := GetKeccak256Hasher() 61 defer PutKeccak256Hasher(hasher) 62 count := len(t) 63 if count <= 2 { 64 return nil 65 } 66 67 pow2cnt := utils.PreviousPowerOfTwo(uint64(count)) 68 offset := pow2cnt*2 - count 69 70 temporaryTree := make(BinaryTreeHash, pow2cnt) 71 copy(temporaryTree, t[:offset]) 72 73 offsetTree := temporaryTree[offset:] 74 75 for i := range offsetTree { 76 if (offset + i*2) == 0 { 77 mainBranch = append(mainBranch, t[1]) 78 } 79 offsetTree[i] = t[offset+i*2:].leafHash(hasher) 80 } 81 82 for pow2cnt >>= 1; pow2cnt > 1; pow2cnt >>= 1 { 83 for i := range temporaryTree[:pow2cnt] { 84 if i == 0 { 85 mainBranch = append(mainBranch, temporaryTree[1]) 86 } 87 88 temporaryTree[i] = temporaryTree[i*2:].leafHash(hasher) 89 } 90 } 91 92 mainBranch = append(mainBranch, temporaryTree[1]) 93 94 return 95 }