|
88 | 88 | value: 0, |
89 | 89 | script_pubkey: Builder::new().push_opcode(opcodes::OP_TRUE).into_script(), |
90 | 90 | }), |
91 | | - final_script_sig: Some(Script::default()), // "finalize" the input with an empty scriptSig |
| 91 | + final_script_sig: Some(Script::default()), /* "finalize" the input with an empty scriptSig */ |
92 | 92 | ..Default::default() |
93 | 93 | }; |
94 | 94 |
|
@@ -174,9 +174,13 @@ pub fn verify_proof( |
174 | 174 | } |
175 | 175 |
|
176 | 176 | // Verify the SIGHASH |
177 | | - if let Some((i, _psbt_in)) = psbt.inputs.iter().enumerate().find(|(_i, psbt_in)| { |
178 | | - psbt_in.sighash_type.is_some() && psbt_in.sighash_type != Some(SigHashType::All) |
179 | | - }) { |
| 177 | + if let Some((i, _inp)) = tx |
| 178 | + .input |
| 179 | + .iter() |
| 180 | + .enumerate() |
| 181 | + .skip(1) |
| 182 | + .find(|(_i, inp)| !verify_sighash_type_all(inp)) |
| 183 | + { |
180 | 184 | return Err(Error::Proof(ProofError::UnsupportedSighashType(i))); |
181 | 185 | } |
182 | 186 |
|
@@ -276,6 +280,39 @@ fn challenge_txin(message: &str) -> TxIn { |
276 | 280 | } |
277 | 281 | } |
278 | 282 |
|
| 283 | +/// Verify the SIGHASH type for a TxIn |
| 284 | +fn verify_sighash_type_all(inp: &TxIn) -> bool { |
| 285 | + if inp.witness.is_empty() { |
| 286 | + if let Some(sht) = inp.script_sig.as_bytes().last() { |
| 287 | + #[allow(clippy::if_same_then_else)] |
| 288 | + #[allow(clippy::needless_bool)] |
| 289 | + if SigHashType::from_u32(*sht as u32) == SigHashType::All { |
| 290 | + true |
| 291 | + } else if *sht == 174 { |
| 292 | + // ToDo: What is the meaning of this? |
| 293 | + true |
| 294 | + } else { |
| 295 | + false |
| 296 | + } |
| 297 | + } else { |
| 298 | + false |
| 299 | + } |
| 300 | + } else { |
| 301 | + for wit in &inp.witness[..inp.witness.len() - 1] { |
| 302 | + // ToDo: Why do we skip the last element? |
| 303 | + if wit.last().is_none() { |
| 304 | + // ToDo: Why are there empty elements? |
| 305 | + continue; |
| 306 | + } |
| 307 | + let sht = SigHashType::from_u32(*wit.last().unwrap() as u32); |
| 308 | + if SigHashType::All != sht { |
| 309 | + return false; |
| 310 | + } |
| 311 | + } |
| 312 | + true |
| 313 | + } |
| 314 | +} |
| 315 | + |
279 | 316 | #[cfg(test)] |
280 | 317 | mod test { |
281 | 318 | use bitcoin::secp256k1::Secp256k1; |
@@ -326,6 +363,44 @@ mod test { |
326 | 363 | let spendable = wallet.verify_proof(&psbt, &message)?; |
327 | 364 | assert_eq!(spendable, balance); |
328 | 365 |
|
| 366 | + // additional temporary checks |
| 367 | + match descriptor { |
| 368 | + "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)" => { |
| 369 | + let tx = psbt.extract_tx(); |
| 370 | + assert_eq!(tx.input.len(), 2); |
| 371 | + let txin = &tx.input[1]; |
| 372 | + assert_eq!(txin.witness.len(), 2); |
| 373 | + assert_eq!(txin.script_sig.len(), 0); |
| 374 | + assert_eq!(txin.witness[0].len(), 71); |
| 375 | + assert_eq!(txin.witness[1].len(), 33); |
| 376 | + assert_eq!(txin.witness[0], vec![48, 68, 2, 32, 38, 53, 34, 73, 249, 21, 56, 117, 41, 128, 169, 39, 62, 213, 31, 44, 155, 35, 92, 72, 115, 7, 109, 71, 51, 146, 206, 98, 39, 232, 190, 209, 2, 32, 79, 16, 232, 251, 225, 31, 117, 45, 146, 104, 183, 113, 208, 209, 6, 209, 219, 58, 137, 157, 116, 6, 242, 34, 255, 179, 182, 18, 6, 148, 142, 127, 1]); |
| 377 | + assert_eq!(txin.witness[1], vec![3, 43, 5, 88, 7, 139, 236, 56, 105, 74, 132, 147, 61, 101, 147, 3, 226, 87, 93, 174, 126, 145, 104, 89, 17, 69, 65, 21, 191, 214, 68, 135, 227]); |
| 378 | + } |
| 379 | + "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))" => { |
| 380 | + let tx = psbt.extract_tx(); |
| 381 | + assert_eq!(tx.input.len(), 2); |
| 382 | + let txin = &tx.input[1]; |
| 383 | + assert_eq!(txin.witness.len(), 2); |
| 384 | + assert_eq!(txin.script_sig.len(), 0); |
| 385 | + assert_eq!(txin.witness[0].len(), 71); |
| 386 | + assert_eq!(txin.witness[1].len(), 37); |
| 387 | + assert_eq!(txin.witness[0], vec![48, 68, 2, 32, 9, 75, 75, 249, 73, 139, 223, 112, 98, 163, 248, 70, 132, 28, 43, 36, 80, 193, 49, 199, 11, 175, 177, 233, 24, 18, 157, 120, 240, 22, 40, 184, 2, 32, 121, 245, 45, 179, 155, 59, 126, 164, 59, 94, 229, 236, 251, 222, 176, 100, 76, 115, 167, 158, 80, 165, 40, 2, 9, 177, 208, 72, 98, 188, 192, 84, 1]); |
| 388 | + assert_eq!(txin.witness[1], vec![33, 3, 43, 5, 88, 7, 139, 236, 56, 105, 74, 132, 147, 61, 101, 147, 3, 226, 87, 93, 174, 126, 145, 104, 89, 17, 69, 65, 21, 191, 214, 68, 135, 227, 173, 86, 178]); |
| 389 | + } |
| 390 | + "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))" => { |
| 391 | + let tx = psbt.extract_tx(); |
| 392 | + assert_eq!(tx.input.len(), 2); |
| 393 | + let txin = &tx.input[1]; |
| 394 | + assert_eq!(txin.witness.len(), 2); |
| 395 | + assert_eq!(txin.script_sig.len(), 0); |
| 396 | + assert_eq!(txin.witness[0].len(), 72); |
| 397 | + assert_eq!(txin.witness[1].len(), 40); |
| 398 | + assert_eq!(txin.witness[0], vec![48, 69, 2, 33, 0, 129, 112, 186, 87, 10, 201, 60, 176, 239, 226, 217, 254, 222, 11, 72, 220, 154, 120, 89, 193, 177, 57, 133, 41, 11, 81, 233, 37, 15, 229, 167, 11, 2, 32, 80, 74, 124, 217, 113, 88, 92, 181, 217, 40, 236, 30, 251, 66, 160, 218, 39, 248, 153, 99, 17, 43, 23, 229, 39, 140, 28, 66, 47, 18, 238, 53, 1]); |
| 399 | + assert_eq!(txin.witness[1], vec![33, 3, 43, 5, 88, 7, 139, 236, 56, 105, 74, 132, 147, 61, 101, 147, 3, 226, 87, 93, 174, 126, 145, 104, 89, 17, 69, 65, 21, 191, 214, 68, 135, 227, 173, 3, 160, 134, 1, 177]); |
| 400 | + } |
| 401 | + _ => panic!("should not happen"), |
| 402 | + } |
| 403 | + |
329 | 404 | Ok(()) |
330 | 405 | } |
331 | 406 |
|
@@ -553,6 +628,124 @@ mod test { |
553 | 628 | ); |
554 | 629 | assert_eq!(finalized, true); |
555 | 630 |
|
| 631 | + // additional temporary checks |
| 632 | + match script_type { |
| 633 | + MultisigType::Wsh => { |
| 634 | + let tx = psbt.clone().extract_tx(); |
| 635 | + assert_eq!(tx.input.len(), 2); |
| 636 | + let txin = &tx.input[1]; |
| 637 | + assert_eq!(txin.witness.len(), 4); |
| 638 | + assert_eq!(txin.script_sig.len(), 0); |
| 639 | + assert_eq!(txin.witness[0].len(), 0); |
| 640 | + assert_eq!(txin.witness[1].len(), 72); |
| 641 | + assert_eq!(txin.witness[2].len(), 72); |
| 642 | + assert_eq!(txin.witness[3].len(), 105); |
| 643 | + assert_eq!( |
| 644 | + txin.witness[1], |
| 645 | + vec![ |
| 646 | + 48, 69, 2, 33, 0, 171, 133, 140, 57, 207, 82, 96, 69, 210, 155, 200, 52, |
| 647 | + 115, 36, 240, 220, 145, 81, 89, 24, 31, 18, 45, 4, 195, 231, 246, 242, 13, |
| 648 | + 23, 2, 100, 2, 32, 21, 23, 134, 76, 123, 229, 9, 211, 37, 181, 73, 20, 193, |
| 649 | + 74, 93, 137, 164, 227, 104, 118, 154, 54, 3, 211, 151, 209, 203, 31, 139, |
| 650 | + 148, 203, 106, 1 |
| 651 | + ] |
| 652 | + ); |
| 653 | + assert_eq!( |
| 654 | + txin.witness[2], |
| 655 | + vec![ |
| 656 | + 48, 69, 2, 33, 0, 130, 9, 233, 255, 114, 175, 169, 62, 234, 225, 138, 107, |
| 657 | + 35, 134, 82, 77, 131, 189, 240, 164, 49, 213, 53, 111, 51, 79, 91, 51, 10, |
| 658 | + 204, 4, 180, 2, 32, 88, 21, 142, 187, 197, 167, 24, 105, 77, 116, 189, 136, |
| 659 | + 5, 18, 202, 145, 19, 139, 75, 180, 185, 46, 129, 129, 201, 225, 123, 5, |
| 660 | + 182, 47, 148, 185, 1 |
| 661 | + ] |
| 662 | + ); |
| 663 | + assert_eq!( |
| 664 | + txin.witness[3], |
| 665 | + vec![ |
| 666 | + 82, 33, 2, 5, 128, 246, 213, 193, 72, 37, 223, 179, 53, 9, 132, 24, 26, |
| 667 | + 213, 12, 163, 129, 213, 184, 112, 60, 166, 28, 248, 235, 104, 189, 63, 95, |
| 668 | + 172, 172, 33, 2, 166, 123, 134, 89, 178, 94, 143, 195, 164, 240, 85, 28, |
| 669 | + 187, 155, 22, 120, 8, 1, 253, 207, 106, 91, 21, 54, 121, 28, 251, 37, 85, |
| 670 | + 221, 56, 231, 33, 3, 121, 25, 56, 158, 67, 99, 99, 210, 140, 34, 214, 49, |
| 671 | + 87, 84, 248, 9, 19, 4, 237, 255, 35, 98, 175, 72, 67, 232, 58, 170, 234, |
| 672 | + 28, 195, 131, 83, 174 |
| 673 | + ] |
| 674 | + ); |
| 675 | + } |
| 676 | + MultisigType::ShWsh => { |
| 677 | + let tx = psbt.clone().extract_tx(); |
| 678 | + assert_eq!(tx.input.len(), 2); |
| 679 | + let txin = &tx.input[1]; |
| 680 | + assert_eq!(txin.witness.len(), 4); |
| 681 | + assert_eq!(txin.script_sig.len(), 35); |
| 682 | + assert_eq!(txin.witness[0].len(), 0); |
| 683 | + assert_eq!(txin.witness[1].len(), 71); |
| 684 | + assert_eq!(txin.witness[2].len(), 71); |
| 685 | + assert_eq!(txin.witness[3].len(), 105); |
| 686 | + assert_eq!( |
| 687 | + txin.witness[1], |
| 688 | + vec![ |
| 689 | + 48, 68, 2, 32, 115, 178, 228, 102, 102, 178, 180, 26, 84, 63, 216, 60, 247, |
| 690 | + 251, 114, 236, 96, 119, 54, 228, 5, 236, 26, 199, 189, 105, 70, 241, 208, |
| 691 | + 133, 153, 189, 2, 32, 126, 101, 10, 179, 132, 249, 156, 159, 169, 194, 53, |
| 692 | + 34, 52, 85, 97, 29, 23, 35, 238, 18, 170, 130, 10, 184, 157, 104, 55, 115, |
| 693 | + 133, 14, 92, 78, 1 |
| 694 | + ] |
| 695 | + ); |
| 696 | + assert_eq!( |
| 697 | + txin.witness[2], |
| 698 | + vec![ |
| 699 | + 48, 68, 2, 32, 38, 84, 239, 143, 248, 86, 171, 110, 32, 124, 133, 252, 183, |
| 700 | + 143, 158, 75, 133, 10, 59, 129, 250, 60, 17, 10, 179, 192, 19, 145, 3, 62, |
| 701 | + 203, 197, 2, 32, 110, 198, 250, 19, 50, 37, 208, 57, 57, 133, 82, 211, 64, |
| 702 | + 120, 250, 33, 123, 248, 68, 16, 251, 113, 162, 119, 194, 241, 242, 130, |
| 703 | + 195, 38, 40, 239, 1 |
| 704 | + ] |
| 705 | + ); |
| 706 | + assert_eq!( |
| 707 | + txin.witness[3], |
| 708 | + vec![ |
| 709 | + 82, 33, 2, 5, 128, 246, 213, 193, 72, 37, 223, 179, 53, 9, 132, 24, 26, |
| 710 | + 213, 12, 163, 129, 213, 184, 112, 60, 166, 28, 248, 235, 104, 189, 63, 95, |
| 711 | + 172, 172, 33, 2, 166, 123, 134, 89, 178, 94, 143, 195, 164, 240, 85, 28, |
| 712 | + 187, 155, 22, 120, 8, 1, 253, 207, 106, 91, 21, 54, 121, 28, 251, 37, 85, |
| 713 | + 221, 56, 231, 33, 3, 121, 25, 56, 158, 67, 99, 99, 210, 140, 34, 214, 49, |
| 714 | + 87, 84, 248, 9, 19, 4, 237, 255, 35, 98, 175, 72, 67, 232, 58, 170, 234, |
| 715 | + 28, 195, 131, 83, 174 |
| 716 | + ] |
| 717 | + ); |
| 718 | + } |
| 719 | + MultisigType::P2sh => { |
| 720 | + let tx = psbt.clone().extract_tx(); |
| 721 | + assert_eq!(tx.input.len(), 4); |
| 722 | + let txin = &tx.input[1]; |
| 723 | + assert_eq!(txin.witness.len(), 0); |
| 724 | + assert_eq!(txin.script_sig.len(), 252); |
| 725 | + assert_eq!( |
| 726 | + txin.script_sig.as_bytes(), |
| 727 | + vec![ |
| 728 | + 0, 71, 48, 68, 2, 32, 97, 26, 132, 211, 161, 8, 118, 150, 201, 249, 97, |
| 729 | + 205, 144, 34, 67, 71, 47, 204, 225, 151, 249, 68, 212, 32, 213, 118, 61, |
| 730 | + 60, 180, 235, 82, 108, 2, 32, 119, 242, 247, 13, 18, 164, 36, 200, 144, |
| 731 | + 166, 165, 153, 39, 201, 151, 237, 14, 96, 49, 183, 146, 236, 151, 245, 9, |
| 732 | + 13, 171, 109, 16, 59, 37, 114, 1, 71, 48, 68, 2, 32, 30, 111, 238, 231, |
| 733 | + 141, 160, 199, 182, 158, 23, 100, 176, 99, 113, 23, 121, 27, 61, 84, 125, |
| 734 | + 221, 181, 101, 131, 155, 2, 110, 74, 236, 146, 23, 43, 2, 32, 72, 225, 67, |
| 735 | + 21, 114, 13, 125, 224, 52, 50, 93, 27, 134, 201, 102, 116, 133, 67, 100, |
| 736 | + 101, 137, 4, 137, 117, 124, 167, 101, 134, 198, 29, 138, 63, 1, 76, 105, |
| 737 | + 82, 33, 2, 5, 128, 246, 213, 193, 72, 37, 223, 179, 53, 9, 132, 24, 26, |
| 738 | + 213, 12, 163, 129, 213, 184, 112, 60, 166, 28, 248, 235, 104, 189, 63, 95, |
| 739 | + 172, 172, 33, 2, 166, 123, 134, 89, 178, 94, 143, 195, 164, 240, 85, 28, |
| 740 | + 187, 155, 22, 120, 8, 1, 253, 207, 106, 91, 21, 54, 121, 28, 251, 37, 85, |
| 741 | + 221, 56, 231, 33, 3, 121, 25, 56, 158, 67, 99, 99, 210, 140, 34, 214, 49, |
| 742 | + 87, 84, 248, 9, 19, 4, 237, 255, 35, 98, 175, 72, 67, 232, 58, 170, 234, |
| 743 | + 28, 195, 131, 83, 174 |
| 744 | + ] |
| 745 | + ); |
| 746 | + } |
| 747 | + } |
| 748 | + |
556 | 749 | let spendable = wallet1.verify_proof(&psbt, &message)?; |
557 | 750 | assert_eq!(spendable, balance); |
558 | 751 |
|
|
0 commit comments