diff --git a/src/raw.rs b/src/raw.rs index a2c0b0a..a5ecec5 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -20,8 +20,8 @@ use bitcoin::hex::DisplayHex; use crate::io::{self, BufRead, Write}; use crate::prelude::*; -use crate::serialize; use crate::serialize::{Deserialize, Serialize}; +use crate::{serialize, v0}; /// A PSBT key-value pair in its raw byte form. /// @@ -112,6 +112,10 @@ impl Key { Ok(Key { type_value, key }) } + + pub(crate) fn into_v0(self) -> v0::bitcoin::raw::Key { + v0::bitcoin::raw::Key { type_value: self.type_value, key: self.key } + } } impl Serialize for Key { @@ -160,6 +164,14 @@ where { /// Constructs full [Key] corresponding to this proprietary key type pub fn to_key(&self) -> Key { Key { type_value: 0xFC, key: serialize(self) } } + + pub(crate) fn into_v0(self) -> v0::bitcoin::raw::ProprietaryKey { + v0::bitcoin::raw::ProprietaryKey { + prefix: self.prefix, + subtype: self.subtype, + key: self.key, + } + } } impl TryFrom for ProprietaryKey diff --git a/src/v2/map/input.rs b/src/v2/map/input.rs index 91dedbb..b0cc43d 100644 --- a/src/v2/map/input.rs +++ b/src/v2/map/input.rs @@ -30,7 +30,7 @@ use crate::prelude::*; use crate::serialize::{Deserialize, Serialize}; use crate::sighash_type::{InvalidSighashTypeError, PsbtSighashType}; use crate::v2::map::Map; -use crate::{raw, serialize}; +use crate::{raw, serialize, v0}; /// A key-value map for an input of the corresponding index in the unsigned /// transaction. @@ -156,32 +156,35 @@ impl Input { } } - // /// Converts this `Input` to a `v0::Input`. - // pub(crate) fn into_v0(self) -> v0::Input { - // v0::Input { - // non_witness_utxo: self.non_witness_utxo, - // witness_utxo: self.witness_utxo, - // partial_sigs: self.partial_sigs, - // sighash_type: self.sighash_type, - // redeem_script: self.redeem_script, - // witness_script: self.witness_script, - // bip32_derivation: self.bip32_derivations, - // final_script_sig: self.final_script_sig, - // final_script_witness: self.final_script_witness, - // ripemd160_preimages: self.ripemd160_preimages, - // sha256_preimages: self.sha256_preimages, - // hash160_preimages: self.hash160_preimages, - // hash256_preimages: self.hash256_preimages, - // tap_key_sig: self.tap_key_sig, - // tap_script_sigs: self.tap_script_sigs, - // tap_scripts: self.tap_scripts, - // tap_key_origins: self.tap_key_origins, - // tap_internal_key: self.tap_internal_key, - // tap_merkle_root: self.tap_merkle_root, - // proprietary: self.proprietaries, - // unknown: self.unknowns, - // } - // } + /// Converts this `Input` to a `v0::Input`. + pub(crate) fn into_v0(self) -> v0::Input { + let proprietary = self.proprietaries.into_iter().map(|(k, v)| (k.into_v0(), v)).collect(); + let unknown = self.unknowns.into_iter().map(|(k, v)| (k.into_v0(), v)).collect(); + + v0::Input { + non_witness_utxo: self.non_witness_utxo, + witness_utxo: self.witness_utxo, + partial_sigs: self.partial_sigs, + sighash_type: self.sighash_type, + redeem_script: self.redeem_script, + witness_script: self.witness_script, + bip32_derivation: self.bip32_derivations, + final_script_sig: self.final_script_sig, + final_script_witness: self.final_script_witness, + ripemd160_preimages: self.ripemd160_preimages, + sha256_preimages: self.sha256_preimages, + hash160_preimages: self.hash160_preimages, + hash256_preimages: self.hash256_preimages, + tap_key_sig: self.tap_key_sig, + tap_script_sigs: self.tap_script_sigs, + tap_scripts: self.tap_scripts, + tap_key_origins: self.tap_key_origins, + tap_internal_key: self.tap_internal_key, + tap_merkle_root: self.tap_merkle_root, + proprietary, + unknown, + } + } /// Creates a new finalized input. /// diff --git a/src/v2/map/output.rs b/src/v2/map/output.rs index 60745cf..656d966 100644 --- a/src/v2/map/output.rs +++ b/src/v2/map/output.rs @@ -18,7 +18,7 @@ use crate::error::write_err; use crate::prelude::*; use crate::serialize::{Deserialize, Serialize}; use crate::v2::map::Map; -use crate::{raw, serialize}; +use crate::{raw, serialize, v0}; /// A key-value map for an output of the corresponding index in the unsigned /// transaction. @@ -72,19 +72,22 @@ impl Output { } } - // /// Converts this `Output` to a `v0::Output`. - // pub(crate) fn into_v0(self) -> v0::Output { - // v0::Output { - // redeem_script: self.redeem_script, - // witness_script: self.witness_script, - // bip32_derivation: self.bip32_derivations, - // tap_internal_key: self.tap_internal_key, - // tap_tree: self.tap_tree, - // tap_key_origins: self.tap_key_origins, - // proprietary: self.proprietaries, - // unknown: self.unknowns, - // } - // } + /// Converts this `Output` to a `v0::Output`. + pub(crate) fn into_v0(self) -> v0::Output { + let proprietary = self.proprietaries.into_iter().map(|(k, v)| (k.into_v0(), v)).collect(); + let unknown = self.unknowns.into_iter().map(|(k, v)| (k.into_v0(), v)).collect(); + + v0::Output { + redeem_script: self.redeem_script, + witness_script: self.witness_script, + bip32_derivation: self.bip32_derivations, + tap_internal_key: self.tap_internal_key, + tap_tree: self.tap_tree, + tap_key_origins: self.tap_key_origins, + proprietary, + unknown, + } + } /// Creates the [`TxOut`] associated with this `Output`. pub(crate) fn tx_out(&self) -> TxOut { diff --git a/src/v2/mod.rs b/src/v2/mod.rs index 73a7208..615657e 100644 --- a/src/v2/mod.rs +++ b/src/v2/mod.rs @@ -44,6 +44,7 @@ use bitcoin::{ecdsa, transaction, Amount, Sequence, Transaction, TxOut, Txid}; use crate::error::{write_err, FeeError, FundingUtxoError}; use crate::prelude::*; use crate::v2::map::Map; +use crate::{v0, Version}; #[rustfmt::skip] // Keep public exports separate. #[doc(inline)] @@ -404,18 +405,31 @@ impl Updater { Ok(self) } - // /// Converts the inner PSBT v2 to a PSBT v0. - // pub fn into_psbt_v0(self) -> v0::Psbt { - // let unsigned_tx = - // self.0.unsigned_tx().expect("Updater guarantees lock time can be determined"); - // let psbt = self.psbt(); - - // let global = psbt.global.into_v0(unsigned_tx); - // let inputs = psbt.inputs.into_iter().map(|input| input.into_v0()).collect(); - // let outputs = psbt.outputs.into_iter().map(|output| output.into_v0()).collect(); - - // v0::Psbt { global, inputs, outputs } - // } + /// Converts the inner PSBT v2 to a PSBT v0. + /// + /// Conversion is lossy because PSBT v2 introduced global types not present in v0. + /// See [BIP-370] for a list of differences. + /// + /// [BIP-370]: + pub fn into_psbt_v0(self) -> v0::Psbt { + let unsigned_tx = + self.0.unsigned_tx().expect("Updater guarantees lock time can be determined"); + let inputs = self.0.inputs.into_iter().map(|input| input.into_v0()).collect(); + let outputs = self.0.outputs.into_iter().map(|output| output.into_v0()).collect(); + let proprietary = + self.0.global.proprietaries.into_iter().map(|(k, v)| (k.into_v0(), v)).collect(); + let unknown = self.0.global.unknowns.into_iter().map(|(k, v)| (k.into_v0(), v)).collect(); + + v0::Psbt { + unsigned_tx, + inputs, + outputs, + version: Version::ZERO.to_u32(), + xpub: self.0.global.xpubs, + proprietary, + unknown, + } + } /// Returns the inner [`Psbt`]. pub fn psbt(self) -> Psbt { self.0 }