Skip to content

Commit

Permalink
Merge pull request #11 from tcharding/09-25-bitcoin-master
Browse files Browse the repository at this point in the history
Port over changes from `rust-bitcoin` master
  • Loading branch information
tcharding authored Sep 29, 2024
2 parents 8ce3727 + 55afb16 commit 33a3520
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 122 deletions.
12 changes: 6 additions & 6 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ pub enum Error {
InvalidXOnlyPublicKey,
/// Parsing error indicating invalid ECDSA signatures
InvalidEcdsaSignature(ecdsa::Error),
/// Parsing error indicating invalid taproot signatures
/// Parsing error indicating invalid Taproot signatures
InvalidTaprootSignature(taproot::SigFromSliceError),
/// Parsing error indicating invalid control block
InvalidControlBlock,
/// Parsing error indicating invalid leaf version
InvalidLeafVersion,
/// Parsing error indicating a taproot error
/// Parsing error indicating a Taproot error
Taproot(&'static str),
/// Taproot tree deserilaization error
TapTree(taproot::IncompleteBuilderError),
Expand Down Expand Up @@ -135,7 +135,7 @@ impl fmt::Display for Error {
InvalidHash(ref e) => write_err!(f, "invalid hash when parsing slice"; e),
InvalidPreimageHashPair { ref preimage, ref hash, ref hash_type } => {
// directly using debug forms of psbthash enums
write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash)
write!(f, "preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash)
}
CombineInconsistentKeySources(ref s) => {
write!(f, "combine conflict: {}", s)
Expand All @@ -147,11 +147,11 @@ impl fmt::Display for Error {
InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e),
InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"),
InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e),
InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e),
InvalidTaprootSignature(ref e) => write_err!(f, "invalid Taproot signature"; e),
InvalidControlBlock => f.write_str("invalid control block"),
InvalidLeafVersion => f.write_str("invalid leaf version"),
Taproot(s) => write!(f, "taproot error - {}", s),
TapTree(ref e) => write_err!(f, "taproot tree error"; e),
Taproot(s) => write!(f, "Taproot error - {}", s),
TapTree(ref e) => write_err!(f, "Taproot tree error"; e),
XPubKey(s) => write!(f, "xpub key error - {}", s),
Version(s) => write!(f, "version error {}", s),
PartialDataConsumption =>
Expand Down
114 changes: 56 additions & 58 deletions src/lib.rs

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ macro_rules! impl_psbtmap_ser_de_serialize {
#[rustfmt::skip]
macro_rules! impl_psbt_insert_pair {
($slf:ident.$unkeyed_name:ident <= <$raw_key:ident: _>|<$raw_value:ident: $unkeyed_value_type:ty>) => {
if $raw_key.key.is_empty() {
if $raw_key.key_data.is_empty() {
if $slf.$unkeyed_name.is_none() {
let val: $unkeyed_value_type = $crate::serialize::Deserialize::deserialize(&$raw_value)?;
$slf.$unkeyed_name = Some(val)
Expand All @@ -96,8 +96,8 @@ macro_rules! impl_psbt_insert_pair {
}
};
($slf:ident.$keyed_name:ident <= <$raw_key:ident: $keyed_key_type:ty>|<$raw_value:ident: $keyed_value_type:ty>) => {
if !$raw_key.key.is_empty() {
let key_val: $keyed_key_type = $crate::serialize::Deserialize::deserialize(&$raw_key.key)?;
if !$raw_key.key_data.is_empty() {
let key_val: $keyed_key_type = $crate::serialize::Deserialize::deserialize(&$raw_key.key_data)?;
match $slf.$keyed_name.entry(key_val) {
$crate::prelude::btree_map::Entry::Vacant(empty_key) => {
let val: $keyed_value_type = $crate::serialize::Deserialize::deserialize(&$raw_value)?;
Expand All @@ -118,7 +118,7 @@ macro_rules! impl_psbt_get_pair {
$rv.push($crate::raw::Pair {
key: $crate::raw::Key {
type_value: $unkeyed_typeval,
key: vec![],
key_data: vec![],
},
value: $crate::serialize::Serialize::serialize($unkeyed_name),
});
Expand All @@ -129,7 +129,7 @@ macro_rules! impl_psbt_get_pair {
$rv.push($crate::raw::Pair {
key: $crate::raw::Key {
type_value: $keyed_typeval,
key: $crate::serialize::Serialize::serialize(key),
key_data: $crate::serialize::Serialize::serialize(key),
},
value: $crate::serialize::Serialize::serialize(val),
});
Expand Down
24 changes: 12 additions & 12 deletions src/map/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl Map for Psbt {
let mut rv: Vec<raw::Pair> = Default::default();

rv.push(raw::Pair {
key: raw::Key { type_value: PSBT_GLOBAL_UNSIGNED_TX, key: vec![] },
key: raw::Key { type_value: PSBT_GLOBAL_UNSIGNED_TX, key_data: vec![] },
value: {
// Manually serialized to ensure 0-input txs are serialized
// without witnesses.
Expand All @@ -39,7 +39,7 @@ impl Map for Psbt {

for (xpub, (fingerprint, derivation)) in &self.xpub {
rv.push(raw::Pair {
key: raw::Key { type_value: PSBT_GLOBAL_XPUB, key: xpub.encode().to_vec() },
key: raw::Key { type_value: PSBT_GLOBAL_XPUB, key_data: xpub.encode().to_vec() },
value: {
let mut ret = Vec::with_capacity(4 + derivation.len() * 4);
ret.extend(fingerprint.as_bytes());
Expand All @@ -52,7 +52,7 @@ impl Map for Psbt {
// Serializing version only for non-default value; otherwise test vectors fail
if self.version > 0 {
rv.push(raw::Pair {
key: raw::Key { type_value: PSBT_GLOBAL_VERSION, key: vec![] },
key: raw::Key { type_value: PSBT_GLOBAL_VERSION, key_data: vec![] },
value: self.version.to_le_bytes().to_vec(),
});
}
Expand Down Expand Up @@ -84,7 +84,7 @@ impl Psbt {
match pair.key.type_value {
PSBT_GLOBAL_UNSIGNED_TX => {
// key has to be empty
if pair.key.key.is_empty() {
if pair.key.key_data.is_empty() {
// there can only be one unsigned transaction
if tx.is_none() {
let vlen: usize = pair.value.len();
Expand All @@ -111,23 +111,23 @@ impl Psbt {
}
}
PSBT_GLOBAL_XPUB => {
if !pair.key.key.is_empty() {
let xpub = Xpub::decode(&pair.key.key)
if !pair.key.key_data.is_empty() {
let xpub = Xpub::decode(&pair.key.key_data)
.map_err(|_| Error::XPubKey(
"Can't deserialize ExtendedPublicKey from global XPUB key data"
"can't deserialize ExtendedPublicKey from global XPUB key data"
))?;

if pair.value.is_empty() || pair.value.len() % 4 != 0 {
return Err(Error::XPubKey(
"Incorrect length of global xpub derivation data",
"incorrect length of global xpub derivation data",
));
}

let child_count = pair.value.len() / 4 - 1;
let mut decoder = Cursor::new(pair.value);
let mut fingerprint = [0u8; 4];
decoder.read_exact(&mut fingerprint[..]).map_err(|_| {
Error::XPubKey("Can't read global xpub fingerprint")
Error::XPubKey("can't read global xpub fingerprint")
})?;
let mut path = Vec::<ChildNumber>::with_capacity(child_count);
while let Ok(index) = u32::consensus_decode(&mut decoder) {
Expand All @@ -139,17 +139,17 @@ impl Psbt {
.insert(xpub, (Fingerprint::from(fingerprint), derivation))
.is_some()
{
return Err(Error::XPubKey("Repeated global xpub key"));
return Err(Error::XPubKey("repeated global xpub key"));
}
} else {
return Err(Error::XPubKey(
"Xpub global key must contain serialized Xpub data",
"xpub global key must contain serialized Xpub data",
));
}
}
PSBT_GLOBAL_VERSION => {
// key has to be empty
if pair.key.key.is_empty() {
if pair.key.key_data.is_empty() {
// there can only be one version
if version.is_none() {
let vlen: usize = pair.value.len();
Expand Down
51 changes: 42 additions & 9 deletions src/map/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub struct Input {
/// including P2SH embedded ones.
pub witness_utxo: Option<TxOut>,
/// 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.
/// pushed to the stack from a scriptSig or witness for a non-Taproot inputs.
pub partial_sigs: BTreeMap<PublicKey, ecdsa::Signature>,
/// The sighash type to be used for this input. Signatures for this input
/// must use the sighash type.
Expand Down Expand Up @@ -104,7 +104,7 @@ pub struct Input {
/// HAS256 hash to preimage map.
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
/// Serialized taproot signature with sighash type for key spend.
/// Serialized Taproot signature with sighash type for key spend.
pub tap_key_sig: Option<taproot::Signature>,
/// Map of `<xonlypubkey>|<leafhash>` with signature.
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
Expand All @@ -129,10 +129,20 @@ pub struct Input {

/// A Signature hash type for the corresponding input.
///
/// As of taproot upgrade, the signature hash type can be either [`EcdsaSighashType`] or
/// As of Taproot upgrade, the signature hash type can be either [`EcdsaSighashType`] or
/// [`TapSighashType`] 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.
///
/// # Examples
///
/// ```
/// use bitcoin::{EcdsaSighashType, TapSighashType};
/// use psbt_v0::PsbtSighashType;
///
/// let _ecdsa_sighash_all: PsbtSighashType = EcdsaSighashType::All.into();
/// let _tap_sighash_all: PsbtSighashType = TapSighashType::All.into();
/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
Expand All @@ -156,7 +166,7 @@ impl FromStr for PsbtSighashType {
fn from_str(s: &str) -> Result<Self, Self::Err> {
// We accept strings of form: "SIGHASH_ALL" etc.
//
// NB: some of Taproot sighash types are non-standard for pre-taproot
// NB: some of Taproot 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) = TapSighashType::from_str(s) {
Expand Down Expand Up @@ -205,6 +215,22 @@ impl std::error::Error for ParseSighashTypeError {
}

impl PsbtSighashType {
/// Ambiguous `ALL` sighash type, may refer to either [`EcdsaSighashType::All`]
/// or [`TapSighashType::All`].
///
/// This is equivalent to either `EcdsaSighashType::All.into()` or `TapSighashType::All.into()`.
/// For sighash types other than `ALL` use the ECDSA or Taproot sighash type directly.
///
/// # Examples
///
/// ```
/// use bitcoin::{EcdsaSighashType, TapSighashType};
/// use bitcoin::psbt::PsbtSighashType;
/// let _ecdsa_sighash_anyone_can_pay: PsbtSighashType = EcdsaSighashType::AllPlusAnyoneCanPay.into();
/// let _tap_sighash_anyone_can_pay: PsbtSighashType = TapSighashType::AllPlusAnyoneCanPay.into();
/// ```
pub const ALL: PsbtSighashType = PsbtSighashType { inner: 0x01 };

/// Returns the [`EcdsaSighashType`] if the [`PsbtSighashType`] can be
/// converted to one.
pub fn ecdsa_hash_ty(self) -> Result<EcdsaSighashType, NonStandardSighashTypeError> {
Expand Down Expand Up @@ -522,10 +548,10 @@ fn psbt_insert_hash_pair<H>(
where
H: bitcoin::hashes::Hash + Deserialize,
{
if raw_key.key.is_empty() {
if raw_key.key_data.is_empty() {
return Err(Error::InvalidKey(raw_key));
}
let key_val: H = Deserialize::deserialize(&raw_key.key)?;
let key_val: H = Deserialize::deserialize(&raw_key.key_data)?;
match map.entry(key_val) {
btree_map::Entry::Vacant(empty_key) => {
let val: Vec<u8> = Deserialize::deserialize(&raw_value)?;
Expand Down Expand Up @@ -559,7 +585,7 @@ mod test {
] {
let sighash = PsbtSighashType::from(*ecdsa);
let s = format!("{}", sighash);
let back = PsbtSighashType::from_str(&s).unwrap();
let back = s.parse::<PsbtSighashType>().unwrap();
assert_eq!(back, sighash);
assert_eq!(back.ecdsa_hash_ty().unwrap(), *ecdsa);
}
Expand All @@ -578,7 +604,7 @@ mod test {
] {
let sighash = PsbtSighashType::from(*tap);
let s = format!("{}", sighash);
let back = PsbtSighashType::from_str(&s).unwrap();
let back = s.parse::<PsbtSighashType>().unwrap();
assert_eq!(back, sighash);
assert_eq!(back.taproot_hash_ty().unwrap(), *tap);
}
Expand All @@ -589,10 +615,17 @@ mod test {
let nonstd = 0xdddddddd;
let sighash = PsbtSighashType { inner: nonstd };
let s = format!("{}", sighash);
let back = PsbtSighashType::from_str(&s).unwrap();
let back = s.parse::<PsbtSighashType>().unwrap();

assert_eq!(back, sighash);
assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashTypeError(nonstd)));
assert_eq!(back.taproot_hash_ty(), Err(InvalidSighashTypeError(nonstd)));
}

#[test]
fn psbt_sighash_const_all() {
assert_eq!(PsbtSighashType::ALL.to_u32(), 0x01);
assert_eq!(PsbtSighashType::ALL.ecdsa_hash_ty().unwrap(), EcdsaSighashType::All);
assert_eq!(PsbtSighashType::ALL.taproot_hash_ty().unwrap(), TapSighashType::All);
}
}
23 changes: 12 additions & 11 deletions src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ use crate::prelude::*;
use crate::Error;

/// A PSBT key in its raw byte form.
///
/// `<key> := <keylen> <keytype> <keydata>`
#[derive(Debug, PartialEq, Hash, Eq, Clone, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
pub struct Key {
/// The type of this PSBT key.
pub type_value: u8,
/// The key itself in raw byte form.
/// `<key> := <keylen> <keytype> <keydata>`
/// The key data itself in raw byte form.
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))]
pub key: Vec<u8>,
pub key_data: Vec<u8>,
}

/// A PSBT key-value pair in its raw byte form.
Expand Down Expand Up @@ -70,7 +71,7 @@ where

impl fmt::Display for Key {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "type: {:#x}, key: {:x}", self.type_value, self.key.as_hex())
write!(f, "type: {:#x}, key: {:x}", self.type_value, self.key_data.as_hex())
}
}

Expand All @@ -94,25 +95,25 @@ impl Key {

let type_value: u8 = Decodable::consensus_decode(r)?;

let mut key = Vec::with_capacity(key_byte_size as usize);
let mut key_data = Vec::with_capacity(key_byte_size as usize);
for _ in 0..key_byte_size {
key.push(Decodable::consensus_decode(r)?);
key_data.push(Decodable::consensus_decode(r)?);
}

Ok(Key { type_value, key })
Ok(Key { type_value, key_data })
}
}

impl Serialize for Key {
fn serialize(&self) -> Vec<u8> {
let mut buf = Vec::new();
VarInt::from(self.key.len() + 1)
VarInt::from(self.key_data.len() + 1)
.consensus_encode(&mut buf)
.expect("in-memory writers don't error");

self.type_value.consensus_encode(&mut buf).expect("in-memory writers don't error");

for key in &self.key {
for key in &self.key_data {
key.consensus_encode(&mut buf).expect("in-memory writers don't error");
}

Expand Down Expand Up @@ -178,7 +179,7 @@ where
Subtype: Copy + From<u8> + Into<u8>,
{
/// Constructs full [Key] corresponding to this proprietary key type
pub fn to_key(&self) -> Key { Key { type_value: 0xFC, key: serialize(self) } }
pub fn to_key(&self) -> Key { Key { type_value: 0xFC, key_data: serialize(self) } }
}

impl<Subtype> TryFrom<Key> for ProprietaryKey<Subtype>
Expand All @@ -196,6 +197,6 @@ where
return Err(Error::InvalidProprietaryKey);
}

Ok(deserialize(&key.key)?)
Ok(deserialize(&key.key_data)?)
}
}
Loading

0 comments on commit 33a3520

Please sign in to comment.