Skip to content

Commit 5a966c7

Browse files
committed
Merge rust-bitcoin/rust-bitcoin#1068: Implement human-readable serde for Witness
a1df62a Witness human-readable serde test (Dr Maxim Orlovsky) 68577df Witness human-readable serde (Dr Maxim Orlovsky) 93b66c5 Witness serde: test binary encoding to be backward-compatible (Dr Maxim Orlovsky) b409ae7 witness: Refactor import statements (Tobin C. Harding) e23d3a8 Remove unnecessary whitespace (Tobin C. Harding) ac55b10 Add whitespace between functions (Tobin C. Harding) Pull request description: This is dr-orlovsky's [PR](rust-bitcoin/rust-bitcoin#899) picked up at his permission in the discussion thread. I went through the review comments and implemented everything except the perf optimisations. Also includes a patch at the front of the PR that adds a unit test that can be run to see the "before and after", not sure if we want it in, perhaps it should be removed before merge. This PR implicitly fixes 942. To test this PR works as advertised run `cargo test display_transaction --features=serde -- --nocapture` after creating a unit test as follows: ```rust // Used to verify that parts of a transaction pretty print. // `cargo test display_transaction --features=serde -- --nocapture` #[cfg(feature = "serde")] #[test] fn serde_display_transaction() { let tx_bytes = Vec::from_hex( "02000000000101595895ea20179de87052b4046dfe6fd515860505d6511a9004cf12a1f93cac7c01000000\ 00ffffffff01deb807000000000017a9140f3444e271620c736808aa7b33e370bd87cb5a078702483045022\ 100fb60dad8df4af2841adc0346638c16d0b8035f5e3f3753b88db122e70c79f9370220756e6633b17fd271\ 0e626347d28d60b0a2d6cbb41de51740644b9fb3ba7751040121028fa937ca8cba2197a37c007176ed89410\ 55d3bcb8627d085e94553e62f057dcc00000000" ).unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap(); let ser = serde_json::to_string_pretty(&tx).unwrap(); println!("{}", ser); } ``` Fixes: #942 ACKs for top commit: apoelstra: ACK a1df62a Kixunil: ACK a1df62a Tree-SHA512: d0ef5b8cbf1cf8456eaaea490a793f1ac7dfb18067c4019a2c3a1bdd9627a231a4dd0a0151a4df9af2b32b909d4b384a5bec1dd3e38d44dc6a23f9c40aa4f1f9
2 parents 90cffc0 + 2f7c3a5 commit 5a966c7

File tree

1 file changed

+79
-12
lines changed

1 file changed

+79
-12
lines changed

src/blockdata/witness.rs

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
//! This module contains the [`Witness`] struct and related methods to operate on it
66
//!
77
8+
use secp256k1::ecdsa;
9+
810
use crate::blockdata::transaction::EcdsaSighashType;
911
use crate::consensus::encode::{Error, MAX_VEC_SIZE};
1012
use crate::consensus::{Decodable, Encodable, WriteExt};
1113
use crate::io::{self, Read, Write};
1214
use crate::prelude::*;
13-
use secp256k1::ecdsa;
1415
use crate::VarInt;
1516

1617
/// The Witness is the data used to unlock bitcoins since the [segwit upgrade](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki)
@@ -124,7 +125,6 @@ impl Encodable for Witness {
124125
}
125126

126127
impl Witness {
127-
128128
/// Create a new empty [`Witness`]
129129
pub fn new() -> Self {
130130
Witness::default()
@@ -281,25 +281,77 @@ impl serde::Serialize for Witness {
281281
where
282282
S: serde::Serializer,
283283
{
284-
use serde::ser::SerializeSeq;
284+
use hashes::hex::ToHex;
285+
use serde::ser::SerializeSeq;
285286

287+
let human_readable = serializer.is_human_readable();
286288
let mut seq = serializer.serialize_seq(Some(self.witness_elements))?;
287289

288290
for elem in self.iter() {
289-
seq.serialize_element(&elem)?;
291+
if human_readable {
292+
seq.serialize_element(&elem.to_hex())?;
293+
} else {
294+
seq.serialize_element(&elem)?;
295+
}
290296
}
291-
292297
seq.end()
293298
}
294299
}
300+
295301
#[cfg(feature = "serde")]
296302
impl<'de> serde::Deserialize<'de> for Witness {
297303
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
298304
where
299305
D: serde::Deserializer<'de>,
300306
{
301-
let vec: Vec<Vec<u8>> = serde::Deserialize::deserialize(deserializer)?;
302-
Ok(Witness::from_vec(vec))
307+
struct Visitor; // Human-readable visitor.
308+
impl<'de> serde::de::Visitor<'de> for Visitor
309+
{
310+
type Value = Witness;
311+
312+
fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
313+
write!(f, "a sequence of hex arrays")
314+
}
315+
316+
fn visit_seq<A: serde::de::SeqAccess<'de>>(self, mut a: A) -> Result<Self::Value, A::Error>
317+
{
318+
use hashes::hex::FromHex;
319+
use hashes::hex::Error::*;
320+
use serde::de::{self, Unexpected};
321+
322+
let mut ret = match a.size_hint() {
323+
Some(len) => Vec::with_capacity(len),
324+
None => Vec::new(),
325+
};
326+
327+
while let Some(elem) = a.next_element::<String>()? {
328+
let vec = Vec::<u8>::from_hex(&elem).map_err(|e| {
329+
match e {
330+
InvalidChar(b) => {
331+
match core::char::from_u32(b.into()) {
332+
Some(c) => de::Error::invalid_value(Unexpected::Char(c), &"a valid hex character"),
333+
None => de::Error::invalid_value(Unexpected::Unsigned(b.into()), &"a valid hex character")
334+
}
335+
}
336+
OddLengthString(len) => de::Error::invalid_length(len, &"an even length string"),
337+
InvalidLength(expected, got) => {
338+
let exp = format!("expected length: {}", expected);
339+
de::Error::invalid_length(got, &exp.as_str())
340+
}
341+
}
342+
})?;
343+
ret.push(vec);
344+
}
345+
Ok(Witness::from_vec(ret))
346+
}
347+
}
348+
349+
if deserializer.is_human_readable() {
350+
deserializer.deserialize_seq(Visitor)
351+
} else {
352+
let vec: Vec<Vec<u8>> = serde::Deserialize::deserialize(deserializer)?;
353+
Ok(Witness::from_vec(vec))
354+
}
303355
}
304356
}
305357

@@ -424,20 +476,35 @@ mod test {
424476

425477
#[cfg(feature = "serde")]
426478
#[test]
427-
fn test_serde() {
428-
use serde_json;
479+
fn test_serde_bincode() {
480+
use bincode;
429481

430482
let old_witness_format = vec![vec![0u8], vec![2]];
431483
let new_witness_format = Witness::from_vec(old_witness_format.clone());
432484

433-
let old = serde_json::to_string(&old_witness_format).unwrap();
434-
let new = serde_json::to_string(&new_witness_format).unwrap();
485+
let old = bincode::serialize(&old_witness_format).unwrap();
486+
let new = bincode::serialize(&new_witness_format).unwrap();
435487

436488
assert_eq!(old, new);
437489

438-
let back = serde_json::from_str(&new).unwrap();
490+
let back: Witness = bincode::deserialize(&new).unwrap();
439491
assert_eq!(new_witness_format, back);
440492
}
493+
494+
#[cfg(feature = "serde")]
495+
#[test]
496+
fn test_serde_human() {
497+
use serde_json;
498+
499+
let witness = Witness::from_vec(vec![vec![0u8, 123, 75], vec![2u8, 6, 3, 7, 8]]);
500+
501+
let json = serde_json::to_string(&witness).unwrap();
502+
503+
assert_eq!(json, r#"["007b4b","0206030708"]"#);
504+
505+
let back: Witness = serde_json::from_str(&json).unwrap();
506+
assert_eq!(witness, back);
507+
}
441508
}
442509

443510

0 commit comments

Comments
 (0)