Skip to content

Commit

Permalink
Merge 3ebe4fd into ebc2ee6
Browse files Browse the repository at this point in the history
  • Loading branch information
esdrubal committed Jul 15, 2024
2 parents ebc2ee6 + 3ebe4fd commit e6358f9
Show file tree
Hide file tree
Showing 9 changed files with 745 additions and 735 deletions.
314 changes: 61 additions & 253 deletions Cargo.lock

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,25 @@ exclude = [

[workspace.dependencies]
# Dependencies from the `fuel-core` repository:
fuel-core-client = { version = "0.28.0", default-features = false }
fuel-core-types = { version = "0.28.0", default-features = false }
fuel-core-client = { version = "0.31.0", default-features = false }
fuel-core-types = { version = "0.31.0", default-features = false }

# Dependencies from the `fuel-vm` repository:
fuel-asm = "0.52.0"
fuel-crypto = "0.52.0"
fuel-types = "0.52.0"
fuel-tx = "0.52.0"
fuel-vm = "0.52.0"
fuel-asm = "0.55.0"
fuel-crypto = "0.55.0"
fuel-types = "0.55.0"
fuel-tx = "0.55.0"
fuel-vm = "0.55.0"

# Dependencies from the `fuels-rs` repository:
fuels-core = "0.64.0"
fuels-accounts = "0.64.0"
fuels-core = { git = "https://github.com/FuelLabs/fuels-rs", branch = "hal3e/new-fuel-abi-spec" }
fuels-accounts = { git = "https://github.com/FuelLabs/fuels-rs", branch = "hal3e/new-fuel-abi-spec" }

# Dependencies from the `forc-wallet` repository:
forc-wallet = "0.8.1"
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.0"
fuel-abi-types = "0.6.0"

[workspace.package]
edition = "2021"
Expand Down
151 changes: 13 additions & 138 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 @@ -1832,28 +1831,39 @@ pub fn compile(
);

const NEW_ENCODING_VERSION: &str = "1";
const SPEC_VERSION: &str = "1";
const ABI_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()),
SPEC_VERSION.into(),
ABI_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 @@ -2482,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 @@ -2506,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
2 changes: 1 addition & 1 deletion forc-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ pub fn decode_log_data(
let type_lookup = program_abi
.types
.iter()
.map(|decl| (decl.type_id, decl.clone()))
.map(|decl| (decl.type_id.clone(), decl.clone()))
.collect::<HashMap<_, _>>();

let logged_type_lookup: HashMap<_, _> = program_abi
Expand Down
26 changes: 20 additions & 6 deletions sway-core/src/abi_generation/abi_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ use sway_types::integer_bits::IntegerBits;

use crate::{language::CallPath, Engines, TypeArgument, TypeId, TypeInfo};

#[derive(Clone)]
pub struct AbiStrContext {
pub program_name: Option<String>,
pub abi_with_callpaths: bool,
pub abi_with_fully_specified_types: bool,
pub abi_with_generic_type_parameters: bool,
}

impl TypeId {
Expand All @@ -32,22 +34,34 @@ impl TypeId {
}
(TypeInfo::Tuple(fields), TypeInfo::Tuple(resolved_fields)) => {
assert_eq!(fields.len(), resolved_fields.len());
let field_strs = fields
let field_strs = resolved_fields
.iter()
.map(|f| {
if ctx.abi_with_fully_specified_types {
type_engine.get(f.type_id).abi_str(ctx, engines)
type_engine.get(f.type_id).abi_str(
&AbiStrContext {
abi_with_generic_type_parameters: true,
..ctx.clone()
},
engines,
)
} else {
"_".to_string()
}
})
.collect::<Vec<String>>();
format!("({})", field_strs.join(", "))
}
(TypeInfo::Array(type_arg, count), TypeInfo::Array(_, resolved_count)) => {
(TypeInfo::Array(_, count), TypeInfo::Array(type_arg, resolved_count)) => {
assert_eq!(count.val(), resolved_count.val());
let inner_type = if ctx.abi_with_fully_specified_types {
type_engine.get(type_arg.type_id).abi_str(ctx, engines)
type_engine.get(type_arg.type_id).abi_str(
&AbiStrContext {
abi_with_generic_type_parameters: true,
..ctx.clone()
},
engines,
)
} else {
"_".to_string()
};
Expand Down Expand Up @@ -102,7 +116,7 @@ impl TypeInfo {
Enum(decl_ref) => {
let decl = decl_engine.get_enum(decl_ref);
let type_params =
if !ctx.abi_with_fully_specified_types || decl.type_parameters.is_empty() {
if !ctx.abi_with_generic_type_parameters || decl.type_parameters.is_empty() {
"".into()
} else {
format!(
Expand All @@ -123,7 +137,7 @@ impl TypeInfo {
Struct(decl_ref) => {
let decl = decl_engine.get_struct(decl_ref);
let type_params =
if !ctx.abi_with_fully_specified_types || decl.type_parameters.is_empty() {
if !ctx.abi_with_generic_type_parameters || decl.type_parameters.is_empty() {
"".into()
} else {
format!(
Expand Down
Loading

0 comments on commit e6358f9

Please sign in to comment.