Skip to content

Commit ed33185

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

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

crates/electrum/src/bdk_electrum_client.rs

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

0 commit comments

Comments
 (0)