1use crate::encoding;
16use crate::error::SignerError;
17use sha2::{Digest, Sha256};
18
19pub const MAX_MULTISIG_KEYS: usize = 15;
25
26pub const MAX_REDEEM_SCRIPT_SIZE: usize = 520;
28
29pub fn multisig_redeem_script(
46 threshold: usize,
47 pubkeys: &[[u8; 33]],
48) -> Result<Vec<u8>, SignerError> {
49 let n = pubkeys.len();
50
51 if n == 0 {
52 return Err(SignerError::ParseError("no public keys provided".into()));
53 }
54 if n > MAX_MULTISIG_KEYS {
55 return Err(SignerError::ParseError(format!(
56 "too many public keys: {n} (max {MAX_MULTISIG_KEYS})"
57 )));
58 }
59 if threshold == 0 {
60 return Err(SignerError::ParseError("threshold must be >= 1".into()));
61 }
62 if threshold > n {
63 return Err(SignerError::ParseError(format!(
64 "threshold {threshold} exceeds key count {n}"
65 )));
66 }
67
68 let op_m = 0x50 + threshold as u8;
70 let op_n = 0x50 + n as u8;
71
72 let mut script = Vec::with_capacity(3 + n * 34);
74 script.push(op_m);
75
76 for pk in pubkeys {
77 script.push(33); script.extend_from_slice(pk);
79 }
80
81 script.push(op_n);
82 script.push(0xAE); if script.len() > MAX_REDEEM_SCRIPT_SIZE {
85 return Err(SignerError::ParseError(format!(
86 "redeem script too large: {} bytes (max {MAX_REDEEM_SCRIPT_SIZE})",
87 script.len()
88 )));
89 }
90
91 Ok(script)
92}
93
94pub fn script_hash160(script: &[u8]) -> [u8; 20] {
102 super::hash160(script)
103}
104
105pub fn witness_script_hash(script: &[u8]) -> [u8; 32] {
109 let mut hasher = Sha256::new();
110 hasher.update(script);
111 let result = hasher.finalize();
112 let mut out = [0u8; 32];
113 out.copy_from_slice(&result);
114 out
115}
116
117#[must_use]
125pub fn p2sh_script_pubkey(script_hash: &[u8; 20]) -> Vec<u8> {
126 let mut spk = Vec::with_capacity(23);
127 spk.push(0xA9); spk.push(0x14); spk.extend_from_slice(script_hash);
130 spk.push(0x87); spk
132}
133
134#[must_use]
138pub fn p2wsh_script_pubkey(script_hash: &[u8; 32]) -> Vec<u8> {
139 let mut spk = Vec::with_capacity(34);
140 spk.push(0x00); spk.push(0x20); spk.extend_from_slice(script_hash);
143 spk
144}
145
146#[must_use]
153pub fn p2sh_p2wsh_script_pubkey(witness_script_hash: &[u8; 32]) -> Vec<u8> {
154 let inner = p2wsh_script_pubkey(witness_script_hash);
156 let hash = script_hash160(&inner);
157 p2sh_script_pubkey(&hash)
158}
159
160#[must_use]
169pub fn p2sh_address(redeem_script: &[u8], testnet: bool) -> String {
170 let hash = script_hash160(redeem_script);
171 let version = if testnet { 0xC4 } else { 0x05 };
172 encoding::base58check_encode(version, &hash)
173}
174
175pub fn p2wsh_address(witness_script: &[u8], testnet: bool) -> Result<String, SignerError> {
182 let hash = witness_script_hash(witness_script);
183 let hrp = if testnet { "tb" } else { "bc" };
184 encoding::bech32_encode(hrp, 0, &hash)
185}
186
187#[must_use]
195pub fn p2sh_p2wsh_address(witness_script: &[u8], testnet: bool) -> String {
196 let wsh = witness_script_hash(witness_script);
197 let inner = p2wsh_script_pubkey(&wsh);
198 p2sh_address(&inner, testnet)
199}
200
201#[must_use]
215pub fn multisig_witness(signatures: &[Vec<u8>], witness_script: &[u8]) -> Vec<Vec<u8>> {
216 let mut witness = Vec::with_capacity(2 + signatures.len());
217 witness.push(vec![]); for sig in signatures {
219 witness.push(sig.clone());
220 }
221 witness.push(witness_script.to_vec());
222 witness
223}
224
225#[must_use]
231pub fn multisig_script_sig(signatures: &[Vec<u8>], redeem_script: &[u8]) -> Vec<u8> {
232 let mut script_sig = Vec::new();
233 script_sig.push(0x00); for sig in signatures {
236 push_data_script(&mut script_sig, sig);
237 }
238 push_data_script(&mut script_sig, redeem_script);
239
240 script_sig
241}
242
243#[must_use]
249pub fn p2sh_p2wsh_script_sig(witness_script_hash: &[u8; 32]) -> Vec<u8> {
250 let inner = p2wsh_script_pubkey(witness_script_hash);
251 let mut script_sig = Vec::with_capacity(1 + inner.len());
252 push_data_script(&mut script_sig, &inner);
253 script_sig
254}
255
256fn push_data_script(script: &mut Vec<u8>, data: &[u8]) {
262 let len = data.len();
263 if len <= 75 {
264 script.push(len as u8);
265 } else if len <= 255 {
266 script.push(0x4C); script.push(len as u8);
268 } else if len <= 65535 {
269 script.push(0x4D); script.extend_from_slice(&(len as u16).to_le_bytes());
271 }
272 script.extend_from_slice(data);
273}
274
275#[must_use]
279pub fn is_p2sh(script: &[u8]) -> bool {
280 script.len() == 23 && script[0] == 0xA9 && script[1] == 0x14 && script[22] == 0x87
281}
282
283#[must_use]
287pub fn is_p2wsh(script: &[u8]) -> bool {
288 script.len() == 34 && script[0] == 0x00 && script[1] == 0x20
289}
290
291pub fn decode_multisig_script(script: &[u8]) -> Option<(usize, usize)> {
296 if script.len() < 3 {
298 return None;
299 }
300
301 let last = script[script.len() - 1];
302 if last != 0xAE {
303 return None;
305 }
306
307 let op_m = script[0];
308 let op_n = script[script.len() - 2];
309
310 if !(0x51..=0x60).contains(&op_m) || !(0x51..=0x60).contains(&op_n) {
312 return None;
313 }
314
315 let m = (op_m - 0x50) as usize;
316 let n = (op_n - 0x50) as usize;
317
318 if m > n || n > MAX_MULTISIG_KEYS {
319 return None;
320 }
321
322 let expected_len = 3 + n * 34;
324 if script.len() != expected_len {
325 return None;
326 }
327
328 let mut pos = 1;
330 for _ in 0..n {
331 if pos >= script.len() || script[pos] != 33 {
332 return None;
333 }
334 pos += 34; }
336
337 Some((m, n))
338}
339
340pub fn extract_pubkeys(script: &[u8]) -> Option<Vec<[u8; 33]>> {
344 let (_, n) = decode_multisig_script(script)?;
345
346 let mut keys = Vec::with_capacity(n);
347 let mut pos = 1; for _ in 0..n {
349 if script[pos] != 33 {
350 return None;
351 }
352 let mut key = [0u8; 33];
353 key.copy_from_slice(&script[pos + 1..pos + 34]);
354 keys.push(key);
355 pos += 34;
356 }
357
358 Some(keys)
359}
360
361#[cfg(test)]
366#[allow(clippy::unwrap_used, clippy::expect_used)]
367mod tests {
368 use super::*;
369
370 fn dummy_keys(n: usize) -> Vec<[u8; 33]> {
371 (0..n)
372 .map(|i| {
373 let mut key = [0x02u8; 33];
374 key[32] = i as u8;
375 key
376 })
377 .collect()
378 }
379
380 fn real_pubkeys() -> Vec<[u8; 33]> {
382 let hex_keys = [
383 "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", ];
387 hex_keys
388 .iter()
389 .map(|h| {
390 let bytes = hex::decode(h).unwrap();
391 let mut key = [0u8; 33];
392 key.copy_from_slice(&bytes);
393 key
394 })
395 .collect()
396 }
397
398 #[test]
401 fn test_multisig_2_of_3() {
402 let keys = dummy_keys(3);
403 let script = multisig_redeem_script(2, &keys).unwrap();
404 assert_eq!(script[0], 0x52); assert_eq!(script[script.len() - 2], 0x53); assert_eq!(script[script.len() - 1], 0xAE); assert_eq!(script.len(), 3 + 3 * 34);
408 }
409
410 #[test]
411 fn test_multisig_1_of_1() {
412 let keys = dummy_keys(1);
413 let script = multisig_redeem_script(1, &keys).unwrap();
414 assert_eq!(script[0], 0x51);
415 assert_eq!(script[script.len() - 2], 0x51);
416 }
417
418 #[test]
419 fn test_multisig_15_of_15() {
420 let keys = dummy_keys(15);
421 let script = multisig_redeem_script(15, &keys).unwrap();
422 assert_eq!(script[0], 0x5F);
423 assert_eq!(script[script.len() - 2], 0x5F);
424 }
425
426 #[test]
427 fn test_multisig_threshold_zero() {
428 let keys = dummy_keys(3);
429 assert!(multisig_redeem_script(0, &keys).is_err());
430 }
431
432 #[test]
433 fn test_multisig_threshold_exceeds_n() {
434 let keys = dummy_keys(2);
435 assert!(multisig_redeem_script(3, &keys).is_err());
436 }
437
438 #[test]
439 fn test_multisig_empty_keys() {
440 assert!(multisig_redeem_script(1, &[]).is_err());
441 }
442
443 #[test]
444 fn test_multisig_too_many_keys() {
445 let keys = dummy_keys(16);
446 assert!(multisig_redeem_script(1, &keys).is_err());
447 }
448
449 #[test]
450 fn test_multisig_contains_all_keys() {
451 let keys = dummy_keys(3);
452 let script = multisig_redeem_script(2, &keys).unwrap();
453 for key in &keys {
454 assert!(script.windows(33).any(|w| w == key));
455 }
456 }
457
458 #[test]
461 fn test_real_pubkey_2_of_3_redeem_script() {
462 let keys = real_pubkeys();
463 let script = multisig_redeem_script(2, &keys).unwrap();
464 assert_eq!(script[0], 0x52); assert_eq!(script[1], 33); assert_eq!(&script[2..35], &keys[0]);
468 assert_eq!(script[35], 33);
469 assert_eq!(&script[36..69], &keys[1]);
470 assert_eq!(script[69], 33);
471 assert_eq!(&script[70..103], &keys[2]);
472 assert_eq!(script[103], 0x53); assert_eq!(script[104], 0xAE); assert_eq!(script.len(), 105);
475 }
476
477 #[test]
478 fn test_real_pubkey_p2sh_address_stable() {
479 let keys = real_pubkeys();
480 let script = multisig_redeem_script(2, &keys).unwrap();
481 let addr = p2sh_address(&script, false);
482 let addr2 = p2sh_address(&script, false);
484 assert_eq!(addr, addr2);
485 assert!(addr.starts_with('3'));
486 assert_eq!(addr.len(), 34);
488 }
489
490 #[test]
491 fn test_real_pubkey_p2wsh_address_length() {
492 let keys = real_pubkeys();
493 let script = multisig_redeem_script(2, &keys).unwrap();
494 let addr = p2wsh_address(&script, false).unwrap();
495 assert!(addr.starts_with("bc1q"));
497 assert_eq!(addr.len(), 62);
498 }
499
500 #[test]
501 fn test_real_pubkey_decode_roundtrip() {
502 let keys = real_pubkeys();
503 let script = multisig_redeem_script(2, &keys).unwrap();
504 let (m, n) = decode_multisig_script(&script).unwrap();
505 assert_eq!(m, 2);
506 assert_eq!(n, 3);
507 let extracted = extract_pubkeys(&script).unwrap();
508 assert_eq!(extracted, keys);
509 }
510
511 #[test]
514 fn test_all_valid_thresholds_1_to_15() {
515 for n in 1..=15usize {
516 let keys = dummy_keys(n);
517 for m in 1..=n {
518 let script = multisig_redeem_script(m, &keys).unwrap();
519 assert_eq!(script[0], 0x50 + m as u8, "OP_m for {m}-of-{n}");
520 assert_eq!(
521 script[script.len() - 2],
522 0x50 + n as u8,
523 "OP_n for {m}-of-{n}"
524 );
525 assert_eq!(script[script.len() - 1], 0xAE, "OP_CMS for {m}-of-{n}");
526 assert_eq!(script.len(), 3 + n * 34, "length for {m}-of-{n}");
527
528 let (dm, dn) = decode_multisig_script(&script).unwrap();
530 assert_eq!(dm, m, "decoded m for {m}-of-{n}");
531 assert_eq!(dn, n, "decoded n for {m}-of-{n}");
532
533 let extracted = extract_pubkeys(&script).unwrap();
535 assert_eq!(extracted.len(), n);
536 assert_eq!(extracted, keys, "keys roundtrip for {m}-of-{n}");
537 }
538 }
539 }
540
541 #[test]
544 fn test_witness_script_hash_known_vector() {
545 let hash = witness_script_hash(b"");
547 assert_eq!(
548 hex::encode(hash),
549 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
550 );
551 }
552
553 #[test]
554 fn test_witness_script_hash_abc() {
555 let hash = witness_script_hash(b"abc");
557 assert_eq!(
558 hex::encode(hash),
559 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
560 );
561 }
562
563 #[test]
566 fn test_script_hash160_deterministic() {
567 let data = b"test script";
568 assert_eq!(script_hash160(data), script_hash160(data));
569 }
570
571 #[test]
572 fn test_witness_script_hash_deterministic() {
573 let data = b"test witness script";
574 assert_eq!(witness_script_hash(data), witness_script_hash(data));
575 }
576
577 #[test]
578 fn test_witness_script_hash_differs_from_hash160() {
579 let data = b"test";
580 let h160 = script_hash160(data);
581 let wsh = witness_script_hash(data);
582 assert_ne!(&h160[..], &wsh[..20]);
583 }
584
585 #[test]
586 fn test_hash160_empty_input() {
587 let h = script_hash160(b"");
589 assert_eq!(h.len(), 20);
590 let expected = "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb";
592 assert_eq!(hex::encode(h), expected);
593 }
594
595 #[test]
598 fn test_p2sh_script_pubkey_structure() {
599 let hash = [0xAA; 20];
600 let spk = p2sh_script_pubkey(&hash);
601 assert_eq!(spk.len(), 23);
602 assert_eq!(spk[0], 0xA9);
603 assert_eq!(spk[1], 0x14);
604 assert_eq!(&spk[2..22], &hash);
605 assert_eq!(spk[22], 0x87);
606 }
607
608 #[test]
609 fn test_p2wsh_script_pubkey_structure() {
610 let hash = [0xBB; 32];
611 let spk = p2wsh_script_pubkey(&hash);
612 assert_eq!(spk.len(), 34);
613 assert_eq!(spk[0], 0x00);
614 assert_eq!(spk[1], 0x20);
615 assert_eq!(&spk[2..34], &hash);
616 }
617
618 #[test]
619 fn test_p2sh_p2wsh_script_pubkey_is_p2sh() {
620 let wsh = [0xCC; 32];
621 let spk = p2sh_p2wsh_script_pubkey(&wsh);
622 assert!(is_p2sh(&spk));
623 }
624
625 #[test]
626 fn test_p2sh_script_pubkey_hex_encoding() {
627 let hash = [0u8; 20];
629 let spk = p2sh_script_pubkey(&hash);
630 let expected = "a914000000000000000000000000000000000000000087";
631 assert_eq!(hex::encode(&spk), expected);
632 }
633
634 #[test]
635 fn test_p2wsh_script_pubkey_hex_encoding() {
636 let hash = [0u8; 32];
638 let spk = p2wsh_script_pubkey(&hash);
639 let expected = "00200000000000000000000000000000000000000000000000000000000000000000";
640 assert_eq!(hex::encode(&spk), expected);
641 }
642
643 #[test]
646 fn test_p2sh_address_mainnet_starts_with_3() {
647 let keys = dummy_keys(2);
648 let script = multisig_redeem_script(2, &keys).unwrap();
649 let addr = p2sh_address(&script, false);
650 assert!(addr.starts_with('3'));
651 }
652
653 #[test]
654 fn test_p2sh_address_testnet_starts_with_2() {
655 let keys = dummy_keys(2);
656 let script = multisig_redeem_script(2, &keys).unwrap();
657 let addr = p2sh_address(&script, true);
658 assert!(addr.starts_with('2'));
659 }
660
661 #[test]
662 fn test_p2wsh_address_mainnet_starts_with_bc1() {
663 let keys = dummy_keys(2);
664 let script = multisig_redeem_script(2, &keys).unwrap();
665 let addr = p2wsh_address(&script, false).unwrap();
666 assert!(addr.starts_with("bc1"));
667 }
668
669 #[test]
670 fn test_p2wsh_address_testnet_starts_with_tb1() {
671 let keys = dummy_keys(2);
672 let script = multisig_redeem_script(2, &keys).unwrap();
673 let addr = p2wsh_address(&script, true).unwrap();
674 assert!(addr.starts_with("tb1"));
675 }
676
677 #[test]
678 fn test_p2sh_p2wsh_address_mainnet() {
679 let keys = dummy_keys(3);
680 let script = multisig_redeem_script(2, &keys).unwrap();
681 let addr = p2sh_p2wsh_address(&script, false);
682 assert!(addr.starts_with('3'));
683 }
684
685 #[test]
686 fn test_p2sh_p2wsh_address_testnet() {
687 let keys = dummy_keys(3);
688 let script = multisig_redeem_script(2, &keys).unwrap();
689 let addr = p2sh_p2wsh_address(&script, true);
690 assert!(addr.starts_with('2'));
691 }
692
693 #[test]
694 fn test_different_wrapping_produces_different_addresses() {
695 let keys = dummy_keys(2);
696 let script = multisig_redeem_script(2, &keys).unwrap();
697 let a1 = p2sh_address(&script, false);
698 let a2 = p2wsh_address(&script, false).unwrap();
699 let a3 = p2sh_p2wsh_address(&script, false);
700 assert_ne!(a1, a2);
701 assert_ne!(a1, a3);
702 assert_ne!(a2, a3);
703 }
704
705 #[test]
706 fn test_mainnet_vs_testnet_addresses_differ() {
707 let keys = dummy_keys(2);
708 let script = multisig_redeem_script(2, &keys).unwrap();
709 assert_ne!(p2sh_address(&script, false), p2sh_address(&script, true));
710 assert_ne!(
711 p2wsh_address(&script, false).unwrap(),
712 p2wsh_address(&script, true).unwrap()
713 );
714 assert_ne!(
715 p2sh_p2wsh_address(&script, false),
716 p2sh_p2wsh_address(&script, true),
717 );
718 }
719
720 #[test]
723 fn test_multisig_witness_structure() {
724 let sigs = vec![vec![0x30; 71], vec![0x30; 72]];
725 let script = vec![0xAE; 10];
726 let witness = multisig_witness(&sigs, &script);
727 assert_eq!(witness.len(), 4);
728 assert!(witness[0].is_empty());
729 assert_eq!(witness[1], sigs[0]);
730 assert_eq!(witness[2], sigs[1]);
731 assert_eq!(witness[3], script);
732 }
733
734 #[test]
735 fn test_multisig_witness_single_sig() {
736 let sigs = vec![vec![0x30; 72]];
737 let script = vec![0xAE];
738 let witness = multisig_witness(&sigs, &script);
739 assert_eq!(witness.len(), 3); }
741
742 #[test]
743 fn test_multisig_witness_empty_sigs() {
744 let witness = multisig_witness(&[], &[0xAE]);
745 assert_eq!(witness.len(), 2); assert!(witness[0].is_empty());
747 assert_eq!(witness[1], vec![0xAE]);
748 }
749
750 #[test]
751 fn test_multisig_script_sig_structure() {
752 let sigs = vec![vec![0x30, 0x44], vec![0x30, 0x45]];
753 let redeem = vec![0xAE; 10];
754 let script_sig = multisig_script_sig(&sigs, &redeem);
755 assert_eq!(script_sig[0], 0x00);
756 assert!(script_sig.len() > 3 + sigs[0].len() + sigs[1].len() + redeem.len());
757 }
758
759 #[test]
760 fn test_multisig_script_sig_with_real_script() {
761 let keys = dummy_keys(3);
762 let redeem = multisig_redeem_script(2, &keys).unwrap();
763 let sig1 = vec![0x30; 72];
765 let sig2 = vec![0x30; 71];
766 let ss = multisig_script_sig(&[sig1.clone(), sig2.clone()], &redeem);
767
768 assert_eq!(ss[0], 0x00);
770 assert_eq!(ss[1], 72);
772 assert_eq!(&ss[2..74], &sig1[..]);
773 assert_eq!(ss[74], 71);
775 assert_eq!(&ss[75..146], &sig2[..]);
776 assert_eq!(ss[146], 0x4C);
778 assert_eq!(ss[147], 105);
779 }
780
781 #[test]
782 fn test_p2sh_p2wsh_script_sig_structure() {
783 let wsh = [0xCC; 32];
784 let script_sig = p2sh_p2wsh_script_sig(&wsh);
785 assert_eq!(script_sig[0], 34);
786 assert_eq!(script_sig[1], 0x00);
787 assert_eq!(script_sig[2], 0x20);
788 assert_eq!(script_sig.len(), 35);
789 assert_eq!(&script_sig[3..35], &wsh);
791 }
792
793 #[test]
796 fn test_is_p2sh() {
797 let hash = [0xAA; 20];
798 let spk = p2sh_script_pubkey(&hash);
799 assert!(is_p2sh(&spk));
800 assert!(!is_p2sh(&[0u8; 34]));
801 assert!(!is_p2sh(&[]));
802 }
803
804 #[test]
805 fn test_is_p2sh_wrong_length() {
806 assert!(!is_p2sh(&[0xA9, 0x14, 0x00])); let mut too_long = vec![0xA9, 0x14];
808 too_long.extend_from_slice(&[0; 20]);
809 too_long.push(0x87);
810 too_long.push(0xFF); assert!(!is_p2sh(&too_long));
812 }
813
814 #[test]
815 fn test_is_p2sh_wrong_opcodes() {
816 let mut bad = vec![0x00, 0x14]; bad.extend_from_slice(&[0; 20]);
818 bad.push(0x87);
819 assert!(!is_p2sh(&bad));
820 }
821
822 #[test]
823 fn test_is_p2wsh() {
824 let hash = [0xBB; 32];
825 let spk = p2wsh_script_pubkey(&hash);
826 assert!(is_p2wsh(&spk));
827 assert!(!is_p2wsh(&[0u8; 23]));
828 assert!(!is_p2wsh(&[]));
829 }
830
831 #[test]
832 fn test_is_p2wsh_wrong_version() {
833 let mut bad = vec![0x01, 0x20]; bad.extend_from_slice(&[0; 32]);
835 assert!(!is_p2wsh(&bad));
836 }
837
838 #[test]
841 fn test_decode_multisig_2_of_3() {
842 let keys = dummy_keys(3);
843 let script = multisig_redeem_script(2, &keys).unwrap();
844 let (m, n) = decode_multisig_script(&script).unwrap();
845 assert_eq!(m, 2);
846 assert_eq!(n, 3);
847 }
848
849 #[test]
850 fn test_decode_multisig_1_of_1() {
851 let keys = dummy_keys(1);
852 let script = multisig_redeem_script(1, &keys).unwrap();
853 let (m, n) = decode_multisig_script(&script).unwrap();
854 assert_eq!(m, 1);
855 assert_eq!(n, 1);
856 }
857
858 #[test]
859 fn test_decode_multisig_invalid() {
860 assert!(decode_multisig_script(&[]).is_none());
861 assert!(decode_multisig_script(&[0x00, 0x00]).is_none());
862 assert!(decode_multisig_script(&[0x52, 0x53, 0xAB]).is_none());
863 }
864
865 #[test]
866 fn test_decode_multisig_corrupted_push_byte() {
867 let keys = dummy_keys(2);
868 let mut script = multisig_redeem_script(2, &keys).unwrap();
869 script[1] = 32; assert!(decode_multisig_script(&script).is_none());
872 }
873
874 #[test]
875 fn test_decode_multisig_wrong_length() {
876 let mut script = vec![0x52]; script.push(33);
879 script.extend_from_slice(&[0x02; 33]);
880 script.push(0x53);
882 script.push(0xAE);
883 assert!(decode_multisig_script(&script).is_none());
884 }
885
886 #[test]
887 fn test_decode_m_greater_than_n() {
888 let mut script = vec![0x53]; script.push(33);
892 script.extend_from_slice(&[0x02; 33]);
893 script.push(0x52); script.push(0xAE);
895 assert!(decode_multisig_script(&script).is_none());
896 }
897
898 #[test]
901 fn test_extract_pubkeys() {
902 let keys = dummy_keys(3);
903 let script = multisig_redeem_script(2, &keys).unwrap();
904 let extracted = extract_pubkeys(&script).unwrap();
905 assert_eq!(extracted.len(), 3);
906 assert_eq!(extracted, keys);
907 }
908
909 #[test]
910 fn test_extract_pubkeys_invalid() {
911 assert!(extract_pubkeys(&[]).is_none());
912 }
913
914 #[test]
915 fn test_extract_pubkeys_real_keys() {
916 let keys = real_pubkeys();
917 let script = multisig_redeem_script(2, &keys).unwrap();
918 let extracted = extract_pubkeys(&script).unwrap();
919 assert_eq!(extracted[0], keys[0]);
920 assert_eq!(extracted[1], keys[1]);
921 assert_eq!(extracted[2], keys[2]);
922 }
923
924 #[test]
927 fn test_full_p2sh_multisig_flow() {
928 let keys = dummy_keys(3);
929 let script = multisig_redeem_script(2, &keys).unwrap();
930 let addr = p2sh_address(&script, false);
931 assert!(addr.starts_with('3'));
932
933 let sigs = vec![vec![0x30; 71], vec![0x30; 72]];
934 let ss = multisig_script_sig(&sigs, &script);
935 assert!(!ss.is_empty());
936
937 let (m, n) = decode_multisig_script(&script).unwrap();
938 assert_eq!(m, 2);
939 assert_eq!(n, 3);
940 }
941
942 #[test]
943 fn test_full_p2wsh_multisig_flow() {
944 let keys = dummy_keys(3);
945 let ws = multisig_redeem_script(2, &keys).unwrap();
946 let addr = p2wsh_address(&ws, false).unwrap();
947 assert!(addr.starts_with("bc1"));
948
949 let sigs = vec![vec![0x30; 71], vec![0x30; 72]];
950 let witness = multisig_witness(&sigs, &ws);
951 assert_eq!(witness.len(), 4);
952 }
953
954 #[test]
955 fn test_full_p2sh_p2wsh_flow() {
956 let keys = dummy_keys(3);
957 let ws = multisig_redeem_script(2, &keys).unwrap();
958 let wsh = witness_script_hash(&ws);
959 let addr = p2sh_p2wsh_address(&ws, false);
960 assert!(addr.starts_with('3'));
961
962 let ss = p2sh_p2wsh_script_sig(&wsh);
963 assert_eq!(ss.len(), 35);
964
965 let sigs = vec![vec![0x30; 71], vec![0x30; 72]];
966 let witness = multisig_witness(&sigs, &ws);
967 assert_eq!(witness.len(), 4);
968 }
969
970 #[test]
971 fn test_full_flow_real_keys() {
972 let keys = real_pubkeys();
973
974 let script = multisig_redeem_script(2, &keys).unwrap();
976 let p2sh_addr = p2sh_address(&script, false);
977 assert!(p2sh_addr.starts_with('3'));
978
979 let p2wsh_addr = p2wsh_address(&script, false).unwrap();
981 assert!(p2wsh_addr.starts_with("bc1q"));
982
983 let p2sh_p2wsh_addr = p2sh_p2wsh_address(&script, false);
985 assert!(p2sh_p2wsh_addr.starts_with('3'));
986
987 assert_ne!(p2sh_addr, p2sh_p2wsh_addr);
989 assert_ne!(p2sh_addr, p2wsh_addr);
990
991 let wsh = witness_script_hash(&script);
993 let spk_p2sh = p2sh_script_pubkey(&script_hash160(&script));
994 let spk_p2wsh = p2wsh_script_pubkey(&wsh);
995 assert!(is_p2sh(&spk_p2sh));
996 assert!(is_p2wsh(&spk_p2wsh));
997 assert!(!is_p2sh(&spk_p2wsh));
998 assert!(!is_p2wsh(&spk_p2sh));
999 }
1000
1001 #[test]
1004 fn test_push_data_small() {
1005 let mut s = Vec::new();
1006 push_data_script(&mut s, &[0xAA; 10]);
1007 assert_eq!(s[0], 10);
1008 assert_eq!(&s[1..], &[0xAA; 10]);
1009 }
1010
1011 #[test]
1012 fn test_push_data_boundary_75() {
1013 let mut s = Vec::new();
1015 let data = vec![0xBB; 75];
1016 push_data_script(&mut s, &data);
1017 assert_eq!(s[0], 75);
1018 assert_eq!(s.len(), 76);
1019 }
1020
1021 #[test]
1022 fn test_push_data_boundary_76() {
1023 let mut s = Vec::new();
1025 let data = vec![0xBB; 76];
1026 push_data_script(&mut s, &data);
1027 assert_eq!(s[0], 0x4C); assert_eq!(s[1], 76);
1029 assert_eq!(s.len(), 78);
1030 }
1031
1032 #[test]
1033 fn test_push_data_medium() {
1034 let mut s = Vec::new();
1035 let data = vec![0xBB; 100];
1036 push_data_script(&mut s, &data);
1037 assert_eq!(s[0], 0x4C);
1038 assert_eq!(s[1], 100);
1039 assert_eq!(&s[2..], &data[..]);
1040 }
1041
1042 #[test]
1043 fn test_push_data_boundary_255() {
1044 let mut s = Vec::new();
1045 let data = vec![0xCC; 255];
1046 push_data_script(&mut s, &data);
1047 assert_eq!(s[0], 0x4C); assert_eq!(s[1], 255);
1049 }
1050
1051 #[test]
1052 fn test_push_data_boundary_256() {
1053 let mut s = Vec::new();
1055 let data = vec![0xCC; 256];
1056 push_data_script(&mut s, &data);
1057 assert_eq!(s[0], 0x4D);
1058 let len = u16::from_le_bytes([s[1], s[2]]);
1059 assert_eq!(len, 256);
1060 assert_eq!(s.len(), 259);
1061 }
1062
1063 #[test]
1064 fn test_push_data_large() {
1065 let mut s = Vec::new();
1066 let data = vec![0xCC; 300];
1067 push_data_script(&mut s, &data);
1068 assert_eq!(s[0], 0x4D);
1069 let len = u16::from_le_bytes([s[1], s[2]]);
1070 assert_eq!(len, 300);
1071 }
1072
1073 #[test]
1074 fn test_push_data_empty() {
1075 let mut s = Vec::new();
1076 push_data_script(&mut s, &[]);
1077 assert_eq!(s, vec![0x00]); }
1079
1080 #[test]
1081 fn test_push_data_single_byte() {
1082 let mut s = Vec::new();
1083 push_data_script(&mut s, &[0xFF]);
1084 assert_eq!(s, vec![0x01, 0xFF]);
1085 }
1086
1087 #[test]
1090 fn test_same_keys_same_address() {
1091 let keys = dummy_keys(3);
1092 let s1 = multisig_redeem_script(2, &keys).unwrap();
1093 let s2 = multisig_redeem_script(2, &keys).unwrap();
1094 assert_eq!(p2sh_address(&s1, false), p2sh_address(&s2, false));
1095 }
1096
1097 #[test]
1098 fn test_different_threshold_different_address() {
1099 let keys = dummy_keys(3);
1100 let s1 = multisig_redeem_script(1, &keys).unwrap();
1101 let s2 = multisig_redeem_script(2, &keys).unwrap();
1102 assert_ne!(p2sh_address(&s1, false), p2sh_address(&s2, false));
1103 }
1104
1105 #[test]
1106 fn test_different_key_order_different_address() {
1107 let keys1 = dummy_keys(3);
1108 let mut keys2 = keys1.clone();
1109 keys2.swap(0, 1);
1110 let s1 = multisig_redeem_script(2, &keys1).unwrap();
1111 let s2 = multisig_redeem_script(2, &keys2).unwrap();
1112 assert_ne!(p2sh_address(&s1, false), p2sh_address(&s2, false));
1113 }
1114
1115 #[test]
1118 fn test_p2sh_p2wsh_is_hash_of_p2wsh() {
1119 let keys = dummy_keys(3);
1120 let script = multisig_redeem_script(2, &keys).unwrap();
1121 let wsh = witness_script_hash(&script);
1122
1123 let p2wsh_spk = p2wsh_script_pubkey(&wsh);
1125 let wrapped_addr = p2sh_address(&p2wsh_spk, false);
1126 let direct_addr = p2sh_p2wsh_address(&script, false);
1127 assert_eq!(wrapped_addr, direct_addr);
1128 }
1129
1130 #[test]
1131 fn test_p2sh_p2wsh_script_pubkey_consistency() {
1132 let keys = dummy_keys(2);
1133 let script = multisig_redeem_script(2, &keys).unwrap();
1134 let wsh = witness_script_hash(&script);
1135
1136 let spk1 = p2sh_p2wsh_script_pubkey(&wsh);
1138 let inner = p2wsh_script_pubkey(&wsh);
1139 let spk2 = p2sh_script_pubkey(&script_hash160(&inner));
1140 assert_eq!(spk1, spk2);
1141 }
1142
1143 #[test]
1146 fn test_redeem_script_size_under_520() {
1147 let keys = dummy_keys(15);
1149 let script = multisig_redeem_script(1, &keys).unwrap();
1150 assert!(script.len() <= MAX_REDEEM_SCRIPT_SIZE);
1151 assert_eq!(script.len(), 513);
1152 }
1153
1154 #[test]
1155 fn test_threshold_equal_to_n() {
1156 let keys = dummy_keys(5);
1158 let script = multisig_redeem_script(5, &keys).unwrap();
1159 let (m, n) = decode_multisig_script(&script).unwrap();
1160 assert_eq!(m, 5);
1161 assert_eq!(n, 5);
1162 }
1163
1164 #[test]
1165 fn test_threshold_1_of_15() {
1166 let keys = dummy_keys(15);
1167 let script = multisig_redeem_script(1, &keys).unwrap();
1168 let (m, n) = decode_multisig_script(&script).unwrap();
1169 assert_eq!(m, 1);
1170 assert_eq!(n, 15);
1171 }
1172
1173 #[test]
1176 fn test_error_message_empty_keys() {
1177 let err = multisig_redeem_script(1, &[]).unwrap_err();
1178 let msg = format!("{err}");
1179 assert!(msg.contains("no public keys"), "got: {msg}");
1180 }
1181
1182 #[test]
1183 fn test_error_message_too_many() {
1184 let keys = dummy_keys(16);
1185 let err = multisig_redeem_script(1, &keys).unwrap_err();
1186 let msg = format!("{err}");
1187 assert!(msg.contains("too many") || msg.contains("16"), "got: {msg}");
1188 }
1189
1190 #[test]
1191 fn test_error_message_threshold_zero() {
1192 let keys = dummy_keys(2);
1193 let err = multisig_redeem_script(0, &keys).unwrap_err();
1194 let msg = format!("{err}");
1195 assert!(
1196 msg.contains("threshold") || msg.contains(">= 1"),
1197 "got: {msg}"
1198 );
1199 }
1200
1201 #[test]
1202 fn test_error_message_threshold_exceeds() {
1203 let keys = dummy_keys(2);
1204 let err = multisig_redeem_script(5, &keys).unwrap_err();
1205 let msg = format!("{err}");
1206 assert!(msg.contains("exceeds") || msg.contains("5"), "got: {msg}");
1207 }
1208}