Skip to content

Commit

Permalink
Merge pull request #245 from bitcoin-sv/fix/allow-callbacks-without-b…
Browse files Browse the repository at this point in the history
…lock-info

Fix/allow callbacks without block info
  • Loading branch information
boecklim authored Jan 10, 2024
2 parents aad5d05 + 6f2d775 commit 5d8486d
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 185 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- blockid: 9736
txid: 115361489
pos: 36
inserted_at_num: 2024011012
12 changes: 12 additions & 0 deletions blocktx/store/sql/fixtures/get_transaction_blocks/blocks.yaml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
12 changes: 6 additions & 6 deletions blocktx/store/sql/get_transaction_blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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,
}

Expand Down
86 changes: 56 additions & 30 deletions blocktx/store/sql/get_transaction_blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)

st := &SQL{db: db, engine: postgresEngine}

s.InsertBlockTransactionMap(&store.BlockTransactionMap{
BlockID: block.ID,
TransactionID: tx.ID,
Pos: 2,
})
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()

store, err := NewPostgresStore(DefaultParams)
txHash1, err := chainhash.NewHashFromStr("b0926372c449731ffb84b7d2f808087d4b5e6e26aafee872232bbcd5a5854e16")
require.NoError(s.T(), err)

blockHash, err := chainhash.NewHashFromStr("000000000000000001d29fef90f0f86eb7a99f043b994c7e363e0aa72db05862")
require.NoError(s.T(), err)

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)

b, err := store.GetTransactionBlocks(context.Background(), &blocktx_api.Transactions{
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) {
Expand Down Expand Up @@ -93,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",
Expand All @@ -109,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(
Expand Down
49 changes: 6 additions & 43 deletions metamorph/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,18 +202,22 @@ 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())
if err != nil {
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 {
Expand Down Expand Up @@ -292,47 +296,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()))
Expand Down
Loading

0 comments on commit 5d8486d

Please sign in to comment.