Skip to content

Commit

Permalink
Using derive StrictEncode/Decode macros everywhere its possible
Browse files Browse the repository at this point in the history
Closes #89

Conflicts:
	src/rgb/contract/nodes.rs
	src/rgb/stash/consignment.rs
  • Loading branch information
dr-orlovsky committed Sep 30, 2020
1 parent 86e7f11 commit 4377e5d
Show file tree
Hide file tree
Showing 17 changed files with 66 additions and 273 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ crate-type = ["dylib", "rlib", "staticlib"]
[dependencies]
amplify = { version = "~1.0.0", features = ["serde", "std"] }
amplify_derive = "~1.0.0"
lnpbp_derive = { path = "derive" }
lazy_static = "~1.4.0"
bech32 = "~0.7.2"
ed25519-dalek = { version = "~1.0.0", optional = true }
Expand Down
35 changes: 27 additions & 8 deletions derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ fn attr_nested_one_arg(
mut list: impl ExactSizeIterator<Item = NestedMeta>,
attr_name: &str,
example: &str,
) -> Result<Option<Ident>> {
) -> Result<Option<Path>> {
match list.len() {
0 => proc_macro_err!(attr_name, "unexpected absence of argument", example),
1 => match list.next().expect("Core library iterator is broken") {
NestedMeta::Meta(meta) => match meta {
Meta::Path(path) => Ok(path.get_ident().cloned()),
Meta::Path(path) => Ok(Some(path)),
_ => proc_macro_err!(attr_name, "unexpected attribute type", example),
},
NestedMeta::Lit(_) => proc_macro_err!(
Expand Down Expand Up @@ -436,15 +436,15 @@ fn lnp_api_inner_enum(input: &DeriveInput, data: &DataEnum) -> Result<TokenStrea
// Strict Encode/Decode Derives
// ============================

#[proc_macro_derive(StrictEncode, attributes(strict_error))]
#[proc_macro_derive(StrictEncode, attributes(strict_error, strict_crate))]
pub fn derive_strict_encode(input: TokenStream) -> TokenStream {
let derive_input = parse_macro_input!(input as DeriveInput);
strict_encode_inner(derive_input)
.unwrap_or_else(|e| e.to_compile_error())
.into()
}

#[proc_macro_derive(StrictDecode, attributes(strict_decode))]
#[proc_macro_derive(StrictDecode, attributes(strict_error, strict_crate))]
pub fn derive_strict_decode(input: TokenStream) -> TokenStream {
let derive_input = parse_macro_input!(input as DeriveInput);
strict_decode_inner(derive_input)
Expand Down Expand Up @@ -487,6 +487,7 @@ fn strict_encode_inner_struct(input: &DeriveInput, data: &DataStruct) -> Result<
let ident_name = &input.ident;

let error_type_def = get_strict_error(input, data)?;
let import = get_strict_crate(input, data)?;

let recurse = match data.fields {
Fields::Named(ref fields) => fields
Expand Down Expand Up @@ -527,7 +528,7 @@ fn strict_encode_inner_struct(input: &DeriveInput, data: &DataStruct) -> Result<

Ok(quote! {
#[allow(unused_qualifications)]
impl #impl_generics lnpbp::strict_encoding::StrictEncode for #ident_name #ty_generics #where_clause {
impl #impl_generics #import::StrictEncode for #ident_name #ty_generics #where_clause {
#error_type_def

#[inline]
Expand All @@ -543,6 +544,7 @@ fn strict_decode_inner_struct(input: &DeriveInput, data: &DataStruct) -> Result<
let ident_name = &input.ident;

let error_type_def = get_strict_error(input, data)?;
let import = get_strict_crate(input, data)?;

let inner = match data.fields {
Fields::Named(ref fields) => {
Expand All @@ -552,7 +554,7 @@ fn strict_decode_inner_struct(input: &DeriveInput, data: &DataStruct) -> Result<
.map(|f| {
let name = &f.ident;
quote_spanned! { f.span() =>
#name: lnpbp::strict_encoding::StrictDecode::strict_decode(&mut d)?,
#name: #import::StrictDecode::strict_decode(&mut d)?,
}
})
.collect();
Expand All @@ -568,7 +570,7 @@ fn strict_decode_inner_struct(input: &DeriveInput, data: &DataStruct) -> Result<
.iter()
.map(|f| {
quote_spanned! { f.span() =>
lnpbp::strict_encoding::StrictDecode::strict_decode(&mut d)?,
#import::StrictDecode::strict_decode(&mut d)?,
}
})
.collect();
Expand All @@ -586,7 +588,7 @@ fn strict_decode_inner_struct(input: &DeriveInput, data: &DataStruct) -> Result<

Ok(quote! {
#[allow(unused_qualifications)]
impl #impl_generics lnpbp::strict_encoding::StrictDecode for #ident_name #ty_generics #where_clause {
impl #impl_generics #import::StrictDecode for #ident_name #ty_generics #where_clause {
#error_type_def

#[inline]
Expand All @@ -613,3 +615,20 @@ fn get_strict_error(input: &DeriveInput, data: &DataStruct) -> Result<TokenStrea
None => quote! {},
})
}

fn get_strict_crate(input: &DeriveInput, data: &DataStruct) -> Result<TokenStream2> {
let name = "strict_crate";
let example = "#[strict_crate(lnpbp_other_name)]";
let default = quote! { ::lnpbp::strict_encoding };

let list = match attr_list(&input.attrs, name, example)? {
Some(x) => x,
None => return Ok(default),
};
let strict_crate = attr_nested_one_arg(list.into_iter(), name, example)?;

Ok(match strict_crate {
Some(ident) => quote! { #ident::strict_encoding },
None => return Ok(default),
})
}
5 changes: 4 additions & 1 deletion src/bp/blind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ use crate::commit_verify::CommitVerify;

/// Data required to generate or reveal the information about blinded
/// transaction outpoint
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Default)]
#[derive(
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Default, StrictEncode, StrictDecode,
)]
#[strict_crate(crate)]
#[display(Debug)]
pub struct OutpointReveal {
/// Blinding factor preventing rainbow table bruteforce attack based on
Expand Down
18 changes: 2 additions & 16 deletions src/bp/dbc/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ pub trait Container: Sized {
fn into_proof(self) -> Proof;
}

#[derive(Clone, PartialEq, Eq, Hash, Debug, Display)]
#[derive(Clone, PartialEq, Eq, Hash, Debug, Display, StrictEncode, StrictDecode)]
#[strict_crate(crate)]
#[display(Debug)]
pub struct Proof {
pub pubkey: secp256k1::PublicKey,
Expand Down Expand Up @@ -94,21 +95,6 @@ pub(super) mod strict_encoding {
}
}

impl StrictEncode for Proof {
fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, strict_encoding::Error> {
Ok(strict_encode_list!(e; self.pubkey, self.script_info))
}
}

impl StrictDecode for Proof {
fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, strict_encoding::Error> {
Ok(Self {
pubkey: secp256k1::PublicKey::strict_decode(&mut d)?,
script_info: ScriptInfo::strict_decode(&mut d)?,
})
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
5 changes: 4 additions & 1 deletion src/bp/short_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,10 @@ impl Descriptor {
}
}

#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, Display)]
#[derive(
Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, Display, StrictEncode, StrictDecode,
)]
#[strict_crate(crate)]
#[display(Debug)]
pub struct ShortId(u64);

Expand Down
36 changes: 2 additions & 34 deletions src/bp/strict_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use bitcoin::hashes::{hash160, sha256, sha256d, sha512};
use bitcoin::util::psbt::PartiallySignedTransaction;
use bitcoin::{secp256k1, util::bip32, BlockHash, OutPoint, Script, Txid, XpubIdentifier};

use super::{blind::OutpointHash, blind::OutpointReveal, ShortId};
use super::blind::OutpointHash;
use crate::strict_encoding::{self, Error, StrictDecode, StrictEncode};
use bitcoin::util::bip32::KeyApplication;

Expand Down Expand Up @@ -203,20 +203,6 @@ impl StrictDecode for KeyApplication {
}
}

impl StrictEncode for ShortId {
#[inline]
fn strict_encode<E: io::Write>(&self, e: E) -> Result<usize, Self::Error> {
self.into_u64().strict_encode(e)
}
}

impl StrictDecode for ShortId {
#[inline]
fn strict_decode<D: io::Read>(d: D) -> Result<Self, Self::Error> {
Ok(Self::from(u64::strict_decode(d)?))
}
}

impl StrictEncode for OutPoint {
#[inline]
fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Self::Error> {
Expand All @@ -234,24 +220,6 @@ impl StrictDecode for OutPoint {
}
}

impl StrictEncode for OutpointReveal {
#[inline]
fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Self::Error> {
Ok(strict_encode_list!(e; self.blinding, self.txid, self.vout))
}
}

impl StrictDecode for OutpointReveal {
#[inline]
fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, Self::Error> {
Ok(Self {
blinding: u64::strict_decode(&mut d)?,
txid: Txid::strict_decode(&mut d)?,
vout: u32::strict_decode(&mut d)?,
})
}
}

impl StrictEncode for bip32::ChildNumber {
#[inline]
fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Self::Error> {
Expand Down Expand Up @@ -372,7 +340,7 @@ pub(crate) mod test {
use bitcoin::{hashes::hex::FromHex, secp256k1::Message, BlockHash};

use super::*;
use crate::bp::short_id;
use crate::bp::{blind::OutpointReveal, short_id, ShortId};
use crate::strict_encoding::test::test_suite;

pub(crate) fn encode_decode<T: StrictEncode + StrictDecode>(
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub extern crate bitcoin;
pub extern crate bitcoin_hashes;
pub extern crate miniscript;

#[macro_use]
extern crate lnpbp_derive;

#[macro_use]
mod paradigms;
#[macro_use]
Expand Down
38 changes: 4 additions & 34 deletions src/lnpbps/lnpbp4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@
// If not, see <https://opensource.org/licenses/MIT>.

use std::collections::BTreeMap;
use std::io;

use bitcoin::hashes::{sha256, Hash, HashEngine};
use bitcoin::secp256k1::rand::{thread_rng, Rng};
use bitcoin::util::uint::Uint256;

use crate::commit_verify::TryCommitVerify;
use crate::strict_encoding::{self, StrictDecode, StrictEncode};

/// Source data for creation of multi-message commitments according to LNPBP-4 procedure
pub type MultiMsg = BTreeMap<sha256::Hash, sha256::Hash>;
Expand All @@ -29,7 +27,8 @@ pub type Lnpbp4Hash = sha256::Hash;
#[display(Debug)]
pub struct TooManyMessagesError;

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display, StrictEncode, StrictDecode)]
#[strict_crate(crate)]
#[display(Debug)]
pub struct MultimsgCommitmentItem {
pub protocol: Option<sha256::Hash>,
Expand All @@ -46,7 +45,8 @@ impl MultimsgCommitmentItem {
}

/// Multimessage commitment data according to LNPBP-4 specification
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display, StrictEncode, StrictDecode)]
#[strict_crate(crate)]
#[display(Debug)]
pub struct MultimsgCommitment {
pub commitments: Vec<MultimsgCommitmentItem>,
Expand Down Expand Up @@ -116,33 +116,3 @@ impl TryCommitVerify<MultiMsg> for MultimsgCommitment {
})
}
}

impl StrictEncode for MultimsgCommitmentItem {
fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, strict_encoding::Error> {
Ok(strict_encode_list!(e; self.protocol, self.commitment))
}
}

impl StrictDecode for MultimsgCommitmentItem {
fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, strict_encoding::Error> {
Ok(Self {
protocol: Option::<sha256::Hash>::strict_decode(&mut d)?,
commitment: Lnpbp4Hash::strict_decode(&mut d)?,
})
}
}

impl StrictEncode for MultimsgCommitment {
fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, strict_encoding::Error> {
Ok(strict_encode_list!(e; self.commitments, self.entropy))
}
}

impl StrictDecode for MultimsgCommitment {
fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, strict_encoding::Error> {
Ok(Self {
commitments: Vec::<MultimsgCommitmentItem>::strict_decode(&mut d)?,
entropy: Option::<u64>::strict_decode(&mut d)?,
})
}
}
27 changes: 2 additions & 25 deletions src/paradigms/client_side_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,31 +229,8 @@ hash_newtype!(
);
impl_hashencode!(MerkleNode);

mod strict_encode {
use super::*;
use crate::strict_encoding::{Error, StrictDecode, StrictEncode};

impl StrictEncode for MerkleNode {
type Error = Error;

#[inline]
fn strict_encode<E: io::Write>(&self, e: E) -> Result<usize, Self::Error> {
self.into_inner().to_vec().strict_encode(e)
}
}

impl StrictDecode for MerkleNode {
type Error = Error;

#[inline]
fn strict_decode<D: io::Read>(d: D) -> Result<Self, Self::Error> {
Ok(
Self::from_slice(&Vec::<u8>::strict_decode(d)?).map_err(|_| {
Error::DataIntegrityError("Wrong merkle node hash data size".to_string())
})?,
)
}
}
impl strict_encoding::Strategy for MerkleNode {
type Strategy = strict_encoding::strategies::HashFixedBytes;
}

/// Merklization procedure that uses tagged hashes with depth commitments
Expand Down
22 changes: 2 additions & 20 deletions src/rgb/contract/amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ impl Ord for Revealed {
}
}

#[derive(Clone, Debug, Display, AsAny)]
#[derive(Clone, Debug, Display, AsAny, StrictEncode, StrictDecode)]
#[strict_crate(crate)]
#[display(Debug)]
pub struct Confidential {
pub commitment: pedersen::Commitment,
Expand Down Expand Up @@ -281,25 +282,6 @@ mod strict_encoding {
}
}

impl StrictEncode for Confidential {
type Error = Error;

fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Self::Error> {
Ok(strict_encode_list!(e; self.commitment, self.bulletproof))
}
}

impl StrictDecode for Confidential {
type Error = Error;

fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, Self::Error> {
Ok(Self {
commitment: pedersen::Commitment::strict_decode(&mut d)?,
bulletproof: pedersen::RangeProof::strict_decode(&mut d)?,
})
}
}

impl StrictEncode for Revealed {
type Error = Error;

Expand Down
1 change: 0 additions & 1 deletion src/rgb/contract/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ impl CommitEncodeWithStrategy for Confidential {
type Strategy = commit_strategy::UsingStrict;
}

// TODO: Automate this with #derive macros
pub(super) mod strict_encoding {
use super::*;
use crate::strict_encoding::{strategies, Error, Strategy, StrictDecode, StrictEncode};
Expand Down
Loading

0 comments on commit 4377e5d

Please sign in to comment.