From 436e666fba4c28fff6924d93e0d64585d96ad08e Mon Sep 17 00:00:00 2001 From: Piotr Olszewski Date: Fri, 3 Nov 2023 17:06:49 +0100 Subject: [PATCH] feat: new API for get_module(_abi) RPC calls --- rpc/runtime-api/src/lib.rs | 7 +- rpc/src/lib.rs | 88 ++++++++++++------ src/lib.rs | 15 ++- tests/assets/move/Move.toml | 1 + .../move/build/move/bytecode_modules/Empty.mv | Bin 59 -> 98 bytes tests/assets/move/sources/EmptyBob.move | 4 + tests/modules.rs | 28 +----- 7 files changed, 82 insertions(+), 61 deletions(-) create mode 100644 tests/assets/move/sources/EmptyBob.move diff --git a/rpc/runtime-api/src/lib.rs b/rpc/runtime-api/src/lib.rs index fe37fcc..7fbf01f 100644 --- a/rpc/runtime-api/src/lib.rs +++ b/rpc/runtime-api/src/lib.rs @@ -1,6 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + use frame_support::{dispatch::Vec, weights::Weight}; +use alloc::string::String; // Here we declare the runtime API. It is implemented it the `impl` block in // runtime file (the `runtime/src/lib.rs` of the node) @@ -21,10 +24,10 @@ sp_api::decl_runtime_apis! { fn estimate_gas_execute(account: AccountId, bytecode: Vec, gas_limit: u64) -> u64; // Get module binary by its address - fn get_module(module_id: Vec) -> Result>, Vec>; + fn get_module(address: String, name: String) -> Result>, Vec>; // Get module ABI by its address - fn get_module_abi(module_id: Vec) -> Result>, Vec>; + fn get_module_abi(address: String, name: String) -> Result>, Vec>; // Get resource fn get_resource(account: AccountId, tag: Vec) -> Result>, Vec>; diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 56561f1..15ac1ba 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -54,11 +54,21 @@ pub trait MoveApi { /// Get module ABI using address #[method(name = "mvm_getModuleABI")] - fn get_module_abi(&self, module_id: Vec, at: Option) -> RpcResult>>; + fn get_module_abi( + &self, + address: &str, + name: &str, + at: Option, + ) -> RpcResult>>; /// Get module binary using address #[method(name = "mvm_getModule")] - fn get_module(&self, module_id: Vec, at: Option) -> RpcResult>>; + fn get_module( + &self, + address: &str, + name: &str, + at: Option, + ) -> RpcResult>>; } /// A struct that implements the `MoveApi`. @@ -106,8 +116,12 @@ where at: Option<::Hash>, ) -> RpcResult { let api = self.client.runtime_api(); - let res = - api.estimate_gas_publish(at.unwrap_or_else(|| self.client.info().best_hash), account, bytecode, gas_limit); + let res = api.estimate_gas_publish( + at.unwrap_or_else(|| self.client.info().best_hash), + account, + bytecode, + gas_limit, + ); res.map_err(runtime_error_into_rpc_err) } @@ -120,8 +134,12 @@ where at: Option<::Hash>, ) -> RpcResult { let api = self.client.runtime_api(); - let res = - api.estimate_gas_execute(at.unwrap_or_else(|| self.client.info().best_hash), account, bytecode, gas_limit); + let res = api.estimate_gas_execute( + at.unwrap_or_else(|| self.client.info().best_hash), + account, + bytecode, + gas_limit, + ); res.map_err(runtime_error_into_rpc_err) } @@ -133,7 +151,11 @@ where at: Option<::Hash>, ) -> RpcResult>> { let api = self.client.runtime_api(); - let res = api.get_resource(at.unwrap_or_else(|| self.client.info().best_hash), account, tag); + let res = api.get_resource( + at.unwrap_or_else(|| self.client.info().best_hash), + account, + tag, + ); // Currently, there is always correct value returned so it's safe to unwrap here. res.unwrap().map_err(runtime_error_into_rpc_err) @@ -141,11 +163,16 @@ where fn get_module_abi( &self, - module_id: Vec, + address: &str, + name: &str, at: Option<::Hash>, ) -> RpcResult>> { let api = self.client.runtime_api(); - let res = api.get_module_abi(at.unwrap_or_else(|| self.client.info().best_hash), module_id); + let res = api.get_module_abi( + at.unwrap_or_else(|| self.client.info().best_hash), + address.to_string(), + name.to_string(), + ); // Currently, there is always correct value returned so it's safe to unwrap here. res.unwrap().map_err(runtime_error_into_rpc_err) @@ -153,11 +180,16 @@ where fn get_module( &self, - module_id: Vec, + address: &str, + name: &str, at: Option<::Hash>, ) -> RpcResult>> { let api = self.client.runtime_api(); - let res = api.get_module(at.unwrap_or_else(|| self.client.info().best_hash), module_id); + let res = api.get_module( + at.unwrap_or_else(|| self.client.info().best_hash), + address.to_string(), + name.to_string(), + ); // Currently, there is always correct value returned so it's safe to unwrap here. res.unwrap().map_err(runtime_error_into_rpc_err) @@ -186,16 +218,14 @@ mod tests { let err_str_tst = "\"\\\"test\\\"\""; let res = runtime_error_into_rpc_err(err_str); match res { - JsonRpseeError::Call(err) => { - match err { - CallError::Custom(err) => { - assert_eq!(err.code(), RUNTIME_ERROR); - assert_eq!(err.message(), "Runtime error"); - assert_eq!(err.data().unwrap().get(), err_str_tst) - } - _ => panic!("Wrong error type"), + JsonRpseeError::Call(err) => match err { + CallError::Custom(err) => { + assert_eq!(err.code(), RUNTIME_ERROR); + assert_eq!(err.message(), "Runtime error"); + assert_eq!(err.data().unwrap().get(), err_str_tst) } - } + _ => panic!("Wrong error type"), + }, _ => panic!("Wrong error type"), } } @@ -206,17 +236,15 @@ mod tests { let err_str_tst = "\"\\\"\\\"\""; let res = runtime_error_into_rpc_err(err_str); match res { - JsonRpseeError::Call(err) => { - match err { - CallError::Custom(err) => { - assert_eq!(err.code(), RUNTIME_ERROR); - assert_eq!(err.message(), "Runtime error"); - assert_eq!(err.data().unwrap().get(), err_str_tst) - } - _ => panic!("Wrong error type"), + JsonRpseeError::Call(err) => match err { + CallError::Custom(err) => { + assert_eq!(err.code(), RUNTIME_ERROR); + assert_eq!(err.message(), "Runtime error"); + assert_eq!(err.data().unwrap().get(), err_str_tst) } - } + _ => panic!("Wrong error type"), + }, _ => panic!("Wrong error type"), } } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 2618363..0d493b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -177,17 +177,24 @@ pub mod pallet { }) } - pub fn get_module_abi(module_id: &[u8]) -> Result>, Vec> { + pub fn get_module_abi( + address: &T::AccountId, + name: &str, + ) -> Result>, Vec> { let vm = Self::move_vm()?; - vm.get_module_abi(module_id) + let address = address::to_move_address(&address); + + vm.get_module_abi(address, name) .map_err(|e| format!("error in get_module_abi: {:?}", e).into()) } - pub fn get_module(module_id: &[u8]) -> Result>, Vec> { + pub fn get_module(address: &T::AccountId, name: &str) -> Result>, Vec> { let vm = Self::move_vm()?; - vm.get_module(module_id) + let address = address::to_move_address(&address); + + vm.get_module(address, name) .map_err(|e| format!("error in get_module: {:?}", e).into()) } diff --git a/tests/assets/move/Move.toml b/tests/assets/move/Move.toml index 8d7dad4..f6aab93 100644 --- a/tests/assets/move/Move.toml +++ b/tests/assets/move/Move.toml @@ -8,3 +8,4 @@ MoveStdlib = { git = "https://github.com/move-language/move.git", subdir = "lang [addresses] std = "0x1" TestAccount = "0xCAFE" +Bob = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" diff --git a/tests/assets/move/build/move/bytecode_modules/Empty.mv b/tests/assets/move/build/move/bytecode_modules/Empty.mv index 889cb618a8875cb18d6137ae96c6d844e02f45c8..adc8ee243cfc9ce39f1e23e58ee8a302f7f16936 100644 GIT binary patch literal 98 zcmZ1|^O~EDfq{XQk%5VciG`g_jzdL(%Y_vv#0V61%`GUYOpHv73;;|153m3L literal 59 ocmZ1|^O~EDfq{XUk%5VwiH(Cpfq{Y5HMgLo5-5lVochNA0KQWN+W-In diff --git a/tests/assets/move/sources/EmptyBob.move b/tests/assets/move/sources/EmptyBob.move new file mode 100644 index 0000000..6f16717 --- /dev/null +++ b/tests/assets/move/sources/EmptyBob.move @@ -0,0 +1,4 @@ +module Bob::EmptyBob { + struct EmptyStruct { + } +} diff --git a/tests/modules.rs b/tests/modules.rs index bf24073..f339df5 100644 --- a/tests/modules.rs +++ b/tests/modules.rs @@ -2,11 +2,7 @@ mod mock; use frame_support::assert_ok; use mock::*; -use move_core_types::{ - account_address::AccountAddress, - identifier::Identifier, - language_storage::{ModuleId, StructTag}, -}; +use move_core_types::{identifier::Identifier, language_storage::StructTag}; use pallet_move::address; const EMPTY_ADDR: u64 = 0x000000000CAFE_u64.to_be(); @@ -21,10 +17,7 @@ fn get_module_correct() { assert_ok!(res); - let address = AccountAddress::from_hex_literal("0xCAFE").unwrap(); // Alternative: let address = address::to_move_address(&ACC_ADDR); - let module_id = ModuleId::new(address, Identifier::new("Empty").unwrap()); - - let res = MoveModule::get_module(&bcs::to_bytes(&module_id).unwrap()); + let res = MoveModule::get_module(&EMPTY_ADDR, "Empty"); assert_eq!(res, Ok(Some(module))); }); @@ -34,27 +27,12 @@ fn get_module_correct() { /// Test getting a module that does not exist. fn get_module_nonexistent() { new_test_ext().execute_with(|| { - let address = AccountAddress::from_hex_literal("0xCAFE").unwrap(); - let module_id = ModuleId::new(address, Identifier::new("Empty").unwrap()); - - let res = MoveModule::get_module(&bcs::to_bytes(&module_id).unwrap()); + let res = MoveModule::get_module(&EMPTY_ADDR, "Empty"); assert_eq!(res, Ok(None)); }); } -#[test] -/// Test getting a module providing incorrect (no module name after the address) module id. -fn get_module_invalid_input() { - new_test_ext().execute_with(|| { - let invalid_module_id = [0u8; 32]; - let errmsg = "error in get_module: unexpected end of input".as_bytes(); - let res = MoveModule::get_module(&invalid_module_id); - - assert_eq!(res, Err(errmsg.to_vec())); - }); -} - #[test] #[ignore = "failing - to be investigated"] /// Test getting resource from the module.