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

Cleaner separation of Verifier / Constraint Cheker duties #188

Merged
merged 38 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d3b056f
more sketching
JoshOrndorff Feb 15, 2024
367fa3d
core compiles
JoshOrndorff Feb 15, 2024
8e6f86c
Revert "core compiles"
JoshOrndorff Feb 15, 2024
d8d7eec
checkpoint... again.
JoshOrndorff Feb 16, 2024
96d2604
moar
JoshOrndorff Feb 28, 2024
d8bb7f0
Merge branch 'main' into joshy-constraint-checker-beef-up
JoshOrndorff Feb 28, 2024
c34920b
imports
JoshOrndorff Feb 28, 2024
45e80bb
Pivot toward explicit `ConstraintChecker` trait with all methods.
JoshOrndorff Feb 28, 2024
643dc77
starting to compile
JoshOrndorff Feb 28, 2024
5c13d8d
fmt
JoshOrndorff Feb 28, 2024
d295edf
warnings
JoshOrndorff Feb 28, 2024
c84d23e
executive compiles
JoshOrndorff Feb 28, 2024
f897c1d
inherents back to compiling
JoshOrndorff Feb 28, 2024
169000f
fmt
JoshOrndorff Feb 28, 2024
f332777
start updating wardrobe
JoshOrndorff Feb 28, 2024
02f8e01
Timestamp compiles
JoshOrndorff Feb 28, 2024
221a630
parachain piece
JoshOrndorff Feb 28, 2024
e2e43bb
format
JoshOrndorff Feb 28, 2024
c25f297
seemingly unused imports?
JoshOrndorff Feb 28, 2024
eb9c037
First pass at aggregator simplification
JoshOrndorff Feb 29, 2024
731cb0a
Don't forget the new_unspendable impl
JoshOrndorff Feb 29, 2024
4300853
a little cleanup
JoshOrndorff Feb 29, 2024
4a4a96c
more cleaning in genesis
JoshOrndorff Feb 29, 2024
9e4aa11
Getting closer
JoshOrndorff Feb 29, 2024
6924966
more formatting
JoshOrndorff Mar 1, 2024
cc0758d
Actually mark inherents as such with new adapter type.
JoshOrndorff Mar 17, 2024
4c20e59
fill in commented function body
JoshOrndorff Mar 17, 2024
cb48dda
provide a `new_unspendable` implementation for provided verifiers
JoshOrndorff Mar 18, 2024
ac2d2dc
Aggregator macro provides new_unspendable implementation
JoshOrndorff Mar 18, 2024
e77643f
Make test constraint checker work again.
JoshOrndorff Mar 18, 2024
0e222f3
brush up docs
JoshOrndorff Mar 18, 2024
54d37f3
fix validate block
JoshOrndorff Mar 18, 2024
28f8082
Merge branch 'main' into joshy-constraint-checker-beef-up
JoshOrndorff Mar 18, 2024
8cfd525
unspendable blake2 hashlock
JoshOrndorff Mar 18, 2024
5cce3eb
missed one in validate block
JoshOrndorff Mar 18, 2024
e278748
Timestamp piece no longer has `UpForGrabs` hack
JoshOrndorff Mar 18, 2024
25c8496
note that cleaning up timestamps no longer works for now.
JoshOrndorff Mar 18, 2024
da003a3
Merge branch 'main' into joshy-constraint-checker-beef-up
JoshOrndorff Mar 20, 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
113 changes: 52 additions & 61 deletions tuxedo-core/aggregator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,19 @@ pub fn tuxedo_verifier(_: TokenStream, body: TokenStream) -> TokenStream {
let mut redeemer_type_name = outer_type.to_string();
redeemer_type_name.push_str("Redeemer");
let redeemer_type = Ident::new(&redeemer_type_name, outer_type.span());
let type_for_new_unspendable = inner_types
.clone()
.next()
.expect("At least one verifier variant expected.");

// TODO there must be a better way to do this, right?
let inner_types2 = inner_types.clone();
let variants2 = variants.clone();
let variants3 = variants.clone();
let variant_for_new_unspendable = variants
.clone()
.next()
.expect("At least one verifier variant expected.");

let as_variants = variants.clone().map(|v| {
let s = format!("as_{}", v);
Expand Down Expand Up @@ -160,6 +168,14 @@ pub fn tuxedo_verifier(_: TokenStream, body: TokenStream) -> TokenStream {
)*
}
}

// The aggregation macro assumes that the first variant is able to produce a new unspendable instance.
// In the future this could be made nicer (but maybe not worth the complexity) by allowing an additional
// annotation to the one that can be used as unspendable eg `#[unspendable]`
// If this ever becomes a challenge just add an explicit `Unspendable` variant first.
fn new_unspendable() -> Option<Self> {
#type_for_new_unspendable::new_unspendable().map(|inner| Self::#variant_for_new_unspendable(inner))
}
}
};
output.into()
Expand All @@ -173,9 +189,8 @@ pub fn tuxedo_verifier(_: TokenStream, body: TokenStream) -> TokenStream {
/// just like this original enum. however, the contained values in the error enum are of the corresponding types
/// for the inner constraint checker.
#[proc_macro_attribute]
pub fn tuxedo_constraint_checker(attrs: TokenStream, body: TokenStream) -> TokenStream {
pub fn tuxedo_constraint_checker(_attrs: TokenStream, body: TokenStream) -> TokenStream {
let ast = parse_macro_input!(body as ItemEnum);
let verifier = parse_macro_input!(attrs as Ident);
let original_code = ast.clone();

let outer_type = ast.ident;
Expand Down Expand Up @@ -204,23 +219,16 @@ pub fn tuxedo_constraint_checker(attrs: TokenStream, body: TokenStream) -> Token
error_type_name.push_str("Error");
let error_type = Ident::new(&error_type_name, outer_type.span());

let mut inherent_hooks_name = outer_type.to_string();
inherent_hooks_name.push_str("InherentHooks");
let inherent_hooks = Ident::new(&inherent_hooks_name, outer_type.span());

let vis = ast.vis;

// TODO there must be a better way to do this, right?
let inner_types2 = inner_types.clone();
let inner_types3 = inner_types.clone();
let inner_types4 = inner_types.clone();
let inner_types6 = inner_types.clone();
let inner_types7 = inner_types.clone();
let variants2 = variants.clone();
let variants3 = variants.clone();
let variants4 = variants.clone();
let variants5 = variants.clone();
let variants6 = variants.clone();

let output = quote! {
// Preserve the original enum, and write the From impls
Expand All @@ -235,27 +243,39 @@ pub fn tuxedo_constraint_checker(attrs: TokenStream, body: TokenStream) -> Token
#[derive(Debug)]
#vis enum #error_type {
#(
#variants(<#inner_types as tuxedo_core::ConstraintChecker<#verifier>>::Error),
#variants(<#inner_types as tuxedo_core::ConstraintChecker>::Error),
)*
}

/// This type is generated by the `#[tuxedo_constraint_checker]` macro.
/// It is a combined set of inherent hooks for the inherent hooks of each individual checker.
///
/// This type is accessible downstream as `<OuterConstraintChecker as ConstraintChecker>::InherentHooks`
#[derive(Debug, scale_info::TypeInfo)]
#vis enum #inherent_hooks {
#(
#variants2(<#inner_types2 as tuxedo_core::ConstraintChecker<#verifier>>::InherentHooks),
)*
}
impl tuxedo_core::ConstraintChecker for #outer_type {
type Error = #error_type;

impl tuxedo_core::inherents::InherentInternal<#verifier, #outer_type> for #inherent_hooks {
fn check (
&self,
inputs: &[tuxedo_core::dynamic_typing::DynamicallyTypedData],
peeks: &[tuxedo_core::dynamic_typing::DynamicallyTypedData],
outputs: &[tuxedo_core::dynamic_typing::DynamicallyTypedData],
) -> Result<TransactionPriority, Self::Error> {
match self {
#(
Self::#variants5(inner) => inner.check(inputs, peeks, outputs).map_err(|e| Self::Error::#variants5(e)),
)*
}
}

fn is_inherent(&self) -> bool {
match self {
#(
Self::#variants2(inner) => inner.is_inherent(),
)*
}

fn create_inherents(
}

fn create_inherents<V: tuxedo_core::Verifier>(
authoring_inherent_data: &InherentData,
previous_inherents: Vec<(tuxedo_core::types::Transaction<#verifier, #outer_type>, sp_core::H256)>,
) -> Vec<tuxedo_core::types::Transaction<#verifier, #outer_type>> {
previous_inherents: Vec<(tuxedo_core::types::Transaction<V, #outer_type>, sp_core::H256)>,
) -> Vec<tuxedo_core::types::Transaction<V, #outer_type>> {

let mut all_inherents = Vec::new();

Expand All @@ -272,7 +292,7 @@ pub fn tuxedo_constraint_checker(attrs: TokenStream, body: TokenStream) -> Token
})
.collect();

let inherents = <#inner_types3 as tuxedo_core::ConstraintChecker<#verifier>>::InherentHooks::create_inherents(authoring_inherent_data, previous_inherents)
let inherents = <#inner_types3 as tuxedo_core::ConstraintChecker>::create_inherents(authoring_inherent_data, previous_inherents)
.iter()
.map(|tx| tx.transform::<#outer_type>())
.collect::<Vec<_>>();
Expand All @@ -284,13 +304,13 @@ pub fn tuxedo_constraint_checker(attrs: TokenStream, body: TokenStream) -> Token
all_inherents
}

fn check_inherents(
fn check_inherents<V: tuxedo_core::Verifier>(
importing_inherent_data: &sp_inherents::InherentData,
inherents: Vec<tuxedo_core::types::Transaction<#verifier, #outer_type>>,
inherents: Vec<tuxedo_core::types::Transaction<V, #outer_type>>,
result: &mut sp_inherents::CheckInherentsResult,
) {
#(
let relevant_inherents: Vec<tuxedo_core::types::Transaction<#verifier, #inner_types4>> = inherents
let relevant_inherents: Vec<tuxedo_core::types::Transaction<V, #inner_types4>> = inherents
.iter()
.filter_map(|tx| {
match tx.checker {
Expand All @@ -300,7 +320,7 @@ pub fn tuxedo_constraint_checker(attrs: TokenStream, body: TokenStream) -> Token
})
.collect();

<#inner_types4 as tuxedo_core::ConstraintChecker<#verifier>>::InherentHooks::check_inherents(importing_inherent_data, relevant_inherents, result);
<#inner_types4 as tuxedo_core::ConstraintChecker>::check_inherents(importing_inherent_data, relevant_inherents, result);

// According to https://paritytech.github.io/polkadot-sdk/master/sp_inherents/struct.CheckInherentsResult.html
// "When a fatal error occurs, all other errors are removed and the implementation needs to abort checking inherents."
Expand All @@ -311,12 +331,12 @@ pub fn tuxedo_constraint_checker(attrs: TokenStream, body: TokenStream) -> Token
}

#[cfg(feature = "std")]
fn genesis_transactions() -> Vec<tuxedo_core::types::Transaction<#verifier, #outer_type>> {
let mut all_transactions: Vec<tuxedo_core::types::Transaction<#verifier, #outer_type>> = Vec::new();
fn genesis_transactions<V: tuxedo_core::Verifier>() -> Vec<tuxedo_core::types::Transaction<V, #outer_type>> {
let mut all_transactions: Vec<tuxedo_core::types::Transaction<V, #outer_type>> = Vec::new();

#(
let transactions =
<<#inner_types6 as tuxedo_core::ConstraintChecker<#verifier>>::InherentHooks as tuxedo_core::inherents::InherentInternal<#verifier, #inner_types6>>::genesis_transactions();
<#inner_types2 as tuxedo_core::ConstraintChecker>::genesis_transactions();
all_transactions.extend(
transactions
.into_iter()
Expand All @@ -329,35 +349,6 @@ pub fn tuxedo_constraint_checker(attrs: TokenStream, body: TokenStream) -> Token
}

}

impl tuxedo_core::ConstraintChecker<#verifier> for #outer_type {
type Error = #error_type;

type InherentHooks = #inherent_hooks;

fn check (
&self,
inputs: &[tuxedo_core::types::Output<#verifier>],
peeks: &[tuxedo_core::types::Output<#verifier>],
outputs: &[tuxedo_core::types::Output<#verifier>],
) -> Result<TransactionPriority, Self::Error> {
match self {
#(
Self::#variants5(inner) => inner.check(inputs, peeks, outputs).map_err(|e| Self::Error::#variants5(e)),
)*
}
}

fn is_inherent(&self) -> bool {
match self {
#(
Self::#variants6(inner) => <#inner_types7 as tuxedo_core::ConstraintChecker<#verifier>>::is_inherent(inner),
)*
}

}

}
};

output.into()
Expand Down
Loading
Loading