Skip to content

Commit fda1ae5

Browse files
committed
taproot-tests: Add test coverage for tx signing
1 parent 360f2ca commit fda1ae5

1 file changed

Lines changed: 112 additions & 8 deletions

File tree

src/wallet/mod.rs

Lines changed: 112 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,7 +1850,7 @@ pub(crate) mod test {
18501850
}
18511851

18521852
pub(crate) fn get_test_tr_single_sig() -> &'static str {
1853-
"tr(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*)"
1853+
"tr(cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG)"
18541854
}
18551855

18561856
pub(crate) fn get_test_tr_with_taptree() -> &'static str {
@@ -1861,6 +1861,14 @@ pub(crate) mod test {
18611861
"tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100)),and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(200))})"
18621862
}
18631863

1864+
pub(crate) fn get_test_tr_single_sig_xprv() -> &'static str {
1865+
"tr(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*)"
1866+
}
1867+
1868+
pub(crate) fn get_test_tr_with_taptree_xprv() -> &'static str {
1869+
"tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{pk(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
1870+
}
1871+
18641872
macro_rules! assert_fee_rate {
18651873
($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
18661874
let mut tx = $tx.clone();
@@ -4180,7 +4188,7 @@ pub(crate) mod test {
41804188

41814189
#[test]
41824190
fn test_taproot_psbt_populate_tap_key_origins() {
4183-
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
4191+
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
41844192
let addr = wallet.get_address(AddressIndex::New).unwrap();
41854193

41864194
let mut builder = wallet.build_tx();
@@ -4317,9 +4325,7 @@ pub(crate) mod test {
43174325
);
43184326
}
43194327

4320-
#[test]
4321-
fn test_taproot_key_spend() {
4322-
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
4328+
fn test_spend_from_wallet(wallet: Wallet<AnyDatabase>) {
43234329
let addr = wallet.get_address(AddressIndex::New).unwrap();
43244330

43254331
let mut builder = wallet.build_tx();
@@ -4328,22 +4334,120 @@ pub(crate) mod test {
43284334

43294335
assert!(
43304336
wallet.sign(&mut psbt, Default::default()).unwrap(),
4331-
"Unable to finalize taproot key spend"
4337+
"Unable to finalize tx"
43324338
);
43334339
}
43344340

4341+
#[test]
4342+
fn test_taproot_key_spend() {
4343+
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
4344+
test_spend_from_wallet(wallet);
4345+
4346+
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
4347+
test_spend_from_wallet(wallet);
4348+
}
4349+
43354350
#[test]
43364351
fn test_taproot_script_spend() {
43374352
let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree());
4353+
test_spend_from_wallet(wallet);
4354+
4355+
let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree_xprv());
4356+
test_spend_from_wallet(wallet);
4357+
}
4358+
4359+
#[test]
4360+
fn test_taproot_sign_derive_index_from_psbt() {
4361+
env_logger::init();
4362+
4363+
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
4364+
43384365
let addr = wallet.get_address(AddressIndex::New).unwrap();
43394366

43404367
let mut builder = wallet.build_tx();
43414368
builder.add_recipient(addr.script_pubkey(), 25_000);
43424369
let (mut psbt, _) = builder.finish().unwrap();
43434370

4371+
// re-create the wallet with an empty db
4372+
let wallet_empty = Wallet::new(
4373+
get_test_tr_single_sig_xprv(),
4374+
None,
4375+
Network::Regtest,
4376+
AnyDatabase::Memory(MemoryDatabase::new()),
4377+
)
4378+
.unwrap();
4379+
4380+
// signing with an empty db means that we will only look at the psbt to infer the
4381+
// derivation index
43444382
assert!(
4345-
wallet.sign(&mut psbt, Default::default()).unwrap(),
4346-
"Unable to finalize taproot script spend"
4383+
wallet_empty.sign(&mut psbt, Default::default()).unwrap(),
4384+
"Unable to finalize tx"
4385+
);
4386+
}
4387+
4388+
#[test]
4389+
fn test_taproot_sign_explicit_sighash_all() {
4390+
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
4391+
let addr = wallet.get_address(New).unwrap();
4392+
let mut builder = wallet.build_tx();
4393+
builder
4394+
.drain_to(addr.script_pubkey())
4395+
.sighash(SchnorrSighashType::All.into())
4396+
.drain_wallet();
4397+
let (mut psbt, _) = builder.finish().unwrap();
4398+
4399+
let result = wallet.sign(&mut psbt, Default::default());
4400+
assert!(
4401+
result.is_ok(),
4402+
"Signing should work because SIGHASH_ALL is safe"
4403+
)
4404+
}
4405+
4406+
#[test]
4407+
fn test_taproot_sign_non_default_sighash() {
4408+
let sighash = SchnorrSighashType::NonePlusAnyoneCanPay;
4409+
4410+
let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
4411+
let addr = wallet.get_address(New).unwrap();
4412+
let mut builder = wallet.build_tx();
4413+
builder
4414+
.drain_to(addr.script_pubkey())
4415+
.sighash(sighash.into())
4416+
.drain_wallet();
4417+
let (mut psbt, _) = builder.finish().unwrap();
4418+
4419+
let result = wallet.sign(&mut psbt, Default::default());
4420+
assert!(
4421+
result.is_err(),
4422+
"Signing should have failed because the TX uses non-standard sighashes"
4423+
);
4424+
assert!(
4425+
matches!(
4426+
result.unwrap_err(),
4427+
Error::Signer(SignerError::NonStandardSighash)
4428+
),
4429+
"Signing failed with the wrong error type"
4430+
);
4431+
4432+
// try again after opting-in
4433+
let result = wallet.sign(
4434+
&mut psbt,
4435+
SignOptions {
4436+
allow_all_sighashes: true,
4437+
..Default::default()
4438+
},
4439+
);
4440+
assert!(result.is_ok(), "Signing should have worked");
4441+
assert!(
4442+
result.unwrap(),
4443+
"Should finalize the input since we can produce signatures"
4444+
);
4445+
4446+
let extracted = psbt.extract_tx();
4447+
assert_eq!(
4448+
*extracted.input[0].witness.to_vec()[0].last().unwrap(),
4449+
sighash as u8,
4450+
"The signature should have been made with the right sighash"
43474451
);
43484452
}
43494453
}

0 commit comments

Comments
 (0)