Skip to content

Commit c0e75fc

Browse files
committed
Split get_tx into its own trait
to make supporting verify_tx easier
1 parent dcd90f8 commit c0e75fc

File tree

10 files changed

+65
-69
lines changed

10 files changed

+65
-69
lines changed

src/blockchain/any.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,6 @@ impl Blockchain for AnyBlockchain {
8989
maybe_await!(impl_inner_method!(self, get_capabilities))
9090
}
9191

92-
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
93-
maybe_await!(impl_inner_method!(self, get_tx, txid))
94-
}
9592
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
9693
maybe_await!(impl_inner_method!(self, broadcast, tx))
9794
}
@@ -108,6 +105,13 @@ impl GetHeight for AnyBlockchain {
108105
}
109106
}
110107

108+
#[maybe_async]
109+
impl GetTx for AnyBlockchain {
110+
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
111+
maybe_await!(impl_inner_method!(self, get_tx, txid))
112+
}
113+
}
114+
111115
#[maybe_async]
112116
impl WalletSync for AnyBlockchain {
113117
fn wallet_sync<D: BatchDatabase>(

src/blockchain/compact_filters/mod.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ mod peer;
6767
mod store;
6868
mod sync;
6969

70-
use super::{Blockchain, Capability, ConfigurableBlockchain, GetHeight, Progress, WalletSync};
70+
use crate::blockchain::*;
7171
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
7272
use crate::error::Error;
7373
use crate::types::{KeychainKind, LocalUtxo, TransactionDetails};
@@ -225,12 +225,6 @@ impl Blockchain for CompactFiltersBlockchain {
225225
vec![Capability::FullHistory].into_iter().collect()
226226
}
227227

228-
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
229-
Ok(self.peers[0]
230-
.get_mempool()
231-
.get_tx(&Inventory::Transaction(*txid)))
232-
}
233-
234228
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
235229
self.peers[0].broadcast_tx(tx.clone())?;
236230

@@ -249,6 +243,14 @@ impl GetHeight for CompactFiltersBlockchain {
249243
}
250244
}
251245

246+
impl GetTx for CompactFiltersBlockchain {
247+
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
248+
Ok(self.peers[0]
249+
.get_mempool()
250+
.get_tx(&Inventory::Transaction(*txid)))
251+
}
252+
}
253+
252254
impl WalletSync for CompactFiltersBlockchain {
253255
#[allow(clippy::mutex_atomic)] // Mutex is easier to understand than a CAS loop.
254256
fn wallet_setup<D: BatchDatabase>(

src/blockchain/electrum.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,6 @@ impl Blockchain for ElectrumBlockchain {
6868
.collect()
6969
}
7070

71-
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
72-
Ok(self.client.transaction_get(txid).map(Option::Some)?)
73-
}
74-
7571
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
7672
Ok(self.client.transaction_broadcast(tx).map(|_| ())?)
7773
}
@@ -94,6 +90,12 @@ impl GetHeight for ElectrumBlockchain {
9490
}
9591
}
9692

93+
impl GetTx for ElectrumBlockchain {
94+
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
95+
Ok(self.client.transaction_get(txid).map(Option::Some)?)
96+
}
97+
}
98+
9799
impl WalletSync for ElectrumBlockchain {
98100
fn wallet_setup<D: BatchDatabase>(
99101
&self,

src/blockchain/esplora/reqwest.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ impl Blockchain for EsploraBlockchain {
9191
.collect()
9292
}
9393

94-
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
95-
Ok(await_or_block!(self.url_client._get_tx(txid))?)
96-
}
97-
9894
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
9995
Ok(await_or_block!(self.url_client._broadcast(tx))?)
10096
}
@@ -112,6 +108,13 @@ impl GetHeight for EsploraBlockchain {
112108
}
113109
}
114110

111+
#[maybe_async]
112+
impl GetTx for EsploraBlockchain {
113+
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
114+
Ok(await_or_block!(self.url_client._get_tx(txid))?)
115+
}
116+
}
117+
115118
#[maybe_async]
116119
impl WalletSync for EsploraBlockchain {
117120
fn wallet_setup<D: BatchDatabase>(

src/blockchain/esplora/ureq.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,6 @@ impl Blockchain for EsploraBlockchain {
8787
.collect()
8888
}
8989

90-
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
91-
Ok(self.url_client._get_tx(txid)?)
92-
}
93-
9490
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
9591
let _txid = self.url_client._broadcast(tx)?;
9692
Ok(())
@@ -108,6 +104,12 @@ impl GetHeight for EsploraBlockchain {
108104
}
109105
}
110106

107+
impl GetTx for EsploraBlockchain {
108+
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
109+
Ok(self.url_client._get_tx(txid)?)
110+
}
111+
}
112+
111113
impl WalletSync for EsploraBlockchain {
112114
fn wallet_setup<D: BatchDatabase>(
113115
&self,

src/blockchain/mod.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,9 @@ pub enum Capability {
8686

8787
/// Trait that defines the actions that must be supported by a blockchain backend
8888
#[maybe_async]
89-
pub trait Blockchain: WalletSync + GetHeight {
89+
pub trait Blockchain: WalletSync + GetHeight + GetTx {
9090
/// Return the set of [`Capability`] supported by this backend
9191
fn get_capabilities(&self) -> HashSet<Capability>;
92-
/// Fetch a transaction from the blockchain given its txid
93-
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
9492
/// Broadcast a transaction
9593
fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
9694
/// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
@@ -104,6 +102,13 @@ pub trait GetHeight {
104102
fn get_height(&self) -> Result<u32, Error>;
105103
}
106104

105+
#[maybe_async]
106+
/// Trait for getting a transaction by txid
107+
pub trait GetTx {
108+
/// Fetch a transaction given its txid
109+
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
110+
}
111+
107112
/// Trait for blockchains that can sync by updating the database directly.
108113
#[maybe_async]
109114
pub trait WalletSync {
@@ -230,9 +235,6 @@ impl<T: Blockchain> Blockchain for Arc<T> {
230235
maybe_await!(self.deref().get_capabilities())
231236
}
232237

233-
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
234-
maybe_await!(self.deref().get_tx(txid))
235-
}
236238
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
237239
maybe_await!(self.deref().broadcast(tx))
238240
}
@@ -242,6 +244,13 @@ impl<T: Blockchain> Blockchain for Arc<T> {
242244
}
243245
}
244246

247+
#[maybe_async]
248+
impl<T: GetTx> GetTx for Arc<T> {
249+
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
250+
maybe_await!(self.deref().get_tx(txid))
251+
}
252+
}
253+
245254
#[maybe_async]
246255
impl<T: GetHeight> GetHeight for Arc<T> {
247256
fn get_height(&self) -> Result<u32, Error> {

src/blockchain/rpc.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@
3333
3434
use crate::bitcoin::consensus::deserialize;
3535
use crate::bitcoin::{Address, Network, OutPoint, Transaction, TxOut, Txid};
36-
use crate::blockchain::{
37-
Blockchain, Capability, ConfigurableBlockchain, GetHeight, Progress, WalletSync,
38-
};
36+
use crate::blockchain::*;
3937
use crate::database::{BatchDatabase, DatabaseUtils};
4038
use crate::{BlockTime, Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails};
4139
use bitcoincore_rpc::json::{
@@ -141,10 +139,6 @@ impl Blockchain for RpcBlockchain {
141139
self.capabilities.clone()
142140
}
143141

144-
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
145-
Ok(Some(self.client.get_raw_transaction(txid, None)?))
146-
}
147-
148142
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
149143
Ok(self.client.send_raw_transaction(tx).map(|_| ())?)
150144
}
@@ -161,6 +155,12 @@ impl Blockchain for RpcBlockchain {
161155
}
162156
}
163157

158+
impl GetTx for RpcBlockchain {
159+
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
160+
Ok(Some(self.client.get_raw_transaction(txid, None)?))
161+
}
162+
}
163+
164164
impl GetHeight for RpcBlockchain {
165165
fn get_height(&self) -> Result<u32, Error> {
166166
Ok(self.client.get_blockchain_info().map(|i| i.blocks as u32)?)

src/testutils/blockchain_tests.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ macro_rules! bdk_blockchain_tests {
10971097
// 2.
10981098
// Core (#2) -> Us (#4)
10991099

1100-
let (wallet, _, mut test_client) = init_single_sig();
1100+
let (wallet, blockchain, _, mut test_client) = init_single_sig();
11011101
let bdk_address = wallet.get_address(AddressIndex::New).unwrap().address;
11021102
let core_address = test_client.get_new_address(None, None).unwrap();
11031103
let tx = testutils! {
@@ -1108,7 +1108,7 @@ macro_rules! bdk_blockchain_tests {
11081108
let txid_1 = test_client.receive(tx);
11091109
let tx_1: Transaction = deserialize(&test_client.get_transaction(&txid_1, None).unwrap().hex).unwrap();
11101110
let vout_1 = tx_1.output.into_iter().position(|o| o.script_pubkey == core_address.script_pubkey()).unwrap() as u32;
1111-
wallet.sync(noop_progress(), None).unwrap();
1111+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
11121112
let tx_1 = wallet.list_transactions(false).unwrap().into_iter().find(|tx| tx.txid == txid_1).unwrap();
11131113
assert_eq!(tx_1.received, 50_000);
11141114
assert_eq!(tx_1.sent, 0);
@@ -1119,7 +1119,7 @@ macro_rules! bdk_blockchain_tests {
11191119
};
11201120
let txid_2 = test_client.receive(tx);
11211121

1122-
wallet.sync(noop_progress(), None).unwrap();
1122+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
11231123
let tx_2 = wallet.list_transactions(false).unwrap().into_iter().find(|tx| tx.txid == txid_2).unwrap();
11241124
assert_eq!(tx_2.received, 10_000);
11251125
assert_eq!(tx_2.sent, 0);

src/wallet/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ impl<D> Wallet<D>
171171
where
172172
D: BatchDatabase,
173173
{
174-
175174
#[deprecated = "Just use Wallet::new -- all wallets are offline now!"]
176175
/// Create a new "offline" wallet
177176
pub fn new_offline<E: IntoWalletDescriptor>(

src/wallet/verify.rs

+5-30
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::fmt;
1717
use bitcoin::consensus::serialize;
1818
use bitcoin::{OutPoint, Transaction, Txid};
1919

20-
use crate::blockchain::Blockchain;
20+
use crate::blockchain::GetTx;
2121
use crate::database::Database;
2222
use crate::error::Error;
2323

@@ -29,7 +29,7 @@ use crate::error::Error;
2929
/// Depending on the [capabilities](crate::blockchain::Blockchain::get_capabilities) of the
3030
/// [`Blockchain`] backend, the method could fail when called with old "historical" transactions or
3131
/// with unconfirmed transactions that have been evicted from the backend's memory.
32-
pub fn verify_tx<D: Database, B: Blockchain>(
32+
pub fn verify_tx<D: Database, B: GetTx>(
3333
tx: &Transaction,
3434
database: &D,
3535
blockchain: &B,
@@ -104,43 +104,18 @@ impl_error!(bitcoinconsensus::Error, Consensus, VerifyError);
104104

105105
#[cfg(test)]
106106
mod test {
107-
use std::collections::HashSet;
108-
107+
use super::*;
108+
use crate::database::{BatchOperations, MemoryDatabase};
109109
use bitcoin::consensus::encode::deserialize;
110110
use bitcoin::hashes::hex::FromHex;
111111
use bitcoin::{Transaction, Txid};
112112

113-
use crate::blockchain::{Blockchain, Capability, Progress};
114-
use crate::database::{BatchDatabase, BatchOperations, MemoryDatabase};
115-
use crate::FeeRate;
116-
117-
use super::*;
118-
119113
struct DummyBlockchain;
120114

121-
impl Blockchain for DummyBlockchain {
122-
fn get_capabilities(&self) -> HashSet<Capability> {
123-
Default::default()
124-
}
125-
fn setup<D: BatchDatabase, P: 'static + Progress>(
126-
&self,
127-
_database: &mut D,
128-
_progress_update: P,
129-
) -> Result<(), Error> {
130-
Ok(())
131-
}
115+
impl GetTx for DummyBlockchain {
132116
fn get_tx(&self, _txid: &Txid) -> Result<Option<Transaction>, Error> {
133117
Ok(None)
134118
}
135-
fn broadcast(&self, _tx: &Transaction) -> Result<(), Error> {
136-
Ok(())
137-
}
138-
fn get_height(&self) -> Result<u32, Error> {
139-
Ok(42)
140-
}
141-
fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
142-
Ok(FeeRate::default_min_relay_fee())
143-
}
144119
}
145120

146121
#[test]

0 commit comments

Comments
 (0)