Skip to content

Commit

Permalink
Add to and from base64 string o pset
Browse files Browse the repository at this point in the history
via standard trait Display and FromStr like it's done in rust-bitcoin PSBT.

Reuse rust-bitcoin base64 re-exported
  • Loading branch information
RCasatta committed Sep 14, 2023
1 parent 1821ade commit cf0609d
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ json-contract = [ "serde_json" ]
"secp256k1-zkp/serde",
"actual-serde"
]
base64 = ["bitcoin/base64"]

[dependencies]
bitcoin = "0.30.0"
Expand All @@ -37,7 +38,6 @@ serde_test = "1.0.19"
serde_json = "1.0"
serde_cbor = "0.8" # older than latest version to support 1.41.1
bincode = "1.3"
base64 = "0.13.0"

[[example]]
name = "pset_blind_coinjoin"
Expand Down
3 changes: 1 addition & 2 deletions elementsd-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
base64 = "0.13.0"
bitcoin = "0.30.0"
elements = {path = "../"}
elements = {path = "../", features = ["base64"]}
elementsd = "0.8.0"
rand = "0.8"

17 changes: 6 additions & 11 deletions elementsd-tests/src/pset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{setup, Call};

use bitcoin::{self, Address, Amount};
use elements::hex::ToHex;
use elements::encode::{deserialize, serialize};
use elements::encode::serialize;
use elements::hashes::Hash;
use elements::pset::PartiallySignedTransaction;
use elements::{AssetId, ContractHash};
Expand Down Expand Up @@ -131,15 +131,16 @@ fn tx_pegin() {
}

fn rtt(base64: &str) -> String {
base64::encode(serialize(&psbt_from_base64(&base64)))
let pset: PartiallySignedTransaction = base64.parse().unwrap();
pset.to_string()
}

fn psbt_rtt(elementsd: &ElementsD, base64: &str) {
let a = elementsd.decode_psbt(&base64).unwrap();

let b_psbt = psbt_from_base64(&base64);
let b_psbt: PartiallySignedTransaction = base64.parse().unwrap();
let mut b_bytes = serialize(&b_psbt);
let b_base64 = base64::encode(&b_bytes);
let b_base64 = bitcoin::base64::encode(&b_bytes);
let b = elementsd.decode_psbt(&b_base64).unwrap();

assert_eq!(a, b);
Expand All @@ -151,16 +152,10 @@ fn psbt_rtt(elementsd: &ElementsD, base64: &str) {
// ensuring decode prints all data inside psbt, randomly changing a byte,
// if the results is still decodable it should not be equal to initial value
b_bytes[i] = b_bytes[i].wrapping_add(1);
let base64 = base64::encode(&b_bytes);
let base64 = bitcoin::base64::encode(&b_bytes);
if let Some(decoded) = elementsd.decode_psbt(&base64) {
assert_ne!(a, decoded, "{} with changed byte {}", b_bytes.to_hex(), i);
}
b_bytes[i] = b_bytes[i].wrapping_sub(1);
}
}

fn psbt_from_base64(base64: &str) -> PartiallySignedTransaction {
let bytes = base64::decode(&base64).unwrap();
deserialize(&bytes).unwrap()
}

3 changes: 3 additions & 0 deletions src/pset/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ mod map;
pub mod raw;
pub mod serialize;

#[cfg(feature = "base64")]
mod str;

use crate::blind::{BlindAssetProofs, BlindValueProofs};
use crate::confidential;
use crate::encode::{self, Decodable, Encodable};
Expand Down
43 changes: 43 additions & 0 deletions src/pset/str.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use super::PartiallySignedTransaction;

#[derive(Debug)]
pub enum Error {
Base64(bitcoin::base64::DecodeError),
Deserialize(crate::encode::Error)
}

impl core::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::Base64(_) => write!(f, "Base64 error"),
Error::Deserialize(_) => write!(f, "Deserialize error"),
}
}
}

impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Base64(e) => Some(e),
Error::Deserialize(e) => Some(e),
}
}

}

impl std::str::FromStr for PartiallySignedTransaction {
type Err=Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let bytes = bitcoin::base64::decode(s).map_err(|e| Error::Base64(e))?;
Ok(crate::encode::deserialize(&bytes).map_err(|e| Error::Deserialize(e))?)
}
}

impl std::fmt::Display for PartiallySignedTransaction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let bytes = crate::encode::serialize(self);
let base64 = bitcoin::base64::encode(&bytes);
write!(f, "{}", base64)
}
}

0 comments on commit cf0609d

Please sign in to comment.