elements_miniscript/interpreter/
error.rs

1// Written in 2019 by Sanket Kanjular and Andrew Poelstra
2// SPDX-License-Identifier: CC0-1.0
3
4use std::{error, fmt};
5
6use elements::hashes::hash160;
7use elements::hex::ToHex;
8use elements::{secp256k1_zkp, taproot};
9use {bitcoin, elements};
10
11use super::BitcoinKey;
12use crate::extensions::EvalError;
13
14/// Detailed Error type for Interpreter
15#[derive(Debug)]
16pub enum Error {
17    /// Could not satisfy, absolute locktime not met
18    AbsoluteLocktimeNotMet(u32),
19    /// Could not satisfy, lock time values are different units
20    AbsoluteLocktimeComparisonInvalid(u32, u32),
21    /// Cannot Infer a taproot descriptor
22    /// Key spends cannot infer the internal key of the descriptor
23    /// Inferring script spends is possible, but is hidden nodes are currently
24    /// not supported in descriptor spec
25    CannotInferTrDescriptors,
26    /// Error parsing taproot control block
27    ControlBlockParse(taproot::TaprootError),
28    /// Tap control block(merkle proofs + tweak) verification error
29    ControlBlockVerificationError,
30    /// General Interpreter error.
31    CouldNotEvaluate,
32    /// EcdsaSig related error
33    EcdsaSig(bitcoin::ecdsa::Error),
34    /// We expected a push (including a `OP_1` but no other numeric pushes)
35    ExpectedPush,
36    /// The preimage to the hash function must be exactly 32 bytes.
37    HashPreimageLengthMismatch,
38    /// Incorrect scriptPubKey (pay-to-pubkeyhash) for the provided public key
39    IncorrectPubkeyHash,
40    /// Incorrect scriptPubKey for the provided redeem script
41    IncorrectScriptHash,
42    /// Incorrect scriptPubKey (pay-to-witness-pubkeyhash) for the provided public key
43    IncorrectWPubkeyHash,
44    /// Incorrect scriptPubKey for the provided witness script
45    IncorrectWScriptHash,
46    /// MultiSig missing at least `1` witness elements out of `k + 1` required
47    InsufficientSignaturesMultiSig,
48    /// Invalid Sighash type
49    InvalidSchnorrSighashType(Vec<u8>),
50    /// ecdsa Signature failed to verify
51    InvalidEcdsaSignature(bitcoin::PublicKey),
52    /// Signature failed to verify
53    InvalidSchnorrSignature(bitcoin::key::XOnlyPublicKey),
54    /// Last byte of this signature isn't a standard sighash type
55    NonStandardSighash(Vec<u8>),
56    /// Miniscript error
57    Miniscript(crate::Error),
58    /// MultiSig requires 1 extra zero element apart from the `k` signatures
59    MissingExtraZeroMultiSig,
60    /// Script abortion because of incorrect dissatisfaction for multisig.
61    /// Any input witness apart from sat(0 sig ...) or nsat(0 0 ..) leads to
62    /// this error. This is network standardness assumption and miniscript only
63    /// supports standard scripts
64    MultiSigEvaluationError,
65    ///Witness must be empty for pre-segwit transactions
66    NonEmptyWitness,
67    ///ScriptSig must be empty for pure segwit transactions
68    NonEmptyScriptSig,
69    /// Script abortion because of incorrect dissatisfaction for Checksig.
70    /// Any input witness apart from sat(sig) or nsat(0) leads to
71    /// this error. This is network standardness assumption and miniscript only
72    /// supports standard scripts
73    // note that BitcoinKey is not exported, create a data structure to convey the same
74    // information in error
75    PkEvaluationError(PkEvalErrInner),
76    /// The Public Key hash check for the given pubkey. This occurs in `PkH`
77    /// node when the given key does not match to Hash in script.
78    PkHashVerifyFail(hash160::Hash),
79    /// Parse Error while parsing a `stack::Element::Push` as a Pubkey. Both
80    /// 33 byte and 65 bytes are supported.
81    PubkeyParseError,
82    /// Parse Error while parsing a `stack::Element::Push` as a XOnlyPublicKey (32 bytes)
83    XOnlyPublicKeyParseError,
84    /// Could not satisfy, relative locktime not met
85    RelativeLocktimeNotMet(u32),
86    /// Forward-secp related errors
87    Secp(secp256k1_zkp::Error),
88    /// Miniscript requires the entire top level script to be satisfied.
89    ScriptSatisfactionError,
90    /// Schnorr Signature error
91    SchnorrSig(elements::SchnorrSigError),
92    /// Errors in signature hash calculations
93    SighashError(elements::sighash::Error),
94    /// Taproot Annex Unsupported
95    TapAnnexUnsupported,
96    /// An uncompressed public key was encountered in a context where it is
97    /// disallowed (e.g. in a Segwit script or p2wpkh output)
98    UncompressedPubkey,
99    /// Got `stack::Element::Satisfied` or `stack::Element::Dissatisfied` when the
100    /// interpreter was expecting `stack::Element::Push`
101    UnexpectedStackBoolean,
102    /// Unexpected Stack End, caused by popping extra elements from stack
103    UnexpectedStackEnd,
104    /// Unexpected Stack Push `stack::Element::Push` element when the interpreter
105    /// was expecting a stack boolean `stack::Element::Satisfied` or
106    /// `stack::Element::Dissatisfied`
107    UnexpectedStackElementPush,
108    /// Verify expects stack top element exactly to be `stack::Element::Satisfied`.
109    /// This error is raised even if the stack top is `stack::Element::Push`.
110    VerifyFailed,
111    /// Incorrect Covenant Witness
112    IncorrectCovenantWitness,
113    /// Covenant witness size mismatch
114    /// eg: supplied a witness at
115    /// nVersion with 5 bytes instead of 4
116    CovWitnessSizeErr {
117        /// Position of the item in sighash Msg
118        pos: usize,
119        /// Expected size
120        expected: usize,
121        /// Actual size
122        actual: usize,
123    },
124    /// Errors related to extensions.
125    ArithError(EvalError),
126}
127
128impl fmt::Display for Error {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        match *self {
131            Error::AbsoluteLocktimeNotMet(n) => write!(
132                f,
133                "required absolute locktime CLTV of {} blocks, not met",
134                n
135            ),
136            Error::AbsoluteLocktimeComparisonInvalid(n, lock_time) => write!(
137                f,
138                "could not satisfy, lock time values are different units n: {} lock_time: {}",
139                n, lock_time
140            ),
141            Error::CannotInferTrDescriptors => write!(f, "Cannot infer taproot descriptors"),
142            Error::ControlBlockParse(ref e) => write!(f, "Control block parse error {}", e),
143            Error::ControlBlockVerificationError => {
144                f.write_str("Control block verification failed")
145            }
146            Error::EcdsaSig(ref s) => write!(f, "Ecdsa sig error: {}", s),
147            Error::ExpectedPush => f.write_str("expected push in script"),
148            Error::CouldNotEvaluate => f.write_str("Interpreter Error: Could not evaluate"),
149            Error::HashPreimageLengthMismatch => f.write_str("Hash preimage should be 32 bytes"),
150            Error::IncorrectPubkeyHash => f.write_str("public key did not match scriptpubkey"),
151            Error::IncorrectScriptHash => f.write_str("redeem script did not match scriptpubkey"),
152            Error::IncorrectWPubkeyHash => {
153                f.write_str("public key did not match scriptpubkey (segwit v0)")
154            }
155            Error::IncorrectWScriptHash => f.write_str("witness script did not match scriptpubkey"),
156            Error::InsufficientSignaturesMultiSig => f.write_str("Insufficient signatures for CMS"),
157            Error::InvalidSchnorrSighashType(ref sig) => write!(
158                f,
159                "Invalid sighash type for schnorr signature '{}'",
160                sig.to_hex()
161            ),
162            Error::InvalidEcdsaSignature(pk) => write!(f, "bad ecdsa signature with pk {}", pk),
163            Error::InvalidSchnorrSignature(pk) => write!(f, "bad schnorr signature with pk {}", pk),
164            Error::NonStandardSighash(ref sig) => write!(
165                f,
166                "Non standard sighash type for signature '{}'",
167                sig.to_hex()
168            ),
169            Error::NonEmptyWitness => f.write_str("legacy spend had nonempty witness"),
170            Error::NonEmptyScriptSig => f.write_str("segwit spend had nonempty scriptsig"),
171            Error::Miniscript(ref e) => write!(f, "parse error: {}", e),
172            Error::MissingExtraZeroMultiSig => f.write_str("CMS missing extra zero"),
173            Error::MultiSigEvaluationError => {
174                f.write_str("CMS script aborted, incorrect satisfaction/dissatisfaction")
175            }
176            Error::PkEvaluationError(ref key) => write!(f, "Incorrect Signature for pk {}", key),
177            Error::PkHashVerifyFail(ref hash) => write!(f, "Pubkey Hash check failed {}", hash),
178            Error::PubkeyParseError => f.write_str("could not parse pubkey"),
179            Error::XOnlyPublicKeyParseError => f.write_str("could not parse x-only pubkey"),
180            Error::RelativeLocktimeNotMet(n) => {
181                write!(f, "required relative locktime CSV of {} blocks, not met", n)
182            }
183            Error::ScriptSatisfactionError => f.write_str("Top level script must be satisfied"),
184            Error::Secp(ref e) => fmt::Display::fmt(e, f),
185            Error::SchnorrSig(ref s) => write!(f, "Schnorr sig error: {}", s),
186            Error::SighashError(ref e) => fmt::Display::fmt(e, f),
187            Error::TapAnnexUnsupported => f.write_str("Encountered annex element"),
188            Error::UncompressedPubkey => {
189                f.write_str("uncompressed pubkey in non-legacy descriptor")
190            }
191            Error::UnexpectedStackBoolean => {
192                f.write_str("Expected Stack Push operation, found stack bool")
193            }
194            Error::UnexpectedStackElementPush => write!(f, "Got {}, expected Stack Boolean", 1),
195            Error::UnexpectedStackEnd => f.write_str("unexpected end of stack"),
196            Error::VerifyFailed => {
197                f.write_str("Expected Satisfied Boolean at stack top for VERIFY")
198            }
199            Error::IncorrectCovenantWitness => f.write_str(
200                "Covenant witness incorrect, the initial stack supplied for \
201                covenant global context is incorrect",
202            ),
203            Error::CovWitnessSizeErr {
204                pos,
205                expected,
206                actual,
207            } => write!(
208                f,
209                "At script code item position{}: Expected size{}, got size {}",
210                pos, expected, actual
211            ),
212            Error::ArithError(ref e) => write!(f, "{}", e),
213        }
214    }
215}
216
217impl error::Error for Error {
218    fn cause(&self) -> Option<&dyn error::Error> {
219        use self::Error::*;
220
221        match self {
222            AbsoluteLocktimeNotMet(_)
223            | AbsoluteLocktimeComparisonInvalid(_, _)
224            | CannotInferTrDescriptors
225            | ControlBlockVerificationError
226            | CouldNotEvaluate
227            | ExpectedPush
228            | HashPreimageLengthMismatch
229            | IncorrectPubkeyHash
230            | IncorrectScriptHash
231            | IncorrectWPubkeyHash
232            | IncorrectWScriptHash
233            | InsufficientSignaturesMultiSig
234            | InvalidEcdsaSignature(_)
235            | InvalidSchnorrSignature(_)
236            | InvalidSchnorrSighashType(_)
237            | NonStandardSighash(_)
238            | MissingExtraZeroMultiSig
239            | MultiSigEvaluationError
240            | NonEmptyWitness
241            | NonEmptyScriptSig
242            | PubkeyParseError
243            | XOnlyPublicKeyParseError
244            | PkEvaluationError(_)
245            | PkHashVerifyFail(_)
246            | RelativeLocktimeNotMet(_)
247            | ScriptSatisfactionError
248            | TapAnnexUnsupported
249            | UncompressedPubkey
250            | UnexpectedStackBoolean
251            | UnexpectedStackEnd
252            | UnexpectedStackElementPush
253            | VerifyFailed => None,
254            ControlBlockParse(e) => Some(e),
255            EcdsaSig(e) => Some(e),
256            Miniscript(e) => Some(e),
257            Secp(e) => Some(e),
258            SchnorrSig(e) => Some(e),
259            SighashError(e) => Some(e),
260            IncorrectCovenantWitness => None,
261            CovWitnessSizeErr { .. } => None,
262            ArithError(..) => None,
263        }
264    }
265}
266
267#[doc(hidden)]
268impl From<secp256k1_zkp::Error> for Error {
269    fn from(e: secp256k1_zkp::Error) -> Error {
270        Error::Secp(e)
271    }
272}
273
274#[doc(hidden)]
275impl From<elements::SchnorrSigError> for Error {
276    fn from(e: elements::SchnorrSigError) -> Error {
277        Error::SchnorrSig(e)
278    }
279}
280
281/// A type of representing which keys errored during interpreter checksig evaluation
282// Note that we can't use BitcoinKey because it is not public
283#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
284pub enum PkEvalErrInner {
285    /// Full Key
286    FullKey(bitcoin::PublicKey),
287    /// XOnly Key
288    XOnlyKey(bitcoin::key::XOnlyPublicKey),
289}
290
291impl From<BitcoinKey> for PkEvalErrInner {
292    fn from(pk: BitcoinKey) -> Self {
293        match pk {
294            BitcoinKey::Fullkey(pk) => PkEvalErrInner::FullKey(pk),
295            BitcoinKey::XOnlyPublicKey(xpk) => PkEvalErrInner::XOnlyKey(xpk),
296        }
297    }
298}
299
300impl fmt::Display for PkEvalErrInner {
301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302        match self {
303            PkEvalErrInner::FullKey(pk) => pk.fmt(f),
304            PkEvalErrInner::XOnlyKey(xpk) => xpk.fmt(f),
305        }
306    }
307}
308
309#[doc(hidden)]
310impl From<elements::sighash::Error> for Error {
311    fn from(e: elements::sighash::Error) -> Error {
312        Error::SighashError(e)
313    }
314}
315
316impl From<elements::secp256k1_zkp::UpstreamError> for Error {
317    fn from(e: elements::secp256k1_zkp::UpstreamError) -> Error {
318        Error::Secp(elements::secp256k1_zkp::Error::Upstream(e))
319    }
320}
321
322#[doc(hidden)]
323impl From<crate::Error> for Error {
324    fn from(e: crate::Error) -> Error {
325        Error::Miniscript(e)
326    }
327}