fix(wallet)!: Simplify SignOptions and improve finalization logic
Rather than comingle various `SignOptions` with the finalization step, we simply clear all fields when finalizing as per the PSBT spec in BIPs 174 and 371 which is more in line with user expectations.
This commit is contained in:
@@ -2780,36 +2780,6 @@ fn test_signing_only_one_of_multiple_inputs() {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_partial_sigs_after_finalize_sign_option() {
|
||||
let (mut wallet, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
||||
|
||||
for remove_partial_sigs in &[true, false] {
|
||||
let addr = wallet.next_unused_address(KeychainKind::External);
|
||||
let mut builder = wallet.build_tx();
|
||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||
let mut psbt = builder.finish().unwrap();
|
||||
|
||||
assert!(wallet
|
||||
.sign(
|
||||
&mut psbt,
|
||||
SignOptions {
|
||||
remove_partial_sigs: *remove_partial_sigs,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap());
|
||||
|
||||
psbt.inputs.iter().for_each(|input| {
|
||||
if *remove_partial_sigs {
|
||||
assert!(input.partial_sigs.is_empty())
|
||||
} else {
|
||||
assert!(!input.partial_sigs.is_empty())
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_finalize_sign_option() {
|
||||
let (mut wallet, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
|
||||
@@ -2833,7 +2803,7 @@ fn test_try_finalize_sign_option() {
|
||||
psbt.inputs.iter().for_each(|input| {
|
||||
if *try_finalize {
|
||||
assert!(finalized);
|
||||
assert!(input.final_script_sig.is_some());
|
||||
assert!(input.final_script_sig.is_none());
|
||||
assert!(input.final_script_witness.is_some());
|
||||
} else {
|
||||
assert!(!finalized);
|
||||
@@ -2844,6 +2814,55 @@ fn test_try_finalize_sign_option() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_taproot_try_finalize_sign_option() {
|
||||
let (mut wallet, _) = get_funded_wallet(get_test_tr_with_taptree());
|
||||
|
||||
for try_finalize in &[true, false] {
|
||||
let addr = wallet.next_unused_address(KeychainKind::External);
|
||||
let mut builder = wallet.build_tx();
|
||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||
let mut psbt = builder.finish().unwrap();
|
||||
|
||||
let finalized = wallet
|
||||
.sign(
|
||||
&mut psbt,
|
||||
SignOptions {
|
||||
try_finalize: *try_finalize,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
psbt.inputs.iter().for_each(|input| {
|
||||
if *try_finalize {
|
||||
assert!(finalized);
|
||||
assert!(input.final_script_sig.is_none());
|
||||
assert!(input.final_script_witness.is_some());
|
||||
assert!(input.tap_key_sig.is_none());
|
||||
assert!(input.tap_script_sigs.is_empty());
|
||||
assert!(input.tap_scripts.is_empty());
|
||||
assert!(input.tap_key_origins.is_empty());
|
||||
assert!(input.tap_internal_key.is_none());
|
||||
assert!(input.tap_merkle_root.is_none());
|
||||
} else {
|
||||
assert!(!finalized);
|
||||
assert!(input.final_script_sig.is_none());
|
||||
assert!(input.final_script_witness.is_none());
|
||||
}
|
||||
});
|
||||
psbt.outputs.iter().for_each(|output| {
|
||||
if *try_finalize {
|
||||
assert!(finalized);
|
||||
assert!(output.tap_key_origins.is_empty());
|
||||
} else {
|
||||
assert!(!finalized);
|
||||
assert!(!output.tap_key_origins.is_empty());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sign_nonstandard_sighash() {
|
||||
let sighash = EcdsaSighashType::NonePlusAnyoneCanPay;
|
||||
@@ -3164,32 +3183,6 @@ fn test_get_address_no_reuse() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_taproot_remove_tapfields_after_finalize_sign_option() {
|
||||
let (mut wallet, _) = get_funded_wallet(get_test_tr_with_taptree());
|
||||
|
||||
let addr = wallet.next_unused_address(KeychainKind::External);
|
||||
let mut builder = wallet.build_tx();
|
||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||
let mut psbt = builder.finish().unwrap();
|
||||
let finalized = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
|
||||
assert!(finalized);
|
||||
|
||||
// removes tap_* from inputs
|
||||
for input in &psbt.inputs {
|
||||
assert!(input.tap_key_sig.is_none());
|
||||
assert!(input.tap_script_sigs.is_empty());
|
||||
assert!(input.tap_scripts.is_empty());
|
||||
assert!(input.tap_key_origins.is_empty());
|
||||
assert!(input.tap_internal_key.is_none());
|
||||
assert!(input.tap_merkle_root.is_none());
|
||||
}
|
||||
// removes key origins from outputs
|
||||
for output in &psbt.outputs {
|
||||
assert!(output.tap_key_origins.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_taproot_psbt_populate_tap_key_origins() {
|
||||
let (desc, change_desc) = get_test_tr_single_sig_xprv_with_change_desc();
|
||||
@@ -3922,7 +3915,6 @@ fn test_fee_rate_sign_no_grinding_high_r() {
|
||||
.sign(
|
||||
&mut psbt,
|
||||
SignOptions {
|
||||
remove_partial_sigs: false,
|
||||
try_finalize: false,
|
||||
allow_grinding: false,
|
||||
..Default::default()
|
||||
@@ -3941,7 +3933,6 @@ fn test_fee_rate_sign_no_grinding_high_r() {
|
||||
.sign(
|
||||
&mut psbt,
|
||||
SignOptions {
|
||||
remove_partial_sigs: false,
|
||||
allow_grinding: false,
|
||||
..Default::default()
|
||||
},
|
||||
@@ -3972,7 +3963,7 @@ fn test_fee_rate_sign_grinding_low_r() {
|
||||
.sign(
|
||||
&mut psbt,
|
||||
SignOptions {
|
||||
remove_partial_sigs: false,
|
||||
try_finalize: false,
|
||||
allow_grinding: true,
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user