From 8a04a79541dce031d79979612e71714f306c9473 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 3 Oct 2023 16:46:14 +0200 Subject: [PATCH] psbt: encode using Base64 instead of hex --- Cargo.lock | 13 ++++++++++--- psbt/Cargo.toml | 1 + psbt/src/global.rs | 29 +++++++++++++++++++++++------ psbt/src/lib.rs | 4 ++-- src/bin/btc-cold.rs | 17 +++++++++-------- 5 files changed, 45 insertions(+), 19 deletions(-) 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 a8ffb4e..0cc429b 100644 --- a/src/bin/btc-cold.rs +++ b/src/bin/btc-cold.rs @@ -749,7 +749,7 @@ impl Args { stdout().flush()?; let stdin = stdin(); let psbt64 = stdin.lock().lines().next().expect("no PSBT data")?; - Psbt::from_str(psbt64.trim()).map_err(Error::psbt_from_consensus)? + Psbt::from_str(psbt64.trim())? }; println!("\n{}", serde_yaml::to_string(&psbt)?); Ok(()) @@ -930,6 +930,9 @@ pub enum Error { #[from] PsbtEncoding(psbt::Error), + #[from] + PsbtParse(PsbtParseError), + #[from] Miniscript(miniscript::Error), @@ -945,9 +948,6 @@ pub enum Error { #[from] Yaml(serde_yaml::Error), - #[from] - PsbtBase58(PsbtParseError), - #[from] PsbtConstruction(construct::Error), @@ -984,10 +984,11 @@ pub enum Error { impl Error { pub fn psbt_from_consensus(e: consensus::encode::Error) -> Error { - let consensus::encode::Error::Psbt(e) = e else { - unreachable!() - }; - Error::PsbtEncoding(e) + match e { + consensus::encode::Error::Psbt(e) => Error::PsbtEncoding(e), + consensus::encode::Error::Io(e) => e.into(), + err => unreachable!("{err:#?}"), + } } }