Skip to content

Commit 4bd918a

Browse files
committed
feat(wallet): expose TxGraph::verify_tx for Wallet
* Add feature `bitcoinconsensus` to Cargo.toml
1 parent e52055b commit 4bd918a

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

crates/wallet/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ all-keys = ["keys-bip39"]
3535
keys-bip39 = ["bip39"]
3636
rusqlite = ["bdk_chain/rusqlite"]
3737
file_store = ["bdk_file_store"]
38+
bitcoinconsensus = ["bdk_chain/bitcoinconsensus"]
3839

3940
[dev-dependencies]
4041
lazy_static = "1.4"

crates/wallet/src/wallet/mod.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2487,6 +2487,45 @@ impl Wallet {
24872487
keychain
24882488
}
24892489
}
2490+
2491+
/// Verify the given transaction is able to spend its inputs.
2492+
///
2493+
/// This method uses [`rust-bitcoinconsensus`][0] to verify a transaction, guaranteeing
2494+
/// that if the method succeeds the transaction meets consensus criteria as defined in
2495+
/// Bitcoin's `libbitcoinconsensus`.
2496+
///
2497+
/// # Example
2498+
///
2499+
/// ```rust,no_run
2500+
/// # use bitcoin::Amount;
2501+
/// # use bdk_wallet::{KeychainKind, SignOptions};
2502+
/// # let mut wallet = bdk_wallet::doctest_wallet!();
2503+
/// # let address = wallet.reveal_next_address(KeychainKind::External);
2504+
/// let mut builder = wallet.build_tx();
2505+
/// builder.add_recipient(address.script_pubkey(), Amount::from_sat(100_000));
2506+
/// let mut psbt = builder.finish().unwrap();
2507+
/// let _ = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
2508+
/// let tx = psbt.extract_tx().unwrap();
2509+
/// assert!(wallet.verify_tx(&tx).is_ok());
2510+
/// ```
2511+
///
2512+
/// Note that validation by the Bitcoin network can ultimately fail in other ways, for
2513+
/// example if a timelock wasn't met. Also verifying that a transaction can spend its
2514+
/// inputs doesn't guarantee it will be accepted to mempools or propagated by nodes on
2515+
/// the peer-to-peer network.
2516+
///
2517+
/// # Errors
2518+
///
2519+
/// If the previous output isn't found for one or more `tx` inputs.
2520+
///
2521+
/// If Bitcoin Script verification fails.
2522+
///
2523+
/// [0]: https://docs.rs/bitcoinconsensus/latest/bitcoinconsensus/
2524+
#[cfg(feature = "bitcoinconsensus")]
2525+
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))]
2526+
pub fn verify_tx(&self, tx: &Transaction) -> Result<(), chain::tx_graph::VerifyTxError> {
2527+
self.tx_graph().verify_tx(tx)
2528+
}
24902529
}
24912530

24922531
/// Methods to construct sync/full-scan requests for spk-based chain sources.
@@ -2619,7 +2658,7 @@ macro_rules! floating_rate {
26192658
/// Macro for getting a wallet for use in a doctest
26202659
macro_rules! doctest_wallet {
26212660
() => {{
2622-
use $crate::bitcoin::{BlockHash, Transaction, absolute, TxOut, Network, hashes::Hash};
2661+
use $crate::bitcoin::{transaction, BlockHash, Transaction, absolute, TxOut, Network, hashes::Hash};
26232662
use $crate::chain::{ConfirmationBlockTime, BlockId, TxGraph, tx_graph};
26242663
use $crate::{Update, KeychainKind, Wallet};
26252664
let descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/0/*)";

0 commit comments

Comments
 (0)