Skip to content

Commit 374ab9a

Browse files
committed
Rework Interpreter: Prepare of tap support
I realize that introducing NoChecksEcdsa/NoChecksSchnorr was the wrong way to go. - Remove lifetimes from return types - Change script from Script to Option<Script> - Makes all the awkward hacks non-public - This makes the tests for internal non-exposed types really ackward with .into() etc, but I don't think this matters much as it is not a public API
1 parent 45c3d05 commit 374ab9a

File tree

8 files changed

+639
-297
lines changed

8 files changed

+639
-297
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ name = "parse"
3333
[[example]]
3434
name = "sign_multisig"
3535

36-
[[example]]
37-
name = "verify_tx"
36+
# TODO: Re-enable in future commit after API re-design
37+
# [[example]]
38+
# name = "verify_tx"
3839

3940
[[example]]
4041
name = "psbt"

src/interpreter/error.rs

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,22 @@ use bitcoin::hashes::{hash160, hex::ToHex};
1616
use bitcoin::{self, secp256k1};
1717
use std::{error, fmt};
1818

19+
use super::BitcoinKey;
20+
1921
/// Detailed Error type for Interpreter
2022
#[derive(Debug)]
2123
pub enum Error {
2224
/// Could not satisfy, absolute locktime not met
2325
AbsoluteLocktimeNotMet(u32),
26+
/// Cannot Infer a taproot descriptor
27+
/// Key spends cannot infer the internal key of the descriptor
28+
/// Inferring script spends is possible, but is hidden nodes are currently
29+
/// not supported in descriptor spec
30+
CannotInferTrDescriptors,
2431
/// General Interpreter error.
2532
CouldNotEvaluate,
33+
/// EcdsaSig related error
34+
EcdsaSig(bitcoin::EcdsaSigError),
2635
/// We expected a push (including a `OP_1` but no other numeric pushes)
2736
ExpectedPush,
2837
/// The preimage to the hash function must be exactly 32 bytes.
@@ -39,8 +48,10 @@ pub enum Error {
3948
InsufficientSignaturesMultiSig,
4049
/// Invalid Sighash type
4150
InvalidSchnorrSigHashType(Vec<u8>),
51+
/// ecdsa Signature failed to verify
52+
InvalidEcdsaSignature(bitcoin::PublicKey),
4253
/// Signature failed to verify
43-
InvalidSignature(bitcoin::PublicKey),
54+
InvalidSchnorrSignature(bitcoin::XOnlyPublicKey),
4455
/// Last byte of this signature isn't a standard sighash type
4556
NonStandardSigHash(Vec<u8>),
4657
/// Miniscript error
@@ -60,19 +71,25 @@ pub enum Error {
6071
/// Any input witness apart from sat(sig) or nsat(0) leads to
6172
/// this error. This is network standardness assumption and miniscript only
6273
/// supports standard scripts
63-
PkEvaluationError(bitcoin::PublicKey),
74+
// note that BitcoinKey is not exported, create a data structure to convey the same
75+
// information in error
76+
PkEvaluationError(PkEvalErrInner),
6477
/// The Public Key hash check for the given pubkey. This occurs in `PkH`
6578
/// node when the given key does not match to Hash in script.
6679
PkHashVerifyFail(hash160::Hash),
6780
/// Parse Error while parsing a `stack::Element::Push` as a Pubkey. Both
6881
/// 33 byte and 65 bytes are supported.
6982
PubkeyParseError,
83+
/// Parse Error while parsing a `stack::Element::Push` as a XOnlyPublicKey (32 bytes)
84+
XOnlyPublicKeyParseError,
7085
/// Could not satisfy, relative locktime not met
7186
RelativeLocktimeNotMet(u32),
7287
/// Forward-secp related errors
7388
Secp(secp256k1::Error),
7489
/// Miniscript requires the entire top level script to be satisfied.
7590
ScriptSatisfactionError,
91+
/// Schnorr Signature error
92+
SchnorrSig(bitcoin::SchnorrSigError),
7693
/// Errors in signature hash calculations
7794
SighashError(bitcoin::util::sighash::Error),
7895
/// An uncompressed public key was encountered in a context where it is
@@ -92,6 +109,34 @@ pub enum Error {
92109
VerifyFailed,
93110
}
94111

112+
/// A type of representing which keys errored during interpreter checksig evaluation
113+
// Note that we can't use BitcoinKey because it is not public
114+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
115+
pub enum PkEvalErrInner {
116+
/// Full Key
117+
FullKey(bitcoin::PublicKey),
118+
/// XOnly Key
119+
XOnlyKey(bitcoin::XOnlyPublicKey),
120+
}
121+
122+
impl From<BitcoinKey> for PkEvalErrInner {
123+
fn from(pk: BitcoinKey) -> Self {
124+
match pk {
125+
BitcoinKey::Fullkey(pk) => PkEvalErrInner::FullKey(pk),
126+
BitcoinKey::XOnlyPublicKey(xpk) => PkEvalErrInner::XOnlyKey(xpk),
127+
}
128+
}
129+
}
130+
131+
impl fmt::Display for PkEvalErrInner {
132+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133+
match self {
134+
PkEvalErrInner::FullKey(pk) => pk.fmt(f),
135+
PkEvalErrInner::XOnlyKey(xpk) => xpk.fmt(f),
136+
}
137+
}
138+
}
139+
95140
#[doc(hidden)]
96141
impl From<secp256k1::Error> for Error {
97142
fn from(e: secp256k1::Error) -> Error {
@@ -106,6 +151,20 @@ impl From<bitcoin::util::sighash::Error> for Error {
106151
}
107152
}
108153

154+
#[doc(hidden)]
155+
impl From<bitcoin::EcdsaSigError> for Error {
156+
fn from(e: bitcoin::EcdsaSigError) -> Error {
157+
Error::EcdsaSig(e)
158+
}
159+
}
160+
161+
#[doc(hidden)]
162+
impl From<bitcoin::SchnorrSigError> for Error {
163+
fn from(e: bitcoin::SchnorrSigError) -> Error {
164+
Error::SchnorrSig(e)
165+
}
166+
}
167+
109168
#[doc(hidden)]
110169
impl From<::Error> for Error {
111170
fn from(e: ::Error) -> Error {
@@ -130,6 +189,8 @@ impl fmt::Display for Error {
130189
"required absolute locktime CLTV of {} blocks, not met",
131190
n
132191
),
192+
Error::CannotInferTrDescriptors => write!(f, "Cannot infer taproot descriptors"),
193+
Error::EcdsaSig(ref s) => write!(f, "Ecdsa sig error: {}", s),
133194
Error::ExpectedPush => f.write_str("expected push in script"),
134195
Error::CouldNotEvaluate => f.write_str("Interpreter Error: Could not evaluate"),
135196
Error::HashPreimageLengthMismatch => f.write_str("Hash preimage should be 32 bytes"),
@@ -147,7 +208,8 @@ impl fmt::Display for Error {
147208
sig.to_hex()
148209
)
149210
}
150-
Error::InvalidSignature(pk) => write!(f, "bad signature with pk {}", pk),
211+
Error::InvalidEcdsaSignature(pk) => write!(f, "bad ecdsa signature with pk {}", pk),
212+
Error::InvalidSchnorrSignature(pk) => write!(f, "bad schnorr signature with pk {}", pk),
151213
Error::NonStandardSigHash(ref sig) => {
152214
write!(
153215
f,
@@ -165,11 +227,13 @@ impl fmt::Display for Error {
165227
Error::PkEvaluationError(ref key) => write!(f, "Incorrect Signature for pk {}", key),
166228
Error::PkHashVerifyFail(ref hash) => write!(f, "Pubkey Hash check failed {}", hash),
167229
Error::PubkeyParseError => f.write_str("could not parse pubkey"),
230+
Error::XOnlyPublicKeyParseError => f.write_str("could not parse x-only pubkey"),
168231
Error::RelativeLocktimeNotMet(n) => {
169232
write!(f, "required relative locktime CSV of {} blocks, not met", n)
170233
}
171234
Error::ScriptSatisfactionError => f.write_str("Top level script must be satisfied"),
172235
Error::Secp(ref e) => fmt::Display::fmt(e, f),
236+
Error::SchnorrSig(ref s) => write!(f, "Schnorr sig error: {}", s),
173237
Error::SighashError(ref e) => fmt::Display::fmt(e, f),
174238
Error::UncompressedPubkey => {
175239
f.write_str("uncompressed pubkey in non-legacy descriptor")

0 commit comments

Comments
 (0)