From 0068573a56d3dbbe4f95761ff54bffa4d5cd748a Mon Sep 17 00:00:00 2001 From: Daniel Frederico Lins Leite Date: Wed, 30 Aug 2023 12:50:53 +0100 Subject: [PATCH] correctly solving string slices usign script offset --- Cargo.lock | 1 + Cargo.toml | 1 + forc-plugins/forc-client/Cargo.toml | 1 + forc-plugins/forc-client/src/op/mod.rs | 2 +- forc-plugins/forc-client/src/op/run/encode.rs | 40 ++++++---- forc-plugins/forc-client/src/op/run/mod.rs | 41 +++++++--- sway-core/src/ir_generation/compile.rs | 1 - sway-lib-core/src/ops.sw | 4 +- sway-lib-core/src/str.sw | 1 - test/src/e2e_vm_tests/harness.rs | 53 ++++++++----- test/src/e2e_vm_tests/mod.rs | 46 +++++++++-- .../json_abi_oracle.json | 78 ++++++++++++++++--- .../main_args_various_types/src/main.sw | 43 +++------- .../main_args_various_types/test.toml | 14 +++- .../storage_access_caller/src/main.sw | 15 ++-- .../src/main.sw | 5 -- test/src/ir_generation/tests/size_of_val.sw | 31 ++++++++ 17 files changed, 260 insertions(+), 117 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef34de28d60..5e0134bf7c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1807,6 +1807,7 @@ dependencies = [ "fuel-vm", "fuels-accounts", "fuels-core", + "fuels-programs", "futures", "hex", "rand", diff --git a/Cargo.toml b/Cargo.toml index 667446d510a..3cda76913ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ fuel-vm = "0.35.3" # Dependencies from the `fuels-rs` repository: fuels-core = "0.45" fuels-accounts = "0.45" +fuels-programs = "0.45" # Dependencies from the `forc-wallet` repository: forc-wallet = "0.2.5" diff --git a/forc-plugins/forc-client/Cargo.toml b/forc-plugins/forc-client/Cargo.toml index 5892360b2df..db6158a6af4 100644 --- a/forc-plugins/forc-client/Cargo.toml +++ b/forc-plugins/forc-client/Cargo.toml @@ -27,6 +27,7 @@ fuel-tx = { workspace = true, features = ["builder"] } fuel-vm = { workspace = true } fuels-accounts = { workspace = true } fuels-core = { workspace = true } +fuels-programs = { workspace = true } futures = "0.3" hex = "0.4.3" rand = "0.8" diff --git a/forc-plugins/forc-client/src/op/mod.rs b/forc-plugins/forc-client/src/op/mod.rs index bb7e5746eb4..1640c497a37 100644 --- a/forc-plugins/forc-client/src/op/mod.rs +++ b/forc-plugins/forc-client/src/op/mod.rs @@ -3,5 +3,5 @@ mod run; mod submit; pub use deploy::deploy; -pub use run::run; +pub use run::{encode_script_data, run, script_offset}; pub use submit::submit; diff --git a/forc-plugins/forc-client/src/op/run/encode.rs b/forc-plugins/forc-client/src/op/run/encode.rs index 3e2ce1ee93f..46cad72c72d 100644 --- a/forc-plugins/forc-client/src/op/run/encode.rs +++ b/forc-plugins/forc-client/src/op/run/encode.rs @@ -87,23 +87,31 @@ mod tests { #[test] fn test_main_encoding_success() { - let test_json_abi = r#"{"types":[{"typeId":0,"type":"()","components":[],"typeParameters":null}, -{"typeId":1,"type":"bool","components":null,"typeParameters":null},{"typeId":2,"type":"u8","components":null, -"typeParameters":null}],"functions":[{"inputs":[{"name":"test_u8","type":2,"typeArguments":null},{"name":"test_bool", -"type":1,"typeArguments":null}],"name":"main","output":{"name":"","type":0,"typeArguments":null},"attributes":null}], -"loggedTypes":[],"messagesTypes":[],"configurables":[]}"#; + let test_json_abi = r#"{"types":[ + {"typeId":0,"type":"()","components":[],"typeParameters":null}, + {"typeId":1,"type":"bool","components":null,"typeParameters":null}, + {"typeId":2,"type":"u8","components":null,"typeParameters":null}, + {"typeId":3,"type":"str","components":null,"typeParameters":null} + ], "functions":[{"inputs":[ + {"name":"test_u8","type":2,"typeArguments":null}, + {"name":"test_bool","type":1,"typeArguments":null}, + {"name":"test_str","type":3,"typeArguments":null} + ],"name":"main","output":{"name":"","type":0,"typeArguments":null},"attributes":null}],"loggedTypes":[],"messagesTypes":[],"configurables":[]}"#; let call_handler = ScriptCallHandler::from_json_abi_str(test_json_abi).unwrap(); - let values = ["2", "true"]; - - let test_data_offset = 0; - let encoded_bytes = call_handler - .encode_arguments(&values) - .unwrap() - .resolve(test_data_offset); - let expected_bytes = vec![ - 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, - ]; - assert_eq!(encoded_bytes, expected_bytes); + + // Encoded from strings + let values = ["2", "true", "abcd"]; + let encoded_bytes = call_handler.encode_arguments(&values).unwrap().resolve(0); + assert_eq!( + encoded_bytes, + vec![ + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, // 2 + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, // true + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 32u8, // "abcd".ptr + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, // "abcd".len + 97u8, 98u8, 99u8, 100u8 // "abcd" + ] + ); } #[test] diff --git a/forc-plugins/forc-client/src/op/run/mod.rs b/forc-plugins/forc-client/src/op/run/mod.rs index ea17dd723a7..c4c3a61b796 100644 --- a/forc-plugins/forc-client/src/op/run/mod.rs +++ b/forc-plugins/forc-client/src/op/run/mod.rs @@ -13,7 +13,9 @@ use forc_pkg::{self as pkg, fuel_core_not_running, PackageManifestFile}; use forc_tracing::println_warning; use forc_util::tx_utils::format_log_receipts; use fuel_core_client::client::FuelClient; -use fuel_tx::{ContractId, Transaction, TransactionBuilder}; +use fuel_tx::{ + field::ScriptData, ConsensusParameters, ContractId, Transaction, TransactionBuilder, +}; use pkg::BuiltPackage; use std::time::Duration; use std::{path::PathBuf, str::FromStr}; @@ -72,16 +74,7 @@ pub async fn run_pkg( let client = FuelClient::new(node_url.clone())?; let script_data = match (&command.data, &command.args) { - (None, Some(args)) => { - let minify_json_abi = true; - let package_json_abi = compiled - .json_abi_string(minify_json_abi)? - .ok_or_else(|| anyhow::anyhow!("Missing json abi string"))?; - let main_arg_handler = ScriptCallHandler::from_json_abi_str(&package_json_abi)?; - let args = args.iter().map(|arg| arg.as_str()).collect::>(); - let unresolved_bytes = main_arg_handler.encode_arguments(args.as_slice())?; - unresolved_bytes.resolve(0) - } + (None, Some(args)) => encode_script_data(compiled, args)?, (Some(_), Some(_)) => { bail!("Both --args and --data provided, must choose one.") } @@ -135,6 +128,32 @@ pub async fn run_pkg( } } +/// See https://specs.fuel.network/master/fuel-vm/index.html#vm-initialization +pub fn script_offset(parameters: &ConsensusParameters, script: &fuel_tx::Script) -> usize { + let tx_offset = fuel_tx::Bytes32::LEN // Tx ID + + fuels_core::constants::WORD_SIZE // Tx size + + parameters.max_inputs as usize * (fuel_tx::AssetId::LEN + fuels_core::constants::WORD_SIZE); // Asset ID/Balance coin input pairs + + tx_offset + script.script_data_offset() +} + +pub fn encode_script_data( + compiled: &BuiltPackage, + args: &[String], +) -> Result, anyhow::Error> { + let minify_json_abi = true; + let package_json_abi = compiled + .json_abi_string(minify_json_abi)? + .ok_or_else(|| anyhow::anyhow!("Missing json abi string"))?; + + let main_arg_handler = ScriptCallHandler::from_json_abi_str(&package_json_abi)?; + + let args = args.iter().map(|arg| arg.as_str()).collect::>(); + let unresolved_bytes = main_arg_handler.encode_arguments(args.as_slice())?; + + Ok(unresolved_bytes.resolve(0)) +} + async fn try_send_tx( node_url: &str, tx: &Transaction, diff --git a/sway-core/src/ir_generation/compile.rs b/sway-core/src/ir_generation/compile.rs index c67b8a22de8..50e2b06c932 100644 --- a/sway-core/src/ir_generation/compile.rs +++ b/sway-core/src/ir_generation/compile.rs @@ -31,7 +31,6 @@ pub(super) fn compile_script( messages_types_map: &HashMap, test_fns: &[(ty::TyFunctionDecl, DeclRefFunction)], ) -> Result> { - println!("1"); let module = Module::new(context, Kind::Script); let mut md_mgr = MetadataManager::default(); diff --git a/sway-lib-core/src/ops.sw b/sway-lib-core/src/ops.sw index 9b5689dc81b..e15414172c8 100644 --- a/sway-lib-core/src/ops.sw +++ b/sway-lib-core/src/ops.sw @@ -1299,8 +1299,8 @@ impl Eq for str { } else { let self_ptr = self.as_ptr(); let other_ptr = other.as_ptr(); - asm(r1: self_ptr, r2: other_ptr, r3, r4) { - addi r3 zero i32; + let l = self.len(); + asm(r1: self_ptr, r2: other_ptr, r3: l, r4) { meq r4 r1 r2 r3; r4: bool } diff --git a/sway-lib-core/src/str.sw b/sway-lib-core/src/str.sw index 6d965cf6cf7..cc5acd5d45c 100644 --- a/sway-lib-core/src/str.sw +++ b/sway-lib-core/src/str.sw @@ -13,4 +13,3 @@ impl str { len } } - diff --git a/test/src/e2e_vm_tests/harness.rs b/test/src/e2e_vm_tests/harness.rs index 8e5345fcfda..6ec8bb33b89 100644 --- a/test/src/e2e_vm_tests/harness.rs +++ b/test/src/e2e_vm_tests/harness.rs @@ -137,14 +137,16 @@ pub(crate) enum VMExecutionResult { pub(crate) fn runs_in_vm( script: BuiltPackage, script_data: Option>, + verbose: bool, ) -> Result { match script.descriptor.target { BuildTarget::Fuel => { let storage = MemoryStorage::default(); + let script_data = script_data.unwrap_or_default(); + let rng = &mut StdRng::seed_from_u64(2322u64); let maturity = 1.into(); - let script_data = script_data.unwrap_or_default(); let block_height = (u32::MAX >> 1).into(); let params = ConsensusParameters { // The default max length is 1MB which isn't enough for the bigger tests. @@ -152,26 +154,41 @@ pub(crate) fn runs_in_vm( ..ConsensusParameters::DEFAULT }; - let tx = TransactionBuilder::script(script.bytecode.bytes, script_data) - .with_params(params) - .add_unsigned_coin_input( - rng.gen(), - rng.gen(), - 1, - Default::default(), - rng.gen(), - 0u32.into(), - ) - .gas_limit(fuel_tx::ConsensusParameters::DEFAULT.max_gas_per_tx) - .maturity(maturity) - .finalize_checked(block_height, &GasCosts::default()); + let tx: fuel_vm::checked_transaction::Checked