taproot-tests: Add test coverage for tx signing

This commit is contained in:
Alekos Filini 2022-05-18 19:55:21 +02:00
parent 461397e590
commit 89cb425e69
No known key found for this signature in database
GPG Key ID: 431401E4A4530061

View File

@ -1855,7 +1855,7 @@ pub(crate) mod test {
}
pub(crate) fn get_test_tr_single_sig() -> &'static str {
"tr(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*)"
"tr(cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG)"
}
pub(crate) fn get_test_tr_with_taptree() -> &'static str {
@ -1866,6 +1866,14 @@ pub(crate) mod test {
"tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100)),and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(200))})"
}
pub(crate) fn get_test_tr_single_sig_xprv() -> &'static str {
"tr(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*)"
}
pub(crate) fn get_test_tr_with_taptree_xprv() -> &'static str {
"tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{pk(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
}
macro_rules! assert_fee_rate {
($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
let mut tx = $tx.clone();
@ -4185,7 +4193,7 @@ pub(crate) mod test {
#[test]
fn test_taproot_psbt_populate_tap_key_origins() {
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
let addr = wallet.get_address(AddressIndex::New).unwrap();
let mut builder = wallet.build_tx();
@ -4322,6 +4330,52 @@ pub(crate) mod test {
);
}
#[test]
fn test_taproot_sign_missing_witness_utxo() {
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
builder.drain_to(addr.script_pubkey()).drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
let witness_utxo = psbt.inputs[0].witness_utxo.take();
let result = wallet.sign(
&mut psbt,
SignOptions {
allow_all_sighashes: true,
..Default::default()
},
);
assert!(
result.is_err(),
"Signing should have failed because the witness_utxo is missing"
);
assert!(
matches!(
result.unwrap_err(),
Error::Signer(SignerError::MissingWitnessUtxo)
),
"Signing failed with the wrong error type"
);
// restore the witness_utxo
psbt.inputs[0].witness_utxo = witness_utxo;
let result = wallet.sign(
&mut psbt,
SignOptions {
allow_all_sighashes: true,
..Default::default()
},
);
assert!(result.is_ok(), "Signing should have worked");
assert!(
result.unwrap(),
"Should finalize the input since we can produce signatures"
);
}
#[test]
fn test_taproot_foreign_utxo() {
let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
@ -4362,9 +4416,7 @@ pub(crate) mod test {
);
}
#[test]
fn test_taproot_key_spend() {
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
fn test_spend_from_wallet(wallet: Wallet<AnyDatabase>) {
let addr = wallet.get_address(AddressIndex::New).unwrap();
let mut builder = wallet.build_tx();
@ -4373,22 +4425,143 @@ pub(crate) mod test {
assert!(
wallet.sign(&mut psbt, Default::default()).unwrap(),
"Unable to finalize taproot key spend"
"Unable to finalize tx"
);
}
#[test]
fn test_taproot_key_spend() {
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
test_spend_from_wallet(wallet);
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
test_spend_from_wallet(wallet);
}
#[test]
fn test_taproot_script_spend() {
let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree());
test_spend_from_wallet(wallet);
let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree_xprv());
test_spend_from_wallet(wallet);
}
#[test]
fn test_taproot_sign_derive_index_from_psbt() {
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
let addr = wallet.get_address(AddressIndex::New).unwrap();
let mut builder = wallet.build_tx();
builder.add_recipient(addr.script_pubkey(), 25_000);
let (mut psbt, _) = builder.finish().unwrap();
// re-create the wallet with an empty db
let wallet_empty = Wallet::new(
get_test_tr_single_sig_xprv(),
None,
Network::Regtest,
AnyDatabase::Memory(MemoryDatabase::new()),
)
.unwrap();
// signing with an empty db means that we will only look at the psbt to infer the
// derivation index
assert!(
wallet.sign(&mut psbt, Default::default()).unwrap(),
"Unable to finalize taproot script spend"
wallet_empty.sign(&mut psbt, Default::default()).unwrap(),
"Unable to finalize tx"
);
}
#[test]
fn test_taproot_sign_explicit_sighash_all() {
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
builder
.drain_to(addr.script_pubkey())
.sighash(SchnorrSighashType::All.into())
.drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
let result = wallet.sign(&mut psbt, Default::default());
assert!(
result.is_ok(),
"Signing should work because SIGHASH_ALL is safe"
)
}
#[test]
fn test_taproot_sign_non_default_sighash() {
let sighash = SchnorrSighashType::NonePlusAnyoneCanPay;
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
let addr = wallet.get_address(New).unwrap();
let mut builder = wallet.build_tx();
builder
.drain_to(addr.script_pubkey())
.sighash(sighash.into())
.drain_wallet();
let (mut psbt, _) = builder.finish().unwrap();
let witness_utxo = psbt.inputs[0].witness_utxo.take();
let result = wallet.sign(&mut psbt, Default::default());
assert!(
result.is_err(),
"Signing should have failed because the TX uses non-standard sighashes"
);
assert!(
matches!(
result.unwrap_err(),
Error::Signer(SignerError::NonStandardSighash)
),
"Signing failed with the wrong error type"
);
// try again after opting-in
let result = wallet.sign(
&mut psbt,
SignOptions {
allow_all_sighashes: true,
..Default::default()
},
);
assert!(
result.is_err(),
"Signing should have failed because the witness_utxo is missing"
);
assert!(
matches!(
result.unwrap_err(),
Error::Signer(SignerError::MissingWitnessUtxo)
),
"Signing failed with the wrong error type"
);
// restore the witness_utxo
psbt.inputs[0].witness_utxo = witness_utxo;
let result = wallet.sign(
&mut psbt,
SignOptions {
allow_all_sighashes: true,
..Default::default()
},
);
assert!(result.is_ok(), "Signing should have worked");
assert!(
result.unwrap(),
"Should finalize the input since we can produce signatures"
);
let extracted = psbt.extract_tx();
assert_eq!(
*extracted.input[0].witness.to_vec()[0].last().unwrap(),
sighash as u8,
"The signature should have been made with the right sighash"
);
}
}