From 71c60c3fd39848e28a625b05c5753ac70d36b4d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=B6ckli?= Date: Wed, 10 Jan 2024 14:27:30 +0100 Subject: [PATCH 1/4] Allow to find block transaction without block information when block_transactions_map is missing --- .../block_transactions_map.yaml | 4 ++ .../get_transaction_blocks/blocks.yaml | 12 ++++ .../get_transaction_blocks/transactions.yaml | 10 ++++ blocktx/store/sql/get_transaction_blocks.go | 12 ++-- .../store/sql/get_transaction_blocks_test.go | 55 ++++++++++++++----- 5 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 blocktx/store/sql/fixtures/get_transaction_blocks/block_transactions_map.yaml create mode 100644 blocktx/store/sql/fixtures/get_transaction_blocks/blocks.yaml create mode 100644 blocktx/store/sql/fixtures/get_transaction_blocks/transactions.yaml diff --git a/blocktx/store/sql/fixtures/get_transaction_blocks/block_transactions_map.yaml b/blocktx/store/sql/fixtures/get_transaction_blocks/block_transactions_map.yaml new file mode 100644 index 000000000..ceb661b15 --- /dev/null +++ b/blocktx/store/sql/fixtures/get_transaction_blocks/block_transactions_map.yaml @@ -0,0 +1,4 @@ +- blockid: 9736 + txid: 115361489 + pos: 36 + inserted_at_num: 2024011012 diff --git a/blocktx/store/sql/fixtures/get_transaction_blocks/blocks.yaml b/blocktx/store/sql/fixtures/get_transaction_blocks/blocks.yaml new file mode 100644 index 000000000..773cb1d01 --- /dev/null +++ b/blocktx/store/sql/fixtures/get_transaction_blocks/blocks.yaml @@ -0,0 +1,12 @@ +- inserted_at: 2024-01-10 13:06:03.375 + id: 9736 + hash: 0x6258b02da70a3e367e4c993b049fa9b76ef8f090ef9fd2010000000000000000 + prevhash: 0x000000000000000001a7aa3999410ca53fb645851531ec0a7a5cb9ce2d4ae313 + merkleroot: 0x0d72bf92e7862df18d1935c171ca4dbb70d268b0f025e46716e913bc7e4f2bdb + height: 826481 + processed_at: 2024-01-10 13:06:06.122 + size: 108689370 + tx_count: 799 + orphanedyn: FALSE + merkle_path: "" + inserted_at_num: 2024011012 diff --git a/blocktx/store/sql/fixtures/get_transaction_blocks/transactions.yaml b/blocktx/store/sql/fixtures/get_transaction_blocks/transactions.yaml new file mode 100644 index 000000000..d2259261c --- /dev/null +++ b/blocktx/store/sql/fixtures/get_transaction_blocks/transactions.yaml @@ -0,0 +1,10 @@ +- id: 110383995 + hash: 0x76732b80598326a18d3bf0a86518adbdf95d0ddc6ff6693004440f4776168c3b + source: "" + merkle_path: "" + inserted_at_num: 2024010913 +- id: 115361489 + hash: 0x164e85a5d5bc2b2372e8feaa266e5e4b7d0808f8d2b784fb1f7349c4726392b0 + source: "" + merkle_path: "" + inserted_at_num: 2024011012 diff --git a/blocktx/store/sql/get_transaction_blocks.go b/blocktx/store/sql/get_transaction_blocks.go index b6e1ad29b..439171e30 100644 --- a/blocktx/store/sql/get_transaction_blocks.go +++ b/blocktx/store/sql/get_transaction_blocks.go @@ -16,11 +16,11 @@ const ( queryGetBlockHashHeightForTxHashesPostgres = ` SELECT b.hash, b.height, t.hash - FROM blocks b - INNER JOIN block_transactions_map m ON m.blockid = b.id - INNER JOIN transactions t ON m.txid = t.id + FROM transactions t + LEFT JOIN block_transactions_map m ON m.txid = t.id + LEFT JOIN blocks b ON m.blockid = b.id WHERE t.hash = ANY($1) - AND b.orphanedyn = FALSE` + ;` queryGetBlockHashHeightForTxHashesSQLite = ` SELECT @@ -80,7 +80,7 @@ func (s *SQL) GetTransactionBlocks(ctx context.Context, transactions *blocktx_ap for rows.Next() { var BlockHash []byte - var BlockHeight uint64 + var BlockHeight sql.NullInt64 var TransactionHash []byte err := rows.Scan(&BlockHash, &BlockHeight, &TransactionHash) if err != nil { @@ -89,7 +89,7 @@ func (s *SQL) GetTransactionBlocks(ctx context.Context, transactions *blocktx_ap newBlockTransaction := &blocktx_api.TransactionBlock{ BlockHash: BlockHash, - BlockHeight: BlockHeight, + BlockHeight: uint64(BlockHeight.Int64), TransactionHash: TransactionHash, } diff --git a/blocktx/store/sql/get_transaction_blocks_test.go b/blocktx/store/sql/get_transaction_blocks_test.go index d81c52c71..d453978f1 100644 --- a/blocktx/store/sql/get_transaction_blocks_test.go +++ b/blocktx/store/sql/get_transaction_blocks_test.go @@ -2,12 +2,14 @@ package sql import ( "context" + "database/sql" "errors" "testing" + "github.com/go-testfixtures/testfixtures/v3" + "github.com/DATA-DOG/go-sqlmock" "github.com/bitcoin-sv/arc/blocktx/blocktx_api" - "github.com/bitcoin-sv/arc/blocktx/store" . "github.com/bitcoin-sv/arc/database_testing" "github.com/libsv/go-p2p/chaincfg/chainhash" "github.com/stretchr/testify/require" @@ -19,31 +21,54 @@ type GetTransactionBlocksSuite struct { } func (s *GetTransactionBlocksSuite) Test() { - block := GetTestBlock() - tx := GetTestTransaction() - s.InsertBlock(block) - s.InsertTransaction(tx) + db, err := sql.Open("postgres", DefaultParams.String()) + require.NoError(s.T(), err) - s.InsertBlockTransactionMap(&store.BlockTransactionMap{ - BlockID: block.ID, - TransactionID: tx.ID, - Pos: 2, - }) + st := &SQL{db: db, engine: postgresEngine} + + fixtures, err := testfixtures.New( + testfixtures.Database(db), + testfixtures.Dialect("postgresql"), + testfixtures.Directory("fixtures/get_transaction_blocks"), // The directory containing the YAML files + ) + require.NoError(s.T(), err) + + err = fixtures.Load() + require.NoError(s.T(), err) + ctx := context.Background() + + txHash1, err := chainhash.NewHashFromStr("b0926372c449731ffb84b7d2f808087d4b5e6e26aafee872232bbcd5a5854e16") + require.NoError(s.T(), err) - store, err := NewPostgresStore(DefaultParams) + blockHash, err := chainhash.NewHashFromStr("000000000000000001d29fef90f0f86eb7a99f043b994c7e363e0aa72db05862") require.NoError(s.T(), err) - b, err := store.GetTransactionBlocks(context.Background(), &blocktx_api.Transactions{ + b, err := st.GetTransactionBlocks(ctx, &blocktx_api.Transactions{ + Transactions: []*blocktx_api.Transaction{ + { + Hash: txHash1[:], + }, + }, + }) + require.NoError(s.T(), err) + require.Equal(s.T(), blockHash[:], b.TransactionBlocks[0].BlockHash) + require.Equal(s.T(), uint64(826481), b.TransactionBlocks[0].BlockHeight) + require.Equal(s.T(), txHash1[:], b.TransactionBlocks[0].TransactionHash) + + txHash2, err := chainhash.NewHashFromStr("3b8c1676470f44043069f66fdc0d5df9bdad1865a8f03b8da1268359802b7376") + require.NoError(s.T(), err) + b, err = st.GetTransactionBlocks(ctx, &blocktx_api.Transactions{ Transactions: []*blocktx_api.Transaction{ { - Hash: []byte(tx.Hash), + Hash: txHash2[:], }, }, }) require.NoError(s.T(), err) - require.Equal(s.T(), block.Hash, string(b.GetTransactionBlocks()[0].GetBlockHash())) - require.Equal(s.T(), tx.Hash, string(b.GetTransactionBlocks()[0].GetTransactionHash())) + require.Nil(s.T(), b.TransactionBlocks[0].BlockHash) + require.Equal(s.T(), uint64(0), b.TransactionBlocks[0].BlockHeight) + require.Equal(s.T(), txHash2[:], b.TransactionBlocks[0].TransactionHash) } func TestGetTransactionBlocksIntegration(t *testing.T) { From 9758880474e54e143425aaec19ad3841431fd8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=B6ckli?= Date: Wed, 10 Jan 2024 14:44:59 +0100 Subject: [PATCH 2/4] Do nothing after loading records. Let go routines do the retrying and checking if mined --- metamorph/processor.go | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/metamorph/processor.go b/metamorph/processor.go index 1a3945886..0896f22bd 100644 --- a/metamorph/processor.go +++ b/metamorph/processor.go @@ -292,47 +292,6 @@ func (p *Processor) LoadUnmined() { pr.Start = record.StoredAt p.ProcessorResponseMap.Set(record.Hash, pr) - - switch record.Status { - case metamorph_api.Status_STORED: - // announce the transaction to the network - pr.SetPeers(p.pm.AnnounceTransaction(record.Hash, nil)) - - err := p.store.UpdateStatus(spanCtx, record.Hash, metamorph_api.Status_ANNOUNCED_TO_NETWORK, "") - if err != nil { - p.logger.Error(failedToUpdateStatus, slog.String("hash", record.Hash.String()), slog.String("err", err.Error())) - } - case metamorph_api.Status_ANNOUNCED_TO_NETWORK: - // we only announced the transaction, but we did not receive a SENT_TO_NETWORK response - // let's send a GETDATA message to the network to check whether the transaction is actually there - p.pm.RequestTransaction(record.Hash) - case metamorph_api.Status_SENT_TO_NETWORK: - p.pm.RequestTransaction(record.Hash) - case metamorph_api.Status_SEEN_ON_NETWORK: - // could it already be mined, and we need to get it from BlockTx? - transactionResponse, err := p.btc.GetTransactionBlock(context.Background(), &blocktx_api.Transaction{Hash: record.Hash[:]}) - if err != nil { - p.logger.Error("failed to get transaction block", slog.String("hash", record.Hash.String()), slog.String("err", err.Error())) - return - } - - if transactionResponse == nil || transactionResponse.GetBlockHeight() <= 0 { - return - } - - // we have a mined transaction, let's update the status - var blockHash *chainhash.Hash - blockHash, err = chainhash.NewHash(transactionResponse.GetBlockHash()) - if err != nil { - p.logger.Error("Failed to convert block hash", slog.String("err", err.Error())) - return - } - - _, err = p.SendStatusMinedForTransaction(record.Hash, blockHash, transactionResponse.GetBlockHeight()) - if err != nil { - p.logger.Error("Failed to update status for mined transaction", slog.String("err", err.Error())) - } - } }) if err != nil { p.logger.Error("Failed to iterate through stored transactions", slog.String("err", err.Error())) From 7c1d4ae7e2b142ac9fd3797c1265ea2e7479b943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=B6ckli?= Date: Wed, 10 Jan 2024 15:01:15 +0100 Subject: [PATCH 3/4] Allow marking as mined with missing block information --- metamorph/processor.go | 8 ++++++-- metamorph/processor_test.go | 20 +++++++++++++++++--- metamorph/store/postgresql/postgres.go | 11 +++++++++-- metamorph/store/postgresql/postgres_test.go | 20 ++++++++++++++++++++ 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/metamorph/processor.go b/metamorph/processor.go index 0896f22bd..745f94853 100644 --- a/metamorph/processor.go +++ b/metamorph/processor.go @@ -202,10 +202,14 @@ func (p *Processor) processCheckIfMined() { p.logger.Debug("found blocks for transactions", slog.Int("number", len(blockTransactions.GetTransactionBlocks()))) for _, blockTxs := range blockTransactions.GetTransactionBlocks() { + var blockHashString string + blockHash, err := chainhash.NewHash(blockTxs.GetBlockHash()) if err != nil { p.logger.Error("failed to parse block hash", slog.String("err", err.Error())) - continue + blockHashString = "" + } else { + blockHashString = blockHash.String() } txHash, err := chainhash.NewHash(blockTxs.GetTransactionHash()) @@ -213,7 +217,7 @@ func (p *Processor) processCheckIfMined() { p.logger.Error("failed to parse tx hash", slog.String("err", err.Error())) continue } - p.logger.Debug("found block for transaction", slog.String("txhash", txHash.String()), slog.String("blockhash", blockHash.String())) + p.logger.Debug("found block for transaction", slog.String("txhash", txHash.String()), slog.String("blockhash", blockHashString)) _, err = p.SendStatusMinedForTransaction(txHash, blockHash, blockTxs.GetBlockHeight()) if err != nil { diff --git a/metamorph/processor_test.go b/metamorph/processor_test.go index f8a7c8c10..0e830664c 100644 --- a/metamorph/processor_test.go +++ b/metamorph/processor_test.go @@ -728,6 +728,22 @@ func TestProcessCheckIfMined(t *testing.T) { expectedNrOfUpdates: 0, }, + { + name: "missing block info", + blocks: []*blocktx_api.TransactionBlock{ + { + TransactionHash: testdata.TX1Hash[:], + }, + { + TransactionHash: testdata.TX2Hash[:], + }, + { + TransactionHash: testdata.TX3Hash[:], + }, + }, + + expectedNrOfUpdates: 3, + }, } for _, tc := range tt { @@ -739,9 +755,7 @@ func TestProcessCheckIfMined(t *testing.T) { UpdateMinedFunc: func(ctx context.Context, hash *chainhash.Hash, blockHash *chainhash.Hash, blockHeight uint64) error { require.Condition(t, func() (success bool) { oneOfHash := hash.IsEqual(testdata.TX1Hash) || hash.IsEqual(testdata.TX2Hash) || hash.IsEqual(testdata.TX3Hash) - isBlockHeight := blockHeight == 1234 - isBlockHash := blockHash.IsEqual(testdata.Block1Hash) - return oneOfHash && isBlockHeight && isBlockHash + return oneOfHash }) return tc.updateMinedErr diff --git a/metamorph/store/postgresql/postgres.go b/metamorph/store/postgresql/postgres.go index 06f75f7ca..034ee6225 100644 --- a/metamorph/store/postgresql/postgres.go +++ b/metamorph/store/postgresql/postgres.go @@ -504,16 +504,23 @@ func (p *PostgreSQL) UpdateMined(ctx context.Context, hash *chainhash.Hash, bloc span, _ := opentracing.StartSpanFromContext(ctx, "sql:UpdateMined") defer span.Finish() + var blockHashBytes []byte + if blockHash == nil { + blockHashBytes = nil + } else { + blockHashBytes = blockHash[:] + } + q := ` UPDATE metamorph.transactions SET status = $1 ,block_hash = $2 ,block_height = $3 - , mined_at = $4 + ,mined_at = $4 WHERE hash = $5 ;` - _, err := p.db.ExecContext(ctx, q, metamorph_api.Status_MINED, blockHash[:], blockHeight, p.now().Format(time.RFC3339), hash[:]) + _, err := p.db.ExecContext(ctx, q, metamorph_api.Status_MINED, blockHashBytes, blockHeight, p.now().Format(time.RFC3339), hash[:]) if err != nil { span.SetTag(string(ext.Error), true) span.LogFields(log.Error(err)) diff --git a/metamorph/store/postgresql/postgres_test.go b/metamorph/store/postgresql/postgres_test.go index 8217ade1b..31e8158e1 100644 --- a/metamorph/store/postgresql/postgres_test.go +++ b/metamorph/store/postgresql/postgres_test.go @@ -298,6 +298,26 @@ func TestPostgresDB(t *testing.T) { require.NoError(t, err) }) + t.Run("update mined - missing block info", func(t *testing.T) { + unmined := *unminedData + err = postgresDB.Set(ctx, unminedHash[:], &unmined) + require.NoError(t, err) + + err := postgresDB.UpdateMined(ctx, unminedHash, nil, 0) + require.NoError(t, err) + + dataReturned, err := postgresDB.Get(ctx, unminedHash[:]) + require.NoError(t, err) + unmined.Status = metamorph_api.Status_MINED + unmined.MinedAt = now + unmined.BlockHeight = 0 + unmined.BlockHash = nil + require.Equal(t, dataReturned, &unmined) + + err = postgresDB.Del(ctx, unminedHash[:]) + require.NoError(t, err) + }) + t.Run("get/set block processed", func(t *testing.T) { err = postgresDB.SetBlockProcessed(ctx, testdata.Block1Hash) require.NoError(t, err) From 6f2d775b19260a6316cb71d4587d3de37c1ae0c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=B6ckli?= Date: Wed, 10 Jan 2024 15:27:23 +0100 Subject: [PATCH 4/4] Adapt tests --- .../store/sql/get_transaction_blocks_test.go | 31 ++--- metamorph/processor_test.go | 110 ++---------------- 2 files changed, 25 insertions(+), 116 deletions(-) diff --git a/blocktx/store/sql/get_transaction_blocks_test.go b/blocktx/store/sql/get_transaction_blocks_test.go index d453978f1..e1a567ae7 100644 --- a/blocktx/store/sql/get_transaction_blocks_test.go +++ b/blocktx/store/sql/get_transaction_blocks_test.go @@ -118,14 +118,15 @@ func TestGetTransactionBlocks(t *testing.T) { name: "query fails", sqlmockExpectations: func(mock sqlmock.Sqlmock) { query := ` - SELECT - b.hash, b.height, t.hash - FROM blocks b - INNER JOIN block_transactions_map m ON m.blockid = b.id - INNER JOIN transactions t ON m.txid = t.id - WHERE t.hash = ANY($1) - AND b.orphanedyn = FALSE` - + SELECT + b.hash, b.height, t.hash + FROM transactions t + LEFT JOIN block_transactions_map m ON m.txid = t.id + LEFT JOIN blocks b ON m.blockid = b.id + WHERE t.hash = ANY($1) + ;` + + //SELECT b.hash, b.height, t.hash FROM transactions t LEFT JOIN block_transactions_map m ON m.txid = t.id LEFT JOIN blocks b ON m.blockid = b.id WHERE t.hash = ANY($1) mock.ExpectQuery(query).WillReturnError(errors.New("db connection error")) }, expectedErrorStr: "db connection error", @@ -134,13 +135,13 @@ func TestGetTransactionBlocks(t *testing.T) { name: "scanning fails", sqlmockExpectations: func(mock sqlmock.Sqlmock) { query := ` - SELECT - b.hash, b.height, t.hash - FROM blocks b - INNER JOIN block_transactions_map m ON m.blockid = b.id - INNER JOIN transactions t ON m.txid = t.id - WHERE t.hash = ANY($1) - AND b.orphanedyn = FALSE` + SELECT + b.hash, b.height, t.hash + FROM transactions t + LEFT JOIN block_transactions_map m ON m.txid = t.id + LEFT JOIN blocks b ON m.blockid = b.id + WHERE t.hash = ANY($1) + ;` mock.ExpectQuery(query).WillReturnRows( sqlmock.NewRows([]string{"hash", "height", "hash"}).AddRow( diff --git a/metamorph/processor_test.go b/metamorph/processor_test.go index 0e830664c..5d49a0189 100644 --- a/metamorph/processor_test.go +++ b/metamorph/processor_test.go @@ -1,7 +1,6 @@ package metamorph_test import ( - "bytes" "context" "errors" "fmt" @@ -101,44 +100,15 @@ func TestLoadUnmined(t *testing.T) { storedAt := time.Date(2023, 10, 3, 5, 0, 0, 0, time.UTC) tt := []struct { - name string - storedData []*store.StoreData - isCentralised bool - updateStatusErr error - getTransactionBlockErr error - delErr error + name string + storedData []*store.StoreData + getUnminedErr error expectedItemTxHashesFinal []*chainhash.Hash }{ { name: "no unmined transactions loaded", }, - { - name: "load 3 unmined transactions, TX2 was mined", - storedData: []*store.StoreData{ - { - StoredAt: storedAt, - AnnouncedAt: storedAt.Add(1 * time.Second), - Hash: testdata.TX1Hash, - Status: metamorph_api.Status_SENT_TO_NETWORK, - }, - { - StoredAt: storedAt, - AnnouncedAt: storedAt.Add(1 * time.Second), - Hash: testdata.TX2Hash, - Status: metamorph_api.Status_SEEN_ON_NETWORK, - CallbackUrl: "http://api.example.com", - }, - { - StoredAt: storedAt, - AnnouncedAt: storedAt.Add(1 * time.Second), - Hash: testdata.TX3Hash, - Status: metamorph_api.Status_SEEN_ON_NETWORK, - }, - }, - - expectedItemTxHashesFinal: []*chainhash.Hash{testdata.TX1Hash, testdata.TX3Hash}, - }, { name: "load 2 unmined transactions, none mined", storedData: []*store.StoreData{ @@ -159,32 +129,11 @@ func TestLoadUnmined(t *testing.T) { expectedItemTxHashesFinal: []*chainhash.Hash{testdata.TX1Hash, testdata.TX2Hash}, }, { - name: "update status fails", - storedData: []*store.StoreData{ - { - StoredAt: storedAt, - AnnouncedAt: storedAt.Add(1 * time.Second), - Hash: testdata.TX2Hash, - Status: metamorph_api.Status_STORED, - }, - }, - updateStatusErr: errors.New("failed to update status"), - - expectedItemTxHashesFinal: []*chainhash.Hash{testdata.TX2Hash}, - }, - { - name: "get transaction block fails", - storedData: []*store.StoreData{ - { - StoredAt: storedAt, - AnnouncedAt: storedAt.Add(1 * time.Second), - Hash: testdata.TX2Hash, - Status: metamorph_api.Status_SEEN_ON_NETWORK, - }, - }, - getTransactionBlockErr: errors.New("failed to get transaction block"), + name: "load 2 unmined transactions, failed to get unmined", + storedData: []*store.StoreData{}, + getUnminedErr: errors.New("failed to get unmined"), - expectedItemTxHashesFinal: []*chainhash.Hash{testdata.TX2Hash}, + expectedItemTxHashesFinal: []*chainhash.Hash{}, }, } @@ -192,62 +141,21 @@ func TestLoadUnmined(t *testing.T) { t.Run(tc.name, func(t *testing.T) { pm := p2p.NewPeerManagerMock() - btxMock := &ClientIMock{ - GetTransactionBlockFunc: func(ctx context.Context, transaction *blocktx_api.Transaction) (*blocktx_api.RegisterTransactionResponse, error) { - var txResponse *blocktx_api.RegisterTransactionResponse - - // TX2 was mined - if bytes.Equal(testdata.TX2Hash[:], transaction.Hash[:]) { - txResponse = &blocktx_api.RegisterTransactionResponse{ - BlockHash: testdata.Block2Hash[:], - BlockHeight: 2, - } - } - - return txResponse, tc.getTransactionBlockErr - }, - } mtmStore := &MetamorphStoreMock{ GetUnminedFunc: func(contextMoqParam context.Context, callback func(s *store.StoreData)) error { for _, data := range tc.storedData { callback(data) } - return nil - }, - UpdateMinedFunc: func(ctx context.Context, hash *chainhash.Hash, blockHash *chainhash.Hash, blockHeight uint64) error { - require.Equal(t, testdata.TX2Hash, hash) - return nil - }, - UpdateStatusFunc: func(ctx context.Context, hash *chainhash.Hash, status metamorph_api.Status, rejectReason string) error { - require.Equal(t, bytes.Compare(testdata.TX2Hash[:], hash[:]), 0) - return tc.updateStatusErr - }, - GetFunc: func(ctx context.Context, key []byte) (*store.StoreData, error) { - return &store.StoreData{ - StoredAt: storedAt, - AnnouncedAt: storedAt.Add(1 * time.Second), - Hash: testdata.TX2Hash, - Status: metamorph_api.Status_SEEN_ON_NETWORK, - CallbackUrl: "http://api.example.com", - BlockHash: testdata.Block2Hash, - BlockHeight: 2, - }, nil - }, - DelFunc: func(ctx context.Context, key []byte) error { - require.Equal(t, testdata.TX2Hash[:], key) - return tc.delErr + return tc.getUnminedErr }, SetUnlockedFunc: func(ctx context.Context, hashes []*chainhash.Hash) error { require.ElementsMatch(t, tc.expectedItemTxHashesFinal, hashes) require.Equal(t, len(tc.expectedItemTxHashesFinal), len(hashes)) return nil }, - RemoveCallbackerFunc: func(ctx context.Context, hash *chainhash.Hash) error { - return nil - }, } - processor, err := NewProcessor(mtmStore, pm, btxMock, + processor, err := NewProcessor(mtmStore, pm, nil, WithProcessCheckIfMinedInterval(time.Hour*24), WithCacheExpiryTime(time.Hour*24), WithNow(func() time.Time {