|
| 1 | +use bdk_wallet::bitcoin::bip32::Xpriv; |
| 2 | +use bdk_wallet::bitcoin::psbt::SigningKeys; |
1 | 3 | use bdk_wallet::bitcoin::{Amount, FeeRate, Psbt, TxIn}; |
2 | 4 | use bdk_wallet::test_utils::*; |
3 | 5 | use bdk_wallet::{psbt, KeychainKind, SignOptions}; |
@@ -221,3 +223,62 @@ fn test_psbt_multiple_internalkey_signers() { |
221 | 223 | let verify_res = secp.verify_schnorr(&signature, &message, &xonlykey); |
222 | 224 | assert!(verify_res.is_ok(), "The wrong internal key was used"); |
223 | 225 | } |
| 226 | + |
| 227 | +// wpkh PSBT with bip32_derivation populated, derived from |
| 228 | +// tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L |
| 229 | +const WPKH_PSBT_WITH_DERIVATION: &str = "cHNidP8BAHECAAAAAbOlV/kRKdNVk6Wn2cay5JUvpFw4tEsKWylqu+HfPKDyAAAAAAD9////ArObAAAAAAAAFgAU2+Ijq+8PDcPUGgHQqOPg9+6n9h8QJwAAAAAAABYAFKENkldInmhd2gMGYjkNwXeFL68T0AcAAAABAHEBAAAAATCzgdcz18YZK+8oNpJzqjM8ErFYW3hJLi+bO4bjmQrRAAAAAAD/////AlDDAAAAAAAAFgAUoQ2SV0ieaF3aAwZiOQ3Bd4UvrxOoYQAAAAAAABYAFIgWLNSQrRaGsRyWtCHaqeauCPYsAAAAAAEBH1DDAAAAAAAAFgAUoQ2SV0ieaF3aAwZiOQ3Bd4UvrxMiBgLOtp4iMz+DVWxdHvunWgM0a/PVLPvTn8XSTe0DTvfZ9Bjic/5CVAAAgAEAAIAAAACAAAAAAAAAAAAAIgIDxWYngmqPgL3saGZ4NTgcy5W/XINU8lkqnqjKC+oJuRwY4nP+QlQAAIABAACAAAAAgAEAAAAAAAAAACICAs62niIzP4NVbF0e+6daAzRr89Us+9OfxdJN7QNO99n0GOJz/kJUAACAAQAAgAAAAIAAAAAAAAAAAAA="; |
| 230 | + |
| 231 | +#[test] |
| 232 | +fn test_sign_psbt_with_xpriv() { |
| 233 | + let mut psbt = Psbt::from_str(WPKH_PSBT_WITH_DERIVATION).unwrap(); |
| 234 | + let (desc, change_desc) = get_test_wpkh_and_change_desc(); |
| 235 | + let (wallet, _) = get_funded_wallet(desc, change_desc); |
| 236 | + |
| 237 | + let xpriv = Xpriv::from_str( |
| 238 | + "tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L", |
| 239 | + ) |
| 240 | + .unwrap(); |
| 241 | + |
| 242 | + let signing_keys = wallet |
| 243 | + .sign_psbt(&mut psbt, &xpriv) |
| 244 | + .expect("sign_psbt should succeed with the correct xpriv"); |
| 245 | + |
| 246 | + assert!( |
| 247 | + !signing_keys.is_empty(), |
| 248 | + "expected at least one input to be signed" |
| 249 | + ); |
| 250 | +} |
| 251 | + |
| 252 | +#[test] |
| 253 | +fn test_sign_psbt_with_wrong_key_signs_nothing() { |
| 254 | + let mut psbt = Psbt::from_str(WPKH_PSBT_WITH_DERIVATION).unwrap(); |
| 255 | + let (desc, change_desc) = get_test_wpkh_and_change_desc(); |
| 256 | + let (wallet, _) = get_funded_wallet(desc, change_desc); |
| 257 | + |
| 258 | + let wrong_xpriv = Xpriv::from_str( |
| 259 | + "tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS", |
| 260 | + ) |
| 261 | + .unwrap(); |
| 262 | + |
| 263 | + let signing_keys = wallet |
| 264 | + .sign_psbt(&mut psbt, &wrong_xpriv) |
| 265 | + .expect("sign_psbt returns Ok even when no keys matched"); |
| 266 | + |
| 267 | + let keys_used: usize = signing_keys |
| 268 | + .values() |
| 269 | + .map(|keys| match keys { |
| 270 | + SigningKeys::Ecdsa(v) => v.len(), |
| 271 | + SigningKeys::Schnorr(v) => v.len(), |
| 272 | + }) |
| 273 | + .sum(); |
| 274 | + assert_eq!( |
| 275 | + keys_used, 0, |
| 276 | + "expected zero keys used when signing with an unrelated xpriv" |
| 277 | + ); |
| 278 | + for input in &psbt.inputs { |
| 279 | + assert!( |
| 280 | + input.partial_sigs.is_empty(), |
| 281 | + "expected no partial signatures when signing with an unrelated key" |
| 282 | + ); |
| 283 | + } |
| 284 | +} |
0 commit comments