psbt: Serialize maps with byte values using hex
This commit is contained in:
parent
a05f8feec6
commit
5fd92d1c09
|
@ -1,9 +1,65 @@
|
||||||
|
|
||||||
//! Module for special serde serializations.
|
//! Module for special serde serializations.
|
||||||
|
|
||||||
|
pub mod btreemap_byte_values {
|
||||||
|
//! Module for serialization of BTreeMaps with hex byte values.
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
|
// NOTE: This module can be exactly copied to use with HashMap.
|
||||||
|
|
||||||
|
use ::std::collections::BTreeMap;
|
||||||
|
use hashes::hex::{FromHex, ToHex};
|
||||||
|
use serde;
|
||||||
|
|
||||||
|
pub fn serialize<S, T>(v: &BTreeMap<T, Vec<u8>>, s: S)
|
||||||
|
-> Result<S::Ok, S::Error> where
|
||||||
|
S: serde::Serializer,
|
||||||
|
T: serde::Serialize + ::std::hash::Hash + Eq + Ord,
|
||||||
|
{
|
||||||
|
use serde::ser::SerializeMap;
|
||||||
|
|
||||||
|
let mut map = s.serialize_map(Some(v.len()))?;
|
||||||
|
for (key, value) in v.iter() {
|
||||||
|
map.serialize_entry(key, &value.to_hex())?;
|
||||||
|
}
|
||||||
|
map.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, D, T>(d: D)
|
||||||
|
-> Result<BTreeMap<T, Vec<u8>>, D::Error> where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
T: serde::Deserialize<'de> + ::std::hash::Hash + Eq + Ord,
|
||||||
|
{
|
||||||
|
use ::std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct Visitor<T>(PhantomData<T>);
|
||||||
|
impl<'de, T> serde::de::Visitor<'de> for Visitor<T> where
|
||||||
|
T: serde::Deserialize<'de> + ::std::hash::Hash + Eq + Ord,
|
||||||
|
{
|
||||||
|
type Value = BTreeMap<T, Vec<u8>>;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
write!(f, "a map with hexadecimal values")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<A: serde::de::MapAccess<'de>>(self, mut a: A)
|
||||||
|
-> Result<Self::Value, A::Error>
|
||||||
|
{
|
||||||
|
let mut ret = BTreeMap::new();
|
||||||
|
while let Some((key, value)) = a.next_entry()? {
|
||||||
|
ret.insert(key, FromHex::from_hex(value).map_err(serde::de::Error::custom)?);
|
||||||
|
}
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.deserialize_map(Visitor(PhantomData))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub mod btreemap_as_seq {
|
pub mod btreemap_as_seq {
|
||||||
//! Module for serialization of BTreeMaps because serde_json will
|
//! Module for serialization of BTreeMaps as lists of sequences because
|
||||||
//! not serialize hashmaps with non-string keys be default.
|
//! serde_json will not serialize hashmaps with non-string keys be default.
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
// NOTE: This module can be exactly copied to use with HashMap.
|
// NOTE: This module can be exactly copied to use with HashMap.
|
||||||
|
@ -61,7 +117,7 @@ pub mod btreemap_as_seq {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod btreemap_as_seq_byte_values {
|
pub mod btreemap_as_seq_byte_values {
|
||||||
//! Module for serialization of BTreeMaps with Vec<u8> values because
|
//! Module for serialization of BTreeMaps as lists of sequences because
|
||||||
//! serde_json will not serialize hashmaps with non-string keys be default.
|
//! serde_json will not serialize hashmaps with non-string keys be default.
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ pub struct Input {
|
||||||
pub witness_utxo: Option<TxOut>,
|
pub witness_utxo: Option<TxOut>,
|
||||||
/// A map from public keys to their corresponding signature as would be
|
/// A map from public keys to their corresponding signature as would be
|
||||||
/// pushed to the stack from a scriptSig or witness.
|
/// pushed to the stack from a scriptSig or witness.
|
||||||
|
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
|
||||||
pub partial_sigs: BTreeMap<PublicKey, Vec<u8>>,
|
pub partial_sigs: BTreeMap<PublicKey, Vec<u8>>,
|
||||||
/// The sighash type to be used for this input. Signatures for this input
|
/// The sighash type to be used for this input. Signatures for this input
|
||||||
/// must use the sighash type.
|
/// must use the sighash type.
|
||||||
|
@ -90,12 +91,16 @@ pub struct Input {
|
||||||
pub final_script_witness: Option<Vec<Vec<u8>>>,
|
pub final_script_witness: Option<Vec<Vec<u8>>>,
|
||||||
/// TODO: Proof of reserves commitment
|
/// TODO: Proof of reserves commitment
|
||||||
/// RIPEMD160 hash to preimage map
|
/// RIPEMD160 hash to preimage map
|
||||||
|
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
|
||||||
pub ripemd160_preimages: BTreeMap<ripemd160::Hash, Vec<u8>>,
|
pub ripemd160_preimages: BTreeMap<ripemd160::Hash, Vec<u8>>,
|
||||||
/// SHA256 hash to preimage map
|
/// SHA256 hash to preimage map
|
||||||
|
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
|
||||||
pub sha256_preimages: BTreeMap<sha256::Hash, Vec<u8>>,
|
pub sha256_preimages: BTreeMap<sha256::Hash, Vec<u8>>,
|
||||||
/// HSAH160 hash to preimage map
|
/// HSAH160 hash to preimage map
|
||||||
|
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
|
||||||
pub hash160_preimages: BTreeMap<hash160::Hash, Vec<u8>>,
|
pub hash160_preimages: BTreeMap<hash160::Hash, Vec<u8>>,
|
||||||
/// HAS256 hash to preimage map
|
/// HAS256 hash to preimage map
|
||||||
|
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
|
||||||
pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
|
pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
|
||||||
/// Proprietary key-value pairs for this input.
|
/// Proprietary key-value pairs for this input.
|
||||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
|
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
|
||||||
|
|
|
@ -319,6 +319,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serde_psbt() {
|
fn test_serde_psbt() {
|
||||||
//! Create a full PSBT value with various fields filled and make sure it can be JSONized.
|
//! Create a full PSBT value with various fields filled and make sure it can be JSONized.
|
||||||
|
use hashes::sha256d;
|
||||||
use util::psbt::map::Input;
|
use util::psbt::map::Input;
|
||||||
|
|
||||||
// create some values to use in the PSBT
|
// create some values to use in the PSBT
|
||||||
|
@ -393,6 +394,10 @@ mod tests {
|
||||||
)].into_iter().collect(),
|
)].into_iter().collect(),
|
||||||
bip32_derivation: keypaths.clone(),
|
bip32_derivation: keypaths.clone(),
|
||||||
final_script_witness: Some(vec![vec![1, 3], vec![5]]),
|
final_script_witness: Some(vec![vec![1, 3], vec![5]]),
|
||||||
|
ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
||||||
|
sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
||||||
|
hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
||||||
|
hash256_preimages: vec![(sha256d::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
||||||
proprietary: proprietary.clone(),
|
proprietary: proprietary.clone(),
|
||||||
unknown: unknown.clone(),
|
unknown: unknown.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -405,6 +410,7 @@ mod tests {
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
let encoded = ::serde_json::to_string(&psbt).unwrap();
|
let encoded = ::serde_json::to_string(&psbt).unwrap();
|
||||||
|
println!("encoded PSBT: {}", encoded);
|
||||||
let decoded: PartiallySignedTransaction = ::serde_json::from_str(&encoded).unwrap();
|
let decoded: PartiallySignedTransaction = ::serde_json::from_str(&encoded).unwrap();
|
||||||
assert_eq!(psbt, decoded);
|
assert_eq!(psbt, decoded);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue