1use std::{error, fmt, hash};
5
6use bitcoin::hashes::{hash160, ripemd160, sha256};
7use bitcoin::{self, Weight};
8
9use super::decode::ParseableKey;
10use crate::miniscript::limits::{
11 MAX_OPS_PER_SCRIPT, MAX_PUBKEYS_PER_MULTISIG, MAX_SCRIPTSIG_SIZE, MAX_SCRIPT_ELEMENT_SIZE,
12 MAX_SCRIPT_SIZE, MAX_STACK_SIZE, MAX_STANDARD_P2WSH_SCRIPT_SIZE,
13 MAX_STANDARD_P2WSH_STACK_ITEMS,
14};
15use crate::miniscript::types;
16use crate::util::witness_to_scriptsig;
17pub use crate::SigType;
18use crate::{hash256, Error, Extension, Miniscript, MiniscriptKey, Terminal};
19
20#[derive(Clone, PartialEq, Eq, Debug)]
22pub enum ScriptContextError {
23 MalleablePkH,
27 MalleableOrI,
30 MalleableDupIf,
33 CompressedOnly(String),
36 XOnlyKeysNotAllowed(String, &'static str),
39 UncompressedKeysNotAllowed,
42 MaxWitnessItemssExceeded { actual: usize, limit: usize },
45 MaxOpCountExceeded,
48 MaxWitnessScriptSizeExceeded,
51 MaxRedeemScriptSizeExceeded,
54 MaxScriptSigSizeExceeded,
56 ImpossibleSatisfaction,
58 CovElementSizeExceeded,
60 TaprootMultiDisabled,
62 StackSizeLimitExceeded { actual: usize, limit: usize },
64 CheckMultiSigLimitExceeded,
66 MultiANotAllowed,
68 ExtensionError(String),
70}
71
72impl error::Error for ScriptContextError {
73 fn cause(&self) -> Option<&dyn error::Error> {
74 use self::ScriptContextError::*;
75
76 match self {
77 MalleablePkH
78 | MalleableOrI
79 | MalleableDupIf
80 | CompressedOnly(_)
81 | XOnlyKeysNotAllowed(_, _)
82 | UncompressedKeysNotAllowed
83 | MaxWitnessItemssExceeded { .. }
84 | MaxOpCountExceeded
85 | MaxWitnessScriptSizeExceeded
86 | MaxRedeemScriptSizeExceeded
87 | MaxScriptSigSizeExceeded
88 | ImpossibleSatisfaction
89 | TaprootMultiDisabled
90 | StackSizeLimitExceeded { .. }
91 | CheckMultiSigLimitExceeded
92 | MultiANotAllowed
93 | CovElementSizeExceeded
94 | ExtensionError(_) => None,
95 }
96 }
97}
98
99impl fmt::Display for ScriptContextError {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match *self {
102 ScriptContextError::MalleablePkH => write!(f, "PkH is malleable under Legacy rules"),
103 ScriptContextError::MalleableOrI => write!(f, "OrI is malleable under Legacy rules"),
104 ScriptContextError::MalleableDupIf => {
105 write!(f, "DupIf is malleable under Legacy rules")
106 }
107 ScriptContextError::CompressedOnly(ref pk) => {
108 write!(
109 f,
110 "Only Compressed pubkeys are allowed in segwit context. Found {}",
111 pk
112 )
113 }
114 ScriptContextError::XOnlyKeysNotAllowed(ref pk, ref ctx) => {
115 write!(f, "x-only key {} not allowed in {}", pk, ctx)
116 }
117 ScriptContextError::UncompressedKeysNotAllowed => {
118 write!(
119 f,
120 "uncompressed keys cannot be used in Taproot descriptors."
121 )
122 }
123 ScriptContextError::MaxWitnessItemssExceeded { actual, limit } => write!(
124 f,
125 "At least one spending path in the Miniscript fragment has {} more \
126 witness items than limit {}.",
127 actual, limit
128 ),
129 ScriptContextError::MaxOpCountExceeded => write!(
130 f,
131 "At least one satisfaction path in the Miniscript fragment contains \
132 more than MAX_OPS_PER_SCRIPT opcodes."
133 ),
134 ScriptContextError::MaxWitnessScriptSizeExceeded => write!(
135 f,
136 "The Miniscript corresponding Script would be larger than \
137 MAX_STANDARD_P2WSH_SCRIPT_SIZE bytes."
138 ),
139 ScriptContextError::MaxRedeemScriptSizeExceeded => write!(
140 f,
141 "The Miniscript corresponding Script would be larger than \
142 MAX_SCRIPT_ELEMENT_SIZE bytes."
143 ),
144 ScriptContextError::MaxScriptSigSizeExceeded => write!(
145 f,
146 "At least one satisfaction in Miniscript would be larger than \
147 MAX_SCRIPTSIG_SIZE scriptsig"
148 ),
149 ScriptContextError::ImpossibleSatisfaction => {
150 write!(
151 f,
152 "Impossible to satisfy Miniscript under the current context"
153 )
154 }
155 ScriptContextError::CovElementSizeExceeded => {
156 write!(
157 f,
158 "Prefix/Suffix len in sighash covenents exceeds 520 bytes"
159 )
160 }
161 ScriptContextError::TaprootMultiDisabled => {
162 write!(f, "Invalid use of Multi node in taproot context")
163 }
164 ScriptContextError::StackSizeLimitExceeded { actual, limit } => {
165 write!(
166 f,
167 "Stack limit {} can exceed the allowed limit {} in at least one script path during script execution",
168 actual, limit
169 )
170 }
171 ScriptContextError::CheckMultiSigLimitExceeded => {
172 write!(
173 f,
174 "CHECkMULTISIG ('multi()' descriptor) only supports up to 20 pubkeys"
175 )
176 }
177 ScriptContextError::MultiANotAllowed => {
178 write!(f, "Multi a(CHECKSIGADD) only allowed post tapscript")
179 }
180 ScriptContextError::ExtensionError(ref s) => write!(f, "Extension Error: {}", s),
181 }
182 }
183}
184
185pub trait ScriptContext:
190 fmt::Debug + Clone + Ord + PartialOrd + Eq + PartialEq + hash::Hash + private::Sealed
191where
192 Self::Key: MiniscriptKey<Sha256 = sha256::Hash>,
193 Self::Key: MiniscriptKey<Hash256 = hash256::Hash>,
194 Self::Key: MiniscriptKey<Ripemd160 = ripemd160::Hash>,
195 Self::Key: MiniscriptKey<Hash160 = hash160::Hash>,
196{
197 type Key: ParseableKey;
199 fn check_terminal_non_malleable<Pk, Ext>(
208 _frag: &Terminal<Pk, Self, Ext>,
209 ) -> Result<(), ScriptContextError>
210 where
211 Pk: MiniscriptKey,
212 Ext: Extension;
213
214 fn check_witness<Pk, Ext>(_witness: &[Vec<u8>]) -> Result<(), ScriptContextError>
218 where
219 Pk: MiniscriptKey,
220 Ext: Extension,
221 {
222 Ok(())
226 }
227
228 fn max_satisfaction_size<Pk, Ext>(ms: &Miniscript<Pk, Self, Ext>) -> Option<usize>
230 where
231 Pk: MiniscriptKey,
232 Ext: Extension;
233 fn check_global_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
244 _ms: &Miniscript<Pk, Self, Ext>,
245 ) -> Result<(), ScriptContextError> {
246 Ok(())
247 }
248
249 fn check_global_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
258 _ms: &Miniscript<Pk, Self, Ext>,
259 ) -> Result<(), ScriptContextError> {
260 Ok(())
261 }
262
263 fn check_local_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
268 _ms: &Miniscript<Pk, Self, Ext>,
269 ) -> Result<(), ScriptContextError> {
270 Ok(())
271 }
272
273 fn check_local_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
279 _ms: &Miniscript<Pk, Self, Ext>,
280 ) -> Result<(), ScriptContextError> {
281 Ok(())
282 }
283
284 fn check_global_validity<Pk, Ext>(
287 ms: &Miniscript<Pk, Self, Ext>,
288 ) -> Result<(), ScriptContextError>
289 where
290 Pk: MiniscriptKey,
291 Ext: Extension,
292 {
293 Self::check_global_consensus_validity(ms)?;
294 Self::check_global_policy_validity(ms)?;
295 Ok(())
296 }
297
298 fn check_local_validity<Pk: MiniscriptKey, Ext: Extension>(
301 ms: &Miniscript<Pk, Self, Ext>,
302 ) -> Result<(), ScriptContextError> {
303 Self::check_global_consensus_validity(ms)?;
304 Self::check_global_policy_validity(ms)?;
305 Self::check_local_consensus_validity(ms)?;
306 Self::check_local_policy_validity(ms)?;
307 Ok(())
308 }
309
310 fn top_level_type_check<Pk: MiniscriptKey, Ext: Extension>(
312 ms: &Miniscript<Pk, Self, Ext>,
313 ) -> Result<(), Error> {
314 if ms.ty.corr.base != types::Base::B {
315 return Err(Error::NonTopLevel(format!("{:?}", ms)));
316 }
317 Ok(())
318 }
319
320 fn other_top_level_checks<Pk, Ext>(_ms: &Miniscript<Pk, Self, Ext>) -> Result<(), Error>
322 where
323 Pk: MiniscriptKey,
324 Ext: Extension,
325 {
326 Ok(())
327 }
328
329 fn top_level_checks<Pk: MiniscriptKey, Ext: Extension>(
339 ms: &Miniscript<Pk, Self, Ext>,
340 ) -> Result<(), Error> {
341 Self::top_level_type_check(ms)?;
342 Self::other_top_level_checks(ms)
343 }
344
345 fn sig_type() -> SigType;
349
350 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize;
355
356 fn name_str() -> &'static str;
358}
359
360#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
365pub enum Legacy {}
366
367impl ScriptContext for Legacy {
368 type Key = bitcoin::PublicKey;
369
370 fn check_terminal_non_malleable<Pk: MiniscriptKey, Ext: Extension>(
371 frag: &Terminal<Pk, Self, Ext>,
372 ) -> Result<(), ScriptContextError> {
373 match *frag {
374 Terminal::PkH(ref _pkh) => Err(ScriptContextError::MalleablePkH),
375 Terminal::RawPkH(ref _pk) => Err(ScriptContextError::MalleablePkH),
376 Terminal::OrI(ref _a, ref _b) => Err(ScriptContextError::MalleableOrI),
377 Terminal::DupIf(ref _ms) => Err(ScriptContextError::MalleableDupIf),
378 _ => Ok(()),
379 }
380 }
381
382 fn check_witness<Pk: MiniscriptKey, Ext: Extension>(
383 witness: &[Vec<u8>],
384 ) -> Result<(), ScriptContextError> {
385 if witness_to_scriptsig(witness).len() > MAX_SCRIPTSIG_SIZE {
388 return Err(ScriptContextError::MaxScriptSigSizeExceeded);
389 }
390 Ok(())
391 }
392
393 fn check_global_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
394 ms: &Miniscript<Pk, Self, Ext>,
395 ) -> Result<(), ScriptContextError> {
396 if ms.ext.pk_cost > MAX_SCRIPT_ELEMENT_SIZE {
397 return Err(ScriptContextError::MaxRedeemScriptSizeExceeded);
398 }
399
400 match ms.node {
401 Terminal::PkK(ref key) if key.is_x_only_key() => {
402 return Err(ScriptContextError::XOnlyKeysNotAllowed(
403 key.to_string(),
404 Self::name_str(),
405 ))
406 }
407 Terminal::Multi(_k, ref pks) => {
408 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
409 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
410 }
411 for pk in pks.iter() {
412 if pk.is_x_only_key() {
413 return Err(ScriptContextError::XOnlyKeysNotAllowed(
414 pk.to_string(),
415 Self::name_str(),
416 ));
417 }
418 }
419 }
420 Terminal::MultiA(..) => {
421 return Err(ScriptContextError::MultiANotAllowed);
422 }
423 _ => {}
424 }
425 if let Terminal::Ext(ref _e) = ms.node {
426 return Err(ScriptContextError::ExtensionError(String::from(
427 "No Extensions in Legacy context",
428 )));
429 }
430 Ok(())
431 }
432
433 fn check_local_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
434 ms: &Miniscript<Pk, Self, Ext>,
435 ) -> Result<(), ScriptContextError> {
436 match ms.ext.ops.op_count() {
437 None => Err(ScriptContextError::MaxOpCountExceeded),
438 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
439 Err(ScriptContextError::MaxOpCountExceeded)
440 }
441 _ => Ok(()),
442 }
443 }
444
445 fn check_local_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
446 ms: &Miniscript<Pk, Self, Ext>,
447 ) -> Result<(), ScriptContextError> {
448 match ms.max_satisfaction_size() {
452 Err(_e) => Err(ScriptContextError::ImpossibleSatisfaction),
453 Ok(size) if size > MAX_SCRIPTSIG_SIZE => {
454 Err(ScriptContextError::MaxScriptSigSizeExceeded)
455 }
456 _ => Ok(()),
457 }
458 }
459
460 fn max_satisfaction_size<Pk: MiniscriptKey, Ext: Extension>(
461 ms: &Miniscript<Pk, Self, Ext>,
462 ) -> Option<usize> {
463 ms.ext.max_sat_size.map(|x| x.1)
465 }
466
467 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize {
468 if pk.is_uncompressed() {
469 66
470 } else {
471 34
472 }
473 }
474
475 fn name_str() -> &'static str {
476 "Legacy/p2sh"
477 }
478
479 fn sig_type() -> SigType {
480 SigType::Ecdsa
481 }
482}
483
484#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
486pub enum Segwitv0 {}
487
488impl ScriptContext for Segwitv0 {
489 type Key = bitcoin::PublicKey;
490
491 fn check_terminal_non_malleable<Pk: MiniscriptKey, Ext: Extension>(
492 _frag: &Terminal<Pk, Self, Ext>,
493 ) -> Result<(), ScriptContextError> {
494 Ok(())
495 }
496
497 fn check_witness<Pk: MiniscriptKey, Ext: Extension>(
498 witness: &[Vec<u8>],
499 ) -> Result<(), ScriptContextError> {
500 if witness.len() > MAX_STANDARD_P2WSH_STACK_ITEMS {
501 return Err(ScriptContextError::MaxWitnessItemssExceeded {
502 actual: witness.len(),
503 limit: MAX_STANDARD_P2WSH_STACK_ITEMS,
504 });
505 }
506 Ok(())
507 }
508
509 fn check_global_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
510 ms: &Miniscript<Pk, Self, Ext>,
511 ) -> Result<(), ScriptContextError> {
512 if ms.ext.pk_cost > MAX_SCRIPT_SIZE {
513 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
514 }
515
516 match ms.node {
517 Terminal::PkK(ref pk) => {
518 if pk.is_uncompressed() {
519 return Err(ScriptContextError::CompressedOnly(pk.to_string()));
520 } else if pk.is_x_only_key() {
521 return Err(ScriptContextError::XOnlyKeysNotAllowed(
522 pk.to_string(),
523 Self::name_str(),
524 ));
525 }
526 Ok(())
527 }
528 Terminal::Multi(_k, ref pks) => {
529 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
530 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
531 }
532 for pk in pks.iter() {
533 if pk.is_uncompressed() {
534 return Err(ScriptContextError::CompressedOnly(pk.to_string()));
535 } else if pk.is_x_only_key() {
536 return Err(ScriptContextError::XOnlyKeysNotAllowed(
537 pk.to_string(),
538 Self::name_str(),
539 ));
540 }
541 }
542 Ok(())
543 }
544 Terminal::Ext(ref e) => {
545 e.segwit_ctx_checks()?;
546 Ok(())
547 }
548 Terminal::MultiA(..) => Err(ScriptContextError::MultiANotAllowed),
549 _ => Ok(()),
550 }
551 }
552
553 fn check_local_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
554 ms: &Miniscript<Pk, Self, Ext>,
555 ) -> Result<(), ScriptContextError> {
556 match ms.ext.ops.op_count() {
557 None => Err(ScriptContextError::MaxOpCountExceeded),
558 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
559 Err(ScriptContextError::MaxOpCountExceeded)
560 }
561 _ => Ok(()),
562 }
563 }
564
565 fn check_global_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
566 ms: &Miniscript<Pk, Self, Ext>,
567 ) -> Result<(), ScriptContextError> {
568 if ms.ext.pk_cost > MAX_STANDARD_P2WSH_SCRIPT_SIZE {
569 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
570 }
571 Ok(())
572 }
573
574 fn check_local_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
575 ms: &Miniscript<Pk, Self, Ext>,
576 ) -> Result<(), ScriptContextError> {
577 match ms.max_satisfaction_witness_elements() {
581 Err(_e) => Err(ScriptContextError::ImpossibleSatisfaction),
583 Ok(max_witness_items) if max_witness_items > MAX_STANDARD_P2WSH_STACK_ITEMS => {
584 Err(ScriptContextError::MaxWitnessItemssExceeded {
585 actual: max_witness_items,
586 limit: MAX_STANDARD_P2WSH_STACK_ITEMS,
587 })
588 }
589 _ => Ok(()),
590 }
591 }
592
593 fn max_satisfaction_size<Pk: MiniscriptKey, Ext: Extension>(
594 ms: &Miniscript<Pk, Self, Ext>,
595 ) -> Option<usize> {
596 ms.ext.max_sat_size.map(|x| x.0)
598 }
599
600 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
601 34
602 }
603
604 fn name_str() -> &'static str {
605 "Segwitv0"
606 }
607
608 fn sig_type() -> SigType {
609 SigType::Ecdsa
610 }
611}
612
613#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
615pub enum Tap {}
616
617impl ScriptContext for Tap {
618 type Key = bitcoin::secp256k1::XOnlyPublicKey;
619 fn check_terminal_non_malleable<Pk: MiniscriptKey, Ext: Extension>(
620 _frag: &Terminal<Pk, Self, Ext>,
621 ) -> Result<(), ScriptContextError> {
622 Ok(())
625 }
626
627 fn check_witness<Pk: MiniscriptKey, Ext: Extension>(
628 witness: &[Vec<u8>],
629 ) -> Result<(), ScriptContextError> {
630 if witness.len() > MAX_STACK_SIZE {
632 return Err(ScriptContextError::MaxWitnessItemssExceeded {
633 actual: witness.len(),
634 limit: MAX_STACK_SIZE,
635 });
636 }
637 Ok(())
638 }
639
640 fn check_global_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
641 ms: &Miniscript<Pk, Self, Ext>,
642 ) -> Result<(), ScriptContextError> {
643 if ms.ext.pk_cost > Weight::MAX_BLOCK.to_wu() as usize {
649 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
650 }
651
652 match ms.node {
653 Terminal::PkK(ref pk) => {
654 if pk.is_uncompressed() {
655 return Err(ScriptContextError::UncompressedKeysNotAllowed);
656 }
657 Ok(())
658 }
659 Terminal::Multi(..) => Err(ScriptContextError::TaprootMultiDisabled),
660 Terminal::Ext(ref e) => {
661 e.tap_ctx_checks()?;
662 Ok(())
663 }
664 _ => Ok(()),
665 }
666 }
667
668 fn check_local_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
669 ms: &Miniscript<Pk, Self, Ext>,
670 ) -> Result<(), ScriptContextError> {
671 if let (Some(s), Some(h)) = (
681 ms.ext.exec_stack_elem_count_sat,
682 ms.ext.stack_elem_count_sat,
683 ) {
684 if s + h > MAX_STACK_SIZE {
685 return Err(ScriptContextError::StackSizeLimitExceeded {
686 actual: s + h,
687 limit: MAX_STACK_SIZE,
688 });
689 }
690 }
691 Ok(())
692 }
693
694 fn check_global_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
695 _ms: &Miniscript<Pk, Self, Ext>,
696 ) -> Result<(), ScriptContextError> {
697 Ok(())
699 }
700
701 fn check_local_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
702 _ms: &Miniscript<Pk, Self, Ext>,
703 ) -> Result<(), ScriptContextError> {
704 Ok(())
705 }
706
707 fn max_satisfaction_size<Pk: MiniscriptKey, Ext: Extension>(
708 ms: &Miniscript<Pk, Self, Ext>,
709 ) -> Option<usize> {
710 ms.ext.max_sat_size.map(|x| x.0)
712 }
713
714 fn sig_type() -> SigType {
715 SigType::Schnorr
716 }
717
718 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
719 33
720 }
721
722 fn name_str() -> &'static str {
723 "TapscriptCtx"
724 }
725}
726
727#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
732pub enum BareCtx {}
733
734impl ScriptContext for BareCtx {
735 type Key = bitcoin::PublicKey;
736 fn check_terminal_non_malleable<Pk: MiniscriptKey, Ext: Extension>(
737 _frag: &Terminal<Pk, Self, Ext>,
738 ) -> Result<(), ScriptContextError> {
739 Ok(())
744 }
745
746 fn check_global_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
747 ms: &Miniscript<Pk, Self, Ext>,
748 ) -> Result<(), ScriptContextError> {
749 if ms.ext.pk_cost > MAX_SCRIPT_SIZE {
750 return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
751 }
752
753 if let Terminal::Ext(ref _e) = ms.node {
754 return Err(ScriptContextError::ExtensionError(String::from(
755 "No Extensions in Bare context",
756 )));
757 }
758 match ms.node {
759 Terminal::PkK(ref key) if key.is_x_only_key() => {
760 Err(ScriptContextError::XOnlyKeysNotAllowed(
761 key.to_string(),
762 Self::name_str(),
763 ))
764 }
765 Terminal::Multi(_k, ref pks) => {
766 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
767 return Err(ScriptContextError::CheckMultiSigLimitExceeded);
768 }
769 for pk in pks.iter() {
770 if pk.is_x_only_key() {
771 return Err(ScriptContextError::XOnlyKeysNotAllowed(
772 pk.to_string(),
773 Self::name_str(),
774 ));
775 }
776 }
777 Ok(())
778 }
779 Terminal::MultiA(..) => Err(ScriptContextError::MultiANotAllowed),
780 _ => Ok(()),
781 }
782 }
783
784 fn check_local_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
785 ms: &Miniscript<Pk, Self, Ext>,
786 ) -> Result<(), ScriptContextError> {
787 match ms.ext.ops.op_count() {
788 None => Err(ScriptContextError::MaxOpCountExceeded),
789 Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
790 Err(ScriptContextError::MaxOpCountExceeded)
791 }
792 _ => Ok(()),
793 }
794 }
795
796 fn other_top_level_checks<Pk: MiniscriptKey, Ext: Extension>(
797 ms: &Miniscript<Pk, Self, Ext>,
798 ) -> Result<(), Error> {
799 match &ms.node {
800 Terminal::Check(ref ms) => match &ms.node {
801 Terminal::RawPkH(_pkh) => Ok(()),
802 Terminal::PkK(_pk) | Terminal::PkH(_pk) => Ok(()),
803 _ => Err(Error::NonStandardBareScript),
804 },
805 Terminal::Multi(_k, subs) if subs.len() <= 3 => Ok(()),
806 _ => Err(Error::NonStandardBareScript),
807 }
808 }
809
810 fn max_satisfaction_size<Pk: MiniscriptKey, Ext: Extension>(
811 ms: &Miniscript<Pk, Self, Ext>,
812 ) -> Option<usize> {
813 ms.ext.max_sat_size.map(|x| x.1)
815 }
816
817 fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize {
818 if pk.is_uncompressed() {
819 66
820 } else {
821 34
822 }
823 }
824
825 fn name_str() -> &'static str {
826 "BareCtx"
827 }
828
829 fn sig_type() -> SigType {
830 SigType::Ecdsa
831 }
832}
833
834#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
840pub enum NoChecks {}
841impl ScriptContext for NoChecks {
842 type Key = bitcoin::PublicKey;
843 fn check_terminal_non_malleable<Pk: MiniscriptKey, Ext: Extension>(
844 _frag: &Terminal<Pk, Self, Ext>,
845 ) -> Result<(), ScriptContextError> {
846 Ok(())
847 }
848
849 fn check_global_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
850 _ms: &Miniscript<Pk, Self, Ext>,
851 ) -> Result<(), ScriptContextError> {
852 Ok(())
853 }
854
855 fn check_global_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
856 _ms: &Miniscript<Pk, Self, Ext>,
857 ) -> Result<(), ScriptContextError> {
858 Ok(())
859 }
860
861 fn check_local_policy_validity<Pk: MiniscriptKey, Ext: Extension>(
862 _ms: &Miniscript<Pk, Self, Ext>,
863 ) -> Result<(), ScriptContextError> {
864 Ok(())
865 }
866
867 fn check_local_consensus_validity<Pk: MiniscriptKey, Ext: Extension>(
868 _ms: &Miniscript<Pk, Self, Ext>,
869 ) -> Result<(), ScriptContextError> {
870 Ok(())
871 }
872
873 fn max_satisfaction_size<Pk: MiniscriptKey, Ext: Extension>(
874 _ms: &Miniscript<Pk, Self, Ext>,
875 ) -> Option<usize> {
876 panic!("Tried to compute a satisfaction size bound on a no-checks ecdsa miniscript")
877 }
878
879 fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
880 panic!("Tried to compute a pk len bound on a no-checks ecdsa miniscript")
881 }
882
883 fn name_str() -> &'static str {
884 "NochecksEcdsa"
886 }
887
888 fn check_witness<Pk: MiniscriptKey, Ext: Extension>(
889 _witness: &[Vec<u8>],
890 ) -> Result<(), ScriptContextError> {
891 Ok(())
895 }
896
897 fn check_global_validity<Pk: MiniscriptKey, Ext: Extension>(
898 ms: &Miniscript<Pk, Self, Ext>,
899 ) -> Result<(), ScriptContextError> {
900 Self::check_global_consensus_validity(ms)?;
901 Self::check_global_policy_validity(ms)?;
902 Ok(())
903 }
904
905 fn check_local_validity<Pk: MiniscriptKey, Ext: Extension>(
906 ms: &Miniscript<Pk, Self, Ext>,
907 ) -> Result<(), ScriptContextError> {
908 Self::check_global_consensus_validity(ms)?;
909 Self::check_global_policy_validity(ms)?;
910 Self::check_local_consensus_validity(ms)?;
911 Self::check_local_policy_validity(ms)?;
912 Ok(())
913 }
914
915 fn top_level_type_check<Pk: MiniscriptKey, Ext: Extension>(
916 ms: &Miniscript<Pk, Self, Ext>,
917 ) -> Result<(), Error> {
918 if ms.ty.corr.base != types::Base::B {
919 return Err(Error::NonTopLevel(format!("{:?}", ms)));
920 }
921 Ok(())
922 }
923
924 fn other_top_level_checks<Pk: MiniscriptKey, Ext: Extension>(
925 _ms: &Miniscript<Pk, Self, Ext>,
926 ) -> Result<(), Error> {
927 Ok(())
928 }
929
930 fn top_level_checks<Pk: MiniscriptKey, Ext: Extension>(
931 ms: &Miniscript<Pk, Self, Ext>,
932 ) -> Result<(), Error> {
933 Self::top_level_type_check(ms)?;
934 Self::other_top_level_checks(ms)
935 }
936
937 fn sig_type() -> SigType {
938 SigType::Ecdsa
939 }
940}
941
942mod private {
944 use super::{BareCtx, Legacy, NoChecks, Segwitv0, Tap};
945
946 pub trait Sealed {}
947
948 impl Sealed for BareCtx {}
950 impl Sealed for Legacy {}
951 impl Sealed for Segwitv0 {}
952 impl Sealed for Tap {}
953 impl Sealed for NoChecks {}
954}