Skip to content

Commit

Permalink
feat: add merkletreeparent util functions
Browse files Browse the repository at this point in the history
  • Loading branch information
wregulski committed Oct 17, 2024
1 parent 41fc75e commit 6bb8110
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
54 changes: 54 additions & 0 deletions transaction/merkletreeparent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package transaction

import (
"encoding/hex"

"github.com/bitcoin-sv/go-sdk/chainhash"
crypto "github.com/bitcoin-sv/go-sdk/primitives/hash"
"github.com/bitcoin-sv/go-sdk/util"
)

// MerkleTreeParentStr returns the Merkle Tree parent of two Merkle
// Tree children using hex strings instead of just bytes.
func MerkleTreeParentStr(leftNode, rightNode string) (string, error) {
l, err := hex.DecodeString(leftNode)
if err != nil {
return "", err
}
r, err := hex.DecodeString(rightNode)
if err != nil {
return "", err
}

return hex.EncodeToString(MerkleTreeParent(l, r)), nil
}

// MerkleTreeParent returns the Merkle Tree parent of two Merkle
// Tree children.
func MerkleTreeParent(leftNode, rightNode []byte) []byte {
// swap endianness before concatenating
l := util.ReverseBytes(leftNode)
r := util.ReverseBytes(rightNode)

// concatenate leaves
concat := append(l, r...)

// hash the concatenation
hash := crypto.Sha256d(concat)

// swap endianness at the end and convert to hex string
return util.ReverseBytes(hash)
}

// MerkleTreeParentBytes returns the Merkle Tree parent of two Merkle Tree children.
// The expectation is that the bytes are not reversed.
func MerkleTreeParentBytes(l *chainhash.Hash, r *chainhash.Hash) *chainhash.Hash {
lb := l.CloneBytes()
rb := r.CloneBytes()
concat := append(lb, rb...)
hash, err := chainhash.NewHash(crypto.Sha256d(concat))
if err != nil {
return &chainhash.Hash{}
}
return hash
}
32 changes: 32 additions & 0 deletions transaction/merkletreeparent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package transaction_test

import (
"encoding/hex"
"testing"

"github.com/bitcoin-sv/go-sdk/transaction"
"github.com/stretchr/testify/require"
)

func TestGetMerkleTreeParentStr(t *testing.T) {
leftNode := "d6c79a6ef05572f0cb8e9a450c561fc40b0a8a7d48faad95e20d93ddeb08c231"
rightNode := "b1ed931b79056438b990d8981ba46fae97e5574b142445a74a44b978af284f98"

expected := "b0d537b3ee52e472507f453df3d69561720346118a5a8c4d85ca0de73bc792be"

parent, err := transaction.MerkleTreeParentStr(leftNode, rightNode)

require.NoError(t, err)
require.Equal(t, expected, parent)
}

func TestGetMerkleTreeParent(t *testing.T) {
leftNode, _ := hex.DecodeString("d6c79a6ef05572f0cb8e9a450c561fc40b0a8a7d48faad95e20d93ddeb08c231")
rightNode, _ := hex.DecodeString("b1ed931b79056438b990d8981ba46fae97e5574b142445a74a44b978af284f98")

expected, _ := hex.DecodeString("b0d537b3ee52e472507f453df3d69561720346118a5a8c4d85ca0de73bc792be")

parent := transaction.MerkleTreeParent(leftNode, rightNode)

require.Equal(t, expected, parent)
}

0 comments on commit 6bb8110

Please sign in to comment.