1use std::{fmt, hash};
16
17use bitcoin;
18use bitcoin::blockdata::constants::MAX_BLOCK_WEIGHT;
19use miniscript::limits::{
20 MAX_OPS_PER_SCRIPT, MAX_PUBKEYS_PER_MULTISIG, MAX_SCRIPTSIG_SIZE, MAX_SCRIPT_ELEMENT_SIZE,
21 MAX_SCRIPT_SIZE, MAX_STACK_SIZE, MAX_STANDARD_P2WSH_SCRIPT_SIZE,
22 MAX_STANDARD_P2WSH_STACK_ITEMS,
23};
24use miniscript::types;
25use util::witness_to_scriptsig;
26use Error;
27
28use super::decode::ParseableKey;
29
30use {Miniscript, MiniscriptKey, Terminal};
31
32#[derive(Clone, PartialEq, Eq, Debug)]
34pub enum ScriptContextError {
35 MalleablePkH,
39 MalleableOrI,
42 MalleableDupIf,
45 CompressedOnly(String),
48 XOnlyKeysNotAllowed(String, &'static str),
51 UncompressedKeysNotAllowed,
54 MaxWitnessItemssExceeded { actual: usize, limit: usize },
57 MaxOpCountExceeded,
60 MaxWitnessScriptSizeExceeded,
63 MaxRedeemScriptSizeExceeded,
66 MaxScriptSigSizeExceeded,
68 ImpossibleSatisfaction,
70 TaprootMultiDisabled,
72 StackSizeLimitExceeded { actual: usize, limit: usize },
74 CheckMultiSigLimitExceeded,
76 MultiANotAllowed,
78}
79
80#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
81pub enum SigType {
82 Ecdsa,
84 Schnorr,
86}
87
88impl fmt::Display for ScriptContextError {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 match *self {
91 ScriptContextError::MalleablePkH => write!(f, "PkH is malleable under Legacy rules"),
92 ScriptContextError::MalleableOrI => write!(f, "OrI is malleable under Legacy rules"),
93 ScriptContextError::MalleableDupIf => {
94 write!(f, "DupIf is malleable under Legacy rules")
95 }
96 ScriptContextError::CompressedOnly(ref pk) => {
97 write!(
98 f,
99 "Only Compressed pubkeys are allowed in segwit context. Found {}",
100 pk
101 )
102 }
103 ScriptContextError::XOnlyKeysNotAllowed(ref pk, ref ctx) => {
104 write!(f, "x-only key {} not allowed in {}", pk, ctx)
105 }
106 ScriptContextError::UncompressedKeysNotAllowed => {
107 write!(
108 f,
109 "uncompressed keys cannot be used in Taproot descriptors."
110 )
111 }
112 ScriptContextError::MaxWitnessItemssExceeded { actual, limit } => write!(
113 f,
114 "At least one spending path in the Miniscript fragment has {} more \
115 witness items than limit {}.",
116 actual, limit
117 ),
118 ScriptContextError::MaxOpCountExceeded => write!(
119 f,
120 "At least one satisfaction path in the Miniscript fragment contains \
121 more than MAX_OPS_PER_SCRIPT opcodes."
122 ),
123 ScriptContextError::MaxWitnessScriptSizeExceeded => write!(
124 f,
125 "The Miniscript corresponding Script would be larger than \
126 MAX_STANDARD_P2WSH_SCRIPT_SIZE bytes."
127 ),
128 ScriptContextError::MaxRedeemScriptSizeExceeded => write!(
129 f,
130 "The Miniscript corresponding Script would be larger than \
131 MAX_SCRIPT_ELEMENT_SIZE bytes."
132 ),
133 ScriptContextError::MaxScriptSigSizeExceeded => write!(
134 f,
135 "At least one satisfaction in Miniscript would be larger than \
136 MAX_SCRIPTSIG_SIZE scriptsig"
137 ),
138 ScriptContextError::ImpossibleSatisfaction => {
139 write!(
140 f,
141 "Impossible to satisfy Miniscript under the current context"
142 )
143 }
144 ScriptContextError::TaprootMultiDisabled => {
145 write!(f, "Invalid use of Multi node in taproot context")
146 }
147 ScriptContextError::StackSizeLimitExceeded { actual, limit } => {
148 write!(
149 f,
150 "Stack limit {} can exceed the allowed limit {} in at least one script path during script execution",
151 actual, limit
152 )
153 }
154 ScriptContextError::CheckMultiSigLimitExceeded => {
155 write!(
156 f,
157 "CHECkMULTISIG ('multi()' descriptor) only supports up to 20 pubkeys"
158 )
159 }
160 ScriptContextError::MultiANotAllowed => {
161 write!(f, "Multi a(CHECKSIGADD) only allowed post tapscript")
162 }
163 }
164 }
165}
166
167pub trait ScriptContext:
172 fmt::Debug + Clone + Ord + PartialOrd + Eq + PartialEq + hash::Hash + private::Sealed
173where
174 Self::Key: MiniscriptKey<Hash = bitcoin::hashes::hash160::Hash>,
175{
176 type Key: ParseableKey;
178 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
187 _frag: &Terminal<Pk, Self>,
188 ) -> Result<(), ScriptContextError>;
189
190 fn check_witness<Pk: MiniscriptKey>(_witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
194 Ok(())
198 }
199
200 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize>;
202 fn check_global_consensus_validity<Pk: MiniscriptKey>(
213 _ms: &Miniscript<Pk, Self>,
214 ) -> Result<(), ScriptContextError> {
215 Ok(())
216 }
217
218 fn check_global_policy_validity<Pk: MiniscriptKey>(
227 _ms: &Miniscript<Pk, Self>,
228 ) -> Result<(), ScriptContextError> {
229 Ok(())
230 }
231
232 fn check_local_consensus_validity<Pk: MiniscriptKey>(
237 _ms: &Miniscript<Pk, Self>,
238 ) -> Result<(), ScriptContextError> {
239 Ok(())
240 }
241
242 fn check_local_policy_validity<Pk: MiniscriptKey>(
248 _ms: &Miniscript<Pk, Self>,
249 ) -> Result<(), ScriptContextError> {
250 Ok(())
251 }
252
253 fn check_global_validity<Pk: MiniscriptKey>(
256 ms: &Miniscript<Pk, Self>,
257 ) -> Result<(), ScriptContextError> {
258 Self::check_global_consensus_validity(ms)?;
259 Self::check_global_policy_validity(ms)?;
260 Ok(())
261 }
262
263 fn check_local_validity<Pk: MiniscriptKey>(
266 ms: &Miniscript<Pk, Self>,
267 ) -> Result<(), ScriptContextError> {
268 Self::check_global_consensus_validity(ms)?;
269 Self::check_global_policy_validity(ms)?;
270 Self::check_local_consensus_validity(ms)?;
271 Self::check_local_policy_validity(ms)?;
272 Ok(())
273 }
274
275 fn top_level_type_check<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
277 if ms.ty.corr.base != types::Base::B {
278 return Err(Error::NonTopLevel(format!("{:?}", ms)));
279 }
280 Ok(())
281 }
282
283 fn other_top_level_checks<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
285 Ok(())
286 }
287
288 fn top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
298 Self::top_level_type_check(ms)?;
299 Self::other_top_level_checks(ms)
300 }
301
302 fn sig_type() -> SigType;
306
307 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize;
312
313 fn name_str() -> &'static str;
315}
316
317#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
322pub enum Legacy {}
323
324impl ScriptContext for Legacy {
325 type Key = bitcoin::PublicKey;
326 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
327 frag: &Terminal<Pk, Self>,
328 ) -> Result<(), ScriptContextError> {
329 match *frag {
330 Terminal::PkH(ref _pkh) => Err(ScriptContextError::MalleablePkH),
331 Terminal::OrI(ref _a, ref _b) => Err(ScriptContextError::MalleableOrI),
332 Terminal::DupIf(ref _ms) => Err(ScriptContextError::MalleableDupIf),
333 _ => Ok(()),
334 }
335 }
336
337 fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
338 if witness_to_scriptsig(witness).len() > MAX_SCRIPTSIG_SIZE {
341 return Err(ScriptContextError::MaxScriptSigSizeExceeded);
342 }
343 Ok(())
344 }
345
346 fn check_global_consensus_validity<Pk: MiniscriptKey>(
347 ms: &Miniscript<Pk, Self>,
348 ) -> Result<(), ScriptContextError> {
349 if ms.ext.pk_cost > MAX_SCRIPT_ELEMENT_SIZE {
350 return Err(ScriptContextError::MaxRedeemScriptSizeExceeded);
351 }
352
353 match ms.node {
354 Terminal::PkK(ref key) if key.is_x_only_key() => {
355 return Err(ScriptContextError::XOnlyKeysNotAllowed(
356 key.to_string(),
357 Self::name_str(),
358 ))
359 }
360 Terminal::Multi(_k, ref pks) => {
361 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
362 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
363 }
364 for pk in pks.iter() {
365 if pk.is_x_only_key() {
366 return Err(ScriptContextError::XOnlyKeysNotAllowed(
367 pk.to_string(),
368 Self::name_str(),
369 ));
370 }
371 }
372 }
373 Terminal::MultiA(..) => {
374 return Err(ScriptContextError::MultiANotAllowed);
375 }
376 _ => {}
377 }
378 Ok(())
379 }
380
381 fn check_local_consensus_validity<Pk: MiniscriptKey>(
382 ms: &Miniscript<Pk, Self>,
383 ) -> Result<(), ScriptContextError> {
384 match ms.ext.ops_count_sat {
385 None => Err(ScriptContextError::MaxOpCountExceeded),
386 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
387 Err(ScriptContextError::MaxOpCountExceeded)
388 }
389 _ => Ok(()),
390 }
391 }
392
393 fn check_local_policy_validity<Pk: MiniscriptKey>(
394 ms: &Miniscript<Pk, Self>,
395 ) -> Result<(), ScriptContextError> {
396 match ms.max_satisfaction_size() {
400 Err(_e) => Err(ScriptContextError::ImpossibleSatisfaction),
401 Ok(size) if size > MAX_SCRIPTSIG_SIZE => {
402 Err(ScriptContextError::MaxScriptSigSizeExceeded)
403 }
404 _ => Ok(()),
405 }
406 }
407
408 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
409 ms.ext.max_sat_size.map(|x| x.1)
411 }
412
413 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize {
414 if pk.is_uncompressed() {
415 66
416 } else {
417 34
418 }
419 }
420
421 fn name_str() -> &'static str {
422 "Legacy/p2sh"
423 }
424
425 fn sig_type() -> SigType {
426 SigType::Ecdsa
427 }
428}
429
430#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
432pub enum Segwitv0 {}
433
434impl ScriptContext for Segwitv0 {
435 type Key = bitcoin::PublicKey;
436 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
437 _frag: &Terminal<Pk, Self>,
438 ) -> Result<(), ScriptContextError> {
439 Ok(())
440 }
441
442 fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
443 if witness.len() > MAX_STANDARD_P2WSH_STACK_ITEMS {
444 return Err(ScriptContextError::MaxWitnessItemssExceeded {
445 actual: witness.len(),
446 limit: MAX_STANDARD_P2WSH_STACK_ITEMS,
447 });
448 }
449 Ok(())
450 }
451
452 fn check_global_consensus_validity<Pk: MiniscriptKey>(
453 ms: &Miniscript<Pk, Self>,
454 ) -> Result<(), ScriptContextError> {
455 if ms.ext.pk_cost > MAX_SCRIPT_SIZE {
456 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
457 }
458
459 match ms.node {
460 Terminal::PkK(ref pk) => {
461 if pk.is_uncompressed() {
462 return Err(ScriptContextError::CompressedOnly(pk.to_string()));
463 } else if pk.is_x_only_key() {
464 return Err(ScriptContextError::XOnlyKeysNotAllowed(
465 pk.to_string(),
466 Self::name_str(),
467 ));
468 }
469 Ok(())
470 }
471 Terminal::Multi(_k, ref pks) => {
472 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
473 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
474 }
475 for pk in pks.iter() {
476 if pk.is_uncompressed() {
477 return Err(ScriptContextError::CompressedOnly(pk.to_string()));
478 } else if pk.is_x_only_key() {
479 return Err(ScriptContextError::XOnlyKeysNotAllowed(
480 pk.to_string(),
481 Self::name_str(),
482 ));
483 }
484 }
485 Ok(())
486 }
487 Terminal::MultiA(..) => {
488 return Err(ScriptContextError::MultiANotAllowed);
489 }
490 _ => Ok(()),
491 }
492 }
493
494 fn check_local_consensus_validity<Pk: MiniscriptKey>(
495 ms: &Miniscript<Pk, Self>,
496 ) -> Result<(), ScriptContextError> {
497 match ms.ext.ops_count_sat {
498 None => Err(ScriptContextError::MaxOpCountExceeded),
499 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
500 Err(ScriptContextError::MaxOpCountExceeded)
501 }
502 _ => Ok(()),
503 }
504 }
505
506 fn check_global_policy_validity<Pk: MiniscriptKey>(
507 ms: &Miniscript<Pk, Self>,
508 ) -> Result<(), ScriptContextError> {
509 if ms.ext.pk_cost > MAX_STANDARD_P2WSH_SCRIPT_SIZE {
510 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
511 }
512 Ok(())
513 }
514
515 fn check_local_policy_validity<Pk: MiniscriptKey>(
516 ms: &Miniscript<Pk, Self>,
517 ) -> Result<(), ScriptContextError> {
518 match ms.max_satisfaction_witness_elements() {
522 Err(_e) => Err(ScriptContextError::ImpossibleSatisfaction),
524 Ok(max_witness_items) if max_witness_items > MAX_STANDARD_P2WSH_STACK_ITEMS => {
525 Err(ScriptContextError::MaxWitnessItemssExceeded {
526 actual: max_witness_items,
527 limit: MAX_STANDARD_P2WSH_STACK_ITEMS,
528 })
529 }
530 _ => Ok(()),
531 }
532 }
533
534 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
535 ms.ext.max_sat_size.map(|x| x.0)
537 }
538
539 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
540 34
541 }
542
543 fn name_str() -> &'static str {
544 "Segwitv0"
545 }
546
547 fn sig_type() -> SigType {
548 SigType::Ecdsa
549 }
550}
551
552#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
554pub enum Tap {}
555
556impl ScriptContext for Tap {
557 type Key = bitcoin::secp256k1::XOnlyPublicKey;
558 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
559 _frag: &Terminal<Pk, Self>,
560 ) -> Result<(), ScriptContextError> {
561 Ok(())
564 }
565
566 fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
567 if witness.len() > MAX_STACK_SIZE {
569 return Err(ScriptContextError::MaxWitnessItemssExceeded {
570 actual: witness.len(),
571 limit: MAX_STACK_SIZE,
572 });
573 }
574 Ok(())
575 }
576
577 fn check_global_consensus_validity<Pk: MiniscriptKey>(
578 ms: &Miniscript<Pk, Self>,
579 ) -> Result<(), ScriptContextError> {
580 if ms.ext.pk_cost > MAX_BLOCK_WEIGHT as usize {
586 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
587 }
588
589 match ms.node {
590 Terminal::PkK(ref pk) => {
591 if pk.is_uncompressed() {
592 return Err(ScriptContextError::UncompressedKeysNotAllowed);
593 }
594 Ok(())
595 }
596 Terminal::Multi(..) => {
597 return Err(ScriptContextError::TaprootMultiDisabled);
598 }
599 _ => Ok(()),
600 }
601 }
602
603 fn check_local_consensus_validity<Pk: MiniscriptKey>(
604 ms: &Miniscript<Pk, Self>,
605 ) -> Result<(), ScriptContextError> {
606 if let (Some(s), Some(h)) = (
616 ms.ext.exec_stack_elem_count_sat,
617 ms.ext.stack_elem_count_sat,
618 ) {
619 if s + h > MAX_STACK_SIZE {
620 return Err(ScriptContextError::StackSizeLimitExceeded {
621 actual: s + h,
622 limit: MAX_STACK_SIZE,
623 });
624 }
625 }
626 Ok(())
627 }
628
629 fn check_global_policy_validity<Pk: MiniscriptKey>(
630 _ms: &Miniscript<Pk, Self>,
631 ) -> Result<(), ScriptContextError> {
632 Ok(())
634 }
635
636 fn check_local_policy_validity<Pk: MiniscriptKey>(
637 _ms: &Miniscript<Pk, Self>,
638 ) -> Result<(), ScriptContextError> {
639 Ok(())
640 }
641
642 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
643 ms.ext.max_sat_size.map(|x| x.0)
645 }
646
647 fn sig_type() -> SigType {
648 SigType::Schnorr
649 }
650
651 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
652 33
653 }
654
655 fn name_str() -> &'static str {
656 "TapscriptCtx"
657 }
658}
659
660#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
665pub enum BareCtx {}
666
667impl ScriptContext for BareCtx {
668 type Key = bitcoin::PublicKey;
669 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
670 _frag: &Terminal<Pk, Self>,
671 ) -> Result<(), ScriptContextError> {
672 Ok(())
677 }
678
679 fn check_global_consensus_validity<Pk: MiniscriptKey>(
680 ms: &Miniscript<Pk, Self>,
681 ) -> Result<(), ScriptContextError> {
682 if ms.ext.pk_cost > MAX_SCRIPT_SIZE {
683 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
684 }
685 match ms.node {
686 Terminal::PkK(ref key) if key.is_x_only_key() => {
687 return Err(ScriptContextError::XOnlyKeysNotAllowed(
688 key.to_string(),
689 Self::name_str(),
690 ))
691 }
692 Terminal::Multi(_k, ref pks) => {
693 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
694 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
695 }
696 for pk in pks.iter() {
697 if pk.is_x_only_key() {
698 return Err(ScriptContextError::XOnlyKeysNotAllowed(
699 pk.to_string(),
700 Self::name_str(),
701 ));
702 }
703 }
704 Ok(())
705 }
706 Terminal::MultiA(..) => return Err(ScriptContextError::MultiANotAllowed),
707 _ => Ok(()),
708 }
709 }
710
711 fn check_local_consensus_validity<Pk: MiniscriptKey>(
712 ms: &Miniscript<Pk, Self>,
713 ) -> Result<(), ScriptContextError> {
714 match ms.ext.ops_count_sat {
715 None => Err(ScriptContextError::MaxOpCountExceeded),
716 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
717 Err(ScriptContextError::MaxOpCountExceeded)
718 }
719 _ => Ok(()),
720 }
721 }
722
723 fn other_top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
724 match &ms.node {
725 Terminal::Check(ref ms) => match &ms.node {
726 Terminal::PkH(_pkh) => Ok(()),
727 Terminal::PkK(_pk) => Ok(()),
728 _ => Err(Error::NonStandardBareScript),
729 },
730 Terminal::Multi(_k, subs) if subs.len() <= 3 => Ok(()),
731 _ => Err(Error::NonStandardBareScript),
732 }
733 }
734
735 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
736 ms.ext.max_sat_size.map(|x| x.1)
738 }
739
740 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize {
741 if pk.is_uncompressed() {
742 65
743 } else {
744 33
745 }
746 }
747
748 fn name_str() -> &'static str {
749 "BareCtx"
750 }
751
752 fn sig_type() -> SigType {
753 SigType::Ecdsa
754 }
755}
756
757#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
763pub enum NoChecks {}
764impl ScriptContext for NoChecks {
765 type Key = bitcoin::PublicKey;
767 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
768 _frag: &Terminal<Pk, Self>,
769 ) -> Result<(), ScriptContextError> {
770 Ok(())
771 }
772
773 fn check_global_policy_validity<Pk: MiniscriptKey>(
774 _ms: &Miniscript<Pk, Self>,
775 ) -> Result<(), ScriptContextError> {
776 Ok(())
777 }
778
779 fn check_global_consensus_validity<Pk: MiniscriptKey>(
780 _ms: &Miniscript<Pk, Self>,
781 ) -> Result<(), ScriptContextError> {
782 Ok(())
783 }
784
785 fn check_local_policy_validity<Pk: MiniscriptKey>(
786 _ms: &Miniscript<Pk, Self>,
787 ) -> Result<(), ScriptContextError> {
788 Ok(())
789 }
790
791 fn check_local_consensus_validity<Pk: MiniscriptKey>(
792 _ms: &Miniscript<Pk, Self>,
793 ) -> Result<(), ScriptContextError> {
794 Ok(())
795 }
796
797 fn max_satisfaction_size<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Option<usize> {
798 panic!("Tried to compute a satisfaction size bound on a no-checks ecdsa miniscript")
799 }
800
801 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
802 panic!("Tried to compute a pk len bound on a no-checks ecdsa miniscript")
803 }
804
805 fn name_str() -> &'static str {
806 "NochecksEcdsa"
808 }
809
810 fn check_witness<Pk: MiniscriptKey>(_witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
811 Ok(())
815 }
816
817 fn check_global_validity<Pk: MiniscriptKey>(
818 ms: &Miniscript<Pk, Self>,
819 ) -> Result<(), ScriptContextError> {
820 Self::check_global_consensus_validity(ms)?;
821 Self::check_global_policy_validity(ms)?;
822 Ok(())
823 }
824
825 fn check_local_validity<Pk: MiniscriptKey>(
826 ms: &Miniscript<Pk, Self>,
827 ) -> Result<(), ScriptContextError> {
828 Self::check_global_consensus_validity(ms)?;
829 Self::check_global_policy_validity(ms)?;
830 Self::check_local_consensus_validity(ms)?;
831 Self::check_local_policy_validity(ms)?;
832 Ok(())
833 }
834
835 fn top_level_type_check<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
836 if ms.ty.corr.base != types::Base::B {
837 return Err(Error::NonTopLevel(format!("{:?}", ms)));
838 }
839 Ok(())
840 }
841
842 fn other_top_level_checks<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
843 Ok(())
844 }
845
846 fn top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
847 Self::top_level_type_check(ms)?;
848 Self::other_top_level_checks(ms)
849 }
850
851 fn sig_type() -> SigType {
852 SigType::Ecdsa
853 }
854}
855
856mod private {
858 use super::{BareCtx, Legacy, NoChecks, Segwitv0, Tap};
859
860 pub trait Sealed {}
861
862 impl Sealed for BareCtx {}
864 impl Sealed for Legacy {}
865 impl Sealed for Segwitv0 {}
866 impl Sealed for Tap {}
867 impl Sealed for NoChecks {}
868}