-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chainntnfs: ensure proper fallback to scanning tx manually #1585
chainntnfs: ensure proper fallback to scanning tx manually #1585
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! The code reads well to me. However, ideally we also have a test that fails as is in the current master. See my comment in line which goes over how to write such a test.
// scanning the chain manually. We'll also need to look at the | ||
// error message returned as the error code is used for multiple | ||
// errors. | ||
txNotFoundErr := "No such mempool or blockchain transaction" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have we confirmed that this is the exact help text? Ideally we also have a test along with this PR which will fail if the backend detects a query to the GetBlocks
when we query for a transaction that was never even broadcast. The test would need to skip the neutrino backend, and only execute for the btcd and bitocind backends.
530f182
to
66439b3
Compare
Updated the PR to include some tests. I realize there's a lot of code duplication, but I have a branch locally where I've begun to refactor all the different |
// We'll then check the status of the transaction lookup returned to | ||
// determine whether we should proceed with any fallback methods. | ||
switch { | ||
// The transaction was found within the node's txindex. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment should say "mempool"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
if txConf != nil { | ||
return txConf, nil | ||
// The transaction was not found within the node's mempool or txindex. | ||
case txStatus == txNotFoundIndex && err == nil: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we return in the case of err != nil
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This indicates that the transaction simply doesn't exist, as it was not found within the txindex or mempool. The err != nil
case is handled in the default
case, as that means something went wrong when looking at the index (either because it's disabled or something else went wrong), so we should fall back to scanning manually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should check the error first, as now it can return (_, 0, err)
which will match the txFoundMempool
case.
} | ||
|
||
// Make sure we actually retrieved a transaction that is included in a | ||
// block. Without this, we won't be able to retrieve its confirmation | ||
// details. | ||
if tx == nil || tx.BlockHash == "" { | ||
return nil, nil | ||
return nil, txFoundMempool, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it in the mempool in this case? Update comment to explain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't the comment as is imply this though by it not being included in a block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If tx == nil
, does that mean it is in the mempool?
if err := waitForMempoolTx(miner, txid); err != nil { | ||
t.Fatal(err) | ||
} | ||
if _, err := miner.Node.Generate(1); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check the mempool case before generating a block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't do so for bitcoind
at the moment until btcsuite/btcd#1222 is in as we'll need to wait for bitcoind
to detect the transaction in its mempool.
// txConfStatus denotes the status of a transaction's lookup. | ||
type txConfStatus uint8 | ||
|
||
const ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: as discussed, would be nice to later make these shared between all backends, and then include them in SpendEvents
etc
chainntnfs/btcdnotify/btcd.go
Outdated
// We'll then check the status of the transaction lookup returned to | ||
// determine whether we should proceed with any fallback methods. | ||
switch { | ||
// The transaction was found within the node's txindex. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the comments apply to btcd
as well, I guess.
Build failing on all instances. Looks to be an issue with the commit of |
It's due to the removal of extended filters in neutrino. This PR as is adds a lot of duplicate code for tests. After seeing how they've been handled in #1439, I'll be modifying this PR to closely follow that approach. Will ping once done. |
Ping on rebase, almost forgot about this one! |
a5acd1c
to
fd50eb0
Compare
In this commit, we extract some of the helper test variables and functions into their own file and guard them under a build flag. This is needed as some unit tests will be introduced in a future commit where most of the same functions within the interface tests are reused. In order to prevent these variables and functions from being exportable, we guard them by the "debug" build tag.
In this commit, we address a bug where it's possible that we still attempt to manually scan for a transaction to determine whether it's been included in the chain even after successfully checking the txindex and not finding it there. Now, we'll short-circuit this process by exiting early if the txindex lookup was successful but the transaction in question was not found. Otherwise, we'll fall back to the manual scan.
526b289
to
a317236
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty good 👍
One thing I that could be improved is to document more clearly the relation between the different conf states. A suggestion would be to make say confDetailsFromTxIndex
return states [mempool, block, not-found]
, and confDetailsManually
return states [found, not-found]
. Then historicalConfDetails
could use these values to determine which of the txConfStatus
s to return (and then I believe we could replace all *notFound
statuses there with a single txNotFound
status.
Also needs a rebase!
@@ -431,84 +457,102 @@ func (b *BitcoindNotifier) handleRelevantTx(tx chain.RelevantTx, bestHeight int3 | |||
// historicalConfDetails looks up whether a transaction is already included in a | |||
// block in the active chain and, if so, returns details about the confirmation. | |||
func (b *BitcoindNotifier) historicalConfDetails(txid *chainhash.Hash, | |||
heightHint, currentHeight uint32) (*chainntnfs.TxConfirmation, error) { | |||
heightHint, currentHeight uint32) (*chainntnfs.TxConfirmation, txConfStatus, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: long line?
if txConf != nil { | ||
return txConf, nil | ||
// The transaction was not found within the node's mempool or txindex. | ||
case txStatus == txNotFoundIndex && err == nil: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should check the error first, as now it can return (_, 0, err)
which will match the txFoundMempool
case.
} | ||
|
||
// Make sure we actually retrieved a transaction that is included in a | ||
// block. Without this, we won't be able to retrieve its confirmation | ||
// details. | ||
if tx == nil || tx.BlockHash == "" { | ||
return nil, nil | ||
return nil, txFoundMempool, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If tx == nil
, does that mean it is in the mempool?
// Now, we'll create a test transaction, confirm it, and attempt to | ||
// retrieve its confirmation details. | ||
// | ||
// TODO(wilmer): add mempool case once trickle timeout can be specified |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is now added.
In this commit, we address a bug where it's possible that we still
attempt to manually scan for a transaction to determine whether it's
been included in the chain even after successfully checking the txindex
and not finding it there. Now, we'll short-circuit this process by
exiting early if the txindex lookup was successful but the transaction
in question was not found. Otherwise, we'll fall back to the manual
scan.