Skip to content

Commit e54e22b

Browse files
committed
test(electrum): tests for exploit fixes
1 parent df15a4a commit e54e22b

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

crates/electrum/src/bdk_electrum_client.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,3 +569,86 @@ fn chain_update(
569569
}
570570
Ok(tip)
571571
}
572+
573+
#[cfg(test)]
574+
mod test {
575+
use crate::{bdk_electrum_client::TxUpdate, BdkElectrumClient};
576+
use bdk_chain::bitcoin::{Amount, OutPoint, ScriptBuf, Transaction, TxIn, TxOut};
577+
use bdk_testenv::{utils::new_tx, TestEnv};
578+
use electrum_client::Client;
579+
use std::{collections::BTreeMap, sync::Arc};
580+
581+
#[test]
582+
fn test_populate_with_txids_without_output() {
583+
let env = TestEnv::new().unwrap();
584+
let electrum_client = Client::new(env.electrsd.electrum_url.as_str()).unwrap();
585+
let client = BdkElectrumClient::new(electrum_client);
586+
587+
// Setup transaction with no outputs.
588+
let tx = new_tx(0);
589+
590+
// Populate tx_cache with `tx` to make it fetchable.
591+
client.populate_tx_cache(vec![tx.clone()]);
592+
593+
// Test that populate_with_txids does not panic or process a tx with no output.
594+
let mut tx_update = TxUpdate::default();
595+
let _ = client.populate_with_txids(&mut tx_update, vec![tx.compute_txid()]);
596+
597+
assert_eq!(tx_update.txs, Vec::new());
598+
}
599+
600+
#[test]
601+
fn test_fetch_prev_txout_with_coinbase() {
602+
let env = TestEnv::new().unwrap();
603+
let electrum_client = Client::new(env.electrsd.electrum_url.as_str()).unwrap();
604+
let client = BdkElectrumClient::new(electrum_client);
605+
606+
// Setup the transactions necessary for fetch_prev_txout to fetch `txouts` for `tx`.
607+
let expected_txout = TxOut {
608+
value: Amount::from_sat(10_000),
609+
script_pubkey: ScriptBuf::default(),
610+
};
611+
612+
let prev_tx = Transaction {
613+
output: vec![expected_txout.clone()],
614+
..new_tx(0)
615+
};
616+
617+
let expected_outpoint = OutPoint::new(prev_tx.compute_txid(), 0);
618+
619+
let tx = Transaction {
620+
input: vec![TxIn {
621+
previous_output: expected_outpoint,
622+
..Default::default()
623+
}],
624+
..new_tx(0)
625+
};
626+
627+
// Populate tx_cache with `prev_tx` to make it fetchable.
628+
client.populate_tx_cache(vec![prev_tx.clone()]);
629+
630+
// Test fetch_prev_txout to see if we get our expected `txouts`.
631+
let mut tx_update = TxUpdate {
632+
txs: vec![Arc::new(tx.clone())],
633+
..Default::default()
634+
};
635+
let _ = client.fetch_prev_txout(&mut tx_update);
636+
637+
assert_eq!(
638+
tx_update.txouts,
639+
BTreeMap::from([(expected_outpoint, expected_txout)])
640+
);
641+
642+
// Assert that `tx` is now a coinbase transaction.
643+
let _ = client.update_coinbase_txid(tx.compute_txid());
644+
645+
// Test that fetch_prev_txout does not fetch `txouts` for coinbase tx.
646+
let mut tx_update = TxUpdate {
647+
txs: vec![Arc::new(tx)],
648+
..Default::default()
649+
};
650+
let _ = client.fetch_prev_txout(&mut tx_update);
651+
652+
assert_eq!(tx_update.txouts, BTreeMap::default());
653+
}
654+
}

0 commit comments

Comments
 (0)