From c3f817f45bdfb8e87e90f89788bccc7ce84fd512 Mon Sep 17 00:00:00 2001
From: deggen <d.kellenschwiler@bsvblockchain.org>
Date: Fri, 1 Dec 2023 14:27:57 -0600
Subject: [PATCH] fix: only include the hashes for the txid we're interested in
 (#81)

Previously this function returned a BUMP of the whole tree which quickly exhausts ARC resources when there are thousands in memory.

It should be one txid per BUMP, which is significantly less data.

Signed-off-by: Darren Kellenschwiler <d.kellenschwiler@bsvblockchain.org>
---
 bump.go      | 11 +++++++++++
 bump_test.go | 25 +++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/bump.go b/bump.go
index 6eabc61..bf1b4ab 100644
--- a/bump.go
+++ b/bump.go
@@ -233,6 +233,7 @@ func NewBUMPFromMerkleTreeAndIndex(blockHeight uint64, merkleTree []*chainhash.H
 		return nil, errors.New("merkle tree is empty")
 	}
 
+	// these are the offsets for the txid we're interested in.
 	offsets := make([]uint64, treeHeight)
 	for i := 0; i < treeHeight; i++ {
 		if txIndex>>uint64(i)&1 == 0 {
@@ -251,6 +252,16 @@ func NewBUMPFromMerkleTreeAndIndex(blockHeight uint64, merkleTree []*chainhash.H
 			bump.Path = append(bump.Path, leaves)
 			for offset := 0; offset < numOfHashes; offset++ {
 				o := uint64(offset)
+				// only include the hashes for the txid we're interested in.
+				if height == 0 {
+					if o != txIndex && o != offsets[height] {
+						continue
+					}
+				} else {
+					if o != offsets[height] {
+						continue
+					}
+				}
 				thisLeaf := leaf{Offset: &o}
 				hash := merkleTree[levelOffset+offset]
 				if hash.IsEqual(nil) {
diff --git a/bump_test.go b/bump_test.go
index 2d908a8..4cdc46a 100644
--- a/bump_test.go
+++ b/bump_test.go
@@ -1,6 +1,7 @@
 package bc
 
 import (
+	"math"
 	"testing"
 
 	"github.com/libsv/go-p2p/chaincfg/chainhash"
@@ -168,3 +169,27 @@ func TestTxids(t *testing.T) {
 	txids := bump.Txids()
 	require.Equal(t, []string{testnetBlockExample[0]}, txids)
 }
+
+func TestOnlySpecifiedPathsStored(t *testing.T) {
+	chainHashBlock := make([]*chainhash.Hash, 0)
+	for _, txid := range blockTxExample {
+		hash, err := chainhash.NewHashFromStr(txid)
+		require.NoError(t, err)
+		chainHashBlock = append(chainHashBlock, hash)
+	}
+	merkles, err := BuildMerkleTreeStoreChainHash(chainHashBlock)
+	require.NoError(t, err)
+
+	for idx := range blockTxExample {
+		bump, err := NewBUMPFromMerkleTreeAndIndex(1575794, merkles, uint64(idx))
+		require.NoError(t, err)
+		totalHashes := 0
+		for _, level := range bump.Path {
+			totalHashes += len(level)
+		}
+		// number of levels plus the txid itself.
+		l := int(math.Log2(float64(len(blockTxExample)))) + 1
+		require.Equal(t, l, totalHashes)
+	}
+
+}