miniscript_qtum/miniscript/
context.rs

1// Written in 2019 by Sanket Kanjalkar and Andrew Poelstra
2// SPDX-License-Identifier: CC0-1.0
3
4use core::{fmt, hash};
5#[cfg(feature = "std")]
6use std::error;
7
8use qtum::constants::MAX_BLOCK_WEIGHT;
9use qtum::hashes::{hash160, ripemd160, sha256};
10
11use super::decode::ParseableKey;
12use crate::miniscript::limits::{
13    MAX_OPS_PER_SCRIPT, MAX_PUBKEYS_PER_MULTISIG, MAX_SCRIPTSIG_SIZE, MAX_SCRIPT_ELEMENT_SIZE,
14    MAX_SCRIPT_SIZE, MAX_STACK_SIZE, MAX_STANDARD_P2WSH_SCRIPT_SIZE,
15    MAX_STANDARD_P2WSH_STACK_ITEMS,
16};
17use crate::miniscript::types;
18use crate::prelude::*;
19use crate::util::witness_to_scriptsig;
20use crate::{hash256, Error, ForEachKey, Miniscript, MiniscriptKey, Terminal};
21
22/// Error for Script Context
23#[derive(Clone, PartialEq, Eq, Debug)]
24pub enum ScriptContextError {
25    /// Script Context does not permit PkH for non-malleability
26    /// It is not possible to estimate the pubkey size at the creation
27    /// time because of uncompressed pubkeys
28    MalleablePkH,
29    /// Script Context does not permit OrI for non-malleability
30    /// Legacy fragments allow non-minimal IF which results in malleability
31    MalleableOrI,
32    /// Script Context does not permit DupIf for non-malleability
33    /// Legacy fragments allow non-minimal IF which results in malleability
34    MalleableDupIf,
35    /// Only Compressed keys allowed under current descriptor
36    /// Segwitv0 fragments do not allow uncompressed pubkeys
37    CompressedOnly(String),
38    /// XOnly keys are only allowed in Tap context
39    /// The first element is key, and second element is current script context
40    XOnlyKeysNotAllowed(String, &'static str),
41    /// Tapscript descriptors cannot contain uncompressed keys
42    /// Tap context can contain compressed or xonly
43    UncompressedKeysNotAllowed,
44    /// At least one satisfaction path in the Miniscript fragment has more than
45    /// `MAX_STANDARD_P2WSH_STACK_ITEMS` (100) witness elements.
46    MaxWitnessItemssExceeded { actual: usize, limit: usize },
47    /// At least one satisfaction path in the Miniscript fragment contains more
48    /// than `MAX_OPS_PER_SCRIPT`(201) opcodes.
49    MaxOpCountExceeded,
50    /// The Miniscript(under segwit context) corresponding
51    /// Script would be larger than `MAX_STANDARD_P2WSH_SCRIPT_SIZE` bytes.
52    MaxWitnessScriptSizeExceeded,
53    /// The Miniscript (under p2sh context) corresponding Script would be
54    /// larger than `MAX_SCRIPT_ELEMENT_SIZE` bytes.
55    MaxRedeemScriptSizeExceeded,
56    /// The policy rules of bitcoin core only permit Script size upto 1650 bytes
57    MaxScriptSigSizeExceeded,
58    /// Impossible to satisfy the miniscript under the current context
59    ImpossibleSatisfaction,
60    /// No Multi Node in Taproot context
61    TaprootMultiDisabled,
62    /// Stack size exceeded in script execution
63    StackSizeLimitExceeded { actual: usize, limit: usize },
64    /// More than 20 keys in a Multi fragment
65    CheckMultiSigLimitExceeded,
66    /// MultiA is only allowed in post tapscript
67    MultiANotAllowed,
68}
69
70#[cfg(feature = "std")]
71impl error::Error for ScriptContextError {
72    fn cause(&self) -> Option<&dyn error::Error> {
73        use self::ScriptContextError::*;
74
75        match self {
76            MalleablePkH
77            | MalleableOrI
78            | MalleableDupIf
79            | CompressedOnly(_)
80            | XOnlyKeysNotAllowed(_, _)
81            | UncompressedKeysNotAllowed
82            | MaxWitnessItemssExceeded { .. }
83            | MaxOpCountExceeded
84            | MaxWitnessScriptSizeExceeded
85            | MaxRedeemScriptSizeExceeded
86            | MaxScriptSigSizeExceeded
87            | ImpossibleSatisfaction
88            | TaprootMultiDisabled
89            | StackSizeLimitExceeded { .. }
90            | CheckMultiSigLimitExceeded
91            | MultiANotAllowed => None,
92        }
93    }
94}
95
96impl fmt::Display for ScriptContextError {
97    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98        match *self {
99            ScriptContextError::MalleablePkH => write!(f, "PkH is malleable under Legacy rules"),
100            ScriptContextError::MalleableOrI => write!(f, "OrI is malleable under Legacy rules"),
101            ScriptContextError::MalleableDupIf => {
102                write!(f, "DupIf is malleable under Legacy rules")
103            }
104            ScriptContextError::CompressedOnly(ref pk) => {
105                write!(
106                    f,
107                    "Only Compressed pubkeys are allowed in segwit context. Found {}",
108                    pk
109                )
110            }
111            ScriptContextError::XOnlyKeysNotAllowed(ref pk, ref ctx) => {
112                write!(f, "x-only key {} not allowed in {}", pk, ctx)
113            }
114            ScriptContextError::UncompressedKeysNotAllowed => {
115                write!(
116                    f,
117                    "uncompressed keys cannot be used in Taproot descriptors."
118                )
119            }
120            ScriptContextError::MaxWitnessItemssExceeded { actual, limit } => write!(
121                f,
122                "At least one spending path in the Miniscript fragment has {} more \
123                 witness items than limit {}.",
124                actual, limit
125            ),
126            ScriptContextError::MaxOpCountExceeded => write!(
127                f,
128                "At least one satisfaction path in the Miniscript fragment contains \
129                 more than MAX_OPS_PER_SCRIPT opcodes."
130            ),
131            ScriptContextError::MaxWitnessScriptSizeExceeded => write!(
132                f,
133                "The Miniscript corresponding Script would be larger than \
134                    MAX_STANDARD_P2WSH_SCRIPT_SIZE bytes."
135            ),
136            ScriptContextError::MaxRedeemScriptSizeExceeded => write!(
137                f,
138                "The Miniscript corresponding Script would be larger than \
139                MAX_SCRIPT_ELEMENT_SIZE bytes."
140            ),
141            ScriptContextError::MaxScriptSigSizeExceeded => write!(
142                f,
143                "At least one satisfaction in Miniscript would be larger than \
144                MAX_SCRIPTSIG_SIZE scriptsig"
145            ),
146            ScriptContextError::ImpossibleSatisfaction => {
147                write!(
148                    f,
149                    "Impossible to satisfy Miniscript under the current context"
150                )
151            }
152            ScriptContextError::TaprootMultiDisabled => {
153                write!(f, "Invalid use of Multi node in taproot context")
154            }
155            ScriptContextError::StackSizeLimitExceeded { actual, limit } => {
156                write!(
157                    f,
158                    "Stack limit {} can exceed the allowed limit {} in at least one script path during script execution",
159                    actual, limit
160                )
161            }
162            ScriptContextError::CheckMultiSigLimitExceeded => {
163                write!(
164                    f,
165                    "CHECkMULTISIG ('multi()' descriptor) only supports up to 20 pubkeys"
166                )
167            }
168            ScriptContextError::MultiANotAllowed => {
169                write!(f, "Multi a(CHECKSIGADD) only allowed post tapscript")
170            }
171        }
172    }
173}
174
175/// The ScriptContext for Miniscript. Additional type information associated with
176/// miniscript that is used for carrying out checks that dependent on the
177/// context under which the script is used.
178/// For example, disallowing uncompressed keys in Segwit context
179pub trait ScriptContext:
180    fmt::Debug + Clone + Ord + PartialOrd + Eq + PartialEq + hash::Hash + private::Sealed
181where
182    Self::Key: MiniscriptKey<Sha256 = sha256::Hash>,
183    Self::Key: MiniscriptKey<Hash256 = hash256::Hash>,
184    Self::Key: MiniscriptKey<Ripemd160 = ripemd160::Hash>,
185    Self::Key: MiniscriptKey<Hash160 = hash160::Hash>,
186{
187    /// The consensus key associated with the type. Must be a parseable key
188    type Key: ParseableKey;
189    /// Depending on ScriptContext, fragments can be malleable. For Example,
190    /// under Legacy context, PkH is malleable because it is possible to
191    /// estimate the cost of satisfaction because of compressed keys
192    /// This is currently only used in compiler code for removing malleable
193    /// compilations.
194    /// This does NOT recursively check if the children of the fragment are
195    /// valid or not. Since the compilation proceeds in a leaf to root fashion,
196    /// a recursive check is unnecessary.
197    fn check_terminal_non_malleable<Pk: MiniscriptKey>(
198        _frag: &Terminal<Pk, Self>,
199    ) -> Result<(), ScriptContextError>;
200
201    /// Check whether the given satisfaction is valid under the ScriptContext
202    /// For example, segwit satisfactions may fail if the witness len is more
203    /// 3600 or number of stack elements are more than 100.
204    fn check_witness<Pk: MiniscriptKey>(_witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
205        // Only really need to do this for segwitv0 and legacy
206        // Bare is already restrcited by standardness rules
207        // and would reach these limits.
208        Ok(())
209    }
210
211    /// Each context has slightly different rules on what Pks are allowed in descriptors
212    /// Legacy/Bare does not allow x_only keys
213    /// Segwit does not allow uncompressed keys and x_only keys
214    /// Tapscript does not allow uncompressed keys
215    fn check_pk<Pk: MiniscriptKey>(pk: &Pk) -> Result<(), ScriptContextError>;
216
217    /// Depending on script context, the size of a satifaction witness may slightly differ.
218    fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize>;
219    /// Depending on script Context, some of the Terminals might not
220    /// be valid under the current consensus rules.
221    /// Or some of the script resource limits may have been exceeded.
222    /// These miniscripts would never be accepted by the Bitcoin network and hence
223    /// it is safe to discard them
224    /// For example, in Segwit Context with MiniscriptKey as qtum::PublicKey
225    /// uncompressed public keys are non-standard and thus invalid.
226    /// In LegacyP2SH context, scripts above 520 bytes are invalid.
227    /// Post Tapscript upgrade, this would have to consider other nodes.
228    /// This does *NOT* recursively check the miniscript fragments.
229    fn check_global_consensus_validity<Pk: MiniscriptKey>(
230        _ms: &Miniscript<Pk, Self>,
231    ) -> Result<(), ScriptContextError> {
232        Ok(())
233    }
234
235    /// Depending on script Context, some of the script resource limits
236    /// may have been exceeded under the current bitcoin core policy rules
237    /// These miniscripts would never be accepted by the Bitcoin network and hence
238    /// it is safe to discard them. (unless explicitly disabled by non-standard flag)
239    /// For example, in Segwit Context with MiniscriptKey as qtum::PublicKey
240    /// scripts over 3600 bytes are invalid.
241    /// Post Tapscript upgrade, this would have to consider other nodes.
242    /// This does *NOT* recursively check the miniscript fragments.
243    fn check_global_policy_validity<Pk: MiniscriptKey>(
244        _ms: &Miniscript<Pk, Self>,
245    ) -> Result<(), ScriptContextError> {
246        Ok(())
247    }
248
249    /// Consensus rules at the Miniscript satisfaction time.
250    /// It is possible that some paths of miniscript may exceed resource limits
251    /// and our current satisfier and lifting analysis would not work correctly.
252    /// For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes.
253    fn check_local_consensus_validity<Pk: MiniscriptKey>(
254        _ms: &Miniscript<Pk, Self>,
255    ) -> Result<(), ScriptContextError> {
256        Ok(())
257    }
258
259    /// Policy rules at the Miniscript satisfaction time.
260    /// It is possible that some paths of miniscript may exceed resource limits
261    /// and our current satisfier and lifting analysis would not work correctly.
262    /// For example, satisfaction path in Legacy context scriptSig more
263    /// than 1650 bytes
264    fn check_local_policy_validity<Pk: MiniscriptKey>(
265        _ms: &Miniscript<Pk, Self>,
266    ) -> Result<(), ScriptContextError> {
267        Ok(())
268    }
269
270    /// Check the consensus + policy(if not disabled) rules that are not based
271    /// satisfaction
272    fn check_global_validity<Pk: MiniscriptKey>(
273        ms: &Miniscript<Pk, Self>,
274    ) -> Result<(), ScriptContextError> {
275        Self::check_global_consensus_validity(ms)?;
276        Self::check_global_policy_validity(ms)?;
277        Ok(())
278    }
279
280    /// Check the consensus + policy(if not disabled) rules including the
281    /// ones for satisfaction
282    fn check_local_validity<Pk: MiniscriptKey>(
283        ms: &Miniscript<Pk, Self>,
284    ) -> Result<(), ScriptContextError> {
285        Self::check_global_consensus_validity(ms)?;
286        Self::check_global_policy_validity(ms)?;
287        Self::check_local_consensus_validity(ms)?;
288        Self::check_local_policy_validity(ms)?;
289        Ok(())
290    }
291
292    /// Check whether the top-level is type B
293    fn top_level_type_check<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
294        if ms.ty.corr.base != types::Base::B {
295            return Err(Error::NonTopLevel(format!("{:?}", ms)));
296        }
297        // (Ab)use `for_each_key` to record the number of derivation paths a multipath key has.
298        #[derive(PartialEq)]
299        enum MultipathLenChecker {
300            SinglePath,
301            MultipathLen(usize),
302            LenMismatch,
303        }
304
305        let mut checker = MultipathLenChecker::SinglePath;
306        ms.for_each_key(|key| {
307            match key.num_der_paths() {
308                0 | 1 => {}
309                n => match checker {
310                    MultipathLenChecker::SinglePath => {
311                        checker = MultipathLenChecker::MultipathLen(n);
312                    }
313                    MultipathLenChecker::MultipathLen(len) => {
314                        if len != n {
315                            checker = MultipathLenChecker::LenMismatch;
316                        }
317                    }
318                    MultipathLenChecker::LenMismatch => {}
319                },
320            }
321            true
322        });
323
324        if checker == MultipathLenChecker::LenMismatch {
325            return Err(Error::MultipathDescLenMismatch);
326        }
327        Ok(())
328    }
329
330    /// Other top level checks that are context specific
331    fn other_top_level_checks<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
332        Ok(())
333    }
334
335    /// Check top level consensus rules.
336    // All the previous check_ were applied at each fragment while parsing script
337    // Because if any of sub-miniscripts failed the reource level check, the entire
338    // miniscript would also be invalid. However, there are certain checks like
339    // in Bare context, only c:pk(key) (P2PK),
340    // c:pk_h(key) (P2PKH), and thresh_m(k,...) up to n=3 are allowed
341    // that are only applicable at the top-level
342    // We can also combine the top-level check for Base::B here
343    // even though it does not depend on context, but helps in cleaner code
344    fn top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
345        Self::top_level_type_check(ms)?;
346        Self::other_top_level_checks(ms)
347    }
348
349    /// The type of signature required for satisfaction
350    // We need to context decide whether the serialize pk to 33 byte or 32 bytes.
351    // And to decide which type of signatures to look for during satisfaction
352    fn sig_type() -> SigType;
353
354    /// Get the len of public key when serialized based on context
355    /// Note that this includes the serialization prefix. Returns
356    /// 34/66 for Bare/Legacy based on key compressedness
357    /// 34 for Segwitv0, 33 for Tap
358    fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize;
359
360    /// Local helper function to display error messages with context
361    fn name_str() -> &'static str;
362}
363
364/// Signature algorithm type
365#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
366pub enum SigType {
367    /// Ecdsa signature
368    Ecdsa,
369    /// Schnorr Signature
370    Schnorr,
371}
372
373/// Legacy ScriptContext
374/// To be used as P2SH scripts
375/// For creation of Bare scriptpubkeys, construct the Miniscript
376/// under `Bare` ScriptContext
377#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
378pub enum Legacy {}
379
380impl ScriptContext for Legacy {
381    type Key = qtum::PublicKey;
382    fn check_terminal_non_malleable<Pk: MiniscriptKey>(
383        frag: &Terminal<Pk, Self>,
384    ) -> Result<(), ScriptContextError> {
385        match *frag {
386            Terminal::PkH(ref _pkh) => Err(ScriptContextError::MalleablePkH),
387            Terminal::RawPkH(ref _pk) => Err(ScriptContextError::MalleablePkH),
388            Terminal::OrI(ref _a, ref _b) => Err(ScriptContextError::MalleableOrI),
389            Terminal::DupIf(ref _ms) => Err(ScriptContextError::MalleableDupIf),
390            _ => Ok(()),
391        }
392    }
393
394    // Only compressed and uncompressed public keys are allowed in Legacy context
395    fn check_pk<Pk: MiniscriptKey>(pk: &Pk) -> Result<(), ScriptContextError> {
396        if pk.is_x_only_key() {
397            Err(ScriptContextError::XOnlyKeysNotAllowed(
398                pk.to_string(),
399                Self::name_str(),
400            ))
401        } else {
402            Ok(())
403        }
404    }
405
406    fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
407        // In future, we could avoid by having a function to count only
408        // len of script instead of converting it.
409        if witness_to_scriptsig(witness).len() > MAX_SCRIPTSIG_SIZE {
410            return Err(ScriptContextError::MaxScriptSigSizeExceeded);
411        }
412        Ok(())
413    }
414
415    fn check_global_consensus_validity<Pk: MiniscriptKey>(
416        ms: &Miniscript<Pk, Self>,
417    ) -> Result<(), ScriptContextError> {
418        if ms.ext.pk_cost > MAX_SCRIPT_ELEMENT_SIZE {
419            return Err(ScriptContextError::MaxRedeemScriptSizeExceeded);
420        }
421
422        match ms.node {
423            Terminal::PkK(ref pk) => Self::check_pk(pk),
424            Terminal::Multi(_k, ref pks) => {
425                if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
426                    return Err(ScriptContextError::CheckMultiSigLimitExceeded);
427                }
428                for pk in pks.iter() {
429                    Self::check_pk(pk)?;
430                }
431                Ok(())
432            }
433            Terminal::MultiA(..) => {
434                return Err(ScriptContextError::MultiANotAllowed);
435            }
436            _ => Ok(()),
437        }
438    }
439
440    fn check_local_consensus_validity<Pk: MiniscriptKey>(
441        ms: &Miniscript<Pk, Self>,
442    ) -> Result<(), ScriptContextError> {
443        match ms.ext.ops.op_count() {
444            None => Err(ScriptContextError::MaxOpCountExceeded),
445            Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
446                Err(ScriptContextError::MaxOpCountExceeded)
447            }
448            _ => Ok(()),
449        }
450    }
451
452    fn check_local_policy_validity<Pk: MiniscriptKey>(
453        ms: &Miniscript<Pk, Self>,
454    ) -> Result<(), ScriptContextError> {
455        // Legacy scripts permit upto 1000 stack elements, 520 bytes consensus limits
456        // on P2SH size, it is not possible to reach the 1000 elements limit and hence
457        // we do not check it.
458        match ms.max_satisfaction_size() {
459            Err(_e) => Err(ScriptContextError::ImpossibleSatisfaction),
460            Ok(size) if size > MAX_SCRIPTSIG_SIZE => {
461                Err(ScriptContextError::MaxScriptSigSizeExceeded)
462            }
463            _ => Ok(()),
464        }
465    }
466
467    fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
468        // The scriptSig cost is the second element of the tuple
469        ms.ext.max_sat_size.map(|x| x.1)
470    }
471
472    fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize {
473        if pk.is_uncompressed() {
474            66
475        } else {
476            34
477        }
478    }
479
480    fn name_str() -> &'static str {
481        "Legacy/p2sh"
482    }
483
484    fn sig_type() -> SigType {
485        SigType::Ecdsa
486    }
487}
488
489/// Segwitv0 ScriptContext
490#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
491pub enum Segwitv0 {}
492
493impl ScriptContext for Segwitv0 {
494    type Key = qtum::PublicKey;
495    fn check_terminal_non_malleable<Pk: MiniscriptKey>(
496        _frag: &Terminal<Pk, Self>,
497    ) -> Result<(), ScriptContextError> {
498        Ok(())
499    }
500
501    // No x-only keys or uncompressed keys in Segwitv0 context
502    fn check_pk<Pk: MiniscriptKey>(pk: &Pk) -> Result<(), ScriptContextError> {
503        if pk.is_uncompressed() {
504            Err(ScriptContextError::UncompressedKeysNotAllowed)
505        } else if pk.is_x_only_key() {
506            Err(ScriptContextError::XOnlyKeysNotAllowed(
507                pk.to_string(),
508                Self::name_str(),
509            ))
510        } else {
511            Ok(())
512        }
513    }
514
515    fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
516        if witness.len() > MAX_STANDARD_P2WSH_STACK_ITEMS {
517            return Err(ScriptContextError::MaxWitnessItemssExceeded {
518                actual: witness.len(),
519                limit: MAX_STANDARD_P2WSH_STACK_ITEMS,
520            });
521        }
522        Ok(())
523    }
524
525    fn check_global_consensus_validity<Pk: MiniscriptKey>(
526        ms: &Miniscript<Pk, Self>,
527    ) -> Result<(), ScriptContextError> {
528        if ms.ext.pk_cost > MAX_SCRIPT_SIZE {
529            return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
530        }
531
532        match ms.node {
533            Terminal::PkK(ref pk) => Self::check_pk(pk),
534            Terminal::Multi(_k, ref pks) => {
535                if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
536                    return Err(ScriptContextError::CheckMultiSigLimitExceeded);
537                }
538                for pk in pks.iter() {
539                    Self::check_pk(pk)?;
540                }
541                Ok(())
542            }
543            Terminal::MultiA(..) => Err(ScriptContextError::MultiANotAllowed),
544            _ => Ok(()),
545        }
546    }
547
548    fn check_local_consensus_validity<Pk: MiniscriptKey>(
549        ms: &Miniscript<Pk, Self>,
550    ) -> Result<(), ScriptContextError> {
551        match ms.ext.ops.op_count() {
552            None => Err(ScriptContextError::MaxOpCountExceeded),
553            Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
554                Err(ScriptContextError::MaxOpCountExceeded)
555            }
556            _ => Ok(()),
557        }
558    }
559
560    fn check_global_policy_validity<Pk: MiniscriptKey>(
561        ms: &Miniscript<Pk, Self>,
562    ) -> Result<(), ScriptContextError> {
563        if ms.ext.pk_cost > MAX_STANDARD_P2WSH_SCRIPT_SIZE {
564            return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
565        }
566        Ok(())
567    }
568
569    fn check_local_policy_validity<Pk: MiniscriptKey>(
570        ms: &Miniscript<Pk, Self>,
571    ) -> Result<(), ScriptContextError> {
572        // We don't need to know if this is actually a p2wsh as the standard satisfaction for
573        // other Segwitv0 defined programs all require (much) less than 100 elements.
574        // The witness script item is accounted for in max_satisfaction_witness_elements().
575        match ms.max_satisfaction_witness_elements() {
576            // No possible satisfactions
577            Err(_e) => Err(ScriptContextError::ImpossibleSatisfaction),
578            Ok(max_witness_items) if max_witness_items > MAX_STANDARD_P2WSH_STACK_ITEMS => {
579                Err(ScriptContextError::MaxWitnessItemssExceeded {
580                    actual: max_witness_items,
581                    limit: MAX_STANDARD_P2WSH_STACK_ITEMS,
582                })
583            }
584            _ => Ok(()),
585        }
586    }
587
588    fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
589        // The witness stack cost is the first element of the tuple
590        ms.ext.max_sat_size.map(|x| x.0)
591    }
592
593    fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
594        34
595    }
596
597    fn name_str() -> &'static str {
598        "Segwitv0"
599    }
600
601    fn sig_type() -> SigType {
602        SigType::Ecdsa
603    }
604}
605
606/// Tap ScriptContext
607#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
608pub enum Tap {}
609
610impl ScriptContext for Tap {
611    type Key = qtum::secp256k1::XOnlyPublicKey;
612    fn check_terminal_non_malleable<Pk: MiniscriptKey>(
613        _frag: &Terminal<Pk, Self>,
614    ) -> Result<(), ScriptContextError> {
615        // No fragment is malleable in tapscript context.
616        // Certain fragments like Multi are invalid, but are not malleable
617        Ok(())
618    }
619
620    // No uncompressed keys in Tap context
621    fn check_pk<Pk: MiniscriptKey>(pk: &Pk) -> Result<(), ScriptContextError> {
622        if pk.is_uncompressed() {
623            Err(ScriptContextError::UncompressedKeysNotAllowed)
624        } else {
625            Ok(())
626        }
627    }
628
629    fn check_witness<Pk: MiniscriptKey>(witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
630        // Note that tapscript has a 1000 limit compared to 100 of segwitv0
631        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>(
641        ms: &Miniscript<Pk, Self>,
642    ) -> Result<(), ScriptContextError> {
643        // No script size checks for global consensus rules
644        // Should we really check for block limits here.
645        // When the transaction sizes get close to block limits,
646        // some guarantees are not easy to satisfy because of knapsack
647        // constraints
648        if ms.ext.pk_cost > MAX_BLOCK_WEIGHT as usize {
649            return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
650        }
651
652        match ms.node {
653            Terminal::PkK(ref pk) => Self::check_pk(pk),
654            Terminal::MultiA(_, ref keys) => {
655                for pk in keys.iter() {
656                    Self::check_pk(pk)?;
657                }
658                Ok(())
659            }
660            Terminal::Multi(..) => Err(ScriptContextError::TaprootMultiDisabled),
661            _ => Ok(()),
662        }
663    }
664
665    fn check_local_consensus_validity<Pk: MiniscriptKey>(
666        ms: &Miniscript<Pk, Self>,
667    ) -> Result<(), ScriptContextError> {
668        // Taproot introduces the concept of sigops budget.
669        // All valid miniscripts satisfy the sigops constraint
670        // Whenever we add new fragment that uses pk(pk() or multi based on checksigadd)
671        // miniscript typing rules ensure that pk when executed successfully has it's
672        // own unique signature. That is, there is no way to re-use signatures from one CHECKSIG
673        // to another checksig. In other words, for each successfully executed checksig
674        // will have it's corresponding 64 bytes signature.
675        // sigops budget = witness_script.len() + witness.size() + 50
676        // Each signature will cover it's own cost(64 > 50) and thus will will never exceed the budget
677        if let (Some(s), Some(h)) = (
678            ms.ext.exec_stack_elem_count_sat,
679            ms.ext.stack_elem_count_sat,
680        ) {
681            if s + h > MAX_STACK_SIZE {
682                return Err(ScriptContextError::StackSizeLimitExceeded {
683                    actual: s + h,
684                    limit: MAX_STACK_SIZE,
685                });
686            }
687        }
688        Ok(())
689    }
690
691    fn check_global_policy_validity<Pk: MiniscriptKey>(
692        _ms: &Miniscript<Pk, Self>,
693    ) -> Result<(), ScriptContextError> {
694        // No script rules, rules are subject to entire tx rules
695        Ok(())
696    }
697
698    fn check_local_policy_validity<Pk: MiniscriptKey>(
699        _ms: &Miniscript<Pk, Self>,
700    ) -> Result<(), ScriptContextError> {
701        Ok(())
702    }
703
704    fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
705        // The witness stack cost is the first element of the tuple
706        ms.ext.max_sat_size.map(|x| x.0)
707    }
708
709    fn sig_type() -> SigType {
710        SigType::Schnorr
711    }
712
713    fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
714        33
715    }
716
717    fn name_str() -> &'static str {
718        "TapscriptCtx"
719    }
720}
721
722/// Bare ScriptContext
723/// To be used as raw script pubkeys
724/// In general, it is not recommended to use Bare descriptors
725/// as they as strongly limited by standardness policies.
726#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
727pub enum BareCtx {}
728
729impl ScriptContext for BareCtx {
730    type Key = qtum::PublicKey;
731    fn check_terminal_non_malleable<Pk: MiniscriptKey>(
732        _frag: &Terminal<Pk, Self>,
733    ) -> Result<(), ScriptContextError> {
734        // Bare fragments can't contain miniscript because of standardness rules
735        // This function is only used in compiler which already checks the standardness
736        // and consensus rules, and because of the limited allowance of bare scripts
737        // we need check for malleable scripts
738        Ok(())
739    }
740
741    // No x-only keys in Bare context
742    fn check_pk<Pk: MiniscriptKey>(pk: &Pk) -> Result<(), ScriptContextError> {
743        if pk.is_x_only_key() {
744            Err(ScriptContextError::XOnlyKeysNotAllowed(
745                pk.to_string(),
746                Self::name_str(),
747            ))
748        } else {
749            Ok(())
750        }
751    }
752
753    fn check_global_consensus_validity<Pk: MiniscriptKey>(
754        ms: &Miniscript<Pk, Self>,
755    ) -> Result<(), ScriptContextError> {
756        if ms.ext.pk_cost > MAX_SCRIPT_SIZE {
757            return Err(ScriptContextError::MaxWitnessScriptSizeExceeded);
758        }
759        match ms.node {
760            Terminal::PkK(ref key) => Self::check_pk(key),
761            Terminal::Multi(_k, ref pks) => {
762                if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
763                    return Err(ScriptContextError::CheckMultiSigLimitExceeded);
764                }
765                for pk in pks.iter() {
766                    Self::check_pk(pk)?;
767                }
768                Ok(())
769            }
770            Terminal::MultiA(..) => Err(ScriptContextError::MultiANotAllowed),
771            _ => Ok(()),
772        }
773    }
774
775    fn check_local_consensus_validity<Pk: MiniscriptKey>(
776        ms: &Miniscript<Pk, Self>,
777    ) -> Result<(), ScriptContextError> {
778        match ms.ext.ops.op_count() {
779            None => Err(ScriptContextError::MaxOpCountExceeded),
780            Some(op_count) if op_count > MAX_OPS_PER_SCRIPT => {
781                Err(ScriptContextError::MaxOpCountExceeded)
782            }
783            _ => Ok(()),
784        }
785    }
786
787    fn other_top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
788        match &ms.node {
789            Terminal::Check(ref ms) => match &ms.node {
790                Terminal::RawPkH(_pkh) => Ok(()),
791                Terminal::PkK(_pk) | Terminal::PkH(_pk) => Ok(()),
792                _ => Err(Error::NonStandardBareScript),
793            },
794            Terminal::Multi(_k, subs) if subs.len() <= 3 => Ok(()),
795            _ => Err(Error::NonStandardBareScript),
796        }
797    }
798
799    fn max_satisfaction_size<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Option<usize> {
800        // The witness stack cost is the first element of the tuple
801        ms.ext.max_sat_size.map(|x| x.1)
802    }
803
804    fn pk_len<Pk: MiniscriptKey>(pk: &Pk) -> usize {
805        if pk.is_uncompressed() {
806            66
807        } else {
808            34
809        }
810    }
811
812    fn name_str() -> &'static str {
813        "BareCtx"
814    }
815
816    fn sig_type() -> SigType {
817        SigType::Ecdsa
818    }
819}
820
821/// "No Checks Ecdsa" Context
822///
823/// Used by the "satisified constraints" iterator, which is intended to read
824/// scripts off of the blockchain without doing any sanity checks on them.
825/// This context should *NOT* be used unless you know what you are doing.
826#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
827pub enum NoChecks {}
828impl ScriptContext for NoChecks {
829    // todo: When adding support for interpreter, we need a enum with all supported keys here
830    type Key = qtum::PublicKey;
831    fn check_terminal_non_malleable<Pk: MiniscriptKey>(
832        _frag: &Terminal<Pk, Self>,
833    ) -> Result<(), ScriptContextError> {
834        Ok(())
835    }
836
837    // No checks in NoChecks
838    fn check_pk<Pk: MiniscriptKey>(_pk: &Pk) -> Result<(), ScriptContextError> {
839        Ok(())
840    }
841
842    fn check_global_policy_validity<Pk: MiniscriptKey>(
843        _ms: &Miniscript<Pk, Self>,
844    ) -> Result<(), ScriptContextError> {
845        Ok(())
846    }
847
848    fn check_global_consensus_validity<Pk: MiniscriptKey>(
849        _ms: &Miniscript<Pk, Self>,
850    ) -> Result<(), ScriptContextError> {
851        Ok(())
852    }
853
854    fn check_local_policy_validity<Pk: MiniscriptKey>(
855        _ms: &Miniscript<Pk, Self>,
856    ) -> Result<(), ScriptContextError> {
857        Ok(())
858    }
859
860    fn check_local_consensus_validity<Pk: MiniscriptKey>(
861        _ms: &Miniscript<Pk, Self>,
862    ) -> Result<(), ScriptContextError> {
863        Ok(())
864    }
865
866    fn max_satisfaction_size<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Option<usize> {
867        panic!("Tried to compute a satisfaction size bound on a no-checks ecdsa miniscript")
868    }
869
870    fn pk_len<Pk: MiniscriptKey>(_pk: &Pk) -> usize {
871        panic!("Tried to compute a pk len bound on a no-checks ecdsa miniscript")
872    }
873
874    fn name_str() -> &'static str {
875        // Internally used code
876        "NochecksEcdsa"
877    }
878
879    fn check_witness<Pk: MiniscriptKey>(_witness: &[Vec<u8>]) -> Result<(), ScriptContextError> {
880        // Only really need to do this for segwitv0 and legacy
881        // Bare is already restrcited by standardness rules
882        // and would reach these limits.
883        Ok(())
884    }
885
886    fn check_global_validity<Pk: MiniscriptKey>(
887        ms: &Miniscript<Pk, Self>,
888    ) -> Result<(), ScriptContextError> {
889        Self::check_global_consensus_validity(ms)?;
890        Self::check_global_policy_validity(ms)?;
891        Ok(())
892    }
893
894    fn check_local_validity<Pk: MiniscriptKey>(
895        ms: &Miniscript<Pk, Self>,
896    ) -> Result<(), ScriptContextError> {
897        Self::check_global_consensus_validity(ms)?;
898        Self::check_global_policy_validity(ms)?;
899        Self::check_local_consensus_validity(ms)?;
900        Self::check_local_policy_validity(ms)?;
901        Ok(())
902    }
903
904    fn top_level_type_check<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
905        if ms.ty.corr.base != types::Base::B {
906            return Err(Error::NonTopLevel(format!("{:?}", ms)));
907        }
908        Ok(())
909    }
910
911    fn other_top_level_checks<Pk: MiniscriptKey>(_ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
912        Ok(())
913    }
914
915    fn top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
916        Self::top_level_type_check(ms)?;
917        Self::other_top_level_checks(ms)
918    }
919
920    fn sig_type() -> SigType {
921        SigType::Ecdsa
922    }
923}
924
925/// Private Mod to prevent downstream from implementing this public trait
926mod private {
927    use super::{BareCtx, Legacy, NoChecks, Segwitv0, Tap};
928
929    pub trait Sealed {}
930
931    // Implement for those same types, but no others.
932    impl Sealed for BareCtx {}
933    impl Sealed for Legacy {}
934    impl Sealed for Segwitv0 {}
935    impl Sealed for Tap {}
936    impl Sealed for NoChecks {}
937}