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

Commit

Permalink
fix flow
Browse files Browse the repository at this point in the history
  • Loading branch information
ra0x3 committed Nov 20, 2023
1 parent d891822 commit 2b460e3
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 49 deletions.
1 change: 1 addition & 0 deletions .markdownlint.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"default": true # Default state for all rules
"MD013": false # Disable rule for line length
"MD033": false # Disable rule banning inline HTML
"MD024": false # Disable duplicate headers
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- [Transactions](./indexing-fuel-types/transactions.md)
- [Receipts](./indexing-fuel-types/receipts.md)
- [Predicates](./indexing-fuel-types/predicates.md)
- [Predicate Witness Data](./indexing-fuel-types/predicate-witness-data.md)
- [Indexing Custom Types](./indexing-custom-types/index.md)
- [Storing Records](./storing-records/index.md)
- [Querying](./querying/index.md)
Expand Down
1 change: 1 addition & 0 deletions docs/src/indexing-fuel-types/predicate-witness-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Predicate Witness Data
2 changes: 1 addition & 1 deletion docs/src/project-components/manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,4 @@ The SHA-256 hash of the predicate bytecode.

_Required._

The `abi` is used to provide a link to the predicate JSON application binary interface (ABI) that is generated when you build your predicate project.
The `abi` is used to provide a link to the predicate JSON application binary interface (ABI) that is generated when you build your predicate project.
8 changes: 7 additions & 1 deletion packages/fuel-indexer-lib/src/graphql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use async_graphql_parser::{
},
Pos, Positioned,
};
use fuel_indexer_types::indexer::{GraphQLEntity, IndexMetadata, IndexerPredicate};
use fuel_indexer_types::indexer::{
GraphQLEntity, IndexMetadata, IndexerPredicate, PredicateCoinOutput,
};
use sha2::{Digest, Sha256};
use std::collections::{HashMap, HashSet};
use types::IdCol;
Expand All @@ -40,6 +42,10 @@ fn inject_native_entities_into_schema(schema: &str) -> String {
schema = format!("{}{}", schema, IndexMetadata::schema_fragment())
}

if !schema.contains("type PredicateCoinOutputEntity") {
schema = format!("{}{}", schema, PredicateCoinOutput::schema_fragment())
}

if !schema.contains("type PredicateEntity") {
schema = format!("{}{}", schema, IndexerPredicate::schema_fragment())
}
Expand Down
126 changes: 83 additions & 43 deletions packages/fuel-indexer-macros/src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,23 @@ pub fn process_transaction_tokens(
pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
let configurables_match = configurables_match_tokens(manifest);
let verification_tokens = predicate_verification_tokens(manifest);

let template_ids = manifest
.predicates()
.map(|p| {
p.templates()
.map(|t| {
t.iter()
.map(|t| {
let template_id = t.id().to_string();
quote! { #template_id.to_string() }
})
.collect::<Vec<proc_macro2::TokenStream>>()
})
.unwrap_or_default()
})
.unwrap_or_default();

quote! {
match &tx.transaction {
fuel::Transaction::Script(script) => {
Expand All @@ -344,11 +361,23 @@ pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
..
} = script;

// TODO: Verify that signaled_predicates' `template_id` matches the `template_id` 3.2a https://github.com/FuelLabs/fuel-indexer/issues/886
let signaled_predicates = witnesses
let template_ids = vec![#(#template_ids),*];

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) {
Some(pwd)
} else {
None
}
})
// Now we can create an indexer-related predicate
.map(|data| {
IndexerPredicate::from_signaled_witness_data(
data.to_owned(),
Expand All @@ -358,8 +387,9 @@ pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
})
.collect::<Vec<_>>();

// Cache signaled predicates
signaled_predicates.iter().for_each(|p| {

// Save OK predicates to the DB
submitted_predicates.iter().for_each(|p| {
let _p = PredicateEntity::from(p.to_owned()).get_or_create();
});

Expand All @@ -376,38 +406,24 @@ pub fn transaction_predicate_tokens(manifest: &Manifest) -> TokenStream {
..
} = coin;

// This could potentially be an InputCoin with no predicate data
if predicate_code.is_empty() || predicate_data.is_empty() {
return;
}

// FIXME: After https://github.com/FuelLabs/fuel-indexer/pull/1446 is merged, use the new .find()
// functionality to look in the DB for the predicate
let pred = signaled_predicates.iter().find(|p| {
let utxo = p.coin_output();
utxo.to == *owner
let signaled_predicates = submitted_predicates.iter().filter(|p| {
let owner = p.coin_output().to;
PredicateCoinOutputEntity::find(PredicateCoinOutputEntity::to().eq(owner.to_owned())).is_some()
});


match pred {
Some(pred) => {
let template_id = pred.template_id().to_string();

// FIXME: What is the difference between these inputs, and the inputs in `predicate_data` from the TX?
// Why do we keep this twice?
let predicate_inputs = pred.inputs().to_owned();
let configurable = match template_id.as_str() {
#(#configurables_match)*
_ => panic!("Unknown predicate template ID; check ABI to make sure that predicate IDs are correct.")
};

match configurable {
#(#verification_tokens)*
_ => panic!("Unrecognized configurable type."),
}
signaled_predicates.for_each(|pred| {
let template_id = pred.template_id().to_string();
let predicate_inputs = pred.inputs().to_owned();
let configurable = match template_id.as_str() {
#(#configurables_match)*
_ => panic!("Unknown predicate template ID; check ABI to make sure that predicate IDs are correct.")
};

match configurable {
#(#verification_tokens)*
_ => panic!("Unrecognized configurable type."),
}
None => {},
}
});
}
_ => {
debug!("Input type ignored for predicates.");
Expand Down Expand Up @@ -527,7 +543,7 @@ pub fn predicate_verification_tokens(manifest: &Manifest) -> Vec<TokenStream> {
});

output.push(quote! {
ConfigurablesContainer::#indexer_variant_name(#indexer_variant_name { #(#input_fields),*, .. }) => {
ConfigurablesContainer::#indexer_variant_name(#indexer_variant_name { #(#input_fields),*, }) => {
let configurables = #sdk_variant_name::new()#(#chained_functions)*;
let predicate_data = #encoder_name::encode_data(#(#input_fields),*);

Expand All @@ -540,6 +556,8 @@ pub fn predicate_verification_tokens(manifest: &Manifest) -> Vec<TokenStream> {
if *predicate.address() == pred.coin_output().to.into() {
let data = bincode::serialize(&predicate).expect("Could not serialize predicate.");
decoder.decode_type(Predicate::type_id(), data).expect("Could not decode predicate.");

// DELETE THE predicate_entity here
}
}
});
Expand Down Expand Up @@ -593,6 +611,10 @@ pub fn predicate_inputs_tokens(manifest: &Manifest) -> TokenStream {
.map(|typ| (typ.type_id, typ.clone()))
.collect::<HashMap<usize, TypeDeclaration>>();

let mut witness_data_decoding = Vec::new();
let mut input_struct_constructor = Vec::new();


let input_fields = main
.inputs
.iter()
Expand All @@ -606,6 +628,27 @@ pub fn predicate_inputs_tokens(manifest: &Manifest) -> TokenStream {
let ty = typ.rust_tokens();
let name = format_ident! { "{}", name };

witness_data_decoding.push(quote! {
let #name = {
// NOTE: If we're not using the packed type ID in the witness data, that means witness data
// items have to be backed in the order that the inputs are found in the predicate
// let ty_id: [u8; 4] = [data[left], data[left+1], data[left+2], data[left+3]];
// let ty_id = u32::from_le_bytes(ty_id);

let len: [u8; 4] = [data[left+4], data[left+5], data[left+6], data[left+7]];
let len = u32::from_le_bytes(len) as usize;
let data = &data[left + 8 .. left + 8 + len];
let decoded = decoder.decode(&#ty::param_type(), data).expect("Could not decode predicate witness data");
let obj: #ty = #ty::from_token(decoded).expect("Could not convert decoded data to predicate witness data");
left = left + 8 + len;
obj
};
});

input_struct_constructor.push(quote!{
#name
});

quote! {
pub #name: #ty
}
Expand All @@ -621,21 +664,18 @@ pub fn predicate_inputs_tokens(manifest: &Manifest) -> TokenStream {

#[derive(Debug, Clone)]
pub struct #ident {
pub id: String,
#(#input_fields),*
}

impl #ident {

// TODO: Should document the standardization of predicate witness data

pub fn new(data: Vec<u8>) -> Self {
// FIXME: This will have to be a part of the codegen
// We need to:
// 1. chunk each piece (ty_id, len, and data)
// 2. Use SDK to decode data into T
// 3. When finished create Self { } using all T's
todo!("Finish!")
let mut left = 0usize;
let decoder = ABIDecoder::default();
#(#witness_data_decoding)*
Self {
#(#input_struct_constructor),*
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/fuel-indexer-tests/tests/indexing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::{collections::HashSet, str::FromStr};

const REVERT_VM_CODE: u64 = 0x0004;
const EXPECTED_CONTRACT_ID: &str =
"f243849dbbbb53783de7ffc1ec12a1d6a42152b456d1b460e413a097694d247d";
"60ddf75280b60e644e90fca5febaffb024882f0203b04ed8c7e9df8aa961060e";
const TRANSFER_BASE_ASSET_ID: &str =
"0000000000000000000000000000000000000000000000000000000000000000";

Expand Down
47 changes: 44 additions & 3 deletions packages/fuel-indexer-types/src/indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ pub struct IndexMetadata {

impl GraphQLEntity for IndexMetadata {
/// Return the GraphQL schema fragment for the `IndexMetadata` type.
///
/// The structure of this fragment should always match `fuel_indexer_types::IndexMetadata`.
fn schema_fragment() -> &'static str {
r#"
Expand All @@ -45,7 +43,50 @@ type IndexMetadataEntity @entity {
}
}

// TODO: Should document the standardization of predicate witness data
impl TypeId for IndexMetadata {
/// Return the type ID for `IndexMetadata`.
fn type_id() -> usize {
type_id(FUEL_TYPES_NAMESPACE, "IndexMetadata") as usize
}
}

/// Native GraphQL `TypeDefinition` used to keep track of chain metadata.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PredicateCoinOutput {
/// Metadata identifier.
pub id: ID,

/// Time of metadata.
pub time: u64,

/// Block height of metadata.
pub block_height: u32,

/// Block ID of metadata.
pub block_id: String,
}

impl GraphQLEntity for PredicateCoinOutput {
/// Return the GraphQL schema fragment for the `PredicateCoinOutput` type.
fn schema_fragment() -> &'static str {
r#"
type PredicateCoinOutputEntity @entity {
id: ID!
to: Address!
amount: U64!
asset_id: AssetId!
}
"#
}
}

impl TypeId for PredicateCoinOutput {
/// Return the type ID for `PredicateCoinOutput`.
fn type_id() -> usize {
type_id(FUEL_TYPES_NAMESPACE, "PredicateCoinOutput") as usize
}
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PredicateWitnessData {
Expand Down

0 comments on commit 2b460e3

Please sign in to comment.