use core::fmt;
use core::str::FromStr;
use hashes::{hash160, ripemd160, sha256, sha256d};
use secp256k1::XOnlyPublicKey;
use crate::bip32::KeySource;
use crate::blockdata::script::ScriptBuf;
use crate::blockdata::transaction::{Transaction, TxOut};
use crate::blockdata::witness::Witness;
use crate::crypto::key::PublicKey;
use crate::crypto::{ecdsa, taproot};
use crate::prelude::*;
use crate::psbt::map::Map;
use crate::psbt::serialize::Deserialize;
use crate::psbt::{self, error, raw, Error};
use crate::sighash::{
EcdsaSighashType, InvalidSighashTypeError, NonStandardSighashTypeError, SighashTypeParseError,
TapSighashType,
};
use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash};
const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
const PSBT_IN_WITNESS_UTXO: u8 = 0x01;
const PSBT_IN_PARTIAL_SIG: u8 = 0x02;
const PSBT_IN_SIGHASH_TYPE: u8 = 0x03;
const PSBT_IN_REDEEM_SCRIPT: u8 = 0x04;
const PSBT_IN_WITNESS_SCRIPT: u8 = 0x05;
const PSBT_IN_BIP32_DERIVATION: u8 = 0x06;
const PSBT_IN_FINAL_SCRIPTSIG: u8 = 0x07;
const PSBT_IN_FINAL_SCRIPTWITNESS: u8 = 0x08;
const PSBT_IN_RIPEMD160: u8 = 0x0a;
const PSBT_IN_SHA256: u8 = 0x0b;
const PSBT_IN_HASH160: u8 = 0x0c;
const PSBT_IN_HASH256: u8 = 0x0d;
const PSBT_IN_TAP_KEY_SIG: u8 = 0x13;
const PSBT_IN_TAP_SCRIPT_SIG: u8 = 0x14;
const PSBT_IN_TAP_LEAF_SCRIPT: u8 = 0x15;
const PSBT_IN_TAP_BIP32_DERIVATION: u8 = 0x16;
const PSBT_IN_TAP_INTERNAL_KEY: u8 = 0x17;
const PSBT_IN_TAP_MERKLE_ROOT: u8 = 0x18;
const PSBT_IN_PROPRIETARY: u8 = 0xFC;
#[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 {
pub non_witness_utxo: Option<Transaction>,
pub witness_utxo: Option<TxOut>,
pub partial_sigs: BTreeMap<PublicKey, ecdsa::Signature>,
pub sighash_type: Option<PsbtSighashType>,
pub redeem_script: Option<ScriptBuf>,
pub witness_script: Option<ScriptBuf>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
pub bip32_derivation: BTreeMap<secp256k1::PublicKey, KeySource>,
pub final_script_sig: Option<ScriptBuf>,
pub final_script_witness: Option<Witness>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
pub ripemd160_preimages: BTreeMap<ripemd160::Hash, Vec<u8>>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
pub sha256_preimages: BTreeMap<sha256::Hash, Vec<u8>>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
pub hash160_preimages: BTreeMap<hash160::Hash, Vec<u8>>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
pub tap_key_sig: Option<taproot::Signature>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), taproot::Signature>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
pub tap_scripts: BTreeMap<ControlBlock, (ScriptBuf, LeafVersion)>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
pub tap_key_origins: BTreeMap<XOnlyPublicKey, (Vec<TapLeafHash>, KeySource)>,
pub tap_internal_key: Option<XOnlyPublicKey>,
pub tap_merkle_root: Option<TapNodeHash>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
}
#[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.taproot_hash_ty() {
Err(_) => write!(f, "{:#x}", self.inner),
Ok(taproot_hash_ty) => fmt::Display::fmt(&taproot_hash_ty, f),
}
}
}
impl FromStr for PsbtSighashType {
type Err = SighashTypeParseError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(ty) = TapSighashType::from_str(s) {
return Ok(ty.into());
}
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<EcdsaSighashType> for PsbtSighashType {
fn from(ecdsa_hash_ty: EcdsaSighashType) -> Self {
PsbtSighashType { inner: ecdsa_hash_ty as u32 }
}
}
impl From<TapSighashType> for PsbtSighashType {
fn from(taproot_hash_ty: TapSighashType) -> Self {
PsbtSighashType { inner: taproot_hash_ty as u32 }
}
}
impl PsbtSighashType {
pub fn ecdsa_hash_ty(self) -> Result<EcdsaSighashType, NonStandardSighashTypeError> {
EcdsaSighashType::from_standard(self.inner)
}
pub fn taproot_hash_ty(self) -> Result<TapSighashType, InvalidSighashTypeError> {
if self.inner > 0xffu32 {
Err(InvalidSighashTypeError(self.inner))
} else {
TapSighashType::from_consensus_u8(self.inner as u8)
}
}
pub fn from_u32(n: u32) -> PsbtSighashType { PsbtSighashType { inner: n } }
pub fn to_u32(self) -> u32 { self.inner }
}
impl Input {
pub fn ecdsa_hash_ty(&self) -> Result<EcdsaSighashType, NonStandardSighashTypeError> {
self.sighash_type
.map(|sighash_type| sighash_type.ecdsa_hash_ty())
.unwrap_or(Ok(EcdsaSighashType::All))
}
pub fn taproot_hash_ty(&self) -> Result<TapSighashType, InvalidSighashTypeError> {
self.sighash_type
.map(|sighash_type| sighash_type.taproot_hash_ty())
.unwrap_or(Ok(TapSighashType::Default))
}
pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), 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 <= <raw_key: _>|<raw_value: Transaction>
}
}
PSBT_IN_WITNESS_UTXO => {
impl_psbt_insert_pair! {
self.witness_utxo <= <raw_key: _>|<raw_value: TxOut>
}
}
PSBT_IN_PARTIAL_SIG => {
impl_psbt_insert_pair! {
self.partial_sigs <= <raw_key: PublicKey>|<raw_value: ecdsa::Signature>
}
}
PSBT_IN_SIGHASH_TYPE => {
impl_psbt_insert_pair! {
self.sighash_type <= <raw_key: _>|<raw_value: PsbtSighashType>
}
}
PSBT_IN_REDEEM_SCRIPT => {
impl_psbt_insert_pair! {
self.redeem_script <= <raw_key: _>|<raw_value: ScriptBuf>
}
}
PSBT_IN_WITNESS_SCRIPT => {
impl_psbt_insert_pair! {
self.witness_script <= <raw_key: _>|<raw_value: ScriptBuf>
}
}
PSBT_IN_BIP32_DERIVATION => {
impl_psbt_insert_pair! {
self.bip32_derivation <= <raw_key: secp256k1::PublicKey>|<raw_value: KeySource>
}
}
PSBT_IN_FINAL_SCRIPTSIG => {
impl_psbt_insert_pair! {
self.final_script_sig <= <raw_key: _>|<raw_value: ScriptBuf>
}
}
PSBT_IN_FINAL_SCRIPTWITNESS => {
impl_psbt_insert_pair! {
self.final_script_witness <= <raw_key: _>|<raw_value: 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 <= <raw_key: _>|<raw_value: taproot::Signature>
}
}
PSBT_IN_TAP_SCRIPT_SIG => {
impl_psbt_insert_pair! {
self.tap_script_sigs <= <raw_key: (XOnlyPublicKey, TapLeafHash)>|<raw_value: taproot::Signature>
}
}
PSBT_IN_TAP_LEAF_SCRIPT => {
impl_psbt_insert_pair! {
self.tap_scripts <= <raw_key: ControlBlock>|< raw_value: (ScriptBuf, LeafVersion)>
}
}
PSBT_IN_TAP_BIP32_DERIVATION => {
impl_psbt_insert_pair! {
self.tap_key_origins <= <raw_key: XOnlyPublicKey>|< raw_value: (Vec<TapLeafHash>, KeySource)>
}
}
PSBT_IN_TAP_INTERNAL_KEY => {
impl_psbt_insert_pair! {
self.tap_internal_key <= <raw_key: _>|< raw_value: XOnlyPublicKey>
}
}
PSBT_IN_TAP_MERKLE_ROOT => {
impl_psbt_insert_pair! {
self.tap_merkle_root <= <raw_key: _>|< raw_value: TapNodeHash>
}
}
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)),
}
}
_ => 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())),
},
}
Ok(())
}
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; }
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<raw::Pair> {
let mut rv: Vec<raw::Pair> = 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<H>(
map: &mut BTreeMap<H, Vec<u8>>,
raw_key: raw::Key,
raw_value: Vec<u8>,
hash_type: error::PsbtHash,
) -> Result<(), Error>
where
H: hashes::Hash + Deserialize,
{
if raw_key.key.is_empty() {
return Err(psbt::Error::InvalidKey(raw_key));
}
let key_val: H = Deserialize::deserialize(&raw_key.key)?;
match map.entry(key_val) {
btree_map::Entry::Vacant(empty_key) => {
let val: Vec<u8> = Deserialize::deserialize(&raw_value)?;
if <H as hashes::Hash>::hash(&val) != key_val {
return Err(psbt::Error::InvalidPreimageHashPair {
preimage: val.into_boxed_slice(),
hash: Box::from(key_val.borrow()),
hash_type,
});
}
empty_key.insert(val);
Ok(())
}
btree_map::Entry::Occupied(_) => Err(psbt::Error::DuplicateKey(raw_key)),
}
}
#[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_taproot() {
for tap in &[
TapSighashType::Default,
TapSighashType::All,
TapSighashType::None,
TapSighashType::Single,
TapSighashType::AllPlusAnyoneCanPay,
TapSighashType::NonePlusAnyoneCanPay,
TapSighashType::SinglePlusAnyoneCanPay,
] {
let sighash = PsbtSighashType::from(*tap);
let s = format!("{}", sighash);
let back = PsbtSighashType::from_str(&s).unwrap();
assert_eq!(back, sighash);
assert_eq!(back.taproot_hash_ty().unwrap(), *tap);
}
}
#[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(NonStandardSighashTypeError(nonstd)));
assert_eq!(back.taproot_hash_ty(), Err(InvalidSighashTypeError(nonstd)));
}
}