Skip to content

Commit 013922c

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 bf308eb commit 013922c

File tree

9 files changed

+231
-16
lines changed

9 files changed

+231
-16
lines changed

src/descriptor/key.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,11 @@ impl DescriptorXKey<bip32::ExtendedPrivKey> {
213213
#[derive(Debug, PartialEq, Clone, Copy)]
214214
pub struct DescriptorKeyParseError(&'static str);
215215

216-
impl error::Error for DescriptorKeyParseError {}
216+
impl error::Error for DescriptorKeyParseError {
217+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
218+
None
219+
}
220+
}
217221

218222
impl fmt::Display for DescriptorKeyParseError {
219223
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -357,7 +361,15 @@ pub enum ConversionError {
357361
HardenedWildcard,
358362
}
359363

360-
impl error::Error for ConversionError {}
364+
impl error::Error for ConversionError {
365+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
366+
use self::ConversionError::*;
367+
368+
match self {
369+
Wildcard | HardenedChild | HardenedWildcard => None,
370+
}
371+
}
372+
}
361373

362374
impl fmt::Display for ConversionError {
363375
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

src/interpreter/error.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,46 @@ pub enum Error {
120120

121121
impl error::Error for Error {
122122
fn cause(&self) -> Option<&dyn error::Error> {
123-
match *self {
124-
Error::Secp(ref err) => Some(err),
125-
ref x => Some(x),
123+
use self::Error::*;
124+
125+
match self {
126+
AbsoluteLocktimeNotMet(_)
127+
| CannotInferTrDescriptors
128+
| ControlBlockVerificationError
129+
| CouldNotEvaluate
130+
| ExpectedPush
131+
| HashPreimageLengthMismatch
132+
| IncorrectPubkeyHash
133+
| IncorrectScriptHash
134+
| IncorrectWPubkeyHash
135+
| IncorrectWScriptHash
136+
| InsufficientSignaturesMultiSig
137+
| InvalidEcdsaSignature(_)
138+
| InvalidSchnorrSignature(_)
139+
| InvalidSchnorrSighashType(_)
140+
| NonStandardSighash(_)
141+
| MissingExtraZeroMultiSig
142+
| MultiSigEvaluationError
143+
| NonEmptyWitness
144+
| NonEmptyScriptSig
145+
| PubkeyParseError
146+
| XOnlyPublicKeyParseError
147+
| PkEvaluationError(_)
148+
| PkHashVerifyFail(_)
149+
| RelativeLocktimeNotMet(_)
150+
| ScriptSatisfactionError
151+
| TapAnnexUnsupported
152+
| UncompressedPubkey
153+
| UnexpectedStackBoolean
154+
| UnexpectedStackEnd
155+
| UnexpectedStackElementPush
156+
| VerifyFailed => None,
157+
ControlBlockParse(e) => Some(e),
158+
EcdsaSig(e) => Some(e),
159+
Miniscript(e) => Some(e),
160+
Secp(e) => Some(e),
161+
SchnorrSig(e) => Some(e),
162+
SighashError(e) => Some(e),
126163
}
127164
}
128165
}

src/lib.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,9 +580,51 @@ pub enum Error {
580580

581581
impl error::Error for Error {
582582
fn cause(&self) -> Option<&dyn error::Error> {
583-
match *self {
584-
Error::BadPubkey(ref e) => Some(e),
585-
_ => None,
583+
use self::Error::*;
584+
585+
match self {
586+
InvalidOpcode(_)
587+
| NonMinimalVerify(_)
588+
| InvalidPush(_)
589+
| CmsTooManyKeys(_)
590+
| MultiATooManyKeys(_)
591+
| Unprintable(_)
592+
| ExpectedChar(_)
593+
| UnexpectedStart
594+
| Unexpected(_)
595+
| MultiColon(_)
596+
| MultiAt(_)
597+
| AtOutsideOr(_)
598+
| LikelyFalse
599+
| UnknownWrapper(_)
600+
| NonTopLevel(_)
601+
| Trailing(_)
602+
| MissingHash(_)
603+
| MissingSig(_)
604+
| RelativeLocktimeNotMet(_)
605+
| AbsoluteLocktimeNotMet(_)
606+
| CouldNotSatisfy
607+
| TypeCheck(_)
608+
| BadDescriptor(_)
609+
| MaxRecursiveDepthExceeded
610+
| ScriptSizeTooLarge
611+
| NonStandardBareScript
612+
| ImpossibleSatisfaction
613+
| BareDescriptorAddr
614+
| TaprootSpendInfoUnavialable
615+
| TrNoScriptCode
616+
| TrNoExplicitScript => None,
617+
Script(e) => Some(e),
618+
AddrError(e) => Some(e),
619+
BadPubkey(e) => Some(e),
620+
Secp(e) => Some(e),
621+
#[cfg(feature = "compiler")]
622+
CompilerError(e) => Some(e),
623+
PolicyError(e) => Some(e),
624+
LiftError(e) => Some(e),
625+
ContextError(e) => Some(e),
626+
AnalysisError(e) => Some(e),
627+
PubKeyCtxError(e, _) => Some(e),
586628
}
587629
}
588630
}

src/miniscript/analyzable.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,19 @@ pub enum AnalysisError {
4646
Malleable,
4747
}
4848

49-
impl error::Error for AnalysisError {}
49+
impl error::Error for AnalysisError {
50+
fn cause(&self) -> Option<&dyn error::Error> {
51+
use self::AnalysisError::*;
52+
53+
match self {
54+
SiglessBranch
55+
| RepeatedPubkeys
56+
| BranchExceedResouceLimits
57+
| HeightTimeLockCombination
58+
| Malleable => None,
59+
}
60+
}
61+
}
5062

5163
impl fmt::Display for AnalysisError {
5264
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

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
@@ -61,7 +61,16 @@ pub enum CompilerError {
6161
PolicyError(policy::concrete::PolicyError),
6262
}
6363

64-
impl error::Error for CompilerError {}
64+
impl error::Error for CompilerError {
65+
fn cause(&self) -> Option<&dyn error::Error> {
66+
use self::CompilerError::*;
67+
68+
match self {
69+
TopLevelNonSafe | ImpossibleNonMalleableCompilation | LimitsExceeded => None,
70+
PolicyError(e) => Some(e),
71+
}
72+
}
73+
}
6574

6675
impl fmt::Display for CompilerError {
6776
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

src/policy/concrete.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,24 @@ pub enum PolicyError {
9292
DuplicatePubKeys,
9393
}
9494

95-
impl error::Error for PolicyError {}
95+
impl error::Error for PolicyError {
96+
fn cause(&self) -> Option<&dyn error::Error> {
97+
use self::PolicyError::*;
98+
99+
match self {
100+
NonBinaryArgAnd
101+
| NonBinaryArgOr
102+
| IncorrectThresh
103+
| ZeroTime
104+
| TimeTooFar
105+
| InsufficientArgsforAnd
106+
| InsufficientArgsforOr
107+
| EntailmentMaxTerminals
108+
| HeightTimeLockCombination
109+
| DuplicatePubKeys => None,
110+
}
111+
}
112+
}
96113

97114
impl fmt::Display for PolicyError {
98115
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

src/policy/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,11 @@ pub enum LiftError {
6868

6969
impl error::Error for LiftError {
7070
fn cause(&self) -> Option<&dyn error::Error> {
71-
None
71+
use self::LiftError::*;
72+
73+
match self {
74+
HeightTimeLockCombination | BranchExceedResourceLimits => None,
75+
}
7276
}
7377
}
7478

src/psbt/mod.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,16 @@ pub enum Error {
6464
},
6565
}
6666

67-
impl error::Error for Error {}
67+
impl error::Error for Error {
68+
fn cause(&self) -> Option<&dyn error::Error> {
69+
use self::Error::*;
70+
71+
match self {
72+
InputError(e, _) => Some(e),
73+
WrongInputCount { .. } | InputIdxOutofBounds { .. } => None,
74+
}
75+
}
76+
}
6877

6978
impl fmt::Display for Error {
7079
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -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 {
@@ -1050,7 +1085,16 @@ pub enum UtxoUpdateError {
10501085
MismatchedScriptPubkey,
10511086
}
10521087

1053-
impl error::Error for UtxoUpdateError {}
1088+
impl error::Error for UtxoUpdateError {
1089+
fn cause(&self) -> Option<&dyn error::Error> {
1090+
use self::UtxoUpdateError::*;
1091+
1092+
match self {
1093+
IndexOutOfBounds(_, _) | MissingInputUtxo | UtxoCheck | MismatchedScriptPubkey => None,
1094+
DerivationError(e) => Some(e),
1095+
}
1096+
}
1097+
}
10541098

10551099
impl fmt::Display for UtxoUpdateError {
10561100
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -1092,8 +1136,21 @@ pub enum SighashError {
10921136
MissingRedeemScript,
10931137
}
10941138

1095-
impl error::Error for SighashError {}
1139+
impl error::Error for SighashError {
1140+
fn cause(&self) -> Option<&dyn error::Error> {
1141+
use self::SighashError::*;
10961142

1143+
match self {
1144+
IndexOutOfBounds(_, _)
1145+
| MissingInputUtxo
1146+
| MissingSpendUtxos
1147+
| InvalidSighashType
1148+
| MissingWitnessScript
1149+
| MissingRedeemScript => None,
1150+
SighashComputationError(e) => Some(e),
1151+
}
1152+
}
1153+
}
10971154
impl fmt::Display for SighashError {
10981155
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10991156
match self {

0 commit comments

Comments
 (0)