Skip to content

Commit 3e5ef23

Browse files
committed
Implement error::Error for all error types
Now that we have an MSRV of 1.41.1 we can implement `std::Error` by way of the `cause` method. Audit the whole codebase and implement `cause` for all error types, matching explicitly on enum variants so we don't forget to update the impls if/when the error enums get modified.
1 parent a5db0f0 commit 3e5ef23

File tree

9 files changed

+232
-16
lines changed

9 files changed

+232
-16
lines changed

src/descriptor/key.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,11 @@ impl fmt::Display for DescriptorKeyParseError {
219219
}
220220
}
221221

222-
impl error::Error for DescriptorKeyParseError {}
222+
impl error::Error for DescriptorKeyParseError {
223+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
224+
None
225+
}
226+
}
223227

224228
impl fmt::Display for DescriptorPublicKey {
225229
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -369,7 +373,15 @@ impl fmt::Display for ConversionError {
369373
}
370374
}
371375

372-
impl error::Error for ConversionError {}
376+
impl error::Error for ConversionError {
377+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
378+
use self::ConversionError::*;
379+
380+
match self {
381+
Wildcard | HardenedChild | HardenedWildcard => None,
382+
}
383+
}
384+
}
373385

374386
impl DescriptorPublicKey {
375387
/// The fingerprint of the master key associated with this key, `0x00000000` if none.

src/interpreter/error.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,46 @@ impl fmt::Display for Error {
194194

195195
impl error::Error for Error {
196196
fn cause(&self) -> Option<&dyn error::Error> {
197-
match *self {
198-
Error::Secp(ref err) => Some(err),
199-
ref x => Some(x),
197+
use self::Error::*;
198+
199+
match self {
200+
AbsoluteLocktimeNotMet(_)
201+
| CannotInferTrDescriptors
202+
| ControlBlockVerificationError
203+
| CouldNotEvaluate
204+
| ExpectedPush
205+
| HashPreimageLengthMismatch
206+
| IncorrectPubkeyHash
207+
| IncorrectScriptHash
208+
| IncorrectWPubkeyHash
209+
| IncorrectWScriptHash
210+
| InsufficientSignaturesMultiSig
211+
| InvalidEcdsaSignature(_)
212+
| InvalidSchnorrSignature(_)
213+
| InvalidSchnorrSighashType(_)
214+
| NonStandardSighash(_)
215+
| MissingExtraZeroMultiSig
216+
| MultiSigEvaluationError
217+
| NonEmptyWitness
218+
| NonEmptyScriptSig
219+
| PubkeyParseError
220+
| XOnlyPublicKeyParseError
221+
| PkEvaluationError(_)
222+
| PkHashVerifyFail(_)
223+
| RelativeLocktimeNotMet(_)
224+
| ScriptSatisfactionError
225+
| TapAnnexUnsupported
226+
| UncompressedPubkey
227+
| UnexpectedStackBoolean
228+
| UnexpectedStackEnd
229+
| UnexpectedStackElementPush
230+
| VerifyFailed => None,
231+
ControlBlockParse(e) => Some(e),
232+
EcdsaSig(e) => Some(e),
233+
Miniscript(e) => Some(e),
234+
Secp(e) => Some(e),
235+
SchnorrSig(e) => Some(e),
236+
SighashError(e) => Some(e),
200237
}
201238
}
202239
}

src/lib.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -660,9 +660,51 @@ impl fmt::Display for Error {
660660

661661
impl error::Error for Error {
662662
fn cause(&self) -> Option<&dyn error::Error> {
663-
match *self {
664-
Error::BadPubkey(ref e) => Some(e),
665-
_ => None,
663+
use self::Error::*;
664+
665+
match self {
666+
InvalidOpcode(_)
667+
| NonMinimalVerify(_)
668+
| InvalidPush(_)
669+
| CmsTooManyKeys(_)
670+
| MultiATooManyKeys(_)
671+
| Unprintable(_)
672+
| ExpectedChar(_)
673+
| UnexpectedStart
674+
| Unexpected(_)
675+
| MultiColon(_)
676+
| MultiAt(_)
677+
| AtOutsideOr(_)
678+
| LikelyFalse
679+
| UnknownWrapper(_)
680+
| NonTopLevel(_)
681+
| Trailing(_)
682+
| MissingHash(_)
683+
| MissingSig(_)
684+
| RelativeLocktimeNotMet(_)
685+
| AbsoluteLocktimeNotMet(_)
686+
| CouldNotSatisfy
687+
| TypeCheck(_)
688+
| BadDescriptor(_)
689+
| MaxRecursiveDepthExceeded
690+
| ScriptSizeTooLarge
691+
| NonStandardBareScript
692+
| ImpossibleSatisfaction
693+
| BareDescriptorAddr
694+
| TaprootSpendInfoUnavialable
695+
| TrNoScriptCode
696+
| TrNoExplicitScript => None,
697+
Script(e) => Some(e),
698+
AddrError(e) => Some(e),
699+
BadPubkey(e) => Some(e),
700+
Secp(e) => Some(e),
701+
#[cfg(feature = "compiler")]
702+
CompilerError(e) => Some(e),
703+
PolicyError(e) => Some(e),
704+
LiftError(e) => Some(e),
705+
ContextError(e) => Some(e),
706+
AnalysisError(e) => Some(e),
707+
PubKeyCtxError(e, _) => Some(e),
666708
}
667709
}
668710
}

src/miniscript/analyzable.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,19 @@ impl fmt::Display for AnalysisError {
6666
}
6767
}
6868

69-
impl error::Error for AnalysisError {}
69+
impl error::Error for AnalysisError {
70+
fn cause(&self) -> Option<&dyn error::Error> {
71+
use self::AnalysisError::*;
72+
73+
match self {
74+
SiglessBranch
75+
| RepeatedPubkeys
76+
| BranchExceedResouceLimits
77+
| HeightTimelockCombination
78+
| Malleable => None,
79+
}
80+
}
81+
}
7082

7183
impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
7284
/// Whether all spend paths of miniscript require a signature

src/miniscript/context.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
1313
//
1414

15-
use std::{fmt, hash};
15+
use std::{error, fmt, hash};
1616

1717
use bitcoin;
1818
use bitcoin::blockdata::constants::MAX_BLOCK_WEIGHT;
@@ -75,6 +75,31 @@ pub enum ScriptContextError {
7575
MultiANotAllowed,
7676
}
7777

78+
impl error::Error for ScriptContextError {
79+
fn cause(&self) -> Option<&dyn error::Error> {
80+
use self::ScriptContextError::*;
81+
82+
match self {
83+
MalleablePkH
84+
| MalleableOrI
85+
| MalleableDupIf
86+
| CompressedOnly(_)
87+
| XOnlyKeysNotAllowed(_, _)
88+
| UncompressedKeysNotAllowed
89+
| MaxWitnessItemssExceeded { .. }
90+
| MaxOpCountExceeded
91+
| MaxWitnessScriptSizeExceeded
92+
| MaxRedeemScriptSizeExceeded
93+
| MaxScriptSigSizeExceeded
94+
| ImpossibleSatisfaction
95+
| TaprootMultiDisabled
96+
| StackSizeLimitExceeded { .. }
97+
| CheckMultiSigLimitExceeded
98+
| MultiANotAllowed => None,
99+
}
100+
}
101+
}
102+
78103
impl fmt::Display for ScriptContextError {
79104
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80105
match *self {

src/policy/compiler.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,16 @@ impl fmt::Display for CompilerError {
7979
}
8080
}
8181

82-
impl error::Error for CompilerError {}
82+
impl error::Error for CompilerError {
83+
fn cause(&self) -> Option<&dyn error::Error> {
84+
use self::CompilerError::*;
85+
86+
match self {
87+
TopLevelNonSafe | ImpossibleNonMalleableCompilation | LimitsExceeded => None,
88+
PolicyError(e) => Some(e),
89+
}
90+
}
91+
}
8392

8493
#[doc(hidden)]
8594
impl From<policy::concrete::PolicyError> for CompilerError {

src/policy/concrete.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,24 @@ impl fmt::Display for PolicyError {
132132
}
133133
}
134134

135-
impl error::Error for PolicyError {}
135+
impl error::Error for PolicyError {
136+
fn cause(&self) -> Option<&dyn error::Error> {
137+
use self::PolicyError::*;
138+
139+
match self {
140+
NonBinaryArgAnd
141+
| NonBinaryArgOr
142+
| IncorrectThresh
143+
| ZeroTime
144+
| TimeTooFar
145+
| InsufficientArgsforAnd
146+
| InsufficientArgsforOr
147+
| EntailmentMaxTerminals
148+
| HeightTimeLockCombination
149+
| DuplicatePubKeys => None,
150+
}
151+
}
152+
}
136153

137154
impl<Pk: MiniscriptKey> Policy<Pk> {
138155
/// Flatten the [`Policy`] tree structure into a Vector of tuple `(leaf script, leaf probability)`

src/policy/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ impl fmt::Display for LiftError {
8181

8282
impl error::Error for LiftError {
8383
fn cause(&self) -> Option<&dyn error::Error> {
84-
None
84+
use self::LiftError::*;
85+
86+
match self {
87+
HeightTimeLockCombination | BranchExceedResourceLimits => None,
88+
}
8589
}
8690
}
8791

src/psbt/mod.rs

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,16 @@ impl fmt::Display for Error {
8282
}
8383
}
8484

85-
impl error::Error for Error {}
85+
impl error::Error for Error {
86+
fn cause(&self) -> Option<&dyn error::Error> {
87+
use self::Error::*;
88+
89+
match self {
90+
InputError(e, _) => Some(e),
91+
WrongInputCount { .. } | InputIdxOutofBounds { .. } => None,
92+
}
93+
}
94+
}
8695

8796
/// Error type for Pbst Input
8897
#[derive(Debug)]
@@ -148,6 +157,32 @@ pub enum InputError {
148157
},
149158
}
150159

160+
impl error::Error for InputError {
161+
fn cause(&self) -> Option<&dyn error::Error> {
162+
use self::InputError::*;
163+
164+
match self {
165+
CouldNotSatisfyTr
166+
| InvalidRedeemScript { .. }
167+
| InvalidWitnessScript { .. }
168+
| InvalidSignature { .. }
169+
| MissingRedeemScript
170+
| MissingWitness
171+
| MissingPubkey
172+
| MissingWitnessScript
173+
| MissingUtxo
174+
| NonEmptyWitnessScript
175+
| NonEmptyRedeemScript
176+
| NonStandardSighashType(_)
177+
| WrongSighashFlag { .. } => None,
178+
SecpErr(e) => Some(e),
179+
KeyErr(e) => Some(e),
180+
Interpreter(e) => Some(e),
181+
MiniscriptError(e) => Some(e),
182+
}
183+
}
184+
}
185+
151186
impl fmt::Display for InputError {
152187
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
153188
match *self {
@@ -1069,7 +1104,16 @@ impl fmt::Display for UtxoUpdateError {
10691104
}
10701105
}
10711106

1072-
impl error::Error for UtxoUpdateError {}
1107+
impl error::Error for UtxoUpdateError {
1108+
fn cause(&self) -> Option<&dyn error::Error> {
1109+
use self::UtxoUpdateError::*;
1110+
1111+
match self {
1112+
IndexOutOfBounds(_, _) | MissingInputUtxo | UtxoCheck | MismatchedScriptPubkey => None,
1113+
DerivationError(e) => Some(e),
1114+
}
1115+
}
1116+
}
10731117

10741118
/// Return error type for [`PsbtExt::sighash_msg`]
10751119
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
@@ -1110,7 +1154,21 @@ impl fmt::Display for SighashError {
11101154
}
11111155
}
11121156

1113-
impl error::Error for SighashError {}
1157+
impl error::Error for SighashError {
1158+
fn cause(&self) -> Option<&dyn error::Error> {
1159+
use self::SighashError::*;
1160+
1161+
match self {
1162+
IndexOutOfBounds(_, _)
1163+
| MissingInputUtxo
1164+
| MissingSpendUtxos
1165+
| InvalidSighashType
1166+
| MissingWitnessScript
1167+
| MissingRedeemScript => None,
1168+
SighashComputationError(e) => Some(e),
1169+
}
1170+
}
1171+
}
11141172

11151173
impl From<bitcoin::util::sighash::Error> for SighashError {
11161174
fn from(e: bitcoin::util::sighash::Error) -> Self {

0 commit comments

Comments
 (0)