fedimint_testing/btc/mod.rs
1pub mod mock;
2pub mod real;
3
4use std::time::Duration;
5
6use async_trait::async_trait;
7use bitcoin::{Address, Transaction, Txid};
8use fedimint_core::Amount;
9use fedimint_core::txoproof::TxOutProof;
10
11#[async_trait]
12pub trait BitcoinTest {
13 /// Make the underlying instance act as if it was exclusively available
14 /// for the existence of the returned guard.
15 async fn lock_exclusive(&self) -> Box<dyn BitcoinTest + Send + Sync>;
16
17 /// Mines a given number of blocks
18 async fn mine_blocks(&self, block_num: u64) -> Vec<bitcoin::BlockHash>;
19
20 /// Prepare funding wallet
21 ///
22 /// If needed will mine initial 100 blocks for `send_and_mine_block` to
23 /// work.
24 async fn prepare_funding_wallet(&self);
25
26 /// Send some bitcoin to an address then mine a block to confirm it.
27 /// Returns the proof that the transaction occurred.
28 ///
29 /// The implementation is responsible for making sure the funds can
30 /// be sent (e.g. first 100 blocks are mined to make funds available)
31 async fn send_and_mine_block(
32 &self,
33 address: &Address,
34 amount: bitcoin::Amount,
35 ) -> (TxOutProof, Transaction);
36
37 /// Send some bitcoin to an address and leave the transaction unconfirmed in
38 /// the mempool.
39 ///
40 /// The counterpart to [`BitcoinTest::send_and_mine_block`], for exercising
41 /// behaviour that depends on a transaction being seen before it is mined.
42 /// Mine a block afterwards to confirm it.
43 async fn send_without_mining(&self, address: &Address, amount: bitcoin::Amount) -> Transaction;
44
45 /// Returns a new address.
46 async fn get_new_address(&self) -> Address;
47
48 /// Mine a block to include any pending transactions then get the amount
49 /// received to an address
50 async fn mine_block_and_get_received(&self, address: &Address) -> Amount;
51
52 /// Waits till tx is found in mempool and returns the fees
53 async fn get_mempool_tx_fee(&self, txid: &Txid) -> Amount;
54
55 /// Returns the block height for the txid if found.
56 ///
57 /// Note: this exists since there's a bug for using bitcoind without txindex
58 /// for finding a tx block height.
59 /// see: `<https://github.com/fedimint/fedimint/issues/5329>`
60 async fn get_tx_block_height(&self, txid: &Txid) -> Option<u64>;
61
62 /// Returns the current block count
63 async fn get_block_count(&self) -> u64;
64
65 /// Returns a transaction with the provided txid if it exists in the mempool
66 async fn get_mempool_tx(&self, txid: &Txid) -> Option<bitcoin::Transaction>;
67
68 /// Makes every subsequent mempool transaction fetch by a guardian fail,
69 /// until called again with `false`.
70 ///
71 /// Lets a test drive a guardian's mempool scan into failing partway
72 /// through, which is otherwise only reachable by breaking a real node.
73 /// Listing the mempool keeps working, so the guardian still learns which
74 /// transactions exist and only the fetches fail.
75 ///
76 /// Only the mock backend can do this, so a test that calls it must skip
77 /// itself on real daemons via `Fixtures::is_real_test`.
78 fn fail_mempool_tx_fetches(&self, _failing: bool) {
79 panic!(
80 "Only the mock bitcoin backend can fail mempool fetches; \
81 guard this test with `Fixtures::is_real_test`"
82 );
83 }
84
85 /// Makes every subsequent mempool transaction fetch by a guardian take
86 /// `delay` before answering, until called again with [`Duration::ZERO`].
87 ///
88 /// Lets a test make a guardian's mempool scan slow enough to run out of its
89 /// time budget, which is otherwise only reachable with a large mempool.
90 ///
91 /// Only the mock backend can do this, so a test that calls it must skip
92 /// itself on real daemons via `Fixtures::is_real_test`.
93 fn delay_mempool_tx_fetches(&self, _delay: Duration) {
94 panic!(
95 "Only the mock bitcoin backend can delay mempool fetches; \
96 guard this test with `Fixtures::is_real_test`"
97 );
98 }
99}