Skip to content

Commit 22bf649

Browse files
committed
Restructure verifier
1 parent ec9de09 commit 22bf649

File tree

5 files changed

+509
-301
lines changed

5 files changed

+509
-301
lines changed

tuxedo-core/aggregator/src/lib.rs

+64-3
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,82 @@ pub fn aggregate(_: TokenStream, body: TokenStream) -> TokenStream {
7373
pub fn tuxedo_verifier(_: TokenStream, body: TokenStream) -> TokenStream {
7474
let ast = parse_macro_input!(body as ItemEnum);
7575
let original_code = ast.clone();
76+
let vis = ast.vis;
7677

7778
let outer_type = ast.ident;
78-
let variants = ast.variants.into_iter().map(|v| v.ident);
79+
let variant_type_pairs = ast.variants.iter().map(|variant| {
80+
// Make sure there is only a single field, and if not, give a helpful error
81+
assert!(
82+
variant.fields.len() == 1,
83+
"Each variant must have a single unnamed field"
84+
);
85+
(
86+
variant.ident.clone(),
87+
variant
88+
.fields
89+
.iter()
90+
.next()
91+
.expect("exactly one field per variant")
92+
.ty
93+
.clone(),
94+
)
95+
});
96+
let variants = variant_type_pairs.clone().map(|(v, _t)| v);
97+
let inner_types = variant_type_pairs.map(|(_v, t)| t);
98+
99+
// Set up the name of the new associated type.
100+
let mut redeemer_type_name = outer_type.to_string();
101+
redeemer_type_name.push_str("Redeemer");
102+
let redeemer_type = Ident::new(&redeemer_type_name, outer_type.span());
103+
104+
// TODO there must be a better way to do this, right?
105+
let inner_types2 = inner_types.clone();
106+
let variants2 = variants.clone();
107+
let variants3 = variants.clone();
108+
let variants4 = variants.clone();
79109

80110
let output = quote! {
81111

82112
// Preserve the original enum, and write the From impls
83113
#[tuxedo_core::aggregate]
84114
#original_code
85115

116+
/// This type is generated by the `#[tuxedo_verifier]` macro.
117+
/// It is a combined redeemer type for the redeemers of each individual verifier.
118+
///
119+
/// This type is accessible downstream as `<OuterVerifier as Verifier>::Redeemer`
120+
#[derive(Debug, Decode)]
121+
#vis enum #redeemer_type {
122+
#(
123+
#variants(<#inner_types as tuxedo_core::Verifier>::Redeemer),
124+
)*
125+
}
126+
127+
// Put a bunch of methods like `.as_variant1()` on the aggregate redeemer type
128+
// These are necessary when unwrapping the onion.
129+
// Might be that we should have a helper macro for this as well
130+
impl #redeemer_type {
131+
#(
132+
//TODO I would rather the function be called as_variant2,
133+
// but my macro n00b skills can't figure it out.
134+
#[allow(non_snake_case)]
135+
pub fn #variants2(&self) -> Option<&<#inner_types2 as tuxedo_core::Verifier>::Redeemer> {
136+
match self {
137+
Self::#variants3(inner) => Some(inner),
138+
_ => None,
139+
}
140+
}
141+
)*
142+
}
143+
86144
impl tuxedo_core::Verifier for #outer_type {
87-
fn verify(&self, simplified_tx: &[u8], redeemer: &[u8]) -> bool {
145+
146+
type Redeemer = #redeemer_type;
147+
148+
fn verify(&self, simplified_tx: &[u8], block_number: u32, redeemer: &Self::Redeemer) -> bool {
88149
match self {
89150
#(
90-
Self::#variants(inner) => inner.verify(simplified_tx, redeemer),
151+
Self::#variants4(inner) => inner.verify(simplified_tx, block_number, redeemer.#variants4().expect("redeemer variant exists because the macro constructed that type.")),
91152
)*
92153
}
93154
}

tuxedo-core/src/executive.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ use sp_std::{collections::btree_set::BTreeSet, vec::Vec};
3535
/// in the proper generic types.
3636
pub struct Executive<B, V, C>(PhantomData<(B, V, C)>);
3737

38-
impl<B: BlockT<Extrinsic = Transaction<V, C>>, V: Verifier, C: ConstraintChecker<V>>
39-
Executive<B, V, C>
38+
impl<B, V, C> Executive<B, V, C>
39+
where
40+
B: BlockT<Extrinsic = Transaction<V, C>>,
41+
B::Header: HeaderT<Number = u32>, // Tuxedo always uses u32 for block number.
42+
V: Verifier,
43+
C: ConstraintChecker<V>,
4044
{
4145
/// Does pool-style validation of a tuxedo transaction.
4246
/// Does not commit anything to storage.
@@ -75,10 +79,12 @@ impl<B: BlockT<Extrinsic = Transaction<V, C>>, V: Verifier, C: ConstraintChecker
7579
let mut missing_inputs = Vec::new();
7680
for input in transaction.inputs.iter() {
7781
if let Some(input_utxo) = TransparentUtxoSet::<V>::peek_utxo(&input.output_ref) {
82+
let redeemer = V::Redeemer::decode(&mut &input.redeemer[..])
83+
.map_err(|_| UtxoError::VerifierError)?;
7884
ensure!(
7985
input_utxo
8086
.verifier
81-
.verify(&stripped_encoded, &input.redeemer),
87+
.verify(&stripped_encoded, Self::block_height(), &redeemer),
8288
UtxoError::VerifierError
8389
);
8490
input_utxos.push(input_utxo);

0 commit comments

Comments
 (0)