lbcd/claimtrie/node/hashfunc.go
Brannon King 9477313d74 added proof RPC
post-merge fixes

other part of test
post-merge fix
2021-12-27 15:55:59 -05:00

113 lines
2.6 KiB
Go

package node
import (
"crypto/sha256"
"encoding/binary"
"strconv"
"github.com/lbryio/lbcd/chaincfg/chainhash"
"github.com/lbryio/lbcd/wire"
)
func HashMerkleBranches(left *chainhash.Hash, right *chainhash.Hash) *chainhash.Hash {
// Concatenate the left and right nodes.
var hash [chainhash.HashSize * 2]byte
copy(hash[:chainhash.HashSize], left[:])
copy(hash[chainhash.HashSize:], right[:])
newHash := chainhash.DoubleHashH(hash[:])
return &newHash
}
func ComputeMerkleRoot(hashes []*chainhash.Hash) *chainhash.Hash {
if len(hashes) <= 0 {
return nil
}
for len(hashes) > 1 {
if (len(hashes) & 1) > 0 { // odd count
hashes = append(hashes, hashes[len(hashes)-1])
}
for i := 0; i < len(hashes); i += 2 { // TODO: parallelize this loop (or use a lib that does it)
hashes[i>>1] = HashMerkleBranches(hashes[i], hashes[i+1])
}
hashes = hashes[:len(hashes)>>1]
}
return hashes[0]
}
func calculateNodeHash(op wire.OutPoint, takeover int32) *chainhash.Hash {
txHash := chainhash.DoubleHashH(op.Hash[:])
nOut := []byte(strconv.Itoa(int(op.Index)))
nOutHash := chainhash.DoubleHashH(nOut)
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(takeover))
heightHash := chainhash.DoubleHashH(buf)
h := make([]byte, 0, sha256.Size*3)
h = append(h, txHash[:]...)
h = append(h, nOutHash[:]...)
h = append(h, heightHash[:]...)
hh := chainhash.DoubleHashH(h)
return &hh
}
func ComputeMerklePath(hashes []*chainhash.Hash, idx int) []*chainhash.Hash {
count := 0
matchlevel := -1
matchh := false
var h *chainhash.Hash
var res []*chainhash.Hash
var inner [32]*chainhash.Hash // old code had 32; dunno if it's big enough for all scenarios
iterateInner := func(level int) int {
for ; (count & (1 << level)) == 0; level++ {
ihash := inner[level]
if matchh {
res = append(res, ihash)
} else if matchlevel == level {
res = append(res, h)
matchh = true
}
h = HashMerkleBranches(ihash, h)
}
return level
}
for count < len(hashes) {
h = hashes[count]
matchh = count == idx
count++
level := iterateInner(0)
// Store the resulting hash at inner position level.
inner[level] = h
if matchh {
matchlevel = level
}
}
level := 0
for (count & (1 << level)) == 0 {
level++
}
h = inner[level]
matchh = matchlevel == level
for count != (1 << level) {
// If we reach this point, h is an inner value that is not the top.
if matchh {
res = append(res, h)
}
h = HashMerkleBranches(h, h)
// Increment count to the value it would have if two entries at this
count += 1 << level
level++
level = iterateInner(level)
}
return res
}