Introduce PsbtSigHashType
This commit is contained in:
parent
b2de2bc33d
commit
382c8f9e4f
|
@ -19,7 +19,7 @@ use ::{EcdsaSig, io};
|
||||||
use secp256k1;
|
use secp256k1;
|
||||||
use blockdata::script::Script;
|
use blockdata::script::Script;
|
||||||
use blockdata::witness::Witness;
|
use blockdata::witness::Witness;
|
||||||
use blockdata::transaction::{EcdsaSigHashType, Transaction, TxOut};
|
use blockdata::transaction::{Transaction, TxOut, NonStandardSigHashType};
|
||||||
use consensus::encode;
|
use consensus::encode;
|
||||||
use hashes::{self, hash160, ripemd160, sha256, sha256d};
|
use hashes::{self, hash160, ripemd160, sha256, sha256d};
|
||||||
use secp256k1::XOnlyPublicKey;
|
use secp256k1::XOnlyPublicKey;
|
||||||
|
@ -32,6 +32,8 @@ use util::psbt::{Error, error};
|
||||||
|
|
||||||
use ::{SchnorrSig};
|
use ::{SchnorrSig};
|
||||||
use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
|
use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
|
||||||
|
use util::sighash;
|
||||||
|
use {EcdsaSigHashType, SchnorrSigHashType};
|
||||||
|
|
||||||
/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
|
/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
|
||||||
const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
|
const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
|
||||||
|
@ -92,7 +94,7 @@ pub struct Input {
|
||||||
pub partial_sigs: BTreeMap<secp256k1::PublicKey, EcdsaSig>,
|
pub partial_sigs: BTreeMap<secp256k1::PublicKey, EcdsaSig>,
|
||||||
/// The sighash type to be used for this input. Signatures for this input
|
/// The sighash type to be used for this input. Signatures for this input
|
||||||
/// must use the sighash type.
|
/// must use the sighash type.
|
||||||
pub sighash_type: Option<EcdsaSigHashType>,
|
pub sighash_type: Option<PsbtSigHashType>,
|
||||||
/// The redeem script for this input.
|
/// The redeem script for this input.
|
||||||
pub redeem_script: Option<Script>,
|
pub redeem_script: Option<Script>,
|
||||||
/// The witness script for this input.
|
/// The witness script for this input.
|
||||||
|
@ -143,6 +145,52 @@ pub struct Input {
|
||||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 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))]
|
||||||
|
pub struct PsbtSigHashType {
|
||||||
|
pub (in ::util::psbt) inner: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EcdsaSigHashType> for PsbtSigHashType {
|
||||||
|
fn from(ecdsa_hash_ty: EcdsaSigHashType) -> Self {
|
||||||
|
PsbtSigHashType {inner: ecdsa_hash_ty as u32}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SchnorrSigHashType> 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, NonStandardSigHashType> {
|
||||||
|
EcdsaSigHashType::from_u32_standard(self.inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the [`SchnorrSigHashType`] if the [`PsbtSigHashType`] can be
|
||||||
|
/// converted to one.
|
||||||
|
pub fn schnorr_hash_ty(self) -> Result<SchnorrSigHashType, sighash::Error> {
|
||||||
|
if self.inner > 0xffu32 {
|
||||||
|
Err(sighash::Error::InvalidSigHashType(self.inner))
|
||||||
|
} else {
|
||||||
|
SchnorrSigHashType::from_u8(self.inner as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtains the inner sighash byte from this [`PsbtSigHashType`].
|
||||||
|
pub fn inner(self) -> u32 {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Map for Input {
|
impl Map for Input {
|
||||||
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
||||||
let raw::Pair {
|
let raw::Pair {
|
||||||
|
@ -168,7 +216,7 @@ impl Map for Input {
|
||||||
}
|
}
|
||||||
PSBT_IN_SIGHASH_TYPE => {
|
PSBT_IN_SIGHASH_TYPE => {
|
||||||
impl_psbt_insert_pair! {
|
impl_psbt_insert_pair! {
|
||||||
self.sighash_type <= <raw_key: _>|<raw_value: EcdsaSigHashType>
|
self.sighash_type <= <raw_key: _>|<raw_value: PsbtSigHashType>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PSBT_IN_REDEEM_SCRIPT => {
|
PSBT_IN_REDEEM_SCRIPT => {
|
||||||
|
|
|
@ -53,6 +53,6 @@ mod global;
|
||||||
mod input;
|
mod input;
|
||||||
mod output;
|
mod output;
|
||||||
|
|
||||||
pub use self::input::Input;
|
pub use self::input::{Input, PsbtSigHashType};
|
||||||
pub use self::output::Output;
|
pub use self::output::Output;
|
||||||
pub use self::output::TapTree;
|
pub use self::output::TapTree;
|
||||||
|
|
|
@ -406,6 +406,7 @@ mod tests {
|
||||||
//! Create a full PSBT value with various fields filled and make sure it can be JSONized.
|
//! Create a full PSBT value with various fields filled and make sure it can be JSONized.
|
||||||
use hashes::sha256d;
|
use hashes::sha256d;
|
||||||
use util::psbt::map::Input;
|
use util::psbt::map::Input;
|
||||||
|
use EcdsaSigHashType;
|
||||||
|
|
||||||
// create some values to use in the PSBT
|
// create some values to use in the PSBT
|
||||||
let tx = Transaction {
|
let tx = Transaction {
|
||||||
|
@ -469,7 +470,7 @@ mod tests {
|
||||||
value: 190303501938,
|
value: 190303501938,
|
||||||
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
|
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
|
||||||
}),
|
}),
|
||||||
sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse().unwrap()),
|
sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<EcdsaSigHashType>().unwrap().into()),
|
||||||
redeem_script: Some(vec![0x51].into()),
|
redeem_script: Some(vec![0x51].into()),
|
||||||
witness_script: None,
|
witness_script: None,
|
||||||
partial_sigs: vec![(
|
partial_sigs: vec![(
|
||||||
|
@ -732,8 +733,8 @@ mod tests {
|
||||||
.is_p2pkh()
|
.is_p2pkh()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(&psbt.inputs[0].sighash_type).as_ref().unwrap(),
|
(&psbt.inputs[0].sighash_type).as_ref().unwrap().ecdsa_hash_ty().unwrap(),
|
||||||
&EcdsaSigHashType::All
|
EcdsaSigHashType::All
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,9 @@ use secp256k1::{self, XOnlyPublicKey};
|
||||||
use util::bip32::{ChildNumber, Fingerprint, KeySource};
|
use util::bip32::{ChildNumber, Fingerprint, KeySource};
|
||||||
use hashes::{hash160, ripemd160, sha256, sha256d, Hash};
|
use hashes::{hash160, ripemd160, sha256, sha256d, Hash};
|
||||||
use util::ecdsa::EcdsaSig;
|
use util::ecdsa::EcdsaSig;
|
||||||
use util::psbt;
|
|
||||||
use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion};
|
use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion};
|
||||||
use schnorr;
|
use schnorr;
|
||||||
use super::map::TapTree;
|
use super::map::{TapTree, PsbtSigHashType};
|
||||||
|
|
||||||
use util::taproot::TaprootBuilder;
|
use util::taproot::TaprootBuilder;
|
||||||
use util::sighash::SchnorrSigHashType;
|
use util::sighash::SchnorrSigHashType;
|
||||||
|
@ -160,22 +159,16 @@ impl Deserialize for Vec<u8> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for EcdsaSigHashType {
|
impl Serialize for PsbtSigHashType {
|
||||||
fn serialize(&self) -> Vec<u8> {
|
fn serialize(&self) -> Vec<u8> {
|
||||||
serialize(&self.as_u32())
|
serialize(&self.inner())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserialize for EcdsaSigHashType {
|
impl Deserialize for PsbtSigHashType {
|
||||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||||
let raw: u32 = encode::deserialize(bytes)?;
|
let raw: u32 = encode::deserialize(bytes)?;
|
||||||
let rv: EcdsaSigHashType = EcdsaSigHashType::from_u32_consensus(raw);
|
Ok(PsbtSigHashType { inner: raw })
|
||||||
|
|
||||||
if rv.as_u32() == raw {
|
|
||||||
Ok(rv)
|
|
||||||
} else {
|
|
||||||
Err(psbt::Error::NonStandardSigHashType(raw).into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ pub enum Error {
|
||||||
WrongAnnex,
|
WrongAnnex,
|
||||||
|
|
||||||
/// Invalid Sighash type
|
/// Invalid Sighash type
|
||||||
InvalidSigHashType(u8),
|
InvalidSigHashType(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
|
@ -286,7 +286,7 @@ impl SchnorrSigHashType {
|
||||||
0x81 => Ok(SchnorrSigHashType::AllPlusAnyoneCanPay),
|
0x81 => Ok(SchnorrSigHashType::AllPlusAnyoneCanPay),
|
||||||
0x82 => Ok(SchnorrSigHashType::NonePlusAnyoneCanPay),
|
0x82 => Ok(SchnorrSigHashType::NonePlusAnyoneCanPay),
|
||||||
0x83 => Ok(SchnorrSigHashType::SinglePlusAnyoneCanPay),
|
0x83 => Ok(SchnorrSigHashType::SinglePlusAnyoneCanPay),
|
||||||
x => Err(Error::InvalidSigHashType(x)),
|
x => Err(Error::InvalidSigHashType(x as u32)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue