Move tests to /tests
To stop my rust-anlayzer from killing me
This commit is contained in:
parent
a40da9ba6c
commit
57538e53e4
161
src/psbt/mod.rs
161
src/psbt/mod.rs
@ -77,164 +77,3 @@ impl PsbtUtils for Psbt {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use crate::bitcoin::TxIn;
|
|
||||||
use crate::psbt::Psbt;
|
|
||||||
use crate::wallet::test::{get_funded_wallet, get_test_wpkh};
|
|
||||||
use crate::wallet::AddressIndex;
|
|
||||||
use crate::wallet::AddressIndex::New;
|
|
||||||
use crate::{psbt, FeeRate, SignOptions};
|
|
||||||
use core::str::FromStr;
|
|
||||||
|
|
||||||
// from bip 174
|
|
||||||
const PSBT_STR: &str = "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA";
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "InputIndexOutOfRange")]
|
|
||||||
fn test_psbt_malformed_psbt_input_legacy() {
|
|
||||||
let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
|
|
||||||
let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
|
|
||||||
let send_to = wallet.get_address(AddressIndex::New);
|
|
||||||
let mut builder = wallet.build_tx();
|
|
||||||
builder.add_recipient(send_to.script_pubkey(), 10_000);
|
|
||||||
let (mut psbt, _) = builder.finish().unwrap();
|
|
||||||
psbt.inputs.push(psbt_bip.inputs[0].clone());
|
|
||||||
let options = SignOptions {
|
|
||||||
trust_witness_utxo: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let _ = wallet.sign(&mut psbt, options).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "InputIndexOutOfRange")]
|
|
||||||
fn test_psbt_malformed_psbt_input_segwit() {
|
|
||||||
let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
|
|
||||||
let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
|
|
||||||
let send_to = wallet.get_address(AddressIndex::New);
|
|
||||||
let mut builder = wallet.build_tx();
|
|
||||||
builder.add_recipient(send_to.script_pubkey(), 10_000);
|
|
||||||
let (mut psbt, _) = builder.finish().unwrap();
|
|
||||||
psbt.inputs.push(psbt_bip.inputs[1].clone());
|
|
||||||
let options = SignOptions {
|
|
||||||
trust_witness_utxo: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let _ = wallet.sign(&mut psbt, options).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "InputIndexOutOfRange")]
|
|
||||||
fn test_psbt_malformed_tx_input() {
|
|
||||||
let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
|
|
||||||
let send_to = wallet.get_address(AddressIndex::New);
|
|
||||||
let mut builder = wallet.build_tx();
|
|
||||||
builder.add_recipient(send_to.script_pubkey(), 10_000);
|
|
||||||
let (mut psbt, _) = builder.finish().unwrap();
|
|
||||||
psbt.unsigned_tx.input.push(TxIn::default());
|
|
||||||
let options = SignOptions {
|
|
||||||
trust_witness_utxo: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let _ = wallet.sign(&mut psbt, options).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_psbt_sign_with_finalized() {
|
|
||||||
let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
|
|
||||||
let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
|
|
||||||
let send_to = wallet.get_address(AddressIndex::New);
|
|
||||||
let mut builder = wallet.build_tx();
|
|
||||||
builder.add_recipient(send_to.script_pubkey(), 10_000);
|
|
||||||
let (mut psbt, _) = builder.finish().unwrap();
|
|
||||||
|
|
||||||
// add a finalized input
|
|
||||||
psbt.inputs.push(psbt_bip.inputs[0].clone());
|
|
||||||
psbt.unsigned_tx
|
|
||||||
.input
|
|
||||||
.push(psbt_bip.unsigned_tx.input[0].clone());
|
|
||||||
|
|
||||||
let _ = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_psbt_fee_rate_with_witness_utxo() {
|
|
||||||
use psbt::PsbtUtils;
|
|
||||||
|
|
||||||
let expected_fee_rate = 1.2345;
|
|
||||||
|
|
||||||
let (mut wallet, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
|
||||||
let addr = wallet.get_address(New);
|
|
||||||
let mut builder = wallet.build_tx();
|
|
||||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
|
||||||
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
|
|
||||||
let (mut psbt, _) = builder.finish().unwrap();
|
|
||||||
let fee_amount = psbt.fee_amount();
|
|
||||||
assert!(fee_amount.is_some());
|
|
||||||
|
|
||||||
let unfinalized_fee_rate = psbt.fee_rate().unwrap();
|
|
||||||
|
|
||||||
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
|
|
||||||
assert!(finalized);
|
|
||||||
|
|
||||||
let finalized_fee_rate = psbt.fee_rate().unwrap();
|
|
||||||
assert!(finalized_fee_rate.as_sat_per_vb() >= expected_fee_rate);
|
|
||||||
assert!(finalized_fee_rate.as_sat_per_vb() < unfinalized_fee_rate.as_sat_per_vb());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_psbt_fee_rate_with_nonwitness_utxo() {
|
|
||||||
use psbt::PsbtUtils;
|
|
||||||
|
|
||||||
let expected_fee_rate = 1.2345;
|
|
||||||
|
|
||||||
let (mut wallet, _) = get_funded_wallet("pkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
|
||||||
let addr = wallet.get_address(New);
|
|
||||||
let mut builder = wallet.build_tx();
|
|
||||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
|
||||||
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
|
|
||||||
let (mut psbt, _) = builder.finish().unwrap();
|
|
||||||
let fee_amount = psbt.fee_amount();
|
|
||||||
assert!(fee_amount.is_some());
|
|
||||||
let unfinalized_fee_rate = psbt.fee_rate().unwrap();
|
|
||||||
|
|
||||||
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
|
|
||||||
assert!(finalized);
|
|
||||||
|
|
||||||
let finalized_fee_rate = psbt.fee_rate().unwrap();
|
|
||||||
assert!(finalized_fee_rate.as_sat_per_vb() >= expected_fee_rate);
|
|
||||||
assert!(finalized_fee_rate.as_sat_per_vb() < unfinalized_fee_rate.as_sat_per_vb());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_psbt_fee_rate_with_missing_txout() {
|
|
||||||
use psbt::PsbtUtils;
|
|
||||||
|
|
||||||
let expected_fee_rate = 1.2345;
|
|
||||||
|
|
||||||
let (mut wpkh_wallet, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
|
||||||
let addr = wpkh_wallet.get_address(New);
|
|
||||||
let mut builder = wpkh_wallet.build_tx();
|
|
||||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
|
||||||
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
|
|
||||||
let (mut wpkh_psbt, _) = builder.finish().unwrap();
|
|
||||||
|
|
||||||
wpkh_psbt.inputs[0].witness_utxo = None;
|
|
||||||
wpkh_psbt.inputs[0].non_witness_utxo = None;
|
|
||||||
assert!(wpkh_psbt.fee_amount().is_none());
|
|
||||||
assert!(wpkh_psbt.fee_rate().is_none());
|
|
||||||
|
|
||||||
let (mut pkh_wallet, _) = get_funded_wallet("pkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
|
||||||
let addr = pkh_wallet.get_address(New);
|
|
||||||
let mut builder = pkh_wallet.build_tx();
|
|
||||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
|
||||||
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
|
|
||||||
let (mut pkh_psbt, _) = builder.finish().unwrap();
|
|
||||||
|
|
||||||
pkh_psbt.inputs[0].non_witness_utxo = None;
|
|
||||||
assert!(pkh_psbt.fee_amount().is_none());
|
|
||||||
assert!(pkh_psbt.fee_rate().is_none());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -112,10 +112,7 @@ use rand::thread_rng;
|
|||||||
|
|
||||||
/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
|
/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
|
||||||
/// overridden
|
/// overridden
|
||||||
#[cfg(not(test))]
|
|
||||||
pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
|
pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
|
||||||
#[cfg(test)]
|
|
||||||
pub type DefaultCoinSelectionAlgorithm = LargestFirstCoinSelection; // make the tests more predictable
|
|
||||||
|
|
||||||
// Base weight of a Txin, not counting the weight needed for satisfying it.
|
// Base weight of a Txin, not counting the weight needed for satisfying it.
|
||||||
// prev_txid (32 bytes) + prev_vout (4 bytes) + sequence (4 bytes)
|
// prev_txid (32 bytes) + prev_vout (4 bytes) + sequence (4 bytes)
|
||||||
@ -373,7 +370,7 @@ impl OutputGroup {
|
|||||||
/// Branch and bound coin selection
|
/// Branch and bound coin selection
|
||||||
///
|
///
|
||||||
/// Code adapted from Bitcoin Core's implementation and from Mark Erhardt Master's Thesis: <http://murch.one/wp-content/uploads/2016/11/erhardt2016coinselection.pdf>
|
/// Code adapted from Bitcoin Core's implementation and from Mark Erhardt Master's Thesis: <http://murch.one/wp-content/uploads/2016/11/erhardt2016coinselection.pdf>
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BranchAndBoundCoinSelection {
|
pub struct BranchAndBoundCoinSelection {
|
||||||
size_of_change: u64,
|
size_of_change: u64,
|
||||||
}
|
}
|
||||||
|
3322
src/wallet/mod.rs
3322
src/wallet/mod.rs
File diff suppressed because it is too large
Load Diff
86
tests/common.rs
Normal file
86
tests/common.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#![allow(unused)]
|
||||||
|
use bdk::{wallet::AddressIndex, Wallet};
|
||||||
|
use bdk_chain::{BlockId, ConfirmationTime};
|
||||||
|
use bitcoin::hashes::Hash;
|
||||||
|
use bitcoin::{BlockHash, Network, Transaction, TxOut};
|
||||||
|
|
||||||
|
/// Return a fake wallet that appears to be funded for testing.
|
||||||
|
pub fn get_funded_wallet(descriptor: &str) -> (Wallet, bitcoin::Txid) {
|
||||||
|
let mut wallet = Wallet::new(descriptor, None, Network::Regtest).unwrap();
|
||||||
|
let address = wallet.get_address(AddressIndex::New).address;
|
||||||
|
|
||||||
|
let tx = Transaction {
|
||||||
|
version: 1,
|
||||||
|
lock_time: bitcoin::PackedLockTime(0),
|
||||||
|
input: vec![],
|
||||||
|
output: vec![TxOut {
|
||||||
|
value: 50_000,
|
||||||
|
script_pubkey: address.script_pubkey(),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
wallet
|
||||||
|
.insert_checkpoint(BlockId {
|
||||||
|
height: 1_000,
|
||||||
|
hash: BlockHash::all_zeros(),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
wallet
|
||||||
|
.insert_tx(
|
||||||
|
tx.clone(),
|
||||||
|
ConfirmationTime::Confirmed {
|
||||||
|
height: 1_000,
|
||||||
|
time: 100,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
(wallet, tx.txid())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_wpkh() -> &'static str {
|
||||||
|
"wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_single_sig_csv() -> &'static str {
|
||||||
|
// and(pk(Alice),older(6))
|
||||||
|
"wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_a_or_b_plus_csv() -> &'static str {
|
||||||
|
// or(pk(Alice),and(pk(Bob),older(144)))
|
||||||
|
"wsh(or_d(pk(cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu),and_v(v:pk(cMnkdebixpXMPfkcNEjjGin7s94hiehAH4mLbYkZoh9KSiNNmqC8),older(144))))"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_single_sig_cltv() -> &'static str {
|
||||||
|
// and(pk(Alice),after(100000))
|
||||||
|
"wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_tr_single_sig() -> &'static str {
|
||||||
|
"tr(cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG)"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_tr_with_taptree() -> &'static str {
|
||||||
|
"tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{pk(cPZzKuNmpuUjD1e8jUU4PVzy2b5LngbSip8mBsxf4e7rSFZVb4Uh),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_tr_with_taptree_both_priv() -> &'static str {
|
||||||
|
"tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{pk(cPZzKuNmpuUjD1e8jUU4PVzy2b5LngbSip8mBsxf4e7rSFZVb4Uh),pk(cNaQCDwmmh4dS9LzCgVtyy1e1xjCJ21GUDHe9K98nzb689JvinGV)})"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_tr_repeated_key() -> &'static str {
|
||||||
|
"tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100)),and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(200))})"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_tr_single_sig_xprv() -> &'static str {
|
||||||
|
"tr(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*)"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_tr_with_taptree_xprv() -> &'static str {
|
||||||
|
"tr(cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG,{pk(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_test_tr_dup_keys() -> &'static str {
|
||||||
|
"tr(cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG,{pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
|
||||||
|
}
|
158
tests/psbt.rs
Normal file
158
tests/psbt.rs
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
use bdk::bitcoin::TxIn;
|
||||||
|
use bdk::wallet::AddressIndex;
|
||||||
|
use bdk::wallet::AddressIndex::New;
|
||||||
|
use bdk::{psbt, FeeRate, SignOptions};
|
||||||
|
use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
|
||||||
|
use core::str::FromStr;
|
||||||
|
mod common;
|
||||||
|
use common::*;
|
||||||
|
|
||||||
|
// from bip 174
|
||||||
|
const PSBT_STR: &str = "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "InputIndexOutOfRange")]
|
||||||
|
fn test_psbt_malformed_psbt_input_legacy() {
|
||||||
|
let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
|
||||||
|
let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
|
||||||
|
let send_to = wallet.get_address(AddressIndex::New);
|
||||||
|
let mut builder = wallet.build_tx();
|
||||||
|
builder.add_recipient(send_to.script_pubkey(), 10_000);
|
||||||
|
let (mut psbt, _) = builder.finish().unwrap();
|
||||||
|
psbt.inputs.push(psbt_bip.inputs[0].clone());
|
||||||
|
let options = SignOptions {
|
||||||
|
trust_witness_utxo: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let _ = wallet.sign(&mut psbt, options).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "InputIndexOutOfRange")]
|
||||||
|
fn test_psbt_malformed_psbt_input_segwit() {
|
||||||
|
let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
|
||||||
|
let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
|
||||||
|
let send_to = wallet.get_address(AddressIndex::New);
|
||||||
|
let mut builder = wallet.build_tx();
|
||||||
|
builder.add_recipient(send_to.script_pubkey(), 10_000);
|
||||||
|
let (mut psbt, _) = builder.finish().unwrap();
|
||||||
|
psbt.inputs.push(psbt_bip.inputs[1].clone());
|
||||||
|
let options = SignOptions {
|
||||||
|
trust_witness_utxo: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let _ = wallet.sign(&mut psbt, options).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "InputIndexOutOfRange")]
|
||||||
|
fn test_psbt_malformed_tx_input() {
|
||||||
|
let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
|
||||||
|
let send_to = wallet.get_address(AddressIndex::New);
|
||||||
|
let mut builder = wallet.build_tx();
|
||||||
|
builder.add_recipient(send_to.script_pubkey(), 10_000);
|
||||||
|
let (mut psbt, _) = builder.finish().unwrap();
|
||||||
|
psbt.unsigned_tx.input.push(TxIn::default());
|
||||||
|
let options = SignOptions {
|
||||||
|
trust_witness_utxo: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let _ = wallet.sign(&mut psbt, options).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_psbt_sign_with_finalized() {
|
||||||
|
let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
|
||||||
|
let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
|
||||||
|
let send_to = wallet.get_address(AddressIndex::New);
|
||||||
|
let mut builder = wallet.build_tx();
|
||||||
|
builder.add_recipient(send_to.script_pubkey(), 10_000);
|
||||||
|
let (mut psbt, _) = builder.finish().unwrap();
|
||||||
|
|
||||||
|
// add a finalized input
|
||||||
|
psbt.inputs.push(psbt_bip.inputs[0].clone());
|
||||||
|
psbt.unsigned_tx
|
||||||
|
.input
|
||||||
|
.push(psbt_bip.unsigned_tx.input[0].clone());
|
||||||
|
|
||||||
|
let _ = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_psbt_fee_rate_with_witness_utxo() {
|
||||||
|
use psbt::PsbtUtils;
|
||||||
|
|
||||||
|
let expected_fee_rate = 1.2345;
|
||||||
|
|
||||||
|
let (mut wallet, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
||||||
|
let addr = wallet.get_address(New);
|
||||||
|
let mut builder = wallet.build_tx();
|
||||||
|
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||||
|
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
|
||||||
|
let (mut psbt, _) = builder.finish().unwrap();
|
||||||
|
let fee_amount = psbt.fee_amount();
|
||||||
|
assert!(fee_amount.is_some());
|
||||||
|
|
||||||
|
let unfinalized_fee_rate = psbt.fee_rate().unwrap();
|
||||||
|
|
||||||
|
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
|
||||||
|
assert!(finalized);
|
||||||
|
|
||||||
|
let finalized_fee_rate = psbt.fee_rate().unwrap();
|
||||||
|
assert!(finalized_fee_rate.as_sat_per_vb() >= expected_fee_rate);
|
||||||
|
assert!(finalized_fee_rate.as_sat_per_vb() < unfinalized_fee_rate.as_sat_per_vb());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_psbt_fee_rate_with_nonwitness_utxo() {
|
||||||
|
use psbt::PsbtUtils;
|
||||||
|
|
||||||
|
let expected_fee_rate = 1.2345;
|
||||||
|
|
||||||
|
let (mut wallet, _) = get_funded_wallet("pkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
||||||
|
let addr = wallet.get_address(New);
|
||||||
|
let mut builder = wallet.build_tx();
|
||||||
|
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||||
|
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
|
||||||
|
let (mut psbt, _) = builder.finish().unwrap();
|
||||||
|
let fee_amount = psbt.fee_amount();
|
||||||
|
assert!(fee_amount.is_some());
|
||||||
|
let unfinalized_fee_rate = psbt.fee_rate().unwrap();
|
||||||
|
|
||||||
|
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
|
||||||
|
assert!(finalized);
|
||||||
|
|
||||||
|
let finalized_fee_rate = psbt.fee_rate().unwrap();
|
||||||
|
assert!(finalized_fee_rate.as_sat_per_vb() >= expected_fee_rate);
|
||||||
|
assert!(finalized_fee_rate.as_sat_per_vb() < unfinalized_fee_rate.as_sat_per_vb());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_psbt_fee_rate_with_missing_txout() {
|
||||||
|
use psbt::PsbtUtils;
|
||||||
|
|
||||||
|
let expected_fee_rate = 1.2345;
|
||||||
|
|
||||||
|
let (mut wpkh_wallet, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
||||||
|
let addr = wpkh_wallet.get_address(New);
|
||||||
|
let mut builder = wpkh_wallet.build_tx();
|
||||||
|
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||||
|
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
|
||||||
|
let (mut wpkh_psbt, _) = builder.finish().unwrap();
|
||||||
|
|
||||||
|
wpkh_psbt.inputs[0].witness_utxo = None;
|
||||||
|
wpkh_psbt.inputs[0].non_witness_utxo = None;
|
||||||
|
assert!(wpkh_psbt.fee_amount().is_none());
|
||||||
|
assert!(wpkh_psbt.fee_rate().is_none());
|
||||||
|
|
||||||
|
let (mut pkh_wallet, _) = get_funded_wallet("pkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
||||||
|
let addr = pkh_wallet.get_address(New);
|
||||||
|
let mut builder = pkh_wallet.build_tx();
|
||||||
|
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||||
|
builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
|
||||||
|
let (mut pkh_psbt, _) = builder.finish().unwrap();
|
||||||
|
|
||||||
|
pkh_psbt.inputs[0].non_witness_utxo = None;
|
||||||
|
assert!(pkh_psbt.fee_amount().is_none());
|
||||||
|
assert!(pkh_psbt.fee_rate().is_none());
|
||||||
|
}
|
3241
tests/wallet.rs
Normal file
3241
tests/wallet.rs
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user