-
Notifications
You must be signed in to change notification settings - Fork 114
Fix evicted transation #605
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
base: main
Are you sure you want to change the base?
Fix evicted transation #605
Conversation
👋 Thanks for assigning @tnull as a reviewer! |
de9c632
to
0a9bee3
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.
Oh, good catch! I think we should fix this right at deserialization time though.
src/chain/bitcoind.rs
Outdated
@@ -1121,7 +1122,12 @@ impl BitcoindClient { | |||
let mempool_entries_cache = mempool_entries_cache.lock().await; | |||
let evicted_txids = unconfirmed_txids | |||
.into_iter() | |||
.filter(|txid| mempool_entries_cache.contains_key(txid)) | |||
.filter(|txid| { | |||
let mut bytes = txid.to_byte_array(); |
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 don't think we should fix this here, but when we first parse in the Txid
, i.e., before we even add it to the cache.
While you're doing this, mind adding a few end-to-end tests for all the JsonResponse
de/serialization, i.e., asserting that we get the same objects when we encode and decode GetRawMempoolResponse
,GetMempoolEntryResponse
, etc. These might also good candidates for simple proptests.
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.
Got it, thanks! I’ll make those changes and add the tests as suggested.
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 this branch also needs a rebase by now.
0a9bee3
to
5961e27
Compare
I updated the implementation to replace I also added property-based tests to ensure that Additionally, I expanded the RBF functional tests to cover two scenarios:
For this, I introduced |
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.
Thanks for catching this!
Changes themselves look mostly good, but I'd prefer to keep the test setup more minimal, as all this boilerplate doesn't provide any real benefit, and the complexity renders CI pretty AFAICT.
@@ -1109,7 +1109,7 @@ impl BitcoindClient { | |||
let mempool_entries_cache = mempool_entries_cache.lock().await; | |||
let evicted_txids = unconfirmed_txids | |||
.into_iter() | |||
.filter(|txid| mempool_entries_cache.contains_key(txid)) | |||
.filter(|txid| !mempool_entries_cache.contains_key(txid)) |
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.
Aaah, good catch. Mind renaming unconfirmed_txids
to bdk_mempool_txids
or bdk_unconfirmed_txids
. I think a bit cleaner naming would have likely avoided that bug in the first place.
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.
Done!
@@ -754,7 +754,7 @@ impl BitcoindClient { | |||
async fn get_raw_transaction_rpc( | |||
rpc_client: Arc<RpcClient>, txid: &Txid, | |||
) -> std::io::Result<Option<Transaction>> { | |||
let txid_hex = bitcoin::consensus::encode::serialize_hex(txid); | |||
let txid_hex = txid.to_string(); |
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.
Ugh, classic mistake. Thanks for catching this.
tests/common/mod.rs
Outdated
@@ -1074,6 +1110,170 @@ pub(crate) fn do_channel_full_cycle<E: ElectrumApi>( | |||
println!("\nB stopped"); | |||
} | |||
|
|||
pub(crate) struct MultiNodeTestSetup { |
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 a lot of boilerplate, and would use a lot of CI resources for no added benefit. I think it would be preferable if the test_rbf
tests would just reuse the existing test utilities. FWIW, to test RBF works as expected you'll only need to setup a single node (maybe one per chain source, as we do for the full_cycle
) test, i.e., should just be able to use setup_node
.
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.
Yeah, I initially made that struct for a different approach, but it turned out unnecessary. I removed it and now use one node per chain type, keeping the test lighter.
94b240f
to
f2cf691
Compare
- Replace `bitcoin::consensus::encode::deserialize_hex()` with `hex_str.parse::<Txid>()` when parsing Txids from RPC, and `serialize_hex()` with `txid.to_string()` when sending to RPC, ensuring proper handling of Bitcoin Core's reversed-byte hexadecimal format. - Fix mempool eviction logic: transactions that are no longer in the mempool are now correctly removed from wallet consideration, preventing stale pending transactions from inflating unconfirmed balances. - Refactor `unconfirmed_txids` to `bdk_unconfirmed_txids` to make it easier to identify what are unconfirmed bdk transactions
- Validate roundtrip serialization/deserialization for Txids, transactions, mempool entries, and fee responses. - Ensure Txid parsing/serialization matches Bitcoin Core RPC expectations.
- Test mempool-only RBF handling and balance adjustments. - Test RBF transactions confirmed in block, ensuring stale unconfirmed txs are removed. - Introduce `distribute_funds_unconfirmed` for creating unconfirmed outputs.
f2cf691
to
f9e0767
Compare
This PR fixes an issue where
BitcoinD
failed to detect when a transaction was removed from the mempool, causing inconsistencies compared toElectrum
andEsplora.
The root cause was an endianness mismatch in the
evicted_txids
check: one txid was in little-endian and the other in big-endian, making proper matching nearly impossible. The fix ensures consistent txid comparison by normalizing endianness.Additionally, this PR adds an RBF functional test to verify that the node correctly: