// SPDX-License-Identifier: CC0-1.0 use crate::prelude::*; use core::fmt; use core::str::FromStr; use core::convert::TryFrom; use secp256k1::XOnlyPublicKey; use crate::blockdata::script::ScriptBuf; use crate::blockdata::witness::Witness; use crate::blockdata::transaction::{Transaction, TxOut}; use crate::consensus::encode; use crate::crypto::{ecdsa, schnorr}; use crate::crypto::key::PublicKey; use crate::hashes::{self, hash160, ripemd160, sha256, sha256d}; use crate::bip32::KeySource; use crate::psbt::map::Map; use crate::psbt::serialize::Deserialize; use crate::psbt::{self, error, raw, Error}; use crate::sighash::{self, NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, SchnorrSighashType}; use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash}; /// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00 const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00; /// Type: Witness UTXO PSBT_IN_WITNESS_UTXO = 0x01 const PSBT_IN_WITNESS_UTXO: u8 = 0x01; /// Type: Partial Signature PSBT_IN_PARTIAL_SIG = 0x02 const PSBT_IN_PARTIAL_SIG: u8 = 0x02; /// Type: Sighash Type PSBT_IN_SIGHASH_TYPE = 0x03 const PSBT_IN_SIGHASH_TYPE: u8 = 0x03; /// Type: Redeem Script PSBT_IN_REDEEM_SCRIPT = 0x04 const PSBT_IN_REDEEM_SCRIPT: u8 = 0x04; /// Type: Witness Script PSBT_IN_WITNESS_SCRIPT = 0x05 const PSBT_IN_WITNESS_SCRIPT: u8 = 0x05; /// Type: BIP 32 Derivation Path PSBT_IN_BIP32_DERIVATION = 0x06 const PSBT_IN_BIP32_DERIVATION: u8 = 0x06; /// Type: Finalized scriptSig PSBT_IN_FINAL_SCRIPTSIG = 0x07 const PSBT_IN_FINAL_SCRIPTSIG: u8 = 0x07; /// Type: Finalized scriptWitness PSBT_IN_FINAL_SCRIPTWITNESS = 0x08 const PSBT_IN_FINAL_SCRIPTWITNESS: u8 = 0x08; /// Type: RIPEMD160 preimage PSBT_IN_RIPEMD160 = 0x0a const PSBT_IN_RIPEMD160: u8 = 0x0a; /// Type: SHA256 preimage PSBT_IN_SHA256 = 0x0b const PSBT_IN_SHA256: u8 = 0x0b; /// Type: HASH160 preimage PSBT_IN_HASH160 = 0x0c const PSBT_IN_HASH160: u8 = 0x0c; /// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d const PSBT_IN_HASH256: u8 = 0x0d; /// Type: Schnorr Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13 const PSBT_IN_TAP_KEY_SIG: u8 = 0x13; /// Type: Schnorr Signature in Script Spend PSBT_IN_TAP_SCRIPT_SIG = 0x14 const PSBT_IN_TAP_SCRIPT_SIG: u8 = 0x14; /// Type: Taproot Leaf Script PSBT_IN_TAP_LEAF_SCRIPT = 0x14 const PSBT_IN_TAP_LEAF_SCRIPT: u8 = 0x15; /// Type: Taproot Key BIP 32 Derivation Path PSBT_IN_TAP_BIP32_DERIVATION = 0x16 const PSBT_IN_TAP_BIP32_DERIVATION: u8 = 0x16; /// Type: Taproot Internal Key PSBT_IN_TAP_INTERNAL_KEY = 0x17 const PSBT_IN_TAP_INTERNAL_KEY: u8 = 0x17; /// Type: Taproot Merkle Root PSBT_IN_TAP_MERKLE_ROOT = 0x18 const PSBT_IN_TAP_MERKLE_ROOT: u8 = 0x18; /// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC const PSBT_IN_PROPRIETARY: u8 = 0xFC; /// A key-value map for an input of the corresponding index in the unsigned /// transaction. #[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct Input { /// The non-witness transaction this input spends from. Should only be /// [std::option::Option::Some] for inputs which spend non-segwit outputs or /// if it is unknown whether an input spends a segwit output. pub non_witness_utxo: Option, /// The transaction output this input spends from. Should only be /// [std::option::Option::Some] for inputs which spend segwit outputs, /// including P2SH embedded ones. pub witness_utxo: Option, /// A map from public keys to their corresponding signature as would be /// pushed to the stack from a scriptSig or witness for a non-taproot inputs. pub partial_sigs: BTreeMap, /// The sighash type to be used for this input. Signatures for this input /// must use the sighash type. pub sighash_type: Option, /// The redeem script for this input. pub redeem_script: Option, /// The witness script for this input. pub witness_script: Option, /// A map from public keys needed to sign this input to their corresponding /// master key fingerprints and derivation paths. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] pub bip32_derivation: BTreeMap, /// The finalized, fully-constructed scriptSig with signatures and any other /// scripts necessary for this input to pass validation. pub final_script_sig: Option, /// The finalized, fully-constructed scriptWitness with signatures and any /// other scripts necessary for this input to pass validation. pub final_script_witness: Option, /// TODO: Proof of reserves commitment /// RIPEMD160 hash to preimage map. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] pub ripemd160_preimages: BTreeMap>, /// SHA256 hash to preimage map. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] pub sha256_preimages: BTreeMap>, /// HSAH160 hash to preimage map. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] pub hash160_preimages: BTreeMap>, /// HAS256 hash to preimage map. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] pub hash256_preimages: BTreeMap>, /// Serialized schnorr signature with sighash type for key spend. pub tap_key_sig: Option, /// Map of `|` with signature. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), schnorr::Signature>, /// Map of Control blocks to Script version pair. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] pub tap_scripts: BTreeMap, /// Map of tap root x only keys to origin info and leaf hashes contained in it. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] pub tap_key_origins: BTreeMap, KeySource)>, /// Taproot Internal key. pub tap_internal_key: Option, /// Taproot Merkle root. pub tap_merkle_root: Option, /// Proprietary key-value pairs for this input. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))] pub proprietary: BTreeMap>, /// Unknown key-value pairs for this input. #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))] pub unknown: BTreeMap>, } /// A Signature hash type for the corresponding input. As of taproot upgrade, the signature hash /// type can be either [`EcdsaSighashType`] or [`SchnorrSighashType`] but it is not possible to know /// directly which signature hash type the user is dealing with. Therefore, the user is responsible /// for converting to/from [`PsbtSighashType`] from/to the desired signature hash type they need. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct PsbtSighashType { pub (in crate::psbt) inner: u32, } impl fmt::Display for PsbtSighashType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.schnorr_hash_ty() { Err(_) => write!(f, "{:#x}", self.inner), Ok(schnorr_hash_ty) => fmt::Display::fmt(&schnorr_hash_ty, f), } } } impl FromStr for PsbtSighashType { type Err = SighashTypeParseError; #[inline] fn from_str(s: &str) -> Result { // We accept strings of form: "SIGHASH_ALL" etc. // // NB: some of Schnorr sighash types are non-standard for pre-taproot // inputs. We also do not support SIGHASH_RESERVED in verbatim form // ("0xFF" string should be used instead). if let Ok(ty) = SchnorrSighashType::from_str(s) { return Ok(ty.into()); } // We accept non-standard sighash values. if let Ok(inner) = u32::from_str_radix(s.trim_start_matches("0x"), 16) { return Ok(PsbtSighashType { inner }); } Err(SighashTypeParseError{ unrecognized: s.to_owned() }) } } impl From for PsbtSighashType { fn from(ecdsa_hash_ty: EcdsaSighashType) -> Self { PsbtSighashType { inner: ecdsa_hash_ty as u32 } } } impl From for PsbtSighashType { fn from(schnorr_hash_ty: SchnorrSighashType) -> Self { PsbtSighashType { inner: schnorr_hash_ty as u32 } } } impl PsbtSighashType { /// Returns the [`EcdsaSighashType`] if the [`PsbtSighashType`] can be /// converted to one. pub fn ecdsa_hash_ty(self) -> Result { EcdsaSighashType::from_standard(self.inner) } /// Returns the [`SchnorrSighashType`] if the [`PsbtSighashType`] can be /// converted to one. pub fn schnorr_hash_ty(self) -> Result { if self.inner > 0xffu32 { Err(sighash::Error::InvalidSighashType(self.inner)) } else { SchnorrSighashType::from_consensus_u8(self.inner as u8) } } /// Creates a [`PsbtSighashType`] from a raw `u32`. /// /// Allows construction of a non-standard or non-valid sighash flag /// ([`EcdsaSighashType`], [`SchnorrSighashType`] respectively). pub fn from_u32(n: u32) -> PsbtSighashType { PsbtSighashType { inner: n } } /// Converts [`PsbtSighashType`] to a raw `u32` sighash flag. /// /// No guarantees are made as to the standardness or validity of the returned value. pub fn to_u32(self) -> u32 { self.inner } } impl Input { /// Obtains the [`EcdsaSighashType`] for this input if one is specified. If no sighash type is /// specified, returns [`EcdsaSighashType::All`]. /// /// # Errors /// /// If the `sighash_type` field is set to a non-standard ECDSA sighash value. pub fn ecdsa_hash_ty(&self) -> Result { self.sighash_type .map(|sighash_type| sighash_type.ecdsa_hash_ty()) .unwrap_or(Ok(EcdsaSighashType::All)) } /// Obtains the [`SchnorrSighashType`] for this input if one is specified. If no sighash type is /// specified, returns [`SchnorrSighashType::Default`]. /// /// # Errors /// /// If the `sighash_type` field is set to a invalid Schnorr sighash value. pub fn schnorr_hash_ty(&self) -> Result { self.sighash_type .map(|sighash_type| sighash_type.schnorr_hash_ty()) .unwrap_or(Ok(SchnorrSighashType::Default)) } pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> { let raw::Pair { key: raw_key, value: raw_value, } = pair; match raw_key.type_value { PSBT_IN_NON_WITNESS_UTXO => { impl_psbt_insert_pair! { self.non_witness_utxo <= | } } PSBT_IN_WITNESS_UTXO => { impl_psbt_insert_pair! { self.witness_utxo <= | } } PSBT_IN_PARTIAL_SIG => { impl_psbt_insert_pair! { self.partial_sigs <= | } } PSBT_IN_SIGHASH_TYPE => { impl_psbt_insert_pair! { self.sighash_type <= | } } PSBT_IN_REDEEM_SCRIPT => { impl_psbt_insert_pair! { self.redeem_script <= | } } PSBT_IN_WITNESS_SCRIPT => { impl_psbt_insert_pair! { self.witness_script <= | } } PSBT_IN_BIP32_DERIVATION => { impl_psbt_insert_pair! { self.bip32_derivation <= | } } PSBT_IN_FINAL_SCRIPTSIG => { impl_psbt_insert_pair! { self.final_script_sig <= | } } PSBT_IN_FINAL_SCRIPTWITNESS => { impl_psbt_insert_pair! { self.final_script_witness <= | } } PSBT_IN_RIPEMD160 => { psbt_insert_hash_pair(&mut self.ripemd160_preimages, raw_key, raw_value, error::PsbtHash::Ripemd)?; } PSBT_IN_SHA256 => { psbt_insert_hash_pair(&mut self.sha256_preimages, raw_key, raw_value, error::PsbtHash::Sha256)?; } PSBT_IN_HASH160 => { psbt_insert_hash_pair(&mut self.hash160_preimages, raw_key, raw_value, error::PsbtHash::Hash160)?; } PSBT_IN_HASH256 => { psbt_insert_hash_pair(&mut self.hash256_preimages, raw_key, raw_value, error::PsbtHash::Hash256)?; } PSBT_IN_TAP_KEY_SIG => { impl_psbt_insert_pair! { self.tap_key_sig <= | } } PSBT_IN_TAP_SCRIPT_SIG => { impl_psbt_insert_pair! { self.tap_script_sigs <= | } } PSBT_IN_TAP_LEAF_SCRIPT => { impl_psbt_insert_pair! { self.tap_scripts <= |< raw_value: (ScriptBuf, LeafVersion)> } } PSBT_IN_TAP_BIP32_DERIVATION => { impl_psbt_insert_pair! { self.tap_key_origins <= |< raw_value: (Vec, KeySource)> } } PSBT_IN_TAP_INTERNAL_KEY => { impl_psbt_insert_pair! { self.tap_internal_key <= |< raw_value: XOnlyPublicKey> } } PSBT_IN_TAP_MERKLE_ROOT => { impl_psbt_insert_pair! { self.tap_merkle_root <= |< raw_value: TapBranchHash> } } PSBT_IN_PROPRIETARY => { let key = raw::ProprietaryKey::try_from(raw_key.clone())?; match self.proprietary.entry(key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); }, btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()), } } _ => match self.unknown.entry(raw_key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); } btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()), }, } Ok(()) } /// Combines this [`Input`] with `other` `Input` (as described by BIP 174). pub fn combine(&mut self, other: Self) { combine!(non_witness_utxo, self, other); if let (&None, Some(witness_utxo)) = (&self.witness_utxo, other.witness_utxo) { self.witness_utxo = Some(witness_utxo); self.non_witness_utxo = None; // Clear out any non-witness UTXO when we set a witness one } self.partial_sigs.extend(other.partial_sigs); self.bip32_derivation.extend(other.bip32_derivation); self.ripemd160_preimages.extend(other.ripemd160_preimages); self.sha256_preimages.extend(other.sha256_preimages); self.hash160_preimages.extend(other.hash160_preimages); self.hash256_preimages.extend(other.hash256_preimages); self.tap_script_sigs.extend(other.tap_script_sigs); self.tap_scripts.extend(other.tap_scripts); self.tap_key_origins.extend(other.tap_key_origins); self.proprietary.extend(other.proprietary); self.unknown.extend(other.unknown); combine!(redeem_script, self, other); combine!(witness_script, self, other); combine!(final_script_sig, self, other); combine!(final_script_witness, self, other); combine!(tap_key_sig, self, other); combine!(tap_internal_key, self, other); combine!(tap_merkle_root, self, other); } } impl Map for Input { fn get_pairs(&self) -> Vec { let mut rv: Vec = Default::default(); impl_psbt_get_pair! { rv.push(self.non_witness_utxo, PSBT_IN_NON_WITNESS_UTXO) } impl_psbt_get_pair! { rv.push(self.witness_utxo, PSBT_IN_WITNESS_UTXO) } impl_psbt_get_pair! { rv.push_map(self.partial_sigs, PSBT_IN_PARTIAL_SIG) } impl_psbt_get_pair! { rv.push(self.sighash_type, PSBT_IN_SIGHASH_TYPE) } impl_psbt_get_pair! { rv.push(self.redeem_script, PSBT_IN_REDEEM_SCRIPT) } impl_psbt_get_pair! { rv.push(self.witness_script, PSBT_IN_WITNESS_SCRIPT) } impl_psbt_get_pair! { rv.push_map(self.bip32_derivation, PSBT_IN_BIP32_DERIVATION) } impl_psbt_get_pair! { rv.push(self.final_script_sig, PSBT_IN_FINAL_SCRIPTSIG) } impl_psbt_get_pair! { rv.push(self.final_script_witness, PSBT_IN_FINAL_SCRIPTWITNESS) } impl_psbt_get_pair! { rv.push_map(self.ripemd160_preimages, PSBT_IN_RIPEMD160) } impl_psbt_get_pair! { rv.push_map(self.sha256_preimages, PSBT_IN_SHA256) } impl_psbt_get_pair! { rv.push_map(self.hash160_preimages, PSBT_IN_HASH160) } impl_psbt_get_pair! { rv.push_map(self.hash256_preimages, PSBT_IN_HASH256) } impl_psbt_get_pair! { rv.push(self.tap_key_sig, PSBT_IN_TAP_KEY_SIG) } impl_psbt_get_pair! { rv.push_map(self.tap_script_sigs, PSBT_IN_TAP_SCRIPT_SIG) } impl_psbt_get_pair! { rv.push_map(self.tap_scripts, PSBT_IN_TAP_LEAF_SCRIPT) } impl_psbt_get_pair! { rv.push_map(self.tap_key_origins, PSBT_IN_TAP_BIP32_DERIVATION) } impl_psbt_get_pair! { rv.push(self.tap_internal_key, PSBT_IN_TAP_INTERNAL_KEY) } impl_psbt_get_pair! { rv.push(self.tap_merkle_root, PSBT_IN_TAP_MERKLE_ROOT) } for (key, value) in self.proprietary.iter() { rv.push(raw::Pair { key: key.to_key(), value: value.clone(), }); } for (key, value) in self.unknown.iter() { rv.push(raw::Pair { key: key.clone(), value: value.clone(), }); } rv } } impl_psbtmap_ser_de_serialize!(Input); fn psbt_insert_hash_pair( map: &mut BTreeMap>, raw_key: raw::Key, raw_value: Vec, hash_type: error::PsbtHash, ) -> Result<(), encode::Error> where H: hashes::Hash + Deserialize, { if raw_key.key.is_empty() { return Err(psbt::Error::InvalidKey(raw_key).into()); } let key_val: H = Deserialize::deserialize(&raw_key.key)?; match map.entry(key_val) { btree_map::Entry::Vacant(empty_key) => { let val: Vec = Deserialize::deserialize(&raw_value)?; if ::hash(&val) != key_val { return Err(psbt::Error::InvalidPreimageHashPair { preimage: val.into_boxed_slice(), hash: Box::from(key_val.borrow()), hash_type, } .into()); } empty_key.insert(val); Ok(()) } btree_map::Entry::Occupied(_) => Err(psbt::Error::DuplicateKey(raw_key).into()), } } #[cfg(test)] mod test { use super::*; #[test] fn psbt_sighash_type_ecdsa() { for ecdsa in &[ EcdsaSighashType::All, EcdsaSighashType::None, EcdsaSighashType::Single, EcdsaSighashType::AllPlusAnyoneCanPay, EcdsaSighashType::NonePlusAnyoneCanPay, EcdsaSighashType::SinglePlusAnyoneCanPay, ] { let sighash = PsbtSighashType::from(*ecdsa); let s = format!("{}", sighash); let back = PsbtSighashType::from_str(&s).unwrap(); assert_eq!(back, sighash); assert_eq!(back.ecdsa_hash_ty().unwrap(), *ecdsa); } } #[test] fn psbt_sighash_type_schnorr() { for schnorr in &[ SchnorrSighashType::Default, SchnorrSighashType::All, SchnorrSighashType::None, SchnorrSighashType::Single, SchnorrSighashType::AllPlusAnyoneCanPay, SchnorrSighashType::NonePlusAnyoneCanPay, SchnorrSighashType::SinglePlusAnyoneCanPay, ] { let sighash = PsbtSighashType::from(*schnorr); let s = format!("{}", sighash); let back = PsbtSighashType::from_str(&s).unwrap(); assert_eq!(back, sighash); assert_eq!(back.schnorr_hash_ty().unwrap(), *schnorr); } } #[test] fn psbt_sighash_type_notstd() { let nonstd = 0xdddddddd; let sighash = PsbtSighashType { inner: nonstd }; let s = format!("{}", sighash); let back = PsbtSighashType::from_str(&s).unwrap(); assert_eq!(back, sighash); assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashType(nonstd))); assert_eq!(back.schnorr_hash_ty(), Err(sighash::Error::InvalidSighashType(nonstd))); } }