Skip to content

Commit

Permalink
Merge efc57dc into e9cdaac
Browse files Browse the repository at this point in the history
  • Loading branch information
esdrubal authored Jul 19, 2024
2 parents e9cdaac + efc57dc commit fc4da40
Show file tree
Hide file tree
Showing 11 changed files with 1,048 additions and 715 deletions.
29 changes: 10 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ fuel-tx = "0.55.0"
fuel-vm = "0.55.0"

# Dependencies from the `fuels-rs` repository:
fuels-core = "0.65.1"
fuels-accounts = "0.65.1"
fuels-core = { git = "https://github.com/FuelLabs/fuels-rs", branch = "esdrubal/abi_changes2" }
fuels-accounts = { git = "https://github.com/FuelLabs/fuels-rs", branch = "esdrubal/abi_changes2" }

# Dependencies from the `forc-wallet` repository:
forc-wallet = "0.8.2"
forc-wallet = { git = "https://github.com/FuelLabs/forc-wallet", branch = "esdrubal/abi_changes" }

# Dependencies from the `fuel-abi-types` repository:
fuel-abi-types = "0.5.2"
fuel-abi-types = { git = "https://github.com/FuelLabs/fuel-abi-types", branch = "esdrubal/abi_changes2" }

[workspace.package]
edition = "2021"
Expand Down
155 changes: 14 additions & 141 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use forc_util::{
default_output_directory, find_file_name, kebab_to_snake_case, print_compiling,
print_on_failure, print_warnings,
};
use fuel_abi_types::abi::program as program_abi;
use petgraph::{
self, dot,
visit::{Bfs, Dfs, EdgeRef, Walker},
Expand Down Expand Up @@ -1833,29 +1832,38 @@ pub fn compile(
metrics
);

const OLD_ENCODING_VERSION: &str = "0";
const NEW_ENCODING_VERSION: &str = "1";
const SPEC_VERSION: &str = "1";

let mut program_abi = match pkg.target {
BuildTarget::Fuel => {
let mut types = vec![];
ProgramABI::Fuel(time_expr!(
let program_abi_res = time_expr!(
"generate JSON ABI program",
"generate_json_abi",
fuel_abi::generate_program_abi(
&handler,
&mut AbiContext {
program: typed_program,
abi_with_callpaths: profile.json_abi_with_callpaths,
type_ids_to_full_type_str: HashMap::<String, String>::new(),
},
engines,
&mut types,
profile
.experimental
.new_encoding
.then(|| NEW_ENCODING_VERSION.into()),
.then(|| NEW_ENCODING_VERSION.into())
.unwrap_or(OLD_ENCODING_VERSION.into()),
SPEC_VERSION.into(),
),
Some(sway_build_config.clone()),
metrics
))
);
let program_abi = match program_abi_res {
Err(_) => return fail(handler),
Ok(program_abi) => program_abi,
};
ProgramABI::Fuel(program_abi)
}
BuildTarget::EVM => {
// Merge the ABI output of ASM gen with ABI gen to handle internal constructors
Expand Down Expand Up @@ -2484,11 +2492,6 @@ pub fn build(
}
source_map.insert_dependency(descriptor.manifest_file.dir());

// TODO: This should probably be in `fuel_abi_json::generate_json_abi_program`?
if let ProgramABI::Fuel(ref mut program_abi) = compiled.program_abi {
standardize_json_abi_types(program_abi);
}

let built_pkg = BuiltPackage {
descriptor,
program_abi: compiled.program_abi,
Expand All @@ -2508,136 +2511,6 @@ pub fn build(
Ok(built_packages)
}

/// Standardize the JSON ABI data structure by eliminating duplicate types. This is an iterative
/// process because every time two types are merged, new opportunities for more merging arise.
fn standardize_json_abi_types(json_abi_program: &mut program_abi::ProgramABI) {
loop {
// If type with id_1 is a duplicate of type with id_2, then keep track of the mapping
// between id_1 and id_2 in the HashMap below.
let mut old_to_new_id: HashMap<usize, usize> = HashMap::new();

// A vector containing unique `program_abi::TypeDeclaration`s.
//
// Two `program_abi::TypeDeclaration` are deemed the same if the have the same
// `type_field`, `components`, and `type_parameters` (even if their `type_id`s are
// different).
let mut deduped_types: Vec<program_abi::TypeDeclaration> = Vec::new();

// Insert values in `deduped_types` if they haven't been inserted before. Otherwise, create
// an appropriate mapping between type IDs in the HashMap `old_to_new_id`.
for decl in &json_abi_program.types {
if let Some(ty) = deduped_types.iter().find(|d| {
d.type_field == decl.type_field
&& d.components == decl.components
&& d.type_parameters == decl.type_parameters
}) {
old_to_new_id.insert(decl.type_id, ty.type_id);
} else {
deduped_types.push(decl.clone());
}
}

// Nothing to do if the hash map is empty as there are not merge opportunities. We can now
// exit the loop.
if old_to_new_id.is_empty() {
break;
}

json_abi_program.types = deduped_types;

// Update all `program_abi::TypeApplication`s and all `program_abi::TypeDeclaration`s
update_all_types(json_abi_program, &old_to_new_id);
}

// Sort the `program_abi::TypeDeclaration`s
json_abi_program
.types
.sort_by(|t1, t2| t1.type_field.cmp(&t2.type_field));

// Standardize IDs (i.e. change them to 0,1,2,... according to the alphabetical order above
let mut old_to_new_id: HashMap<usize, usize> = HashMap::new();
for (ix, decl) in json_abi_program.types.iter_mut().enumerate() {
old_to_new_id.insert(decl.type_id, ix);
decl.type_id = ix;
}

// Update all `program_abi::TypeApplication`s and all `program_abi::TypeDeclaration`s
update_all_types(json_abi_program, &old_to_new_id);
}

/// Recursively updates the type IDs used in a program_abi::ProgramABI
fn update_all_types(
json_abi_program: &mut program_abi::ProgramABI,
old_to_new_id: &HashMap<usize, usize>,
) {
// Update all `program_abi::TypeApplication`s in every function
for func in &mut json_abi_program.functions {
for input in &mut func.inputs {
update_json_type_application(input, old_to_new_id);
}

update_json_type_application(&mut func.output, old_to_new_id);
}

// Update all `program_abi::TypeDeclaration`
for decl in &mut json_abi_program.types {
update_json_type_declaration(decl, old_to_new_id);
}
if let Some(logged_types) = &mut json_abi_program.logged_types {
for logged_type in logged_types {
update_json_type_application(&mut logged_type.application, old_to_new_id);
}
}
if let Some(messages_types) = &mut json_abi_program.messages_types {
for logged_type in messages_types {
update_json_type_application(&mut logged_type.application, old_to_new_id);
}
}
if let Some(configurables) = &mut json_abi_program.configurables {
for logged_type in configurables {
update_json_type_application(&mut logged_type.application, old_to_new_id);
}
}
}

/// Recursively updates the type IDs used in a `program_abi::TypeApplication` given a HashMap from
/// old to new IDs
fn update_json_type_application(
type_application: &mut program_abi::TypeApplication,
old_to_new_id: &HashMap<usize, usize>,
) {
if let Some(new_id) = old_to_new_id.get(&type_application.type_id) {
type_application.type_id = *new_id;
}

if let Some(args) = &mut type_application.type_arguments {
for arg in args.iter_mut() {
update_json_type_application(arg, old_to_new_id);
}
}
}

/// Recursively updates the type IDs used in a `program_abi::TypeDeclaration` given a HashMap from
/// old to new IDs
fn update_json_type_declaration(
type_declaration: &mut program_abi::TypeDeclaration,
old_to_new_id: &HashMap<usize, usize>,
) {
if let Some(params) = &mut type_declaration.type_parameters {
for param in params.iter_mut() {
if let Some(new_id) = old_to_new_id.get(param) {
*param = *new_id;
}
}
}

if let Some(components) = &mut type_declaration.components {
for component in components.iter_mut() {
update_json_type_application(component, old_to_new_id);
}
}
}

/// Compile the entire forc package and return the lexed, parsed and typed programs
/// of the dependencies and project.
/// The final item in the returned vector is the project.
Expand Down
4 changes: 3 additions & 1 deletion forc-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,9 @@ pub fn decode_log_data(
program_abi: &ProgramABI,
) -> anyhow::Result<DecodedLog> {
let program_abi = match program_abi {
ProgramABI::Fuel(fuel_abi) => Some(fuel_abi),
ProgramABI::Fuel(fuel_abi) => Some(
fuel_abi_types::abi::unified_program::UnifiedProgramABI::from_counterpart(fuel_abi)?,
),
_ => None,
}
.ok_or_else(|| anyhow::anyhow!("only fuelvm is supported for log decoding"))?;
Expand Down
Loading

0 comments on commit fc4da40

Please sign in to comment.