Skip to content

Commit 2ca5a35

Browse files
committed
Merge #845: various improvements/refactors of the decoder and its errors
cdb36c1 miniscript: rename parse_* functions to decode_* (Andrew Poelstra) 5fea2b3 miniscript: rename and cleanup decode::KeyParseError (Andrew Poelstra) a57fab3 miniscript: replace many calls to reduce0 in decode with infallible constructors (Andrew Poelstra) 5b736bd miniscript: move lexer errors into their own type (Andrew Poelstra) ceadd0d miniscript: use byte arrays in lexer (Andrew Poelstra) Pull request description: The last commit, which renames `parse_with_ext` to `decode_with_ext`, I think we should backport with deprecation to 12.x. This is a pretty uncommonly used function and is unlikely to bother anybody, but the current name is inconsistent with our general use of "parse" for strings and "decode" for scripts. ACKs for top commit: sanket1729: ACK cdb36c1 Tree-SHA512: 8a3563dd23e49cf9331b299e237337a3d1097c15d5fe143ec9aa3f686d681fda077f019b25f0d66fccdd9a88ec489a84e144fcbb28410a671eb113f38e0fe58d
2 parents 89a9a4c + cdb36c1 commit 2ca5a35

File tree

9 files changed

+227
-187
lines changed

9 files changed

+227
-187
lines changed

fuzz/fuzz_targets/roundtrip_miniscript_script.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn do_test(data: &[u8]) {
88
// Try round-tripping as a script
99
let script = script::Script::from_bytes(data);
1010

11-
if let Ok(pt) = Miniscript::<miniscript::bitcoin::PublicKey, Segwitv0>::parse(script) {
11+
if let Ok(pt) = Miniscript::<miniscript::bitcoin::PublicKey, Segwitv0>::decode(script) {
1212
let output = pt.encode();
1313
assert_eq!(pt.script_size(), output.len());
1414
assert_eq!(&output, script);

fuzz/fuzz_targets/roundtrip_miniscript_script_tap.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn do_test(data: &[u8]) {
88
// Try round-tripping as a script
99
let script = script::Script::from_bytes(data);
1010

11-
if let Ok(pt) = Miniscript::<miniscript::bitcoin::key::XOnlyPublicKey, Tap>::parse(script) {
11+
if let Ok(pt) = Miniscript::<miniscript::bitcoin::key::XOnlyPublicKey, Tap>::decode(script) {
1212
let output = pt.encode();
1313
assert_eq!(pt.script_size(), output.len());
1414
assert_eq!(&output, script);

src/interpreter/inner.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ fn script_from_stack_elem<Ctx: ScriptContext>(
4343
) -> Result<Miniscript<Ctx::Key, Ctx>, Error> {
4444
match *elem {
4545
stack::Element::Push(sl) => {
46-
Miniscript::parse_with_ext(bitcoin::Script::from_bytes(sl), &ExtParams::allow_all())
46+
Miniscript::decode_with_ext(bitcoin::Script::from_bytes(sl), &ExtParams::allow_all())
4747
.map_err(Error::from)
4848
}
4949
stack::Element::Satisfied => Ok(Miniscript::TRUE),
@@ -327,7 +327,7 @@ pub(super) fn from_txdata<'txin>(
327327
} else {
328328
if wit_stack.is_empty() {
329329
// Bare script parsed in BareCtx
330-
let miniscript = Miniscript::<bitcoin::PublicKey, BareCtx>::parse_with_ext(
330+
let miniscript = Miniscript::<bitcoin::PublicKey, BareCtx>::decode_with_ext(
331331
spk,
332332
&ExtParams::allow_all(),
333333
)?;

src/lib.rs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ mod util;
131131
use core::{fmt, hash, str};
132132

133133
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
134-
use bitcoin::hex::DisplayHex;
135-
use bitcoin::{script, Opcode};
136134

137135
pub use crate::blanket_traits::FromStrKey;
138136
pub use crate::descriptor::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
@@ -436,15 +434,8 @@ pub trait ForEachKey<Pk: MiniscriptKey> {
436434
437435
#[derive(Debug)]
438436
pub enum Error {
439-
/// Opcode appeared which is not part of the script subset
440-
InvalidOpcode(Opcode),
441-
/// Some opcode occurred followed by `OP_VERIFY` when it had
442-
/// a `VERIFY` version that should have been used instead
443-
NonMinimalVerify(String),
444-
/// Push was illegal in some context
445-
InvalidPush(Vec<u8>),
446-
/// rust-bitcoin script error
447-
Script(script::Error),
437+
/// Error when lexing a bitcoin Script.
438+
ScriptLexer(crate::miniscript::lex::Error),
448439
/// rust-bitcoin address error
449440
AddrError(bitcoin::address::ParseError),
450441
/// rust-bitcoin p2sh address error
@@ -490,7 +481,7 @@ pub enum Error {
490481
/// Bare descriptors don't have any addresses
491482
BareDescriptorAddr,
492483
/// PubKey invalid under current context
493-
PubKeyCtxError(miniscript::decode::KeyParseError, &'static str),
484+
PubKeyCtxError(miniscript::decode::KeyError, &'static str),
494485
/// No script code for Tr descriptors
495486
TrNoScriptCode,
496487
/// At least two BIP389 key expressions in the descriptor contain tuples of
@@ -519,12 +510,7 @@ const MAX_RECURSION_DEPTH: u32 = 402;
519510
impl fmt::Display for Error {
520511
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
521512
match *self {
522-
Error::InvalidOpcode(op) => write!(f, "invalid opcode {}", op),
523-
Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok),
524-
Error::InvalidPush(ref push) => {
525-
write!(f, "invalid push {:x}", push.as_hex())
526-
},
527-
Error::Script(ref e) => fmt::Display::fmt(e, f),
513+
Error::ScriptLexer(ref e) => e.fmt(f),
528514
Error::AddrError(ref e) => fmt::Display::fmt(e, f),
529515
Error::AddrP2shError(ref e) => fmt::Display::fmt(e, f),
530516
Error::UnexpectedStart => f.write_str("unexpected start of script"),
@@ -576,10 +562,7 @@ impl std::error::Error for Error {
576562
use self::Error::*;
577563

578564
match self {
579-
InvalidOpcode(_)
580-
| NonMinimalVerify(_)
581-
| InvalidPush(_)
582-
| UnexpectedStart
565+
UnexpectedStart
583566
| Unexpected(_)
584567
| UnknownWrapper(_)
585568
| NonTopLevel(_)
@@ -593,7 +576,7 @@ impl std::error::Error for Error {
593576
| BareDescriptorAddr
594577
| TrNoScriptCode
595578
| MultipathDescLenMismatch => None,
596-
Script(e) => Some(e),
579+
ScriptLexer(e) => Some(e),
597580
AddrError(e) => Some(e),
598581
AddrP2shError(e) => Some(e),
599582
Secp(e) => Some(e),
@@ -614,6 +597,11 @@ impl std::error::Error for Error {
614597
}
615598
}
616599

600+
#[doc(hidden)]
601+
impl From<miniscript::lex::Error> for Error {
602+
fn from(e: miniscript::lex::Error) -> Error { Error::ScriptLexer(e) }
603+
}
604+
617605
#[doc(hidden)]
618606
impl From<miniscript::types::Error> for Error {
619607
fn from(e: miniscript::types::Error) -> Error { Error::TypeCheck(e.to_string()) }

src/miniscript/analyzable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::prelude::*;
1313
use crate::{Miniscript, MiniscriptKey, ScriptContext, Terminal};
1414

1515
/// Params for parsing miniscripts that either non-sane or non-specified(experimental) in the spec.
16-
/// Used as a parameter [`Miniscript::from_str_ext`] and [`Miniscript::parse_with_ext`].
16+
/// Used as a parameter [`Miniscript::from_str_ext`] and [`Miniscript::decode_with_ext`].
1717
///
1818
/// This allows parsing miniscripts if
1919
/// 1. It is unsafe(does not require a digital signature to spend it)

0 commit comments

Comments
 (0)