diff --git a/Cargo.lock b/Cargo.lock index 2f0d6e5..fcbbcde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,6 +138,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + [[package]] name = "bech32" version = "0.9.1" @@ -161,7 +167,7 @@ version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" dependencies = [ - "base64", + "base64 0.13.1", "bech32", "bitcoin_hashes", "secp256k1", @@ -208,7 +214,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41b9fc22b90f6dc420b1c3cb12ed2e4d212dced72a304903ca7e44e995d37dcc" dependencies = [ - "base64", + "base64 0.13.1", "bitcoin", "pyo3", "serde", @@ -801,6 +807,7 @@ name = "psbt" version = "0.10.1" dependencies = [ "amplify", + "base64 0.21.4", "bitcoin", "bitcoin_blockchain", "bitcoin_hd", @@ -1073,7 +1080,7 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" dependencies = [ - "base64", + "base64 0.13.1", "chrono", "hex", "indexmap 1.9.3", diff --git a/psbt/Cargo.toml b/psbt/Cargo.toml index 262209b..c4bea6e 100644 --- a/psbt/Cargo.toml +++ b/psbt/Cargo.toml @@ -23,6 +23,7 @@ bitcoin_hd = { workspace = true } bitcoin_onchain = { workspace = true } descriptors = { workspace = true, optional = true } miniscript_crate = { workspace = true, optional = true } +base64 = "0.21.4" serde_crate = { package = "serde", version = "1", optional = true } serde_with = { version = "2.3", features = ["hex"], optional = true } diff --git a/psbt/src/global.rs b/psbt/src/global.rs index 1c566ba..019f387 100644 --- a/psbt/src/global.rs +++ b/psbt/src/global.rs @@ -13,7 +13,7 @@ use std::collections::BTreeMap; use std::fmt::{Display, Formatter}; use std::str::FromStr; -use amplify::hex::{FromHex, ToHex}; +use base64::Engine; use bitcoin::util::bip32::{ExtendedPubKey, KeySource}; use bitcoin::{consensus, Transaction, Txid}; use bitcoin_blockchain::locks::LockTime; @@ -295,17 +295,34 @@ impl Deserialize for Psbt { impl Display for Psbt { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str(&self.serialize().to_hex()) + let engine = base64::engine::GeneralPurpose::new( + &base64::alphabet::STANDARD, + base64::engine::GeneralPurposeConfig::new(), + ); + f.write_str(&engine.encode(self.serialize())) } } +#[derive(Debug, Display, Error, From)] +#[display(inner)] +pub enum PsbtParseError { + #[from] + Data(consensus::encode::Error), + + #[from] + Base64(base64::DecodeError), +} + impl FromStr for Psbt { - type Err = consensus::encode::Error; + type Err = PsbtParseError; fn from_str(s: &str) -> Result { - Psbt::deserialize( - &Vec::::from_hex(s).map_err(|_| Self::Err::ParseFailed("invalid hex encoding"))?, - ) + let engine = base64::engine::GeneralPurpose::new( + &base64::alphabet::STANDARD, + base64::engine::GeneralPurposeConfig::new(), + ); + let bytes = engine.decode(s)?; + Psbt::deserialize(&bytes).map_err(PsbtParseError::from) } } diff --git a/psbt/src/lib.rs b/psbt/src/lib.rs index 6e1b494..76e2da4 100644 --- a/psbt/src/lib.rs +++ b/psbt/src/lib.rs @@ -49,9 +49,9 @@ mod proprietary; pub mod sign; pub use bitcoin::psbt::raw::ProprietaryKey; -pub use bitcoin::psbt::{raw, serialize, Error, PsbtParseError, PsbtSighashType}; +pub use bitcoin::psbt::{raw, serialize, Error, PsbtSighashType}; pub use errors::{FeeError, InputMatchError, TxError, TxinError}; -pub use global::Psbt; +pub use global::{Psbt, PsbtParseError}; pub use input::Input; pub use output::Output; pub(crate) mod v0 { diff --git a/src/bin/btc-cold.rs b/src/bin/btc-cold.rs index 05e78c4..0cc429b 100644 --- a/src/bin/btc-cold.rs +++ b/src/bin/btc-cold.rs @@ -712,7 +712,8 @@ impl Args { let secp = Secp256k1::new(); let data = fs::read(psbt_path)?; - let mut psbt = consensus::encode::deserialize::(&data)?; + let mut psbt = consensus::encode::deserialize::(&data) + .map_err(Error::psbt_from_consensus)?; psbt.finalize_mut(&secp).map_err(VecDisplay::from)?; @@ -742,13 +743,13 @@ impl Args { fn inspect(&self, path: Option<&PathBuf>) -> Result<(), Error> { let psbt = if let Some(path) = path { let data = fs::read(path)?; - Psbt::deserialize(&data)? + Psbt::deserialize(&data).map_err(Error::psbt_from_consensus)? } else { eprint!("Type in Base58 encoded PSBT and press enter: "); stdout().flush()?; let stdin = stdin(); - let psbt58 = stdin.lock().lines().next().expect("no PSBT data")?; - Psbt::from_str(psbt58.trim())? + let psbt64 = stdin.lock().lines().next().expect("no PSBT data")?; + Psbt::from_str(psbt64.trim())? }; println!("\n{}", serde_yaml::to_string(&psbt)?); Ok(()) @@ -756,7 +757,7 @@ impl Args { fn convert(&self, path: &Path) -> Result<(), Error> { let data = fs::read(path)?; - let psbt = Psbt::deserialize(&data)?; + let psbt = Psbt::deserialize(&data).map_err(Error::psbt_from_consensus)?; println!("\n{}\n", psbt); Ok(()) } @@ -927,7 +928,10 @@ pub enum Error { Io(IoError), #[from] - PsbtEncoding(consensus::encode::Error), + PsbtEncoding(psbt::Error), + + #[from] + PsbtParse(PsbtParseError), #[from] Miniscript(miniscript::Error), @@ -944,9 +948,6 @@ pub enum Error { #[from] Yaml(serde_yaml::Error), - #[from] - PsbtBase58(PsbtParseError), - #[from] PsbtConstruction(construct::Error), @@ -981,6 +982,16 @@ pub enum Error { PsbtProprietaryKey(ProprietaryKeyError), } +impl Error { + pub fn psbt_from_consensus(e: consensus::encode::Error) -> Error { + match e { + consensus::encode::Error::Psbt(e) => Error::PsbtEncoding(e), + consensus::encode::Error::Io(e) => e.into(), + err => unreachable!("{err:#?}"), + } + } +} + // TODO: Move to amplify crate #[derive(Debug, From)] pub struct VecDisplay(