Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewamp workflows on generating commitment ids #152

Merged
merged 26 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c12e46e
commit: refactor commitment ids and commit-encode
dr-orlovsky Feb 1, 2024
49173a4
commit: merge encode into id module
dr-orlovsky Feb 1, 2024
ec9b66e
commit: refactor CommitmentId trait system and tags
dr-orlovsky Feb 1, 2024
bce2b34
commit: fix merkle tree commit id generation
dr-orlovsky Feb 1, 2024
7f2e245
chore: update to new STL
dr-orlovsky Feb 3, 2024
ca68662
merkle: fix doc typo
dr-orlovsky Feb 3, 2024
eb290ae
Merge remote-tracking branch 'origin/master' into v0.11
dr-orlovsky Feb 10, 2024
969571b
chore: update dependencies
dr-orlovsky Feb 4, 2024
a98ed20
merkle: support 8--bit-sized collections
dr-orlovsky Feb 10, 2024
9f90575
id: add StrictHash type
dr-orlovsky Feb 10, 2024
ce4d602
stl: add merklization types into library
dr-orlovsky Feb 11, 2024
9562563
chore: update to new strict encode APIs
dr-orlovsky Feb 12, 2024
a129ce9
update commitment tag URNs
dr-orlovsky Feb 12, 2024
e78b28e
chore: update dependencies
dr-orlovsky Feb 15, 2024
7549e50
commit: derive Debug for CommitEngine
dr-orlovsky Feb 16, 2024
5359d84
stl: update
dr-orlovsky Feb 16, 2024
75d5979
commit: add specialized commit methods to CommitEngine
dr-orlovsky Feb 17, 2024
ec95f74
commit: add vesper translator
dr-orlovsky Feb 18, 2024
2b822b9
commit: refactor CommitLayout
dr-orlovsky Feb 18, 2024
49345a1
commit: improve vesper syntax
dr-orlovsky Feb 18, 2024
d81288a
commit: support committing to optionals
dr-orlovsky Feb 18, 2024
b2c5128
merkle: ensure proper large int conversion. Make var names better
dr-orlovsky Feb 19, 2024
0353648
merkle: ensure collection size match
dr-orlovsky Feb 20, 2024
588e97a
merkle: improve test for large trees
dr-orlovsky Feb 25, 2024
3a157c1
Merge pull request #156 from LNP-BP/fix/merklize
dr-orlovsky Feb 26, 2024
b7df64a
Merge pull request #154 from LNP-BP/layouts
dr-orlovsky Feb 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 90 additions & 148 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ rust-version = "1.69" # Due to TOML in amplify dependency
edition = "2021"
license = "Apache-2.0"

[workspace.dependencies]
amplify = "4.6.0"
strict_encoding = "2.7.0-beta.1"
strict_types = "2.7.0-beta.1"

[package]
name = "client_side_validation"
version = { workspace = true }
Expand Down
11 changes: 6 additions & 5 deletions commit_verify/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ name = "commit-stl"
required-features = ["stl"]

[dependencies]
amplify = { version = "4.5.0", features = ["hex", "apfloat"] }
commit_encoding_derive = { version = "0.10.0", path = "derive" }
strict_encoding = "2.6.1"
strict_types = { version = "1.6.3", optional = true }
amplify = { workspace = true, features = ["hex", "apfloat"] }
strict_encoding = { workspace = true }
strict_types = { workspace = true }
vesper-lang = "0.1.0"
commit_encoding_derive = { version = "0.11.0-beta.3", path = "derive" }
sha2 = "0.10.8"
ripemd = "0.1.3"
rand = { version = "0.8.5", optional = true }
Expand All @@ -38,7 +39,7 @@ rand = "0.8.5"
default = ["derive"]
all = ["rand", "serde", "stl", "derive"]
serde = ["serde_crate", "amplify/serde"]
stl = ["strict_types", "strict_types/base64"]
stl = ["strict_types/base85"]
derive = []

[package.metadata.docs.rs]
Expand Down
6 changes: 3 additions & 3 deletions commit_verify/derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "commit_encoding_derive"
version = "0.10.0"
version = { workspace = true }
description = "Commitment encoding derivation macros"
keywords = ["commitments", "proc-macro"]
categories = ["development-tools", "encoding"]
Expand All @@ -16,7 +16,7 @@ readme = "README.md"
proc-macro = true

[dependencies]
amplify = "4.0.0"
amplify = { workspace = true }
quote = "1"
syn = { version = "1", features = ["full"] }
proc-macro2 = "1"
Expand All @@ -25,4 +25,4 @@ amplify_syn = "2.0.0"
[dev-dependencies]
commit_verify = { path = ".." }
compiletest_rs = "0.9.0"
strict_encoding = "2.1.1"
strict_encoding = { workspace = true }
230 changes: 25 additions & 205 deletions commit_verify/derive/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,223 +19,43 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use amplify_syn::{DeriveInner, EnumKind, Field, FieldKind, Fields, Items, NamedField, Variant};
use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
use quote::ToTokens;
use syn::{Error, Index, Result};
use proc_macro2::TokenStream as TokenStream2;
use syn::Result;

use crate::params::{CommitDerive, FieldAttr, StrategyAttr};

struct DeriveCommit<'a>(&'a CommitDerive);
use crate::params::{CommitDerive, StrategyAttr};

impl CommitDerive {
pub fn derive_encode(&self) -> Result<TokenStream2> {
match self.conf.strategy {
StrategyAttr::CommitEncoding => self.data.derive(
&self.conf.commit_crate,
&ident!(CommitEncode),
&DeriveCommit(self),
),
other => self.derive_strategy(other),
}
}

fn derive_strategy(&self, strategy: StrategyAttr) -> Result<TokenStream2> {
let (impl_generics, ty_generics, where_clause) = self.data.generics.split_for_impl();
let trait_crate = &self.conf.commit_crate;
let commitment_id = &self.conf.id;
let ident_name = &self.data.name;
let strategy_name = strategy.to_ident();

Ok(quote! {
#[automatically_derived]
impl #impl_generics #trait_crate::CommitStrategy for #ident_name #ty_generics #where_clause {
type Strategy = #trait_crate::strategies::#strategy_name;
}
})
}

fn derive_fields<'a>(
&self,
fields: impl Iterator<Item = (Option<&'a Ident>, &'a Field)>,
) -> Result<TokenStream2> {
let crate_name = &self.conf.commit_crate;

let conceal_code = if self.conf.conceal {
quote! {
let me = self.conceal();
}
} else {
quote! {
let me = self;
}
};

let mut field_encoding = Vec::new();
for (no, (field_name, unnamed_field)) in fields.enumerate() {
let kind = match field_name {
Some(_) => FieldKind::Named,
None => FieldKind::Unnamed,
};
let attr = FieldAttr::with(unnamed_field.attr.clone(), kind)?;
if attr.skip {
continue;
}
let field_name = field_name
.map(Ident::to_token_stream)
.unwrap_or_else(|| Index::from(no).to_token_stream());
let field = if let Some(tag) = attr.merklize {
quote! {
{
use #crate_name::merkle::MerkleLeaves;
#crate_name::merkle::MerkleNode::merklize(#tag.to_be_bytes(), &me.#field_name).commit_encode(e);
}
}
} else {
quote! {
me.#field_name.commit_encode(e);
}
};
field_encoding.push(field)
}

Ok(quote! {
fn commit_encode(&self, e: &mut impl ::std::io::Write) {
use #crate_name::CommitEncode;
#conceal_code
#( #field_encoding )*
}
})
}
}

impl DeriveInner for DeriveCommit<'_> {
fn derive_unit_inner(&self) -> Result<TokenStream2> {
Err(Error::new(
Span::call_site(),
"CommitEncode must not be derived on a unit types. Use just a unit type instead when \
encoding parent structure.",
))
}

fn derive_struct_inner(&self, fields: &Items<NamedField>) -> Result<TokenStream2> {
self.0
.derive_fields(fields.iter().map(|f| (Some(&f.name), &f.field)))
}

fn derive_tuple_inner(&self, fields: &Items<Field>) -> Result<TokenStream2> {
self.0.derive_fields(fields.iter().map(|f| (None, f)))
}

fn derive_enum_inner(&self, variants: &Items<Variant>) -> Result<TokenStream2> {
let crate_name = &self.0.conf.commit_crate;

if variants.enum_kind() == EnumKind::Primitive {
return Err(Error::new(
Span::call_site(),
"primitive enums can't use `propagate` strategy",
));
}

let conceal_code = if self.0.conf.conceal {
quote! {
let me = self.conceal();
}
} else {
quote! {
let me = self;
}
let inner = match self.conf.strategy {
StrategyAttr::Strict => quote! {
engine.commit_to_serialized(self);
},
StrategyAttr::ConcealStrict => quote! {
use #trait_crate::Conceal;
engine.commit_to_concealed(&self.conceal());
},
StrategyAttr::Transparent => quote! {
use amplify::Wrapper;
engine.commit_to_serialized(self.as_inner());
},
StrategyAttr::Merklize => quote! {
use amplify::Wrapper;
engine.commit_to_merkle(self.as_inner().merklize());
},
};

let mut write_variants = Vec::with_capacity(variants.len());
for var in variants {
let var_name = &var.name;
match &var.fields {
Fields::Unit => {
write_variants.push(quote! {
Self::#var_name => {},
});
}
Fields::Unnamed(fields) if fields.is_empty() => {
write_variants.push(quote! {
Self::#var_name() => {},
});
}
Fields::Named(fields) if fields.is_empty() => {
write_variants.push(quote! {
Self::#var_name {} => {},
});
}
Fields::Unnamed(fields) => {
let mut field_idx = Vec::with_capacity(fields.len());
let mut field_fragments = Vec::with_capacity(fields.len());
for (no, field) in fields.iter().enumerate() {
let index = Ident::new(&format!("_{no}"), Span::call_site());
let attr = FieldAttr::with(field.attr.clone(), FieldKind::Unnamed)?;
field_idx.push(index.clone());
if attr.skip {
continue;
}

if let Some(tag) = attr.merklize {
field_fragments.push(quote! {
MerkleNode::merklize(#tag.to_be_bytes(), #index).commit_encode(e);
})
} else {
field_fragments.push(quote! {
#index.commit_encode(e);
})
}
}
write_variants.push(quote! {
Self::#var_name( #( #field_idx ),* ) => {
#( #field_fragments )*
},
});
}
Fields::Named(fields) => {
let mut field_name = Vec::with_capacity(fields.len());
let mut field_fragments = Vec::with_capacity(fields.len());
for named_field in fields {
let attr =
FieldAttr::with(named_field.field.attr.clone(), FieldKind::Named)?;
let name = &named_field.name;
field_name.push(name.clone());
if attr.skip {
continue;
}

if let Some(tag) = attr.merklize {
field_fragments.push(quote! {
MerkleNode::merklize(#tag.to_be_bytes(), #name).commit_encode(e);
})
} else {
field_fragments.push(quote! {
#name.commit_encode(e);
})
}
}

write_variants.push(quote! {
Self::#var_name { #( #field_name ),* } => {
#( #field_fragments )*
},
});
}
}
}

Ok(quote! {
#[allow(unused_imports, unused_variables)]
fn commit_encode(&self, e: &mut impl ::std::io::Write) {
use #crate_name::CommitEncode;
use #crate_name::merkle::{MerkleLeaves, MerkleNode};
use ::strict_encoding::StrictSum;

#conceal_code
me.variant_ord().commit_encode(e);
#[automatically_derived]
impl #impl_generics #trait_crate::CommitEncode for #ident_name #ty_generics #where_clause {
type CommitmentId = #commitment_id;

match self {
#( #write_variants )*
fn commit_encode(&self, engine: &mut #trait_crate::CommitEngine) {
#inner
}
}
})
Expand Down
Loading
Loading