1use core::{fmt, hash};
16#[cfg(feature = "std")]
17use std::error;
18
19use bitcoin;
20use bitcoin::blockdata::constants::MAX_BLOCK_WEIGHT;
21use bitcoin::hashes::{hash160, ripemd160, sha256};
22
23use super::decode::ParseableKey;
24use crate::miniscript::limits::{
25 MAX_OPS_PER_SCRIPT, MAX_PUBKEYS_PER_MULTISIG, MAX_SCRIPTSIG_SIZE, MAX_SCRIPT_ELEMENT_SIZE,
26 MAX_SCRIPT_SIZE, MAX_STACK_SIZE, MAX_STANDARD_P2WSH_SCRIPT_SIZE,
27 MAX_STANDARD_P2WSH_STACK_ITEMS,
28};
29use crate::miniscript::types;
30use crate::prelude::*;
31use crate::util::witness_to_scriptsig;
32use crate::{hash256, Error, Miniscript, MiniscriptKey, Terminal};
33
34#[derive(Clone, PartialEq, Eq, Debug)]
36pub enum ScriptContextError {
37 MalleablePkH,
41 MalleableOrI,
44 MalleableDupIf,
47 CompressedOnly(String),
50 XOnlyKeysNotAllowed(String, &'static str),
53 UncompressedKeysNotAllowed,
56 MaxWitnessItemssExceeded { actual: usize, limit: usize },
59 MaxOpCountExceeded,
62 MaxWitnessScriptSizeExceeded,
65 MaxRedeemScriptSizeExceeded,
68 MaxScriptSigSizeExceeded,
70 ImpossibleSatisfaction,
72 TaprootMultiDisabled,
74 StackSizeLimitExceeded { actual: usize, limit: usize },
76 CheckMultiSigLimitExceeded,
78 MultiANotAllowed,
80}
81
82#[cfg(feature = "std")]
83impl error::Error for ScriptContextError {
84 fn cause(&self) -> Option<&dyn error::Error> {
85 use self::ScriptContextError::*;
86
87 match self {
88 MalleablePkH
89 | MalleableOrI
90 | MalleableDupIf
91 | CompressedOnly(_)
92 | XOnlyKeysNotAllowed(_, _)
93 | UncompressedKeysNotAllowed
94 | MaxWitnessItemssExceeded { .. }
95 | MaxOpCountExceeded
96 | MaxWitnessScriptSizeExceeded
97 | MaxRedeemScriptSizeExceeded
98 | MaxScriptSigSizeExceeded
99 | ImpossibleSatisfaction
100 | TaprootMultiDisabled
101 | StackSizeLimitExceeded { .. }
102 | CheckMultiSigLimitExceeded
103 | MultiANotAllowed => None,
104 }
105 }
106}
107
108impl fmt::Display for ScriptContextError {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 match *self {
111 ScriptContextError::MalleablePkH => write!(f, "PkH is malleable under Legacy rules"),
112 ScriptContextError::MalleableOrI => write!(f, "OrI is malleable under Legacy rules"),
113 ScriptContextError::MalleableDupIf => {
114 write!(f, "DupIf is malleable under Legacy rules")
115 }
116 ScriptContextError::CompressedOnly(ref pk) => {
117 write!(
118 f,
119 "Only Compressed pubkeys are allowed in segwit context. Found {}",
120 pk
121 )
122 }
123 ScriptContextError::XOnlyKeysNotAllowed(ref pk, ref ctx) => {
124 write!(f, "x-only key {} not allowed in {}", pk, ctx)
125 }
126 ScriptContextError::UncompressedKeysNotAllowed => {
127 write!(
128 f,
129 "uncompressed keys cannot be used in Taproot descriptors."
130 )
131 }
132 ScriptContextError::MaxWitnessItemssExceeded { actual, limit } => write!(
133 f,
134 "At least one spending path in the Miniscript fragment has {} more \
135 witness items than limit {}.",
136 actual, limit
137 ),
138 ScriptContextError::MaxOpCountExceeded => write!(
139 f,
140 "At least one satisfaction path in the Miniscript fragment contains \
141 more than MAX_OPS_PER_SCRIPT opcodes."
142 ),
143 ScriptContextError::MaxWitnessScriptSizeExceeded => write!(
144 f,
145 "The Miniscript corresponding Script would be larger than \
146 MAX_STANDARD_P2WSH_SCRIPT_SIZE bytes."
147 ),
148 ScriptContextError::MaxRedeemScriptSizeExceeded => write!(
149 f,
150 "The Miniscript corresponding Script would be larger than \
151 MAX_SCRIPT_ELEMENT_SIZE bytes."
152 ),
153 ScriptContextError::MaxScriptSigSizeExceeded => write!(
154 f,
155 "At least one satisfaction in Miniscript would be larger than \
156 MAX_SCRIPTSIG_SIZE scriptsig"
157 ),
158 ScriptContextError::ImpossibleSatisfaction => {
159 write!(
160 f,
161 "Impossible to satisfy Miniscript under the current context"
162 )
163 }
164 ScriptContextError::TaprootMultiDisabled => {
165 write!(f, "Invalid use of Multi node in taproot context")
166 }
167 ScriptContextError::StackSizeLimitExceeded { actual, limit } => {
168 write!(
169 f,
170 "Stack limit {} can exceed the allowed limit {} in at least one script path during script execution",
171 actual, limit
172 )
173 }
174 ScriptContextError::CheckMultiSigLimitExceeded => {
175 write!(
176 f,
177 "CHECkMULTISIG ('multi()' descriptor) only supports up to 20 pubkeys"
178 )
179 }
180 ScriptContextError::MultiANotAllowed => {
181 write!(f, "Multi a(CHECKSIGADD) only allowed post tapscript")
182 }
183 }
184 }
185}
186
187pub trait ScriptContext:
192 fmt::Debug + Clone + Ord + PartialOrd + Eq + PartialEq + hash::Hash + private::Sealed
193where
194 Self::Key: MiniscriptKey<Sha256 = sha256::Hash>,
195 Self::Key: MiniscriptKey<Hash256 = hash256::Hash>,
196 Self::Key: MiniscriptKey<Ripemd160 = ripemd160::Hash>,
197 Self::Key: MiniscriptKey<Hash160 = hash160::Hash>,
198{
199 type Key: ParseableKey;
201 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
210 _frag: &Terminal<Pk, Self>,
211 ) -> Result<(), ScriptContextError>;
212
213 fn check_witness<Pk: MiniscriptKey>(_witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
217 Ok(())
221 }
222
223 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize>;
225 fn check_global_consensus_validity<Pk: MiniscriptKey>(
236 _ms: &Miniscript<Pk, Self>,
237 ) -> Result<(), ScriptContextError> {
238 Ok(())
239 }
240
241 fn check_global_policy_validity<Pk: MiniscriptKey>(
250 _ms: &Miniscript<Pk, Self>,
251 ) -> Result<(), ScriptContextError> {
252 Ok(())
253 }
254
255 fn check_local_consensus_validity<Pk: MiniscriptKey>(
260 _ms: &Miniscript<Pk, Self>,
261 ) -> Result<(), ScriptContextError> {
262 Ok(())
263 }
264
265 fn check_local_policy_validity<Pk: MiniscriptKey>(
271 _ms: &Miniscript<Pk, Self>,
272 ) -> Result<(), ScriptContextError> {
273 Ok(())
274 }
275
276 fn check_global_validity<Pk: MiniscriptKey>(
279 ms: &Miniscript<Pk, Self>,
280 ) -> Result<(), ScriptContextError> {
281 Self::check_global_consensus_validity(ms)?;
282 Self::check_global_policy_validity(ms)?;
283 Ok(())
284 }
285
286 fn check_local_validity<Pk: MiniscriptKey>(
289 ms: &Miniscript<Pk, Self>,
290 ) -> Result<(), ScriptContextError> {
291 Self::check_global_consensus_validity(ms)?;
292 Self::check_global_policy_validity(ms)?;
293 Self::check_local_consensus_validity(ms)?;
294 Self::check_local_policy_validity(ms)?;
295 Ok(())
296 }
297
298 fn top_level_type_check<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
300 if ms.ty.corr.base != types::Base::B {
301 return Err(Error::NonTopLevel(format!("{:?}", ms)));
302 }
303 Ok(())
304 }
305
306 fn other_top_level_checks<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
308 Ok(())
309 }
310
311 fn top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
321 Self::top_level_type_check(ms)?;
322 Self::other_top_level_checks(ms)
323 }
324
325 fn sig_type() -> SigType;
329
330 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize;
335
336 fn name_str() -> &'static str;
338}
339
340#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
342pub enum SigType {
343 Ecdsa,
345 Schnorr,
347}
348
349#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
354pub enum Legacy {}
355
356impl ScriptContext for Legacy {
357 type Key = bitcoin::PublicKey;
358 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
359 frag: &Terminal<Pk, Self>,
360 ) -> Result<(), ScriptContextError> {
361 match *frag {
362 Terminal::PkH(ref _pkh) => Err(ScriptContextError::MalleablePkH),
363 Terminal::RawPkH(ref _pk) => Err(ScriptContextError::MalleablePkH),
364 Terminal::OrI(ref _a, ref _b) => Err(ScriptContextError::MalleableOrI),
365 Terminal::DupIf(ref _ms) => Err(ScriptContextError::MalleableDupIf),
366 _ => Ok(()),
367 }
368 }
369
370 fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
371 if witness_to_scriptsig(witness).len() > MAX_SCRIPTSIG_SIZE {
374 return Err(ScriptContextError::MaxScriptSigSizeExceeded);
375 }
376 Ok(())
377 }
378
379 fn check_global_consensus_validity<Pk: MiniscriptKey>(
380 ms: &Miniscript<Pk, Self>,
381 ) -> Result<(), ScriptContextError> {
382 if ms.ext.pk_cost > MAX_SCRIPT_ELEMENT_SIZE {
383 return Err(ScriptContextError::MaxRedeemScriptSizeExceeded);
384 }
385
386 match ms.node {
387 Terminal::PkK(ref key) if key.is_x_only_key() => {
388 return Err(ScriptContextError::XOnlyKeysNotAllowed(
389 key.to_string(),
390 Self::name_str(),
391 ))
392 }
393 Terminal::Multi(_k, ref pks) => {
394 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
395 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
396 }
397 for pk in pks.iter() {
398 if pk.is_x_only_key() {
399 return Err(ScriptContextError::XOnlyKeysNotAllowed(
400 pk.to_string(),
401 Self::name_str(),
402 ));
403 }
404 }
405 }
406 Terminal::MultiA(..) => {
407 return Err(ScriptContextError::MultiANotAllowed);
408 }
409 _ => {}
410 }
411 Ok(())
412 }
413
414 fn check_local_consensus_validity<Pk: MiniscriptKey>(
415 ms: &Miniscript<Pk, Self>,
416 ) -> Result<(), ScriptContextError> {
417 match ms.ext.ops.op_count() {
418 None => Err(ScriptContextError::MaxOpCountExceeded),
419 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
420 Err(ScriptContextError::MaxOpCountExceeded)
421 }
422 _ => Ok(()),
423 }
424 }
425
426 fn check_local_policy_validity<Pk: MiniscriptKey>(
427 ms: &Miniscript<Pk, Self>,
428 ) -> Result<(), ScriptContextError> {
429 match ms.max_satisfaction_size() {
433 Err(_e) => Err(ScriptContextError::ImpossibleSatisfaction),
434 Ok(size) if size > MAX_SCRIPTSIG_SIZE => {
435 Err(ScriptContextError::MaxScriptSigSizeExceeded)
436 }
437 _ => Ok(()),
438 }
439 }
440
441 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
442 ms.ext.max_sat_size.map(|x| x.1)
444 }
445
446 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize {
447 if pk.is_uncompressed() {
448 66
449 } else {
450 34
451 }
452 }
453
454 fn name_str() -> &'static str {
455 "Legacy/p2sh"
456 }
457
458 fn sig_type() -> SigType {
459 SigType::Ecdsa
460 }
461}
462
463#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
465pub enum Segwitv0 {}
466
467impl ScriptContext for Segwitv0 {
468 type Key = bitcoin::PublicKey;
469 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
470 _frag: &Terminal<Pk, Self>,
471 ) -> Result<(), ScriptContextError> {
472 Ok(())
473 }
474
475 fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
476 if witness.len() > MAX_STANDARD_P2WSH_STACK_ITEMS {
477 return Err(ScriptContextError::MaxWitnessItemssExceeded {
478 actual: witness.len(),
479 limit: MAX_STANDARD_P2WSH_STACK_ITEMS,
480 });
481 }
482 Ok(())
483 }
484
485 fn check_global_consensus_validity<Pk: MiniscriptKey>(
486 ms: &Miniscript<Pk, Self>,
487 ) -> Result<(), ScriptContextError> {
488 if ms.ext.pk_cost > MAX_SCRIPT_SIZE {
489 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
490 }
491
492 match ms.node {
493 Terminal::PkK(ref pk) => {
494 if pk.is_uncompressed() {
495 return Err(ScriptContextError::CompressedOnly(pk.to_string()));
496 } else if pk.is_x_only_key() {
497 return Err(ScriptContextError::XOnlyKeysNotAllowed(
498 pk.to_string(),
499 Self::name_str(),
500 ));
501 }
502 Ok(())
503 }
504 Terminal::Multi(_k, ref pks) => {
505 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
506 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
507 }
508 for pk in pks.iter() {
509 if pk.is_uncompressed() {
510 return Err(ScriptContextError::CompressedOnly(pk.to_string()));
511 } else if pk.is_x_only_key() {
512 return Err(ScriptContextError::XOnlyKeysNotAllowed(
513 pk.to_string(),
514 Self::name_str(),
515 ));
516 }
517 }
518 Ok(())
519 }
520 Terminal::MultiA(..) => Err(ScriptContextError::MultiANotAllowed),
521 _ => Ok(()),
522 }
523 }
524
525 fn check_local_consensus_validity<Pk: MiniscriptKey>(
526 ms: &Miniscript<Pk, Self>,
527 ) -> Result<(), ScriptContextError> {
528 match ms.ext.ops.op_count() {
529 None => Err(ScriptContextError::MaxOpCountExceeded),
530 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
531 Err(ScriptContextError::MaxOpCountExceeded)
532 }
533 _ => Ok(()),
534 }
535 }
536
537 fn check_global_policy_validity<Pk: MiniscriptKey>(
538 ms: &Miniscript<Pk, Self>,
539 ) -> Result<(), ScriptContextError> {
540 if ms.ext.pk_cost > MAX_STANDARD_P2WSH_SCRIPT_SIZE {
541 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
542 }
543 Ok(())
544 }
545
546 fn check_local_policy_validity<Pk: MiniscriptKey>(
547 ms: &Miniscript<Pk, Self>,
548 ) -> Result<(), ScriptContextError> {
549 match ms.max_satisfaction_witness_elements() {
553 Err(_e) => Err(ScriptContextError::ImpossibleSatisfaction),
555 Ok(max_witness_items) if max_witness_items > MAX_STANDARD_P2WSH_STACK_ITEMS => {
556 Err(ScriptContextError::MaxWitnessItemssExceeded {
557 actual: max_witness_items,
558 limit: MAX_STANDARD_P2WSH_STACK_ITEMS,
559 })
560 }
561 _ => Ok(()),
562 }
563 }
564
565 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
566 ms.ext.max_sat_size.map(|x| x.0)
568 }
569
570 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
571 34
572 }
573
574 fn name_str() -> &'static str {
575 "Segwitv0"
576 }
577
578 fn sig_type() -> SigType {
579 SigType::Ecdsa
580 }
581}
582
583#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
585pub enum Tap {}
586
587impl ScriptContext for Tap {
588 type Key = bitcoin::secp256k1::XOnlyPublicKey;
589 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
590 _frag: &Terminal<Pk, Self>,
591 ) -> Result<(), ScriptContextError> {
592 Ok(())
595 }
596
597 fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
598 if witness.len() > MAX_STACK_SIZE {
600 return Err(ScriptContextError::MaxWitnessItemssExceeded {
601 actual: witness.len(),
602 limit: MAX_STACK_SIZE,
603 });
604 }
605 Ok(())
606 }
607
608 fn check_global_consensus_validity<Pk: MiniscriptKey>(
609 ms: &Miniscript<Pk, Self>,
610 ) -> Result<(), ScriptContextError> {
611 if ms.ext.pk_cost > MAX_BLOCK_WEIGHT as usize {
617 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
618 }
619
620 match ms.node {
621 Terminal::PkK(ref pk) => {
622 if pk.is_uncompressed() {
623 return Err(ScriptContextError::UncompressedKeysNotAllowed);
624 }
625 Ok(())
626 }
627 Terminal::Multi(..) => Err(ScriptContextError::TaprootMultiDisabled),
628 _ => Ok(()),
629 }
630 }
631
632 fn check_local_consensus_validity<Pk: MiniscriptKey>(
633 ms: &Miniscript<Pk, Self>,
634 ) -> Result<(), ScriptContextError> {
635 if let (Some(s), Some(h)) = (
645 ms.ext.exec_stack_elem_count_sat,
646 ms.ext.stack_elem_count_sat,
647 ) {
648 if s + h > MAX_STACK_SIZE {
649 return Err(ScriptContextError::StackSizeLimitExceeded {
650 actual: s + h,
651 limit: MAX_STACK_SIZE,
652 });
653 }
654 }
655 Ok(())
656 }
657
658 fn check_global_policy_validity<Pk: MiniscriptKey>(
659 _ms: &Miniscript<Pk, Self>,
660 ) -> Result<(), ScriptContextError> {
661 Ok(())
663 }
664
665 fn check_local_policy_validity<Pk: MiniscriptKey>(
666 _ms: &Miniscript<Pk, Self>,
667 ) -> Result<(), ScriptContextError> {
668 Ok(())
669 }
670
671 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
672 ms.ext.max_sat_size.map(|x| x.0)
674 }
675
676 fn sig_type() -> SigType {
677 SigType::Schnorr
678 }
679
680 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
681 33
682 }
683
684 fn name_str() -> &'static str {
685 "TapscriptCtx"
686 }
687}
688
689#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
694pub enum BareCtx {}
695
696impl ScriptContext for BareCtx {
697 type Key = bitcoin::PublicKey;
698 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
699 _frag: &Terminal<Pk, Self>,
700 ) -> Result<(), ScriptContextError> {
701 Ok(())
706 }
707
708 fn check_global_consensus_validity<Pk: MiniscriptKey>(
709 ms: &Miniscript<Pk, Self>,
710 ) -> Result<(), ScriptContextError> {
711 if ms.ext.pk_cost > MAX_SCRIPT_SIZE {
712 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
713 }
714 match ms.node {
715 Terminal::PkK(ref key) if key.is_x_only_key() => {
716 return Err(ScriptContextError::XOnlyKeysNotAllowed(
717 key.to_string(),
718 Self::name_str(),
719 ))
720 }
721 Terminal::Multi(_k, ref pks) => {
722 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
723 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
724 }
725 for pk in pks.iter() {
726 if pk.is_x_only_key() {
727 return Err(ScriptContextError::XOnlyKeysNotAllowed(
728 pk.to_string(),
729 Self::name_str(),
730 ));
731 }
732 }
733 Ok(())
734 }
735 Terminal::MultiA(..) => Err(ScriptContextError::MultiANotAllowed),
736 _ => Ok(()),
737 }
738 }
739
740 fn check_local_consensus_validity<Pk: MiniscriptKey>(
741 ms: &Miniscript<Pk, Self>,
742 ) -> Result<(), ScriptContextError> {
743 match ms.ext.ops.op_count() {
744 None => Err(ScriptContextError::MaxOpCountExceeded),
745 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
746 Err(ScriptContextError::MaxOpCountExceeded)
747 }
748 _ => Ok(()),
749 }
750 }
751
752 fn other_top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
753 match &ms.node {
754 Terminal::Check(ref ms) => match &ms.node {
755 Terminal::RawPkH(_pkh) => Ok(()),
756 Terminal::PkK(_pk) | Terminal::PkH(_pk) => Ok(()),
757 _ => Err(Error::NonStandardBareScript),
758 },
759 Terminal::Multi(_k, subs) if subs.len() <= 3 => Ok(()),
760 _ => Err(Error::NonStandardBareScript),
761 }
762 }
763
764 fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
765 ms.ext.max_sat_size.map(|x| x.1)
767 }
768
769 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize {
770 if pk.is_uncompressed() {
771 66
772 } else {
773 34
774 }
775 }
776
777 fn name_str() -> &'static str {
778 "BareCtx"
779 }
780
781 fn sig_type() -> SigType {
782 SigType::Ecdsa
783 }
784}
785
786#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
792pub enum NoChecks {}
793impl ScriptContext for NoChecks {
794 type Key = bitcoin::PublicKey;
796 fn check_terminal_non_malleable<Pk: MiniscriptKey>(
797 _frag: &Terminal<Pk, Self>,
798 ) -> Result<(), ScriptContextError> {
799 Ok(())
800 }
801
802 fn check_global_policy_validity<Pk: MiniscriptKey>(
803 _ms: &Miniscript<Pk, Self>,
804 ) -> Result<(), ScriptContextError> {
805 Ok(())
806 }
807
808 fn check_global_consensus_validity<Pk: MiniscriptKey>(
809 _ms: &Miniscript<Pk, Self>,
810 ) -> Result<(), ScriptContextError> {
811 Ok(())
812 }
813
814 fn check_local_policy_validity<Pk: MiniscriptKey>(
815 _ms: &Miniscript<Pk, Self>,
816 ) -> Result<(), ScriptContextError> {
817 Ok(())
818 }
819
820 fn check_local_consensus_validity<Pk: MiniscriptKey>(
821 _ms: &Miniscript<Pk, Self>,
822 ) -> Result<(), ScriptContextError> {
823 Ok(())
824 }
825
826 fn max_satisfaction_size<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Option<usize> {
827 panic!("Tried to compute a satisfaction size bound on a no-checks ecdsa miniscript")
828 }
829
830 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
831 panic!("Tried to compute a pk len bound on a no-checks ecdsa miniscript")
832 }
833
834 fn name_str() -> &'static str {
835 "NochecksEcdsa"
837 }
838
839 fn check_witness<Pk: MiniscriptKey>(_witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
840 Ok(())
844 }
845
846 fn check_global_validity<Pk: MiniscriptKey>(
847 ms: &Miniscript<Pk, Self>,
848 ) -> Result<(), ScriptContextError> {
849 Self::check_global_consensus_validity(ms)?;
850 Self::check_global_policy_validity(ms)?;
851 Ok(())
852 }
853
854 fn check_local_validity<Pk: MiniscriptKey>(
855 ms: &Miniscript<Pk, Self>,
856 ) -> Result<(), ScriptContextError> {
857 Self::check_global_consensus_validity(ms)?;
858 Self::check_global_policy_validity(ms)?;
859 Self::check_local_consensus_validity(ms)?;
860 Self::check_local_policy_validity(ms)?;
861 Ok(())
862 }
863
864 fn top_level_type_check<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
865 if ms.ty.corr.base != types::Base::B {
866 return Err(Error::NonTopLevel(format!("{:?}", ms)));
867 }
868 Ok(())
869 }
870
871 fn other_top_level_checks<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
872 Ok(())
873 }
874
875 fn top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
876 Self::top_level_type_check(ms)?;
877 Self::other_top_level_checks(ms)
878 }
879
880 fn sig_type() -> SigType {
881 SigType::Ecdsa
882 }
883}
884
885mod private {
887 use super::{BareCtx, Legacy, NoChecks, Segwitv0, Tap};
888
889 pub trait Sealed {}
890
891 impl Sealed for BareCtx {}
893 impl Sealed for Legacy {}
894 impl Sealed for Segwitv0 {}
895 impl Sealed for Tap {}
896 impl Sealed for NoChecks {}
897}