1use core::fmt;
6
7use bitcoin::sighash::{self, EcdsaSighashType, NonStandardSighashTypeError};
8use bitcoin::{transaction, PublicKey};
9
10use crate::error::{write_err, FundingUtxoError};
11use crate::v2::map::{global, input, output};
12
13#[derive(Debug)]
18#[non_exhaustive]
19pub enum DeserializeError {
20 InvalidMagic,
23 InvalidSeparator,
26 NoMorePairs,
28 DecodeGlobal(global::DecodeError),
30 DecodeInput(input::DecodeError),
32 DecodeOutput(output::DecodeError),
34}
35
36impl fmt::Display for DeserializeError {
37 fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!() }
38}
39
40#[cfg(feature = "std")]
41impl std::error::Error for DeserializeError {
42 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { todo!() }
43}
44
45impl From<global::DecodeError> for DeserializeError {
46 fn from(e: global::DecodeError) -> Self { Self::DecodeGlobal(e) }
47}
48
49impl From<input::DecodeError> for DeserializeError {
50 fn from(e: input::DecodeError) -> Self { Self::DecodeInput(e) }
51}
52
53impl From<output::DecodeError> for DeserializeError {
54 fn from(e: output::DecodeError) -> Self { Self::DecodeOutput(e) }
55}
56
57#[derive(Debug, Clone, PartialEq, Eq)]
59#[non_exhaustive]
60pub enum IndexOutOfBoundsError {
61 Inputs {
63 index: usize,
65 length: usize,
67 },
68 Count {
70 index: usize,
72 count: usize,
74 },
75}
76
77impl fmt::Display for IndexOutOfBoundsError {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 use IndexOutOfBoundsError::*;
80
81 match *self {
82 Inputs { ref index, ref length } => write!(
83 f,
84 "index {} is out-of-bounds for PSBT inputs vector length {}",
85 index, length
86 ),
87 Count { ref index, ref count } =>
88 write!(f, "index {} is greater global.input_count {}", index, count),
89 }
90 }
91}
92
93#[cfg(feature = "std")]
94impl std::error::Error for IndexOutOfBoundsError {
95 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
96 use IndexOutOfBoundsError::*;
97
98 match *self {
99 Inputs { .. } | Count { .. } => None,
100 }
101 }
102}
103
104#[derive(Debug, Clone, PartialEq, Eq)]
106#[non_exhaustive]
107pub enum SignError {
108 IndexOutOfBounds(IndexOutOfBoundsError),
110 InvalidSighashType,
112 MissingInputUtxo,
114 MissingRedeemScript,
116 FundingUtxo(FundingUtxoError),
118 MissingWitnessScript,
120 MismatchedAlgoKey,
122 NotEcdsa,
124 NotWpkh,
126 SegwitV0Sighash(transaction::InputsIndexError),
128 P2wpkhSighash(sighash::P2wpkhError),
130 TaprootError(sighash::TaprootError),
132 UnknownOutputType,
134 KeyNotFound,
136 WrongSigningAlgorithm,
138 Unsupported,
140}
141
142impl fmt::Display for SignError {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 use SignError::*;
145
146 match *self {
147 IndexOutOfBounds(ref e) => write_err!(f, "index out of bounds"; e),
148 InvalidSighashType => write!(f, "invalid sighash type"),
149 MissingInputUtxo => write!(f, "missing input utxo in PBST"),
150 MissingRedeemScript => write!(f, "missing redeem script"),
151 FundingUtxo(ref e) => write_err!(f, "input funding utxo error"; e),
152 MissingWitnessScript => write!(f, "missing witness script"),
153 MismatchedAlgoKey => write!(f, "signing algorithm and key type does not match"),
154 NotEcdsa => write!(f, "attempted to ECDSA sign an non-ECDSA input"),
155 NotWpkh => write!(f, "the scriptPubkey is not a P2WPKH script"),
156 SegwitV0Sighash(ref e) => write_err!(f, "segwit v0 sighash"; e),
157 P2wpkhSighash(ref e) => write_err!(f, "p2wpkh sighash"; e),
158 TaprootError(ref e) => write_err!(f, "taproot sighash"; e),
159 UnknownOutputType => write!(f, "unable to determine the output type"),
160 KeyNotFound => write!(f, "unable to find key"),
161 WrongSigningAlgorithm =>
162 write!(f, "attempt to sign an input with the wrong signing algorithm"),
163 Unsupported => write!(f, "signing request currently unsupported"),
164 }
165 }
166}
167
168#[cfg(feature = "std")]
169impl std::error::Error for SignError {
170 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
171 use SignError::*;
172
173 match *self {
174 SegwitV0Sighash(ref e) => Some(e),
175 P2wpkhSighash(ref e) => Some(e),
176 TaprootError(ref e) => Some(e),
177 IndexOutOfBounds(ref e) => Some(e),
178 FundingUtxo(ref e) => Some(e),
179 InvalidSighashType
180 | MissingInputUtxo
181 | MissingRedeemScript
182 | MissingWitnessScript
183 | MismatchedAlgoKey
184 | NotEcdsa
185 | NotWpkh
186 | UnknownOutputType
187 | KeyNotFound
188 | WrongSigningAlgorithm
189 | Unsupported => None,
190 }
191 }
192}
193
194impl From<sighash::P2wpkhError> for SignError {
195 fn from(e: sighash::P2wpkhError) -> Self { Self::P2wpkhSighash(e) }
196}
197
198impl From<IndexOutOfBoundsError> for SignError {
199 fn from(e: IndexOutOfBoundsError) -> Self { Self::IndexOutOfBounds(e) }
200}
201
202impl From<sighash::TaprootError> for SignError {
203 fn from(e: sighash::TaprootError) -> Self { SignError::TaprootError(e) }
204}
205
206impl From<FundingUtxoError> for SignError {
207 fn from(e: FundingUtxoError) -> Self { Self::FundingUtxo(e) }
208}
209
210#[derive(Debug, Clone, PartialEq, Eq)]
212#[non_exhaustive]
213pub enum PsbtNotModifiableError {
214 Outputs(OutputsNotModifiableError),
216 Inputs(InputsNotModifiableError),
218}
219
220impl fmt::Display for PsbtNotModifiableError {
221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222 use PsbtNotModifiableError::*;
223
224 match *self {
225 Outputs(ref e) => write_err!(f, "outputs not modifiable"; e),
226 Inputs(ref e) => write_err!(f, "inputs not modifiable"; e),
227 }
228 }
229}
230
231#[cfg(feature = "std")]
232impl std::error::Error for PsbtNotModifiableError {
233 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
234 use PsbtNotModifiableError::*;
235
236 match *self {
237 Outputs(ref e) => Some(e),
238 Inputs(ref e) => Some(e),
239 }
240 }
241}
242
243impl From<InputsNotModifiableError> for PsbtNotModifiableError {
244 fn from(e: InputsNotModifiableError) -> Self { Self::Inputs(e) }
245}
246
247impl From<OutputsNotModifiableError> for PsbtNotModifiableError {
248 fn from(e: OutputsNotModifiableError) -> Self { Self::Outputs(e) }
249}
250
251#[derive(Debug, Clone, PartialEq, Eq)]
253#[non_exhaustive]
254pub struct InputsNotModifiableError;
255
256impl fmt::Display for InputsNotModifiableError {
257 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258 f.write_str("PSBT does not have the inputs modifiable flag set")
259 }
260}
261
262#[cfg(feature = "std")]
263impl std::error::Error for InputsNotModifiableError {}
264
265#[derive(Debug, Clone, PartialEq, Eq)]
267#[non_exhaustive]
268pub struct OutputsNotModifiableError;
269
270impl fmt::Display for OutputsNotModifiableError {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 f.write_str("PSBT does not have the outputs modifiable flag set")
273 }
274}
275
276#[cfg(feature = "std")]
277impl std::error::Error for OutputsNotModifiableError {
278 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq)]
283#[non_exhaustive]
284pub enum NotUnsignedError {
285 Finalized,
287 SigData,
289}
290
291impl fmt::Display for NotUnsignedError {
292 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293 use NotUnsignedError::*;
294
295 match *self {
296 Finalized => f.write_str("input has already been finalized"),
297 SigData => f.write_str("input already has signature data"),
298 }
299 }
300}
301
302#[cfg(feature = "std")]
303impl std::error::Error for NotUnsignedError {
304 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
305}
306
307#[derive(Debug, Clone, PartialEq, Eq)]
309#[non_exhaustive]
310pub struct DetermineLockTimeError;
311
312impl fmt::Display for DetermineLockTimeError {
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 f.write_str(
315 "unable to determine lock time, multiple inputs have conflicting locking requirements",
316 )
317 }
318}
319
320#[cfg(feature = "std")]
321impl std::error::Error for DetermineLockTimeError {
322 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
323}
324
325#[derive(Debug)]
328pub enum PartialSigsSighashTypeError {
329 NonStandardInputSighashType {
331 input_index: usize,
333 error: NonStandardSighashTypeError,
335 },
336 NonStandardPartialSigsSighashType {
338 input_index: usize,
340 error: NonStandardSighashTypeError,
342 },
343 WrongSighashFlag {
345 input_index: usize,
347 got: EcdsaSighashType,
349 required: EcdsaSighashType,
351 pubkey: PublicKey,
353 },
354}
355
356impl fmt::Display for PartialSigsSighashTypeError {
357 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358 use PartialSigsSighashTypeError::*;
359
360 match *self {
361 NonStandardInputSighashType { input_index, ref error } =>
362 write_err!(f, "non-standard sighash type for input {} in sighash_type field", input_index; error),
363 NonStandardPartialSigsSighashType { input_index, ref error } =>
364 write_err!(f, "non-standard sighash type for input {} in partial_sigs", input_index; error),
365 WrongSighashFlag { input_index, got, required, pubkey } => write!(
366 f,
367 "wrong sighash flag for input {} (got: {}, required: {}) pubkey: {}",
368 input_index, got, required, pubkey
369 ),
370 }
371 }
372}
373
374#[cfg(feature = "std")]
375impl std::error::Error for PartialSigsSighashTypeError {
376 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
377 use PartialSigsSighashTypeError::*;
378
379 match *self {
381 NonStandardInputSighashType { input_index: _, ref error } => Some(error),
382 NonStandardPartialSigsSighashType { input_index: _, ref error } => Some(error),
383 WrongSighashFlag { .. } => None,
384 }
385 }
386}