Replace serde_struct_impl with derive-based impls
This commit is contained in:
parent
d527a2c2cf
commit
94b7371424
|
@ -23,16 +23,15 @@ secp-lowmemory = ["secp256k1/lowmemory"]
|
|||
secp-recovery = ["secp256k1/recovery"]
|
||||
|
||||
[dependencies]
|
||||
base64-compat = { version = "1.0.0", optional = true }
|
||||
bech32 = "0.7.2"
|
||||
bitcoin_hashes = "0.9.1"
|
||||
secp256k1 = { version = "0.19.0", features = [ "recovery" ] }
|
||||
|
||||
base64-compat = { version = "1.0.0", optional = true }
|
||||
bitcoinconsensus = { version = "0.19.0-1", optional = true }
|
||||
serde = { version = "1", optional = true }
|
||||
serde = { version = "1", features = [ "derive" ], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_derive = "<1.0.99"
|
||||
serde_json = "<1.0.45"
|
||||
serde_test = "1"
|
||||
secp256k1 = { version = "0.19.0", features = [ "recovery", "rand-std" ] }
|
||||
|
|
|
@ -59,6 +59,13 @@ compile with 1.29.0 you will need to run the following version-pinning command:
|
|||
cargo update -p cc --precise "1.0.41" --verbose
|
||||
```
|
||||
|
||||
In order to use the `use-serde` feature or to build the unit tests with 1.29.0,
|
||||
the following version-pinning commands are also needed:
|
||||
```
|
||||
cargo update --package "serde" --precise "1.0.98"
|
||||
cargo update --package "serde_derive" --precise "1.0.98"
|
||||
```
|
||||
|
||||
## Installing Rust
|
||||
Rust can be installed using your package manager of choice or
|
||||
[rustup.rs](https://rustup.rs). The former way is considered more secure since
|
||||
|
|
|
@ -38,6 +38,7 @@ use VarInt;
|
|||
/// A block header, which contains all the block's information except
|
||||
/// the actual transactions
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct BlockHeader {
|
||||
/// The protocol version. Should always be 1.
|
||||
pub version: i32,
|
||||
|
@ -55,7 +56,6 @@ pub struct BlockHeader {
|
|||
}
|
||||
|
||||
impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce);
|
||||
serde_struct_impl!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce);
|
||||
|
||||
impl BlockHeader {
|
||||
/// Return the block hash.
|
||||
|
@ -156,6 +156,7 @@ impl BlockHeader {
|
|||
/// A Bitcoin block, which is a collection of transactions with an attached
|
||||
/// proof of work.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Block {
|
||||
/// The block header
|
||||
pub header: BlockHeader,
|
||||
|
@ -164,7 +165,6 @@ pub struct Block {
|
|||
}
|
||||
|
||||
impl_consensus_encoding!(Block, header, txdata);
|
||||
serde_struct_impl!(Block, header, txdata);
|
||||
|
||||
impl Block {
|
||||
/// Return the block hash.
|
||||
|
|
|
@ -174,6 +174,7 @@ impl ::std::str::FromStr for OutPoint {
|
|||
|
||||
/// A transaction input, which defines old coins to be consumed
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct TxIn {
|
||||
/// The reference to the previous output that is being used an an input
|
||||
pub previous_output: OutPoint,
|
||||
|
@ -192,7 +193,6 @@ pub struct TxIn {
|
|||
/// (de)serialization routines.
|
||||
pub witness: Vec<Vec<u8>>
|
||||
}
|
||||
serde_struct_impl!(TxIn, previous_output, script_sig, sequence, witness);
|
||||
|
||||
impl Default for TxIn {
|
||||
fn default() -> TxIn {
|
||||
|
@ -207,13 +207,13 @@ impl Default for TxIn {
|
|||
|
||||
/// A transaction output, which defines new coins to be created from old ones.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct TxOut {
|
||||
/// The value of the output, in satoshis
|
||||
pub value: u64,
|
||||
/// The script which must satisfy for the output to be spent
|
||||
pub script_pubkey: Script
|
||||
}
|
||||
serde_struct_impl!(TxOut, value, script_pubkey);
|
||||
|
||||
// This is used as a "null txout" in consensus signing code
|
||||
impl Default for TxOut {
|
||||
|
@ -253,6 +253,7 @@ impl Default for TxOut {
|
|||
/// We therefore deviate from the spec by always using the Segwit witness encoding
|
||||
/// for 0-input transactions, which results in unambiguously parseable transactions.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Transaction {
|
||||
/// The protocol version, is currently expected to be 1 or 2 (BIP 68).
|
||||
pub version: i32,
|
||||
|
@ -264,7 +265,6 @@ pub struct Transaction {
|
|||
/// List of outputs
|
||||
pub output: Vec<TxOut>,
|
||||
}
|
||||
serde_struct_impl!(Transaction, version, lock_time, input, output);
|
||||
|
||||
impl Transaction {
|
||||
/// Computes a "normalized TXID" which does not include any signatures.
|
||||
|
|
|
@ -163,148 +163,6 @@ macro_rules! hex_script (($s:expr) => ($crate::blockdata::script::Script::from(<
|
|||
#[cfg(test)]
|
||||
macro_rules! hex_hash (($h:ident, $s:expr) => ($h::from_slice(&<Vec<u8> as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()).unwrap()));
|
||||
|
||||
macro_rules! serde_struct_impl {
|
||||
($name:ident, $($fe:ident),*) => (
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de> $crate::serde::Deserialize<'de> for $name {
|
||||
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
|
||||
where
|
||||
D: $crate::serde::de::Deserializer<'de>,
|
||||
{
|
||||
use ::std::fmt::{self, Formatter};
|
||||
use $crate::serde::de::IgnoredAny;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
enum Enum { Unknown__Field, $($fe),* }
|
||||
|
||||
struct EnumVisitor;
|
||||
impl<'de> $crate::serde::de::Visitor<'de> for EnumVisitor {
|
||||
type Value = Enum;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
formatter.write_str("a field name")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: $crate::serde::de::Error,
|
||||
{
|
||||
match v {
|
||||
$(
|
||||
stringify!($fe) => Ok(Enum::$fe)
|
||||
),*,
|
||||
_ => Ok(Enum::Unknown__Field)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> $crate::serde::Deserialize<'de> for Enum {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: $crate::serde::de::Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_str(EnumVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct Visitor;
|
||||
|
||||
impl<'de> $crate::serde::de::Visitor<'de> for Visitor {
|
||||
type Value = $name;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
formatter.write_str("a struct")
|
||||
}
|
||||
|
||||
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
|
||||
where
|
||||
V: $crate::serde::de::SeqAccess<'de>,
|
||||
{
|
||||
use $crate::serde::de::Error;
|
||||
|
||||
let length = 0;
|
||||
$(
|
||||
let $fe = seq.next_element()?.ok_or_else(|| {
|
||||
Error::invalid_length(length, &self)
|
||||
})?;
|
||||
#[allow(unused_variables)]
|
||||
let length = length + 1;
|
||||
)*
|
||||
|
||||
let ret = $name {
|
||||
$($fe: $fe),*
|
||||
};
|
||||
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: $crate::serde::de::MapAccess<'de>,
|
||||
{
|
||||
use $crate::serde::de::Error;
|
||||
|
||||
$(let mut $fe = None;)*
|
||||
|
||||
loop {
|
||||
match map.next_key::<Enum>()? {
|
||||
Some(Enum::Unknown__Field) => {
|
||||
map.next_value::<IgnoredAny>()?;
|
||||
}
|
||||
$(
|
||||
Some(Enum::$fe) => {
|
||||
$fe = Some(map.next_value()?);
|
||||
}
|
||||
)*
|
||||
None => { break; }
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
let $fe = match $fe {
|
||||
Some(x) => x,
|
||||
None => return Err(A::Error::missing_field(stringify!($fe))),
|
||||
};
|
||||
)*
|
||||
|
||||
let ret = $name {
|
||||
$($fe: $fe),*
|
||||
};
|
||||
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
// end type defs
|
||||
|
||||
static FIELDS: &'static [&'static str] = &[$(stringify!($fe)),*];
|
||||
|
||||
deserializer.deserialize_struct(stringify!($name), FIELDS, Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de> $crate::serde::Serialize for $name {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: $crate::serde::Serializer,
|
||||
{
|
||||
use $crate::serde::ser::SerializeStruct;
|
||||
|
||||
// Only used to get the struct length.
|
||||
static FIELDS: &'static [&'static str] = &[$(stringify!($fe)),*];
|
||||
|
||||
let mut st = serializer.serialize_struct(stringify!($name), FIELDS.len())?;
|
||||
|
||||
$(
|
||||
st.serialize_field(stringify!($fe), &self.$fe)?;
|
||||
)*
|
||||
|
||||
st.end()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! serde_string_impl {
|
||||
($name:ident, $expecting:expr) => {
|
||||
#[cfg(feature = "serde")]
|
||||
|
@ -362,9 +220,8 @@ macro_rules! serde_string_impl {
|
|||
};
|
||||
}
|
||||
|
||||
/// A combination of serde_struct_impl and serde_string_impl where string is
|
||||
/// used for human-readable serialization and struct is used for
|
||||
/// non-human-readable serialization.
|
||||
/// A combination macro where the human-readable serialization is done like
|
||||
/// serde_string_impl and the non-human-readable impl is done as a struct.
|
||||
macro_rules! serde_struct_human_string_impl {
|
||||
($name:ident, $expecting:expr, $($fe:ident),*) => (
|
||||
#[cfg(feature = "serde")]
|
||||
|
|
|
@ -44,8 +44,7 @@ pub extern crate bech32;
|
|||
#[cfg(feature = "base64")] pub extern crate base64;
|
||||
|
||||
#[cfg(feature="bitcoinconsensus")] extern crate bitcoinconsensus;
|
||||
#[cfg(feature = "serde")] extern crate serde;
|
||||
#[cfg(all(test, feature = "serde"))] #[macro_use] extern crate serde_derive; // for 1.22.0 compat
|
||||
#[cfg(feature = "serde")] #[macro_use] extern crate serde;
|
||||
#[cfg(all(test, feature = "serde"))] extern crate serde_json;
|
||||
#[cfg(all(test, feature = "serde"))] extern crate serde_test;
|
||||
#[cfg(all(test, feature = "unstable"))] extern crate test;
|
||||
|
|
|
@ -37,6 +37,7 @@ const PSBT_GLOBAL_PROPRIETARY: u8 = 0xFC;
|
|||
|
||||
/// A key-value map for global data.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Global {
|
||||
/// The unsigned transaction, scriptSigs and witnesses for each input must be
|
||||
/// empty.
|
||||
|
@ -51,7 +52,6 @@ pub struct Global {
|
|||
/// Unknown global key-value pairs.
|
||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||
}
|
||||
serde_struct_impl!(Global, unsigned_tx, version, xpub, proprietary, unknown);
|
||||
|
||||
impl Global {
|
||||
/// Create a Global from an unsigned transaction, error if not unsigned
|
||||
|
|
|
@ -58,6 +58,7 @@ const PSBT_IN_PROPRIETARY: u8 = 0xFC;
|
|||
/// A key-value map for an input of the corresponding index in the unsigned
|
||||
/// transaction.
|
||||
#[derive(Clone, Default, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Input {
|
||||
/// The non-witness transaction this input spends from. Should only be
|
||||
/// [std::option::Option::Some] for inputs which spend non-segwit outputs or
|
||||
|
@ -100,13 +101,6 @@ pub struct Input {
|
|||
/// Unknown key-value pairs for this input.
|
||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||
}
|
||||
serde_struct_impl!(
|
||||
Input, non_witness_utxo, witness_utxo, partial_sigs,
|
||||
sighash_type, redeem_script, witness_script, bip32_derivation,
|
||||
final_script_sig, final_script_witness,
|
||||
ripemd160_preimages, sha256_preimages, hash160_preimages, hash256_preimages,
|
||||
proprietary, unknown
|
||||
);
|
||||
|
||||
impl Map for Input {
|
||||
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
||||
|
|
|
@ -36,6 +36,7 @@ const PSBT_OUT_PROPRIETARY: u8 = 0xFC;
|
|||
/// A key-value map for an output of the corresponding index in the unsigned
|
||||
/// transaction.
|
||||
#[derive(Clone, Default, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Output {
|
||||
/// The redeem script for this output.
|
||||
pub redeem_script: Option<Script>,
|
||||
|
@ -49,9 +50,6 @@ pub struct Output {
|
|||
/// Unknown key-value pairs for this output.
|
||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||
}
|
||||
serde_struct_impl!(
|
||||
Output, redeem_script, witness_script, bip32_derivation, proprietary, unknown
|
||||
);
|
||||
|
||||
impl Map for Output {
|
||||
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
||||
|
|
|
@ -39,6 +39,7 @@ pub use self::map::{Map, Global, Input, Output};
|
|||
|
||||
/// A Partially Signed Transaction.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct PartiallySignedTransaction {
|
||||
/// The key-value pairs for all global data.
|
||||
pub global: Global,
|
||||
|
@ -49,7 +50,6 @@ pub struct PartiallySignedTransaction {
|
|||
/// transaction.
|
||||
pub outputs: Vec<Output>,
|
||||
}
|
||||
serde_struct_impl!(PartiallySignedTransaction, global, inputs, outputs);
|
||||
|
||||
impl PartiallySignedTransaction {
|
||||
/// Create a PartiallySignedTransaction from an unsigned transaction, error
|
||||
|
|
|
@ -25,23 +25,23 @@ use util::psbt::Error;
|
|||
|
||||
/// A PSBT key in its raw byte form.
|
||||
#[derive(Debug, PartialEq, Hash, Eq, Clone, Ord, PartialOrd)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Key {
|
||||
/// The type of this PSBT key.
|
||||
pub type_value: u8,
|
||||
/// The key itself in raw byte form.
|
||||
pub key: Vec<u8>,
|
||||
}
|
||||
serde_struct_impl!(Key, type_value, key);
|
||||
|
||||
/// A PSBT key-value pair in its raw byte form.
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Pair {
|
||||
/// The key of this key-value pair.
|
||||
pub key: Key,
|
||||
/// The value of this key-value pair in raw byte form.
|
||||
pub value: Vec<u8>,
|
||||
}
|
||||
serde_struct_impl!(Pair, key, value);
|
||||
|
||||
/// Default implementation for proprietary key subtyping
|
||||
pub type ProprietaryType = u8;
|
||||
|
@ -49,6 +49,7 @@ pub type ProprietaryType = u8;
|
|||
/// Proprietary keys (i.e. keys starting with 0xFC byte) with their internal
|
||||
/// structure according to BIP 174.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct ProprietaryKey<Subtype = ProprietaryType> where Subtype: Copy + From<u8> + Into<u8> {
|
||||
/// Proprietary type prefix used for grouping together keys under some
|
||||
/// application and avoid namespace collision
|
||||
|
@ -58,7 +59,6 @@ pub struct ProprietaryKey<Subtype = ProprietaryType> where Subtype: Copy + From<
|
|||
/// Additional key bytes (like serialized public key data etc)
|
||||
pub key: Vec<u8>,
|
||||
}
|
||||
serde_struct_impl!(ProprietaryKey, prefix, subtype, key);
|
||||
|
||||
impl fmt::Display for Key {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
|
Loading…
Reference in New Issue