Replace serde_struct_impl with derive-based impls

This commit is contained in:
Steven Roose 2020-10-25 18:03:20 +00:00 committed by Sebastian
parent d527a2c2cf
commit 94b7371424
11 changed files with 24 additions and 170 deletions

View File

@ -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" ] }

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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")]

View File

@ -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;

View File

@ -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

View File

@ -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> {

View File

@ -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> {

View File

@ -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

View File

@ -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 {