diff --git a/src/serde_utils.rs b/src/serde_utils.rs index 0c0b243d..8b74807e 100644 --- a/src/serde_utils.rs +++ b/src/serde_utils.rs @@ -60,6 +60,78 @@ pub mod btreemap { } } +pub mod btreemap_byte_values { + //! Module for serialization of BTreeMaps with Vec values because + //! serde_json will not serialize hashmaps with non-string keys be default. + #![allow(missing_docs)] + + // NOTE: This module can be exactly copied to use with HashMap. + + use ::std::collections::BTreeMap; + use serde; + + /// A custom key-value pair type that serialized the bytes as hex. + #[derive(Debug, Deserialize)] + struct OwnedPair( + T, + #[serde(deserialize_with = "::serde_utils::hex_bytes::deserialize")] + Vec, + ); + + /// A custom key-value pair type that serialized the bytes as hex. + #[derive(Debug, Serialize)] + struct BorrowedPair<'a, T: 'static>( + &'a T, + #[serde(serialize_with = "::serde_utils::hex_bytes::serialize")] + &'a [u8], + ); + + pub fn serialize(v: &BTreeMap>, s: S) + -> Result where + S: serde::Serializer, + T: serde::Serialize + ::std::hash::Hash + Eq + Ord + 'static, + { + use serde::ser::SerializeSeq; + + let mut seq = s.serialize_seq(Some(v.len()))?; + for (key, value) in v.iter() { + seq.serialize_element(&BorrowedPair(key, value))?; + } + seq.end() + } + + pub fn deserialize<'de, D, T>(d: D) + -> Result>, D::Error> where + D: serde::Deserializer<'de>, + T: serde::Deserialize<'de> + ::std::hash::Hash + Eq + Ord, + { + use ::std::marker::PhantomData; + + struct Visitor(PhantomData); + impl<'de, T> serde::de::Visitor<'de> for Visitor where + T: serde::Deserialize<'de> + ::std::hash::Hash + Eq + Ord, + { + type Value = BTreeMap>; + + fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "a sequence of pairs") + } + + fn visit_seq>(self, mut a: A) + -> Result + { + let mut ret = BTreeMap::new(); + while let Option::Some(OwnedPair(key, value)) = a.next_element()? { + ret.insert(key, value); + } + Ok(ret) + } + } + + d.deserialize_seq(Visitor(PhantomData)) + } +} + pub mod hex_bytes { //! Module for serialization of byte arrays as hex strings. #![allow(missing_docs)] diff --git a/src/util/psbt/map/global.rs b/src/util/psbt/map/global.rs index aa5d6254..d3b9c5b4 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -49,10 +49,10 @@ pub struct Global { #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] pub xpub: BTreeMap, /// Global proprietary key-value pairs. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))] pub proprietary: BTreeMap>, /// Unknown global key-value pairs. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))] pub unknown: BTreeMap>, } diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index 112eae9a..4f42a9ac 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -70,7 +70,7 @@ pub struct Input { pub witness_utxo: Option, /// A map from public keys to their corresponding signature as would be /// pushed to the stack from a scriptSig or witness. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))] pub partial_sigs: BTreeMap>, /// The sighash type to be used for this input. Signatures for this input /// must use the sighash type. @@ -99,10 +99,10 @@ pub struct Input { /// HAS256 hash to preimage map pub hash256_preimages: BTreeMap>, /// Proprietary key-value pairs for this input. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))] pub proprietary: BTreeMap>, /// Unknown key-value pairs for this input. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))] pub unknown: BTreeMap>, } diff --git a/src/util/psbt/map/output.rs b/src/util/psbt/map/output.rs index 34861ba5..6a082467 100644 --- a/src/util/psbt/map/output.rs +++ b/src/util/psbt/map/output.rs @@ -47,10 +47,10 @@ pub struct Output { #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] pub bip32_derivation: BTreeMap, /// Proprietary key-value pairs for this output. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))] pub proprietary: BTreeMap>, /// Unknown key-value pairs for this output. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap"))] + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))] pub unknown: BTreeMap>, }