bitcoin/psbt/map/
input.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use core::fmt;
4use core::str::FromStr;
5
6use hashes::{hash160, ripemd160, sha256, sha256d};
7use secp256k1::XOnlyPublicKey;
8
9use crate::bip32::KeySource;
10use crate::blockdata::script::ScriptBuf;
11use crate::blockdata::transaction::{Transaction, TxOut};
12use crate::blockdata::witness::Witness;
13use crate::crypto::key::PublicKey;
14use crate::crypto::{ecdsa, taproot};
15use crate::prelude::*;
16use crate::psbt::map::Map;
17use crate::psbt::serialize::Deserialize;
18use crate::psbt::{self, error, raw, Error};
19use crate::sighash::{
20    EcdsaSighashType, InvalidSighashTypeError, NonStandardSighashTypeError, SighashTypeParseError,
21    TapSighashType,
22};
23use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash};
24
25/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
26const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
27/// Type: Witness UTXO PSBT_IN_WITNESS_UTXO = 0x01
28const PSBT_IN_WITNESS_UTXO: u8 = 0x01;
29/// Type: Partial Signature PSBT_IN_PARTIAL_SIG = 0x02
30const PSBT_IN_PARTIAL_SIG: u8 = 0x02;
31/// Type: Sighash Type PSBT_IN_SIGHASH_TYPE = 0x03
32const PSBT_IN_SIGHASH_TYPE: u8 = 0x03;
33/// Type: Redeem Script PSBT_IN_REDEEM_SCRIPT = 0x04
34const PSBT_IN_REDEEM_SCRIPT: u8 = 0x04;
35/// Type: Witness Script PSBT_IN_WITNESS_SCRIPT = 0x05
36const PSBT_IN_WITNESS_SCRIPT: u8 = 0x05;
37/// Type: BIP 32 Derivation Path PSBT_IN_BIP32_DERIVATION = 0x06
38const PSBT_IN_BIP32_DERIVATION: u8 = 0x06;
39/// Type: Finalized scriptSig PSBT_IN_FINAL_SCRIPTSIG = 0x07
40const PSBT_IN_FINAL_SCRIPTSIG: u8 = 0x07;
41/// Type: Finalized scriptWitness PSBT_IN_FINAL_SCRIPTWITNESS = 0x08
42const PSBT_IN_FINAL_SCRIPTWITNESS: u8 = 0x08;
43/// Type: RIPEMD160 preimage PSBT_IN_RIPEMD160 = 0x0a
44const PSBT_IN_RIPEMD160: u8 = 0x0a;
45/// Type: SHA256 preimage PSBT_IN_SHA256 = 0x0b
46const PSBT_IN_SHA256: u8 = 0x0b;
47/// Type: HASH160 preimage PSBT_IN_HASH160 = 0x0c
48const PSBT_IN_HASH160: u8 = 0x0c;
49/// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d
50const PSBT_IN_HASH256: u8 = 0x0d;
51/// Type: Taproot Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13
52const PSBT_IN_TAP_KEY_SIG: u8 = 0x13;
53/// Type: Taproot Signature in Script Spend PSBT_IN_TAP_SCRIPT_SIG = 0x14
54const PSBT_IN_TAP_SCRIPT_SIG: u8 = 0x14;
55/// Type: Taproot Leaf Script PSBT_IN_TAP_LEAF_SCRIPT = 0x14
56const PSBT_IN_TAP_LEAF_SCRIPT: u8 = 0x15;
57/// Type: Taproot Key BIP 32 Derivation Path PSBT_IN_TAP_BIP32_DERIVATION = 0x16
58const PSBT_IN_TAP_BIP32_DERIVATION: u8 = 0x16;
59/// Type: Taproot Internal Key PSBT_IN_TAP_INTERNAL_KEY = 0x17
60const PSBT_IN_TAP_INTERNAL_KEY: u8 = 0x17;
61/// Type: Taproot Merkle Root PSBT_IN_TAP_MERKLE_ROOT = 0x18
62const PSBT_IN_TAP_MERKLE_ROOT: u8 = 0x18;
63/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC
64const PSBT_IN_PROPRIETARY: u8 = 0xFC;
65
66/// A key-value map for an input of the corresponding index in the unsigned
67/// transaction.
68#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
69#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
70#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
71pub struct Input {
72    /// The non-witness transaction this input spends from. Should only be
73    /// `Option::Some` for inputs which spend non-segwit outputs or
74    /// if it is unknown whether an input spends a segwit output.
75    pub non_witness_utxo: Option<Transaction>,
76    /// The transaction output this input spends from. Should only be
77    /// `Option::Some` for inputs which spend segwit outputs,
78    /// including P2SH embedded ones.
79    pub witness_utxo: Option<TxOut>,
80    /// A map from public keys to their corresponding signature as would be
81    /// pushed to the stack from a scriptSig or witness for a non-taproot inputs.
82    pub partial_sigs: BTreeMap<PublicKey, ecdsa::Signature>,
83    /// The sighash type to be used for this input. Signatures for this input
84    /// must use the sighash type.
85    pub sighash_type: Option<PsbtSighashType>,
86    /// The redeem script for this input.
87    pub redeem_script: Option<ScriptBuf>,
88    /// The witness script for this input.
89    pub witness_script: Option<ScriptBuf>,
90    /// A map from public keys needed to sign this input to their corresponding
91    /// master key fingerprints and derivation paths.
92    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
93    pub bip32_derivation: BTreeMap<secp256k1::PublicKey, KeySource>,
94    /// The finalized, fully-constructed scriptSig with signatures and any other
95    /// scripts necessary for this input to pass validation.
96    pub final_script_sig: Option<ScriptBuf>,
97    /// The finalized, fully-constructed scriptWitness with signatures and any
98    /// other scripts necessary for this input to pass validation.
99    pub final_script_witness: Option<Witness>,
100    /// RIPEMD160 hash to preimage map.
101    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
102    pub ripemd160_preimages: BTreeMap<ripemd160::Hash, Vec<u8>>,
103    /// SHA256 hash to preimage map.
104    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
105    pub sha256_preimages: BTreeMap<sha256::Hash, Vec<u8>>,
106    /// HSAH160 hash to preimage map.
107    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
108    pub hash160_preimages: BTreeMap<hash160::Hash, Vec<u8>>,
109    /// HAS256 hash to preimage map.
110    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
111    pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
112    /// Serialized taproot signature with sighash type for key spend.
113    pub tap_key_sig: Option<taproot::Signature>,
114    /// Map of `<xonlypubkey>|<leafhash>` with signature.
115    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
116    pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), taproot::Signature>,
117    /// Map of Control blocks to Script version pair.
118    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
119    pub tap_scripts: BTreeMap<ControlBlock, (ScriptBuf, LeafVersion)>,
120    /// Map of tap root x only keys to origin info and leaf hashes contained in it.
121    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
122    pub tap_key_origins: BTreeMap<XOnlyPublicKey, (Vec<TapLeafHash>, KeySource)>,
123    /// Taproot Internal key.
124    pub tap_internal_key: Option<XOnlyPublicKey>,
125    /// Taproot Merkle root.
126    pub tap_merkle_root: Option<TapNodeHash>,
127    /// Proprietary key-value pairs for this input.
128    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
129    pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
130    /// Unknown key-value pairs for this input.
131    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
132    pub unknown: BTreeMap<raw::Key, Vec<u8>>,
133}
134
135/// A Signature hash type for the corresponding input.
136///
137/// As of taproot upgrade, the signature hash type can be either [`EcdsaSighashType`] or
138/// [`TapSighashType`] but it is not possible to know directly which signature hash type the user is
139/// dealing with. Therefore, the user is responsible for converting to/from [`PsbtSighashType`]
140/// from/to the desired signature hash type they need.
141#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
142#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
143#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
144pub struct PsbtSighashType {
145    pub(in crate::psbt) inner: u32,
146}
147
148impl fmt::Display for PsbtSighashType {
149    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150        match self.taproot_hash_ty() {
151            Err(_) => write!(f, "{:#x}", self.inner),
152            Ok(taproot_hash_ty) => fmt::Display::fmt(&taproot_hash_ty, f),
153        }
154    }
155}
156
157impl FromStr for PsbtSighashType {
158    type Err = SighashTypeParseError;
159
160    #[inline]
161    fn from_str(s: &str) -> Result<Self, Self::Err> {
162        // We accept strings of form: "SIGHASH_ALL" etc.
163        //
164        // NB: some of Taproot sighash types are non-standard for pre-taproot
165        // inputs. We also do not support SIGHASH_RESERVED in verbatim form
166        // ("0xFF" string should be used instead).
167        if let Ok(ty) = TapSighashType::from_str(s) {
168            return Ok(ty.into());
169        }
170
171        // We accept non-standard sighash values.
172        if let Ok(inner) = u32::from_str_radix(s.trim_start_matches("0x"), 16) {
173            return Ok(PsbtSighashType { inner });
174        }
175
176        Err(SighashTypeParseError { unrecognized: s.to_owned() })
177    }
178}
179impl From<EcdsaSighashType> for PsbtSighashType {
180    fn from(ecdsa_hash_ty: EcdsaSighashType) -> Self {
181        PsbtSighashType { inner: ecdsa_hash_ty as u32 }
182    }
183}
184
185impl From<TapSighashType> for PsbtSighashType {
186    fn from(taproot_hash_ty: TapSighashType) -> Self {
187        PsbtSighashType { inner: taproot_hash_ty as u32 }
188    }
189}
190
191impl PsbtSighashType {
192    /// Returns the [`EcdsaSighashType`] if the [`PsbtSighashType`] can be
193    /// converted to one.
194    pub fn ecdsa_hash_ty(self) -> Result<EcdsaSighashType, NonStandardSighashTypeError> {
195        EcdsaSighashType::from_standard(self.inner)
196    }
197
198    /// Returns the [`TapSighashType`] if the [`PsbtSighashType`] can be
199    /// converted to one.
200    pub fn taproot_hash_ty(self) -> Result<TapSighashType, InvalidSighashTypeError> {
201        if self.inner > 0xffu32 {
202            Err(InvalidSighashTypeError(self.inner))
203        } else {
204            TapSighashType::from_consensus_u8(self.inner as u8)
205        }
206    }
207
208    /// Creates a [`PsbtSighashType`] from a raw `u32`.
209    ///
210    /// Allows construction of a non-standard or non-valid sighash flag
211    /// ([`EcdsaSighashType`], [`TapSighashType`] respectively).
212    pub fn from_u32(n: u32) -> PsbtSighashType { PsbtSighashType { inner: n } }
213
214    /// Converts [`PsbtSighashType`] to a raw `u32` sighash flag.
215    ///
216    /// No guarantees are made as to the standardness or validity of the returned value.
217    pub fn to_u32(self) -> u32 { self.inner }
218}
219
220impl Input {
221    /// Obtains the [`EcdsaSighashType`] for this input if one is specified. If no sighash type is
222    /// specified, returns [`EcdsaSighashType::All`].
223    ///
224    /// # Errors
225    ///
226    /// If the `sighash_type` field is set to a non-standard ECDSA sighash value.
227    pub fn ecdsa_hash_ty(&self) -> Result<EcdsaSighashType, NonStandardSighashTypeError> {
228        self.sighash_type
229            .map(|sighash_type| sighash_type.ecdsa_hash_ty())
230            .unwrap_or(Ok(EcdsaSighashType::All))
231    }
232
233    /// Obtains the [`TapSighashType`] for this input if one is specified. If no sighash type is
234    /// specified, returns [`TapSighashType::Default`].
235    ///
236    /// # Errors
237    ///
238    /// If the `sighash_type` field is set to a invalid Taproot sighash value.
239    pub fn taproot_hash_ty(&self) -> Result<TapSighashType, InvalidSighashTypeError> {
240        self.sighash_type
241            .map(|sighash_type| sighash_type.taproot_hash_ty())
242            .unwrap_or(Ok(TapSighashType::Default))
243    }
244
245    pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> {
246        let raw::Pair { key: raw_key, value: raw_value } = pair;
247
248        match raw_key.type_value {
249            PSBT_IN_NON_WITNESS_UTXO => {
250                impl_psbt_insert_pair! {
251                    self.non_witness_utxo <= <raw_key: _>|<raw_value: Transaction>
252                }
253            }
254            PSBT_IN_WITNESS_UTXO => {
255                impl_psbt_insert_pair! {
256                    self.witness_utxo <= <raw_key: _>|<raw_value: TxOut>
257                }
258            }
259            PSBT_IN_PARTIAL_SIG => {
260                impl_psbt_insert_pair! {
261                    self.partial_sigs <= <raw_key: PublicKey>|<raw_value: ecdsa::Signature>
262                }
263            }
264            PSBT_IN_SIGHASH_TYPE => {
265                impl_psbt_insert_pair! {
266                    self.sighash_type <= <raw_key: _>|<raw_value: PsbtSighashType>
267                }
268            }
269            PSBT_IN_REDEEM_SCRIPT => {
270                impl_psbt_insert_pair! {
271                    self.redeem_script <= <raw_key: _>|<raw_value: ScriptBuf>
272                }
273            }
274            PSBT_IN_WITNESS_SCRIPT => {
275                impl_psbt_insert_pair! {
276                    self.witness_script <= <raw_key: _>|<raw_value: ScriptBuf>
277                }
278            }
279            PSBT_IN_BIP32_DERIVATION => {
280                impl_psbt_insert_pair! {
281                    self.bip32_derivation <= <raw_key: secp256k1::PublicKey>|<raw_value: KeySource>
282                }
283            }
284            PSBT_IN_FINAL_SCRIPTSIG => {
285                impl_psbt_insert_pair! {
286                    self.final_script_sig <= <raw_key: _>|<raw_value: ScriptBuf>
287                }
288            }
289            PSBT_IN_FINAL_SCRIPTWITNESS => {
290                impl_psbt_insert_pair! {
291                    self.final_script_witness <= <raw_key: _>|<raw_value: Witness>
292                }
293            }
294            PSBT_IN_RIPEMD160 => {
295                psbt_insert_hash_pair(
296                    &mut self.ripemd160_preimages,
297                    raw_key,
298                    raw_value,
299                    error::PsbtHash::Ripemd,
300                )?;
301            }
302            PSBT_IN_SHA256 => {
303                psbt_insert_hash_pair(
304                    &mut self.sha256_preimages,
305                    raw_key,
306                    raw_value,
307                    error::PsbtHash::Sha256,
308                )?;
309            }
310            PSBT_IN_HASH160 => {
311                psbt_insert_hash_pair(
312                    &mut self.hash160_preimages,
313                    raw_key,
314                    raw_value,
315                    error::PsbtHash::Hash160,
316                )?;
317            }
318            PSBT_IN_HASH256 => {
319                psbt_insert_hash_pair(
320                    &mut self.hash256_preimages,
321                    raw_key,
322                    raw_value,
323                    error::PsbtHash::Hash256,
324                )?;
325            }
326            PSBT_IN_TAP_KEY_SIG => {
327                impl_psbt_insert_pair! {
328                    self.tap_key_sig <= <raw_key: _>|<raw_value: taproot::Signature>
329                }
330            }
331            PSBT_IN_TAP_SCRIPT_SIG => {
332                impl_psbt_insert_pair! {
333                    self.tap_script_sigs <= <raw_key: (XOnlyPublicKey, TapLeafHash)>|<raw_value: taproot::Signature>
334                }
335            }
336            PSBT_IN_TAP_LEAF_SCRIPT => {
337                impl_psbt_insert_pair! {
338                    self.tap_scripts <= <raw_key: ControlBlock>|< raw_value: (ScriptBuf, LeafVersion)>
339                }
340            }
341            PSBT_IN_TAP_BIP32_DERIVATION => {
342                impl_psbt_insert_pair! {
343                    self.tap_key_origins <= <raw_key: XOnlyPublicKey>|< raw_value: (Vec<TapLeafHash>, KeySource)>
344                }
345            }
346            PSBT_IN_TAP_INTERNAL_KEY => {
347                impl_psbt_insert_pair! {
348                    self.tap_internal_key <= <raw_key: _>|< raw_value: XOnlyPublicKey>
349                }
350            }
351            PSBT_IN_TAP_MERKLE_ROOT => {
352                impl_psbt_insert_pair! {
353                    self.tap_merkle_root <= <raw_key: _>|< raw_value: TapNodeHash>
354                }
355            }
356            PSBT_IN_PROPRIETARY => {
357                let key = raw::ProprietaryKey::try_from(raw_key.clone())?;
358                match self.proprietary.entry(key) {
359                    btree_map::Entry::Vacant(empty_key) => {
360                        empty_key.insert(raw_value);
361                    }
362                    btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)),
363                }
364            }
365            _ => match self.unknown.entry(raw_key) {
366                btree_map::Entry::Vacant(empty_key) => {
367                    empty_key.insert(raw_value);
368                }
369                btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())),
370            },
371        }
372
373        Ok(())
374    }
375
376    /// Combines this [`Input`] with `other` `Input` (as described by BIP 174).
377    pub fn combine(&mut self, other: Self) {
378        combine!(non_witness_utxo, self, other);
379
380        if let (&None, Some(witness_utxo)) = (&self.witness_utxo, other.witness_utxo) {
381            self.witness_utxo = Some(witness_utxo);
382            self.non_witness_utxo = None; // Clear out any non-witness UTXO when we set a witness one
383        }
384
385        self.partial_sigs.extend(other.partial_sigs);
386        self.bip32_derivation.extend(other.bip32_derivation);
387        self.ripemd160_preimages.extend(other.ripemd160_preimages);
388        self.sha256_preimages.extend(other.sha256_preimages);
389        self.hash160_preimages.extend(other.hash160_preimages);
390        self.hash256_preimages.extend(other.hash256_preimages);
391        self.tap_script_sigs.extend(other.tap_script_sigs);
392        self.tap_scripts.extend(other.tap_scripts);
393        self.tap_key_origins.extend(other.tap_key_origins);
394        self.proprietary.extend(other.proprietary);
395        self.unknown.extend(other.unknown);
396
397        combine!(redeem_script, self, other);
398        combine!(witness_script, self, other);
399        combine!(final_script_sig, self, other);
400        combine!(final_script_witness, self, other);
401        combine!(tap_key_sig, self, other);
402        combine!(tap_internal_key, self, other);
403        combine!(tap_merkle_root, self, other);
404    }
405}
406
407impl Map for Input {
408    fn get_pairs(&self) -> Vec<raw::Pair> {
409        let mut rv: Vec<raw::Pair> = Default::default();
410
411        impl_psbt_get_pair! {
412            rv.push(self.non_witness_utxo, PSBT_IN_NON_WITNESS_UTXO)
413        }
414
415        impl_psbt_get_pair! {
416            rv.push(self.witness_utxo, PSBT_IN_WITNESS_UTXO)
417        }
418
419        impl_psbt_get_pair! {
420            rv.push_map(self.partial_sigs, PSBT_IN_PARTIAL_SIG)
421        }
422
423        impl_psbt_get_pair! {
424            rv.push(self.sighash_type, PSBT_IN_SIGHASH_TYPE)
425        }
426
427        impl_psbt_get_pair! {
428            rv.push(self.redeem_script, PSBT_IN_REDEEM_SCRIPT)
429        }
430
431        impl_psbt_get_pair! {
432            rv.push(self.witness_script, PSBT_IN_WITNESS_SCRIPT)
433        }
434
435        impl_psbt_get_pair! {
436            rv.push_map(self.bip32_derivation, PSBT_IN_BIP32_DERIVATION)
437        }
438
439        impl_psbt_get_pair! {
440            rv.push(self.final_script_sig, PSBT_IN_FINAL_SCRIPTSIG)
441        }
442
443        impl_psbt_get_pair! {
444            rv.push(self.final_script_witness, PSBT_IN_FINAL_SCRIPTWITNESS)
445        }
446
447        impl_psbt_get_pair! {
448            rv.push_map(self.ripemd160_preimages, PSBT_IN_RIPEMD160)
449        }
450
451        impl_psbt_get_pair! {
452            rv.push_map(self.sha256_preimages, PSBT_IN_SHA256)
453        }
454
455        impl_psbt_get_pair! {
456            rv.push_map(self.hash160_preimages, PSBT_IN_HASH160)
457        }
458
459        impl_psbt_get_pair! {
460            rv.push_map(self.hash256_preimages, PSBT_IN_HASH256)
461        }
462
463        impl_psbt_get_pair! {
464            rv.push(self.tap_key_sig, PSBT_IN_TAP_KEY_SIG)
465        }
466
467        impl_psbt_get_pair! {
468            rv.push_map(self.tap_script_sigs, PSBT_IN_TAP_SCRIPT_SIG)
469        }
470
471        impl_psbt_get_pair! {
472            rv.push_map(self.tap_scripts, PSBT_IN_TAP_LEAF_SCRIPT)
473        }
474
475        impl_psbt_get_pair! {
476            rv.push_map(self.tap_key_origins, PSBT_IN_TAP_BIP32_DERIVATION)
477        }
478
479        impl_psbt_get_pair! {
480            rv.push(self.tap_internal_key, PSBT_IN_TAP_INTERNAL_KEY)
481        }
482
483        impl_psbt_get_pair! {
484            rv.push(self.tap_merkle_root, PSBT_IN_TAP_MERKLE_ROOT)
485        }
486        for (key, value) in self.proprietary.iter() {
487            rv.push(raw::Pair { key: key.to_key(), value: value.clone() });
488        }
489
490        for (key, value) in self.unknown.iter() {
491            rv.push(raw::Pair { key: key.clone(), value: value.clone() });
492        }
493
494        rv
495    }
496}
497
498impl_psbtmap_ser_de_serialize!(Input);
499
500fn psbt_insert_hash_pair<H>(
501    map: &mut BTreeMap<H, Vec<u8>>,
502    raw_key: raw::Key,
503    raw_value: Vec<u8>,
504    hash_type: error::PsbtHash,
505) -> Result<(), Error>
506where
507    H: hashes::Hash + Deserialize,
508{
509    if raw_key.key.is_empty() {
510        return Err(psbt::Error::InvalidKey(raw_key));
511    }
512    let key_val: H = Deserialize::deserialize(&raw_key.key)?;
513    match map.entry(key_val) {
514        btree_map::Entry::Vacant(empty_key) => {
515            let val: Vec<u8> = Deserialize::deserialize(&raw_value)?;
516            if <H as hashes::Hash>::hash(&val) != key_val {
517                return Err(psbt::Error::InvalidPreimageHashPair {
518                    preimage: val.into_boxed_slice(),
519                    hash: Box::from(key_val.borrow()),
520                    hash_type,
521                });
522            }
523            empty_key.insert(val);
524            Ok(())
525        }
526        btree_map::Entry::Occupied(_) => Err(psbt::Error::DuplicateKey(raw_key)),
527    }
528}
529
530#[cfg(test)]
531mod test {
532    use super::*;
533
534    #[test]
535    fn psbt_sighash_type_ecdsa() {
536        for ecdsa in &[
537            EcdsaSighashType::All,
538            EcdsaSighashType::None,
539            EcdsaSighashType::Single,
540            EcdsaSighashType::AllPlusAnyoneCanPay,
541            EcdsaSighashType::NonePlusAnyoneCanPay,
542            EcdsaSighashType::SinglePlusAnyoneCanPay,
543        ] {
544            let sighash = PsbtSighashType::from(*ecdsa);
545            let s = format!("{}", sighash);
546            let back = PsbtSighashType::from_str(&s).unwrap();
547            assert_eq!(back, sighash);
548            assert_eq!(back.ecdsa_hash_ty().unwrap(), *ecdsa);
549        }
550    }
551
552    #[test]
553    fn psbt_sighash_type_taproot() {
554        for tap in &[
555            TapSighashType::Default,
556            TapSighashType::All,
557            TapSighashType::None,
558            TapSighashType::Single,
559            TapSighashType::AllPlusAnyoneCanPay,
560            TapSighashType::NonePlusAnyoneCanPay,
561            TapSighashType::SinglePlusAnyoneCanPay,
562        ] {
563            let sighash = PsbtSighashType::from(*tap);
564            let s = format!("{}", sighash);
565            let back = PsbtSighashType::from_str(&s).unwrap();
566            assert_eq!(back, sighash);
567            assert_eq!(back.taproot_hash_ty().unwrap(), *tap);
568        }
569    }
570
571    #[test]
572    fn psbt_sighash_type_notstd() {
573        let nonstd = 0xdddddddd;
574        let sighash = PsbtSighashType { inner: nonstd };
575        let s = format!("{}", sighash);
576        let back = PsbtSighashType::from_str(&s).unwrap();
577
578        assert_eq!(back, sighash);
579        assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashTypeError(nonstd)));
580        assert_eq!(back.taproot_hash_ty(), Err(InvalidSighashTypeError(nonstd)));
581    }
582}