Skip to content

Commit a6ca4ce

Browse files
committed
policy: clean up error types in compile_tr
This adds a couple variants to policy::compiler::Error and eliminates a couple calls to errstr. It also changes a few internal functions to return compiler errors instead of the top-level error.
1 parent bedb6d7 commit a6ca4ce

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed

src/policy/compiler.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ pub enum CompilerError {
5050
/// There may exist other miniscripts which are under these limits but the
5151
/// compiler currently does not find them.
5252
LimitsExceeded,
53+
/// In a Taproot compilation, no "unspendable key" was provided and no in-policy
54+
/// key could be used as an internal key.
55+
NoInternalKey,
56+
/// When compiling to Taproot, policy had too many Tapleaves
57+
TooManyTapleaves {
58+
/// Number of Tapleaves inferred from the policy.
59+
n: usize,
60+
/// Maximum allowed number of Tapleaves.
61+
max: usize,
62+
},
5363
///Policy related errors
5464
PolicyError(policy::concrete::PolicyError),
5565
}
@@ -66,6 +76,12 @@ impl fmt::Display for CompilerError {
6676
CompilerError::LimitsExceeded => f.write_str(
6777
"At least one spending path has exceeded the standardness or consensus limits",
6878
),
79+
CompilerError::NoInternalKey => {
80+
f.write_str("Taproot compilation had no internal key available")
81+
}
82+
CompilerError::TooManyTapleaves { n, max } => {
83+
write!(f, "Policy had too many Tapleaves (found {}, maximum {})", n, max)
84+
}
6985
CompilerError::PolicyError(ref e) => fmt::Display::fmt(e, f),
7086
}
7187
}
@@ -77,7 +93,11 @@ impl error::Error for CompilerError {
7793
use self::CompilerError::*;
7894

7995
match self {
80-
TopLevelNonSafe | ImpossibleNonMalleableCompilation | LimitsExceeded => None,
96+
TopLevelNonSafe
97+
| ImpossibleNonMalleableCompilation
98+
| LimitsExceeded
99+
| NoInternalKey
100+
| TooManyTapleaves { .. } => None,
81101
PolicyError(e) => Some(e),
82102
}
83103
}

src/policy/concrete.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
187187

188188
/// Extracts the internal_key from this policy tree.
189189
#[cfg(feature = "compiler")]
190-
fn extract_key(self, unspendable_key: Option<Pk>) -> Result<(Pk, Policy<Pk>), Error> {
190+
fn extract_key(self, unspendable_key: Option<Pk>) -> Result<(Pk, Policy<Pk>), CompilerError> {
191191
let internal_key = self
192192
.tapleaf_probability_iter()
193193
.filter_map(|(prob, ref pol)| match pol {
@@ -200,7 +200,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
200200
match (internal_key, unspendable_key) {
201201
(Some(ref key), _) => Ok((key.clone(), self.translate_unsatisfiable_pk(key))),
202202
(_, Some(key)) => Ok((key, self)),
203-
_ => Err(errstr("No viable internal key found.")),
203+
_ => Err(CompilerError::NoInternalKey),
204204
}
205205
}
206206

@@ -222,11 +222,11 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
222222
/// is also *cost-efficient*.
223223
// TODO: We might require other compile errors for Taproot.
224224
#[cfg(feature = "compiler")]
225-
pub fn compile_tr(&self, unspendable_key: Option<Pk>) -> Result<Descriptor<Pk>, Error> {
226-
self.is_valid().map_err(Error::ConcretePolicy)?;
225+
pub fn compile_tr(&self, unspendable_key: Option<Pk>) -> Result<Descriptor<Pk>, CompilerError> {
226+
self.is_valid().map_err(CompilerError::PolicyError)?;
227227
match self.is_safe_nonmalleable() {
228-
(false, _) => Err(Error::from(CompilerError::TopLevelNonSafe)),
229-
(_, false) => Err(Error::from(CompilerError::ImpossibleNonMalleableCompilation)),
228+
(false, _) => Err(CompilerError::TopLevelNonSafe),
229+
(_, false) => Err(CompilerError::ImpossibleNonMalleableCompilation),
230230
_ => {
231231
let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
232232
policy.check_num_tapleaves()?;
@@ -337,7 +337,9 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
337337
DescriptorCtx::Sh => Descriptor::new_sh(compiler::best_compilation(self)?),
338338
DescriptorCtx::Wsh => Descriptor::new_wsh(compiler::best_compilation(self)?),
339339
DescriptorCtx::ShWsh => Descriptor::new_sh_wsh(compiler::best_compilation(self)?),
340-
DescriptorCtx::Tr(unspendable_key) => self.compile_tr(unspendable_key),
340+
DescriptorCtx::Tr(unspendable_key) => self
341+
.compile_tr(unspendable_key)
342+
.map_err(Error::CompilerError),
341343
},
342344
}
343345
}
@@ -585,9 +587,10 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
585587

586588
/// Does checks on the number of `TapLeaf`s.
587589
#[cfg(feature = "compiler")]
588-
fn check_num_tapleaves(&self) -> Result<(), Error> {
589-
if self.num_tap_leaves() > MAX_COMPILATION_LEAVES {
590-
return Err(errstr("Too many Tapleaves"));
590+
fn check_num_tapleaves(&self) -> Result<(), CompilerError> {
591+
let n = self.num_tap_leaves();
592+
if n > MAX_COMPILATION_LEAVES {
593+
return Err(CompilerError::TooManyTapleaves { n, max: MAX_COMPILATION_LEAVES });
591594
}
592595
Ok(())
593596
}

0 commit comments

Comments
 (0)