psbt_v0/map/
input.rs

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