From ac55b1017e73a9ad279aebf2c7d4525dc30cf369 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 28 Jun 2022 15:27:23 +1000 Subject: [PATCH 1/6] Add whitespace between functions As is customary leave a line of white space between functions. --- src/blockdata/witness.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index cbc0a4fa..95e04bb3 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -290,6 +290,7 @@ impl serde::Serialize for Witness { seq.end() } } + #[cfg(feature = "serde")] impl<'de> serde::Deserialize<'de> for Witness { fn deserialize(deserializer: D) -> Result From e23d3a815c8a61d6542c913aa33fe078eebbf8f6 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 28 Jun 2022 15:36:34 +1000 Subject: [PATCH 2/6] Remove unnecessary whitespace No need for a line of whitespace immediately starting an impl block. --- src/blockdata/witness.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index 95e04bb3..3c7f2f89 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -122,7 +122,6 @@ impl Encodable for Witness { } impl Witness { - /// Create a new empty [`Witness`] pub fn new() -> Self { Witness::default() From b409ae78a4cd898e99c065ad5b5c119361de51a2 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 29 Jun 2022 09:48:52 +1000 Subject: [PATCH 3/6] witness: Refactor import statements Re-order the import statements in `witness` module to separate `crate` imports from dependency imports. --- src/blockdata/witness.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index 3c7f2f89..015739eb 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -3,12 +3,13 @@ //! This module contains the [`Witness`] struct and related methods to operate on it //! +use secp256k1::ecdsa; + use crate::blockdata::transaction::EcdsaSighashType; use crate::consensus::encode::{Error, MAX_VEC_SIZE}; use crate::consensus::{Decodable, Encodable, WriteExt}; use crate::io::{self, Read, Write}; use crate::prelude::*; -use secp256k1::ecdsa; use crate::VarInt; /// The Witness is the data used to unlock bitcoins since the [segwit upgrade](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki) From 93b66c55b3f22635409f212d5fbbaec9eafae073 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 22 Mar 2022 09:32:35 +0100 Subject: [PATCH 4/6] Witness serde: test binary encoding to be backward-compatible This also removes tests for JSON backward-compatible encoding. Human-readable encoding will be changed in the next commit and this will break backward compatibility, thus that part of the test is removed. --- src/blockdata/witness.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index 015739eb..976923f5 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -423,20 +423,21 @@ mod test { #[cfg(feature = "serde")] #[test] - fn test_serde() { - use serde_json; + fn test_serde_bincode() { + use bincode; let old_witness_format = vec![vec![0u8], vec![2]]; let new_witness_format = Witness::from_vec(old_witness_format.clone()); - let old = serde_json::to_string(&old_witness_format).unwrap(); - let new = serde_json::to_string(&new_witness_format).unwrap(); + let old = bincode::serialize(&old_witness_format).unwrap(); + let new = bincode::serialize(&new_witness_format).unwrap(); assert_eq!(old, new); - let back = serde_json::from_str(&new).unwrap(); + let back: Witness = bincode::deserialize(&new).unwrap(); assert_eq!(new_witness_format, back); } + } From 68577dfb506ac37565c2f10c22680ecebcfbd94f Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 22 Mar 2022 09:56:09 +0100 Subject: [PATCH 5/6] Witness human-readable serde Previous implementations of Witness (and Vec>) serde serialization didn't support human-readable representations. This resulted in long unreadable JSON/YAML byte arrays, which were especially ugly when pretty-printed (a line per each byte). Co-authored-by: Tobin C. Harding --- src/blockdata/witness.rs | 61 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index 976923f5..a4582d67 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -279,14 +279,19 @@ impl serde::Serialize for Witness { where S: serde::Serializer, { - use serde::ser::SerializeSeq; + use hashes::hex::ToHex; + use serde::ser::SerializeSeq; + let human_readable = serializer.is_human_readable(); let mut seq = serializer.serialize_seq(Some(self.witness_elements))?; for elem in self.iter() { - seq.serialize_element(&elem)?; + if human_readable { + seq.serialize_element(&elem.to_hex())?; + } else { + seq.serialize_element(&elem)?; + } } - seq.end() } } @@ -297,8 +302,54 @@ impl<'de> serde::Deserialize<'de> for Witness { where D: serde::Deserializer<'de>, { - let vec: Vec> = serde::Deserialize::deserialize(deserializer)?; - Ok(Witness::from_vec(vec)) + struct Visitor; // Human-readable visitor. + impl<'de> serde::de::Visitor<'de> for Visitor + { + type Value = Witness; + + fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "a sequence of hex arrays") + } + + fn visit_seq>(self, mut a: A) -> Result + { + use hashes::hex::FromHex; + use hashes::hex::Error::*; + use serde::de::{self, Unexpected}; + + let mut ret = match a.size_hint() { + Some(len) => Vec::with_capacity(len), + None => Vec::new(), + }; + + while let Some(elem) = a.next_element::()? { + let vec = Vec::::from_hex(&elem).map_err(|e| { + match e { + InvalidChar(b) => { + match core::char::from_u32(b.into()) { + Some(c) => de::Error::invalid_value(Unexpected::Char(c), &"a valid hex character"), + None => de::Error::invalid_value(Unexpected::Unsigned(b.into()), &"a valid hex character") + } + } + OddLengthString(len) => de::Error::invalid_length(len, &"an even length string"), + InvalidLength(expected, got) => { + let exp = format!("expected length: {}", expected); + de::Error::invalid_length(got, &exp.as_str()) + } + } + })?; + ret.push(vec); + } + Ok(Witness::from_vec(ret)) + } + } + + if deserializer.is_human_readable() { + deserializer.deserialize_seq(Visitor) + } else { + let vec: Vec> = serde::Deserialize::deserialize(deserializer)?; + Ok(Witness::from_vec(vec)) + } } } From a1df62a3d927f0a8b66228df5c3db422e220ac03 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 22 Mar 2022 09:56:32 +0100 Subject: [PATCH 6/6] Witness human-readable serde test --- src/blockdata/witness.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index a4582d67..a7540908 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -489,6 +489,20 @@ mod test { assert_eq!(new_witness_format, back); } + #[cfg(feature = "serde")] + #[test] + fn test_serde_human() { + use serde_json; + + let witness = Witness::from_vec(vec![vec![0u8, 123, 75], vec![2u8, 6, 3, 7, 8]]); + + let json = serde_json::to_string(&witness).unwrap(); + + assert_eq!(json, r#"["007b4b","0206030708"]"#); + + let back: Witness = serde_json::from_str(&json).unwrap(); + assert_eq!(witness, back); + } }