Skip to content

Commit

Permalink
chain: add verbose logging when error in getRawTxIgnoreErr
Browse files Browse the repository at this point in the history
This commit modifies the method `getRawTxIgnoreErr` to log more useful
info. It also removes `*mempool` as the method reciever as it's
unnecessary to put it on mempool.
  • Loading branch information
yyforyongyu committed Sep 26, 2023
1 parent 8f67c83 commit 7b7bcba
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 24 deletions.
30 changes: 19 additions & 11 deletions chain/mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ type mempoolConfig struct {
//
// TODO(yy): interface rpcclient.FutureGetRawTransactionResult so we
// can remove this hack.
rawTxReceiver func(getRawTxReceiver) *btcutil.Tx
rawTxReceiver func(chainhash.Hash, getRawTxReceiver) *btcutil.Tx
}

// newMempool creates a new mempool object.
Expand All @@ -168,7 +168,7 @@ func newMempool(cfg *mempoolConfig) *mempool {

// Mount the default methods.
m.cfg.rawMempoolGetter = m.getRawMempool
m.cfg.rawTxReceiver = m.getRawTxIgnoreErr
m.cfg.rawTxReceiver = getRawTxIgnoreErr

return m
}
Expand Down Expand Up @@ -482,9 +482,13 @@ func (m *mempool) batchGetRawTxes(txids []*chainhash.Hash,
len(txids)/m.cfg.getRawTxBatchSize+1)
defer log.Debugf("Finished batch GetRawTransaction")

// txRecievers defines a map that has the txid as its key and the tx's
// response reciever as its value.
type txRecievers map[chainhash.Hash]getRawTxReceiver

// respReceivers stores a list of response receivers returned from
// batch calling `GetRawTransactionAsync`.
respReceivers := make([]getRawTxReceiver, 0, m.cfg.getRawTxBatchSize)
respReceivers := make(txRecievers, m.cfg.getRawTxBatchSize)

// Conditionally init a newTxes slice.
var newTxes []*wire.MsgTx
Expand All @@ -496,16 +500,16 @@ func (m *mempool) batchGetRawTxes(txids []*chainhash.Hash,
// bitcoind and waits for all the responses to return. Each time a
// response is received, it will be used to update the local mempool
// state and conditionally saved to a slice that will be returned.
processBatch := func(results []getRawTxReceiver) error {
processBatch := func(results txRecievers) error {
// Ask the client to send all the batched requests.
err := m.cfg.client.Send()
if err != nil {
return fmt.Errorf("Send GetRawTransaction got %v", err)
}

// Iterate the recievers and fetch the response.
for _, resp := range results {
tx := m.cfg.rawTxReceiver(resp)
for txid, resp := range results {
tx := m.cfg.rawTxReceiver(txid, resp)
if tx == nil {
continue
}
Expand Down Expand Up @@ -533,7 +537,7 @@ func (m *mempool) batchGetRawTxes(txids []*chainhash.Hash,

// Create the async request and save it to txRespReceivers.
resp := m.cfg.client.GetRawTransactionAsync(txHash)
respReceivers = append(respReceivers, resp)
respReceivers[*txHash] = resp

// When getRawTxBatchSize is reached, we'd ask the batch client
// to send the requests and process the responses.
Expand All @@ -555,7 +559,7 @@ func (m *mempool) batchGetRawTxes(txids []*chainhash.Hash,

// Empty the slice for next batch iteration.
respReceivers = make(
[]getRawTxReceiver, 0, m.cfg.getRawTxBatchSize,
txRecievers, m.cfg.getRawTxBatchSize,
)
}
}
Expand All @@ -581,7 +585,9 @@ func (m *mempool) batchGetRawTxes(txids []*chainhash.Hash,
// for the txid in bitcoind's mempool. If the tx is replaced, confirmed, or not
// yet included in bitcoind's mempool, the error txNotFoundErr will be
// returned.
func (m *mempool) getRawTxIgnoreErr(rawTx getRawTxReceiver) *btcutil.Tx {
func getRawTxIgnoreErr(txid chainhash.Hash,
rawTx getRawTxReceiver) *btcutil.Tx {

tx, err := rawTx.Receive()

// Exit early if there's no error.
Expand All @@ -593,12 +599,14 @@ func (m *mempool) getRawTxIgnoreErr(rawTx getRawTxReceiver) *btcutil.Tx {
errStr := strings.ToLower(err.Error())
errExp := strings.ToLower(txNotFoundErr)
if strings.Contains(errStr, errExp) {
log.Debugf("unable to fetch transaction from mempool: %v", err)
log.Debugf("unable to fetch transaction %s from mempool: %v",
txid, err)

} else {
// Otherwise, unexpected error is found, we'll create an error
// log.
log.Errorf("unable to fetch transaction from mempool: %v", err)
log.Errorf("unable to fetch transaction %s from mempool: %v",
txid, err)
}

return nil
Expand Down
21 changes: 8 additions & 13 deletions chain/mempool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,9 @@ func TestUpdateMempoolTxes(t *testing.T) {
m.cfg.rawMempoolGetter = func() ([]*chainhash.Hash, error) {
return mempool1, nil
}
m.cfg.rawTxReceiver = func(reciever getRawTxReceiver) *btcutil.Tx {
m.cfg.rawTxReceiver = func(txid chainhash.Hash,
reciever getRawTxReceiver) *btcutil.Tx {

switch reciever {
case mockTx1Receiver:
return btctx1
Expand Down Expand Up @@ -526,7 +528,9 @@ func TestUpdateMempoolTxes(t *testing.T) {
m.cfg.rawMempoolGetter = func() ([]*chainhash.Hash, error) {
return mempool2, nil
}
m.cfg.rawTxReceiver = func(reciever getRawTxReceiver) *btcutil.Tx {
m.cfg.rawTxReceiver = func(txid chainhash.Hash,
reciever getRawTxReceiver) *btcutil.Tx {

switch reciever {
case mockTx3Receiver:
return btctx3
Expand Down Expand Up @@ -624,14 +628,6 @@ func TestUpdateMempoolTxesOnShutdown(t *testing.T) {
func TestGetRawTxIgnoreErr(t *testing.T) {
require := require.New(t)

// Create a mock client and init our mempool.
mockRPC := &mockRPCClient{}
m := newMempool(&mempoolConfig{
client: mockRPC,
batchWaitInterval: 0,
getRawTxBatchSize: 1,
})

// Create a normal transaction that has two inputs.
op := wire.OutPoint{Hash: chainhash.Hash{1}}
tx := &wire.MsgTx{
Expand All @@ -645,18 +641,17 @@ func TestGetRawTxIgnoreErr(t *testing.T) {
mockReceiver.On("Receive").Return(btctx, nil).Once()

// Call the method and expect the tx to be returned.
resp := m.getRawTxIgnoreErr(mockReceiver)
resp := getRawTxIgnoreErr(tx.TxHash(), mockReceiver)
require.Equal(btctx, resp)

// Mock the reciever to return an error.
dummyErr := errors.New("dummy error")
mockReceiver.On("Receive").Return(nil, dummyErr).Once()

// Call the method again and expect nil response.
resp = m.getRawTxIgnoreErr(mockReceiver)
resp = getRawTxIgnoreErr(tx.TxHash(), mockReceiver)
require.Nil(resp)

// Assert the mock client was called as expected.
mockRPC.AssertExpectations(t)
mockReceiver.AssertExpectations(t)
}

0 comments on commit 7b7bcba

Please sign in to comment.