Skip to content
This repository has been archived by the owner on Oct 25, 2024. It is now read-only.

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
ra0x3 committed Dec 2, 2023
1 parent c72b68e commit 39ae355
Showing 1 changed file with 122 additions and 142 deletions.
264 changes: 122 additions & 142 deletions packages/fuel-indexer-macros/src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,38 +340,138 @@ pub fn process_transaction_tokens(
}
}

/// `TokenStream` used to determine which decoder function on `Decoders` to trigger
/// for a given predicate and its associated `predicate_data` inputs.
fn decode_inputs_tokens(manifest: &Manifest) -> Vec<TokenStream> {
let mut inputs_decoder_match = Vec::new();
manifest.predicates().map(|p| {
p.templates().map(|t| {
t.iter().for_each(|t| {
/// `TokenStream` used to augment the `process_transaction_tokens` `TokenStream` with logic
/// specific to the handling of predicates in the `handle_events` entrypoint.
///
/// If predicates are not enabled, the AST will not be augmented with these tokens.
pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
let configurable_names = predicate_inputs_names_map(manifest);
let verification_tokens = manifest
.predicates()
.map(|p| {
p.templates()
.map(|t| {
t.iter().map(|t| {

let indexer_variant_name =
format_ident! { "{}", predicate_inputs_name(&t.name()) };
let sdk_variant_name =
format_ident! { "{}", configurables_name(&t.name()) };

let abi = get_json_abi(Some(t.abi()))
.expect("Could not derive predicate JSON ABI.");

let abi_types = abi
.types
.iter()
.map(|typ| (typ.type_id, typ.clone()))
.collect::<HashMap<usize, TypeDeclaration>>();

let inputs_fields = abi
.configurables
.iter()
.flatten()
.map(|c| {
let ty_id = c.application.type_id;
let name = configurable_names
.get(&ty_id)
.expect("Could not find configurable naming.");
let name = format_ident! {"{}", name };

format_ident! {"{}", name }
})
.collect::<Vec<_>>();

let chained_functions =
abi.configurables.iter().flat_map(|configurables| {
configurables.iter().map(|c| {
let typ = abi_types.get(&c.application.type_id).expect(
"Predicate configurable type not found in the ABI.",
);

let clone = if is_copy_type(typ) {
quote! { .clone() }
} else {
quote! {}
};

let ty_name = configurable_fn_type_name(c)
.expect("Cannot use unit types '()' in configurables.");
let arg = configurable_names
.get(&c.application.type_id)
.expect("Could not find configurable naming.");
let arg = format_ident! {"{}", arg };
let fn_name = format_ident! { "with_{}", ty_name };
quote! {
.#fn_name(#arg #clone)
}
})
});

quote! {
PredicatesInputs::#indexer_variant_name(#indexer_variant_name { #(#inputs_fields),*, .. }) => {
let configurables = #sdk_variant_name::new()#(#chained_functions)*;
let mut predicate = SDKPredicate::from_code(indexer_predicate.bytecode().clone(), BETA4_CHAIN_ID)
.with_configurables(configurables);
// Convert the SDK predicate to the indexer-friendly predicate
let predicate = Predicate::from(predicate);

if predicate.address() == indexer_predicate.coin_output().owner() {
// IndexerPredicateEntity will automatically save the PredicateCoinOutputEntity
let predicate_entity = IndexerPredicateEntity::from(indexer_predicate.clone());
predicate_entity.save();
}
}
}
}).collect::<Vec<proc_macro2::TokenStream>>()
}).unwrap_or_default()
}).unwrap_or_default();

let decode_inputs_tokens = manifest
.predicates()
.map(|p| {
p.templates()
.map(|t| {
t.iter().map(|t| {
let name = predicate_inputs_name(&t.name());
let template_id = t.id().to_string();
let ident = format_ident! { "{}", name };
let fn_name = format_ident! { "decode_{}", name.to_lowercase() };

inputs_decoder_match.push(quote! {
quote! {
#template_id => {
let obj = #ident::new(predicate_data.to_owned());
decoder.#fn_name(obj).expect("Could not decode predicate.");
},
});
})
}
}).collect::<Vec<proc_macro2::TokenStream>>()
})
.unwrap_or_default()
})
});
inputs_decoder_match
}
.unwrap_or_default();

/// `TokenStream` used to augment the `process_transaction_tokens` `TokenStream` with logic
/// specific to the handling of predicates in the `handle_events` entrypoint.
///
/// If predicates are not enabled, the AST will not be augmented with these tokens.
pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
let configurables_match = inputs_match_tokens(manifest);
let verification_tokens = predicate_verification_tokens(manifest);
let decode_inputs_tokens = decode_inputs_tokens(manifest);
let inputs_match_tokens = manifest
.predicates()
.map(|p| {
p.templates()
.map(|t| {
t.iter()
.map(|t| {
let template_id = t.id().to_string();
let name = predicate_inputs_name(&t.name());
let ident = format_ident! { "{}", name };
quote! {
#template_id => {
let obj = #ident::new(configurables);
PredicatesInputs::#ident(obj)
},
}
})
.collect::<Vec<proc_macro2::TokenStream>>()
})
.unwrap_or_default()
})
.unwrap_or_default();

let template_ids = manifest
.predicates()
Expand Down Expand Up @@ -403,10 +503,8 @@ pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {

let submitted_predicates = witnesses
.iter()
// Verify that a `PredicateWitnessData` can be created from the witness data.
.map(|w| PredicateWitnessData::try_from(w.to_owned()))
.filter_map(Result::ok)
// Verify that the template ID associated with this predicate is relevant to this indexer.
.filter_map(|pwd| {
let template_id = pwd.template_id().to_string();
if template_ids.contains(&template_id) {
Expand All @@ -415,7 +513,6 @@ pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
None
}
})
// Now we can create an indexer-related predicate
.map(|data| {
IndexerPredicate::from_witness(
data.to_owned(),
Expand All @@ -429,7 +526,7 @@ pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
let template_id = indexer_predicate.template_id().to_string();
let configurables = indexer_predicate.configurables().to_owned();
let indexer_configurables = match template_id.as_str() {
#(#configurables_match)*
#(#inputs_match_tokens)*
_ => panic!("Unknown predicate template ID; check ABI to make sure that predicate IDs are correct.")
};

Expand Down Expand Up @@ -483,123 +580,6 @@ pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
}
}

/// `TokenStream` used to build the match statement to derive the predicate inputs object. This predicates
/// input object is passed to the `fuels-rs` predicate encoder for predicate verification.
pub fn inputs_match_tokens(manifest: &Manifest) -> Vec<TokenStream> {
manifest
.predicates()
.map(|p| {
p.templates()
.map(|t| {
t.iter()
.map(|t| {
let template_id = t.id().to_string();
let name = predicate_inputs_name(&t.name());
let ident = format_ident! { "{}", name };
quote! {
#template_id => {
let obj = #ident::new(configurables);
PredicatesInputs::#ident(obj)
},
}
})
.collect::<Vec<proc_macro2::TokenStream>>()
})
.unwrap_or_default()
})
.unwrap_or_default()
}

/// `TokenStream` used to verify a set of predicates in the `handle_events` entrypoint.
pub fn predicate_verification_tokens(manifest: &Manifest) -> Vec<TokenStream> {
let mut output = Vec::new();

if let Some(predicates) = manifest.predicates() {
if predicates.is_empty() {
return output;
}

let configurable_names = predicate_inputs_names_map(manifest);

if let Some(templates) = predicates.templates() {
for template in templates {
let indexer_variant_name =
format_ident! { "{}", predicate_inputs_name(&template.name()) };
let sdk_variant_name =
format_ident! { "{}", configurables_name(&template.name()) };

let abi = get_json_abi(Some(template.abi()))
.expect("Could not derive predicate JSON ABI.");

let abi_types = abi
.types
.iter()
.map(|typ| (typ.type_id, typ.clone()))
.collect::<HashMap<usize, TypeDeclaration>>();

let inputs_fields = abi
.configurables
.iter()
.flatten()
.map(|c| {
let ty_id = c.application.type_id;
let name = configurable_names
.get(&ty_id)
.expect("Could not find configurable naming.");
let name = format_ident! {"{}", name };

format_ident! {"{}", name }
})
.collect::<Vec<_>>();

let chained_functions =
abi.configurables.iter().flat_map(|configurables| {
configurables.iter().map(|c| {
let typ = abi_types.get(&c.application.type_id).expect(
"Predicate configurable type not found in the ABI.",
);

let clone = if is_copy_type(typ) {
quote! { .clone() }
} else {
quote! {}
};

let ty_name = configurable_fn_type_name(c)
.expect("Cannot use unit types '()' in configurables.");
let arg = configurable_names
.get(&c.application.type_id)
.expect("Could not find configurable naming.");
let arg = format_ident! {"{}", arg };
let fn_name = format_ident! { "with_{}", ty_name };
quote! {
.#fn_name(#arg #clone)
}
})
});

output.push(quote! {
PredicatesInputs::#indexer_variant_name(#indexer_variant_name { #(#inputs_fields),*, .. }) => {
let configurables = #sdk_variant_name::new()#(#chained_functions)*;
let mut predicate = SDKPredicate::from_code(indexer_predicate.bytecode().clone(), BETA4_CHAIN_ID)
.with_configurables(configurables);
// Convert the SDK predicate to the indexer-friendly predicate
let predicate = Predicate::from(predicate);

if predicate.address() == indexer_predicate.coin_output().owner() {
// IndexerPredicateEntity will automatically save the PredicateCoinOutputEntity
let predicate_entity = IndexerPredicateEntity::from(indexer_predicate.clone());
predicate_entity.save();
}
}
});
}
}
}

output
}

/// `TokenStream` used to generate a set of indexer-specific predicate inputs.
pub fn predicate_inputs_tokens(manifest: &Manifest) -> TokenStream {
let predicates = manifest.predicates();
Expand Down

0 comments on commit 39ae355

Please sign in to comment.