Skip to content

Commit

Permalink
rust: get_unspent_outputs: fix bug returning utxos from replaced txs
Browse files Browse the repository at this point in the history
In 0a55d99 a regression was
introduced, which caused transactions that have been replaced or
dropped out of mempool be included in the utxos. This might cause
the balance to be incorrect or sent transactions to be rejected.

This commit fixes the above issue.
  • Loading branch information
LeoComandini committed Jun 16, 2022
1 parent 5782c2b commit f32b0d2
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
- Singlesig: Remove is_segwit from GA_get_unspent_outputs returned json
- GA_register_user: Change interface to match GA_login_user.

### Fixed

- GA_get_unspent_outputs: fix bug returning utxos from replaced transactions.

### Removed

- Removed GA_get_mnemonic_passphrase, callers should use GA_get_credentials.
Expand Down
6 changes: 5 additions & 1 deletion subprojects/gdk_rust/gdk_electrum/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,11 @@ impl Account {
let mut inputs = HashSet::new();
let store_read = self.store.read()?;
let acc_store = store_read.account_cache(self.account_num)?;
for txe in acc_store.all_txs.values() {
for (txid, txe) in acc_store.all_txs.iter() {
if !acc_store.heights.contains_key(&txid) {
// transaction has been replaced or dropped out of mempool
continue;
}
inputs.extend(txe.tx.previous_outputs());
for vout in 0..(txe.tx.output_len() as u32) {
let script_pubkey = txe.tx.output_script(vout);
Expand Down
5 changes: 5 additions & 0 deletions subprojects/gdk_rust/gdk_rust/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,9 @@ fn rbf() {
let txid1 = test_session.session.broadcast_transaction(&signed_tx.hex).unwrap();
test_session.wait_tx(vec![1], &txid1, Some(signed_tx.fee), Some(TransactionType::Redeposit));
let txitem = test_session.get_tx_from_list(1, &txid1);
assert!(test_session.utxos(1).0.get("btc").unwrap().iter().any(|e| e.txhash == txid1));
assert_eq!(test_session.balance_account(1, None, None), sat - txitem.fee);

assert_eq!(txitem.fee_rate / 1000, 25);

// Replace it
Expand All @@ -1279,6 +1282,8 @@ fn rbf() {
for i in 0..60 {
std::thread::sleep(std::time::Duration::from_secs(1));
if test_session.get_tx_list(1).iter().all(|e| e.txhash != txid1) {
assert!(test_session.utxos(1).0.get("btc").unwrap().iter().all(|e| e.txhash != txid1));
assert_eq!(test_session.balance_account(1, None, None), sat - txitem.fee);
break;
}
assert!(i < 59, "timeout waiting for replaced transaction to disappear");
Expand Down

0 comments on commit f32b0d2

Please sign in to comment.