sapio_miniscript/interpreter/
error.rs1use bitcoin::hashes::{hash160, hex::ToHex};
16use bitcoin::util::taproot;
17use bitcoin::{self, secp256k1};
18use std::{error, fmt};
19
20use super::BitcoinKey;
21
22#[derive(Debug)]
24pub enum Error {
25 AbsoluteLocktimeNotMet(u32),
27 CannotInferTrDescriptors,
32 ControlBlockParse(taproot::TaprootError),
34 ControlBlockVerificationError,
36 CouldNotEvaluate,
38 EcdsaSig(bitcoin::EcdsaSigError),
40 ExpectedPush,
42 HashPreimageLengthMismatch,
44 TxTemplateHashLengthWrong,
46 TxTemplateHashWrong,
48 IncorrectPubkeyHash,
50 IncorrectScriptHash,
52 IncorrectWPubkeyHash,
54 IncorrectWScriptHash,
56 InsufficientSignaturesMultiSig,
58 InvalidSchnorrSighashType(Vec<u8>),
60 InvalidEcdsaSignature(bitcoin::PublicKey),
62 InvalidSchnorrSignature(bitcoin::XOnlyPublicKey),
64 NonStandardSighash(Vec<u8>),
66 Miniscript(::Error),
68 MissingExtraZeroMultiSig,
70 MultiSigEvaluationError,
75 NonEmptyWitness,
77 NonEmptyScriptSig,
79 PkEvaluationError(PkEvalErrInner),
86 PkHashVerifyFail(hash160::Hash),
89 PubkeyParseError,
92 XOnlyPublicKeyParseError,
94 RelativeLocktimeNotMet(u32),
96 Secp(secp256k1::Error),
98 ScriptSatisfactionError,
100 SchnorrSig(bitcoin::SchnorrSigError),
102 SighashError(bitcoin::util::sighash::Error),
104 TapAnnexUnsupported,
106 UncompressedPubkey,
109 UnexpectedStackBoolean,
112 UnexpectedStackEnd,
114 UnexpectedStackElementPush,
118 VerifyFailed,
121}
122
123#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
126pub enum PkEvalErrInner {
127 FullKey(bitcoin::PublicKey),
129 XOnlyKey(bitcoin::XOnlyPublicKey),
131}
132
133impl From<BitcoinKey> for PkEvalErrInner {
134 fn from(pk: BitcoinKey) -> Self {
135 match pk {
136 BitcoinKey::Fullkey(pk) => PkEvalErrInner::FullKey(pk),
137 BitcoinKey::XOnlyPublicKey(xpk) => PkEvalErrInner::XOnlyKey(xpk),
138 }
139 }
140}
141
142impl fmt::Display for PkEvalErrInner {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 match self {
145 PkEvalErrInner::FullKey(pk) => pk.fmt(f),
146 PkEvalErrInner::XOnlyKey(xpk) => xpk.fmt(f),
147 }
148 }
149}
150
151#[doc(hidden)]
152impl From<secp256k1::Error> for Error {
153 fn from(e: secp256k1::Error) -> Error {
154 Error::Secp(e)
155 }
156}
157
158#[doc(hidden)]
159impl From<bitcoin::util::sighash::Error> for Error {
160 fn from(e: bitcoin::util::sighash::Error) -> Error {
161 Error::SighashError(e)
162 }
163}
164
165#[doc(hidden)]
166impl From<bitcoin::EcdsaSigError> for Error {
167 fn from(e: bitcoin::EcdsaSigError) -> Error {
168 Error::EcdsaSig(e)
169 }
170}
171
172#[doc(hidden)]
173impl From<bitcoin::SchnorrSigError> for Error {
174 fn from(e: bitcoin::SchnorrSigError) -> Error {
175 Error::SchnorrSig(e)
176 }
177}
178
179#[doc(hidden)]
180impl From<::Error> for Error {
181 fn from(e: ::Error) -> Error {
182 Error::Miniscript(e)
183 }
184}
185
186impl error::Error for Error {
187 fn cause(&self) -> Option<&dyn error::Error> {
188 match *self {
189 Error::Secp(ref err) => Some(err),
190 ref x => Some(x),
191 }
192 }
193}
194
195impl fmt::Display for Error {
196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 match *self {
198 Error::AbsoluteLocktimeNotMet(n) => write!(
199 f,
200 "required absolute locktime CLTV of {} blocks, not met",
201 n
202 ),
203 Error::CannotInferTrDescriptors => write!(f, "Cannot infer taproot descriptors"),
204 Error::ControlBlockParse(ref e) => write!(f, "Control block parse error {}", e),
205 Error::ControlBlockVerificationError => {
206 f.write_str("Control block verification failed")
207 }
208 Error::EcdsaSig(ref s) => write!(f, "Ecdsa sig error: {}", s),
209 Error::ExpectedPush => f.write_str("expected push in script"),
210 Error::CouldNotEvaluate => f.write_str("Interpreter Error: Could not evaluate"),
211 Error::HashPreimageLengthMismatch => f.write_str("Hash preimage should be 32 bytes"),
212 Error::TxTemplateHashLengthWrong => f.write_str("Hash should be 32 bytes"),
213 Error::TxTemplateHashWrong => f.write_str("Hash should match the transaction"),
214 Error::IncorrectPubkeyHash => f.write_str("public key did not match scriptpubkey"),
215 Error::IncorrectScriptHash => f.write_str("redeem script did not match scriptpubkey"),
216 Error::IncorrectWPubkeyHash => {
217 f.write_str("public key did not match scriptpubkey (segwit v0)")
218 }
219 Error::IncorrectWScriptHash => f.write_str("witness script did not match scriptpubkey"),
220 Error::InsufficientSignaturesMultiSig => f.write_str("Insufficient signatures for CMS"),
221 Error::InvalidSchnorrSighashType(ref sig) => {
222 write!(
223 f,
224 "Invalid sighash type for schnorr signature '{}'",
225 sig.to_hex()
226 )
227 }
228 Error::InvalidEcdsaSignature(pk) => write!(f, "bad ecdsa signature with pk {}", pk),
229 Error::InvalidSchnorrSignature(pk) => write!(f, "bad schnorr signature with pk {}", pk),
230 Error::NonStandardSighash(ref sig) => {
231 write!(
232 f,
233 "Non standard sighash type for signature '{}'",
234 sig.to_hex()
235 )
236 }
237 Error::NonEmptyWitness => f.write_str("legacy spend had nonempty witness"),
238 Error::NonEmptyScriptSig => f.write_str("segwit spend had nonempty scriptsig"),
239 Error::Miniscript(ref e) => write!(f, "parse error: {}", e),
240 Error::MissingExtraZeroMultiSig => f.write_str("CMS missing extra zero"),
241 Error::MultiSigEvaluationError => {
242 f.write_str("CMS script aborted, incorrect satisfaction/dissatisfaction")
243 }
244 Error::PkEvaluationError(ref key) => write!(f, "Incorrect Signature for pk {}", key),
245 Error::PkHashVerifyFail(ref hash) => write!(f, "Pubkey Hash check failed {}", hash),
246 Error::PubkeyParseError => f.write_str("could not parse pubkey"),
247 Error::XOnlyPublicKeyParseError => f.write_str("could not parse x-only pubkey"),
248 Error::RelativeLocktimeNotMet(n) => {
249 write!(f, "required relative locktime CSV of {} blocks, not met", n)
250 }
251 Error::ScriptSatisfactionError => f.write_str("Top level script must be satisfied"),
252 Error::Secp(ref e) => fmt::Display::fmt(e, f),
253 Error::SchnorrSig(ref s) => write!(f, "Schnorr sig error: {}", s),
254 Error::SighashError(ref e) => fmt::Display::fmt(e, f),
255 Error::TapAnnexUnsupported => f.write_str("Encountered annex element"),
256 Error::UncompressedPubkey => {
257 f.write_str("uncompressed pubkey in non-legacy descriptor")
258 }
259 Error::UnexpectedStackBoolean => {
260 f.write_str("Expected Stack Push operation, found stack bool")
261 }
262 Error::UnexpectedStackElementPush => write!(f, "Got {}, expected Stack Boolean", 1),
263 Error::UnexpectedStackEnd => f.write_str("unexpected end of stack"),
264 Error::VerifyFailed => {
265 f.write_str("Expected Satisfied Boolean at stack top for VERIFY")
266 }
267 }
268 }
269}