From cefbd5edf99646d1be9a2e6c0f372842f144021a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Ver=C5=A1i=C4=87?= Date: Sat, 2 Nov 2024 21:26:45 +0100 Subject: [PATCH] perf: directly provide payload to wasm triggers and smart contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marin Veršić --- crates/iroha/src/secrecy.rs | 2 +- crates/iroha/tests/events/data.rs | 2 +- crates/iroha_config/tests/fixtures.rs | 2 +- .../src/smartcontracts/isi/world.rs | 4 +- crates/iroha_core/src/smartcontracts/wasm.rs | 227 ++++-------------- crates/iroha_crypto/src/hash.rs | 2 +- crates/iroha_executor/src/lib.rs | 50 ++-- .../iroha_executor_derive/src/entrypoint.rs | 8 +- crates/iroha_p2p/src/peer.rs | 8 +- crates/iroha_smart_contract/src/lib.rs | 31 +-- .../src/entrypoint.rs | 4 +- crates/iroha_smart_contract_utils/src/dbg.rs | 8 +- crates/iroha_smart_contract_utils/src/lib.rs | 1 + crates/iroha_smart_contract_utils/src/log.rs | 4 +- crates/iroha_telemetry_derive/src/lib.rs | 3 +- crates/iroha_trigger/src/lib.rs | 36 ++- crates/iroha_trigger_derive/src/entrypoint.rs | 4 +- 17 files changed, 136 insertions(+), 260 deletions(-) diff --git a/crates/iroha/src/secrecy.rs b/crates/iroha/src/secrecy.rs index 19b4db79dcc..cdba906f476 100644 --- a/crates/iroha/src/secrecy.rs +++ b/crates/iroha/src/secrecy.rs @@ -12,7 +12,7 @@ impl SecretString { } } -const REDACTED: &'static str = "[REDACTED]"; +const REDACTED: &str = "[REDACTED]"; impl Serialize for SecretString { fn serialize(&self, serializer: S) -> Result { diff --git a/crates/iroha/tests/events/data.rs b/crates/iroha/tests/events/data.rs index cce8763dc57..debc2c85d95 100644 --- a/crates/iroha/tests/events/data.rs +++ b/crates/iroha/tests/events/data.rs @@ -119,7 +119,7 @@ async fn wasm_execution_should_produce_events() -> Result<()> { {wasm_template} ;; Function which starts the smartcontract execution - (func (export "{main_fn_name}") (param) + (func (export "{main_fn_name}") (param i32) {isi_calls})) "#, main_fn_name = "_iroha_smart_contract_main", diff --git a/crates/iroha_config/tests/fixtures.rs b/crates/iroha_config/tests/fixtures.rs index c6ea25042ca..6ccb67eef4b 100644 --- a/crates/iroha_config/tests/fixtures.rs +++ b/crates/iroha_config/tests/fixtures.rs @@ -215,7 +215,7 @@ fn self_is_presented_in_trusted_peers() { .value() .clone() .into_non_empty_vec() - .contains(&config.common.peer.id())); + .contains(config.common.peer.id())); } #[test] diff --git a/crates/iroha_core/src/smartcontracts/isi/world.rs b/crates/iroha_core/src/smartcontracts/isi/world.rs index 69f6a216c5a..7e2d18c2508 100644 --- a/crates/iroha_core/src/smartcontracts/isi/world.rs +++ b/crates/iroha_core/src/smartcontracts/isi/world.rs @@ -513,8 +513,8 @@ pub mod query { Ok(state_ro .world() .peers() - .cloned() - .filter(move |peer| filter.applies(peer))) + .filter(move |peer| filter.applies(peer)) + .cloned()) } } diff --git a/crates/iroha_core/src/smartcontracts/wasm.rs b/crates/iroha_core/src/smartcontracts/wasm.rs index 899409b330b..b04278363fa 100644 --- a/crates/iroha_core/src/smartcontracts/wasm.rs +++ b/crates/iroha_core/src/smartcontracts/wasm.rs @@ -47,8 +47,6 @@ const WASM_MODULE: &str = "iroha"; mod export { pub const EXECUTE_ISI: &str = "execute_instruction"; pub const EXECUTE_QUERY: &str = "execute_query"; - pub const GET_SMART_CONTRACT_CONTEXT: &str = "get_smart_contract_context"; - pub const GET_TRIGGER_CONTEXT: &str = "get_trigger_context"; pub const SET_DATA_MODEL: &str = "set_data_model"; pub const DBG: &str = "dbg"; @@ -770,11 +768,11 @@ where let instance = self.instantiate_module(module, &mut store)?; let validate_fn = Self::get_typed_func(&instance, &mut store, validate_fn_name)?; - let payload = Self::get_validate_payload(&instance, &mut store); + let context = Self::get_validate_context(&instance, &mut store); // NOTE: This function takes ownership of the pointer let offset = validate_fn - .call(&mut store, payload) + .call(&mut store, context) .map_err(ExportFnCallError::from)?; let memory = @@ -796,19 +794,19 @@ where Ok(validation_res) } - fn get_validate_payload( + fn get_validate_context( instance: &Instance, store: &mut Store>>, ) -> WasmUsize { let state = store.data(); - let payload = payloads::Validate { + let context = payloads::Validate { context: payloads::ExecutorContext { authority: state.authority.clone(), curr_block: state.specific_state.curr_block, }, target: state.specific_state.to_validate.clone(), }; - Runtime::encode_payload(instance, store, payload) + Self::encode_payload(instance, store, context) } } @@ -943,10 +941,11 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime = Self::get_typed_func(&smart_contract, &mut store, import::SMART_CONTRACT_MAIN)?; + let context = Self::get_smart_contract_context(&smart_contract, &mut store); // NOTE: This function takes ownership of the pointer main_fn - .call(&mut store, ()) + .call(&mut store, context) .map_err(ExportFnCallError::from)?; let mut state = store.into_data(); let executed_queries = state.take_executed_queries(); @@ -955,12 +954,16 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime payloads::SmartContractContext { - payloads::SmartContractContext { + fn get_smart_contract_context( + instance: &Instance, + store: &mut Store>, + ) -> WasmUsize { + let state = store.data(); + let payload = payloads::SmartContractContext { authority: state.authority.clone(), curr_block: state.state.0.curr_block, - } + }; + Runtime::encode_payload(instance, store, payload) } } @@ -1018,10 +1021,11 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime = Self::get_typed_func(&instance, &mut store, import::TRIGGER_MAIN)?; + let context = Self::get_trigger_context(&instance, &mut store); // NOTE: This function takes ownership of the pointer main_fn - .call(&mut store, ()) + .call(&mut store, context) .map_err(ExportFnCallError::from)?; let mut state = store.into_data(); @@ -1031,14 +1035,18 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime payloads::TriggerContext { - payloads::TriggerContext { + fn get_trigger_context( + instance: &Instance, + store: &mut Store>, + ) -> WasmUsize { + let state = store.data(); + let payload = payloads::TriggerContext { id: state.specific_state.id.clone(), authority: state.authority.clone(), curr_block: state.state.0.curr_block, event: state.specific_state.triggering_event.clone(), - } + }; + Runtime::encode_payload(instance, store, payload) } } @@ -1301,24 +1309,24 @@ impl<'wrld, 'block, 'state> Runtime = Self::get_typed_func(&instance, &mut store, import::EXECUTOR_MIGRATE)?; - let payload = Self::get_migrate_payload(&instance, &mut store); + let context = Self::get_migrate_context(&instance, &mut store); migrate_fn - .call(&mut store, payload) + .call(&mut store, context) .map_err(ExportFnCallError::from)?; Ok(()) } - fn get_migrate_payload( + fn get_migrate_context( instance: &Instance, store: &mut Store, Migrate>>, ) -> WasmUsize { - let payload = payloads::ExecutorContext { + let context = payloads::ExecutorContext { authority: store.data().authority.clone(), curr_block: store.data().state.0.curr_block, }; - Self::encode_payload(instance, store, payload) + Self::encode_payload(instance, store, context) } } @@ -1435,7 +1443,6 @@ impl<'wrld, 'block, 'state> RuntimeBuilder, export::EXECUTE_ISI => |caller: ::wasmtime::Caller>, offset, len| Runtime::execute_instruction(caller, offset, len), export::EXECUTE_QUERY => |caller: ::wasmtime::Caller>, offset, len| Runtime::execute_query(caller, offset, len), - export::GET_SMART_CONTRACT_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_smart_contract_context(caller), )?; Ok(linker) }) @@ -1455,7 +1462,6 @@ impl<'wrld, 'block, 'state> RuntimeBuilder create_imports!(linker, state::Trigger<'wrld, 'block, 'state>, export::EXECUTE_ISI => |caller: ::wasmtime::Caller>, offset, len| Runtime::execute_instruction(caller, offset, len), export::EXECUTE_QUERY => |caller: ::wasmtime::Caller>, offset, len| Runtime::execute_query(caller, offset, len), - export::GET_TRIGGER_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_trigger_context(caller), )?; Ok(linker) }) @@ -1658,7 +1664,7 @@ mod tests { {memory_and_alloc} ;; Function which starts the smartcontract execution - (func (export "{main_fn_name}") (param) + (func (export "{main_fn_name}") (param i32) (call $exec_fn (i32.const 0) (i32.const {isi_len})) ;; No use of return values @@ -1704,7 +1710,7 @@ mod tests { {memory_and_alloc} ;; Function which starts the smartcontract execution - (func (export "{main_fn_name}") (param) + (func (export "{main_fn_name}") (param i32) (call $exec_fn (i32.const 0) (i32.const {isi_len})) ;; No use of return values @@ -1750,14 +1756,21 @@ mod tests { (module ;; Import host function to execute (import "iroha" "{execute_fn_name}" - (func $exec_fn (param i32 i32))) + (func $exec_fn (param i32 i32) (result i32)) {memory_and_alloc} ;; Function which starts the smartcontract execution - (func (export "{main_fn_name}") (param i32 i32) + (func (export "{main_fn_name}") (param i32) (call $exec_fn (i32.const 0) (i32.const {isi1_end})) - (call $exec_fn (i32.const {isi1_end}) (i32.const {isi2_end})))) + + ;; No use of return value + drop + + (call $exec_fn (i32.const {isi1_end}) (i32.const {isi2_end})) + + ;; No use of return value + drop)) "#, main_fn_name = import::SMART_CONTRACT_MAIN, execute_fn_name = export::EXECUTE_ISI, @@ -1787,160 +1800,4 @@ mod tests { Ok(()) } - - #[test] - async fn instructions_not_allowed() -> Result<(), Error> { - let (authority, _authority_keypair) = gen_account_in("wonderland"); - let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::start_test(); - let state = State::new(world_with_test_account(&authority), kura, query_handle); - - let isi_hex = { - let (new_authority, _new_authority_keypair) = gen_account_in("wonderland"); - let register_isi = Register::account(Account::new(new_authority)); - encode_hex(InstructionBox::from(register_isi)) - }; - - let wat = format!( - r#" - (module - ;; Import host function to execute - (import "iroha" "{execute_fn_name}" - (func $exec_fn (param i32 i32)) - ) - - {memory_and_alloc} - - ;; Function which starts the smartcontract execution - (func (export "{main_fn_name}") (param i32 i32) - (call $exec_fn (i32.const 0) (i32.const {isi_len})) - ) - ) - "#, - main_fn_name = import::SMART_CONTRACT_MAIN, - execute_fn_name = export::EXECUTE_ISI, - memory_and_alloc = memory_and_alloc(&isi_hex), - isi_len = isi_hex.len() / 3, - ); - - let mut runtime = RuntimeBuilder::::new().build()?; - let block_header = ValidBlock::new_dummy(&KeyPair::random().into_parts().1) - .as_ref() - .header(); - let mut state_block = state.block(block_header); - let mut state_transaction = state_block.transaction(); - let res = runtime.validate(&mut state_transaction, authority, wat, nonzero!(1_u64)); - state_transaction.apply(); - state_block.commit(); - - if let Error::ExportFnCall(ExportFnCallError::HostExecution(report)) = - res.expect_err("Execution should fail") - { - assert!(report - .to_string() - .starts_with("Transaction rejected due to insufficient authorisation")); - } - - Ok(()) - } - - #[test] - async fn queries_not_allowed() -> Result<(), Error> { - let (authority, _authority_keypair) = gen_account_in("wonderland"); - let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::start_test(); - let state = State::new(world_with_test_account(&authority), kura, query_handle); - let query_hex = encode_hex(QueryRequest::Singular( - SingularQueryBox::FindExecutorDataModel(FindExecutorDataModel), - )); - - let wat = format!( - r#" - (module - ;; Import host function to execute - (import "iroha" "{execute_fn_name}" - (func $exec_fn (param i32 i32) (result i32))) - - {memory_and_alloc} - - ;; Function which starts the smartcontract execution - (func (export "{main_fn_name}") (param i32 i32) - (call $exec_fn (i32.const 0) (i32.const {isi_len})) - - ;; No use of return value - drop)) - "#, - main_fn_name = import::SMART_CONTRACT_MAIN, - execute_fn_name = export::EXECUTE_QUERY, - memory_and_alloc = memory_and_alloc(&query_hex), - isi_len = query_hex.len() / 3, - ); - - let mut runtime = RuntimeBuilder::::new().build()?; - let block_header = ValidBlock::new_dummy(&KeyPair::random().into_parts().1) - .as_ref() - .header(); - let mut state_block = state.block(block_header); - let mut state_transaction = state_block.transaction(); - let res = runtime.validate(&mut state_transaction, authority, wat, nonzero!(1_u64)); - state_transaction.apply(); - state_block.commit(); - - if let Error::ExportFnCall(ExportFnCallError::HostExecution(report)) = - res.expect_err("Execution should fail") - { - assert!(report.to_string().starts_with("All operations are denied")); - } - - Ok(()) - } - - #[test] - async fn trigger_related_func_is_not_linked_for_smart_contract() -> Result<(), Error> { - let (authority, _authority_keypair) = gen_account_in("wonderland"); - let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::start_test(); - let state = State::new(world_with_test_account(&authority), kura, query_handle); - - let wat = format!( - r#" - (module - ;; Import host function to execute - (import "iroha" "{get_trigger_payload_fn_name}" - (func $exec_fn (param) (result i32))) - - {memory_and_alloc} - - ;; Function which starts the smartcontract execution - (func (export "{main_fn_name}") (param) - (call $exec_fn) - - ;; No use of return values - drop)) - "#, - main_fn_name = import::SMART_CONTRACT_MAIN, - get_trigger_payload_fn_name = export::GET_TRIGGER_CONTEXT, - // this test doesn't use the memory - memory_and_alloc = memory_and_alloc(""), - ); - - let mut runtime = RuntimeBuilder::::new().build()?; - let block_header = ValidBlock::new_dummy(&KeyPair::random().into_parts().1) - .as_ref() - .header(); - let mut state_block = state.block(block_header); - let mut state_transaction = state_block.transaction(); - let err = runtime - .execute(&mut state_transaction, authority, wat) - .expect_err("Execution should fail"); - state_transaction.apply(); - state_block.commit(); - - assert!(matches!( - err, - Error::Instantiation(InstantiationError::Linker(_)) - )); - - Ok(()) - } } diff --git a/crates/iroha_crypto/src/hash.rs b/crates/iroha_crypto/src/hash.rs index 2c390b68e99..cb446a175e2 100644 --- a/crates/iroha_crypto/src/hash.rs +++ b/crates/iroha_crypto/src/hash.rs @@ -278,7 +278,7 @@ impl FromStr for HashOf { type Err = ParseError; fn from_str(s: &str) -> Result { - Ok(s.parse::().map(Self::from_untyped_unchecked)?) + s.parse::().map(Self::from_untyped_unchecked) } } diff --git a/crates/iroha_executor/src/lib.rs b/crates/iroha_executor/src/lib.rs index 098d64b4760..a6146e50b82 100644 --- a/crates/iroha_executor/src/lib.rs +++ b/crates/iroha_executor/src/lib.rs @@ -38,36 +38,57 @@ pub mod utils { use super::*; /// Get context for `validate_transaction()` entrypoint. + /// + /// # Safety + /// + /// It's safe to call this function as long as it's safe to construct, from the given + /// pointer, byte array of prefix length and `Box<[u8]>` containing the encoded object + #[doc(hidden)] #[cfg(not(test))] - pub fn decode_execute_transaction_context( + pub unsafe fn __decode_execute_transaction_context( context: *const u8, ) -> payloads::Validate { - // Safety: ownership of the provided context is transferred into `_decode_from_raw` - - unsafe { decode_with_length_prefix_from_raw(context) } + decode_with_length_prefix_from_raw(context) } /// Get context for `validate_instruction()` entrypoint. + /// + /// # Safety + /// + /// It's safe to call this function as long as it's safe to construct, from the given + /// pointer, byte array of prefix length and `Box<[u8]>` containing the encoded object + #[doc(hidden)] #[cfg(not(test))] - pub fn decode_execute_instruction_context( + pub unsafe fn __decode_execute_instruction_context( context: *const u8, ) -> payloads::Validate { - // Safety: ownership of the provided context is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(context) } + decode_with_length_prefix_from_raw(context) } /// Get context for `validate_query()` entrypoint. + /// + /// # Safety + /// + /// It's safe to call this function as long as it's safe to construct, from the given + /// pointer, byte array of prefix length and `Box<[u8]>` containing the encoded object + #[doc(hidden)] #[cfg(not(test))] - pub fn decode_validate_query_context(context: *const u8) -> payloads::Validate { - // Safety: ownership of the provided context is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(context) } + pub unsafe fn __decode_validate_query_context( + context: *const u8, + ) -> payloads::Validate { + decode_with_length_prefix_from_raw(context) } /// Get context for `migrate()` entrypoint. + /// + /// # Safety + /// + /// It's safe to call this function as long as it's safe to construct, from the given + /// pointer, byte array of prefix length and `Box<[u8]>` containing the encoded object + #[doc(hidden)] #[cfg(not(test))] - pub fn decode_migrate_context(context: *const u8) -> payloads::ExecutorContext { - // Safety: ownership of the provided context is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(context) } + pub unsafe fn __decode_migrate_context(context: *const u8) -> payloads::ExecutorContext { + decode_with_length_prefix_from_raw(context) } } @@ -236,8 +257,7 @@ impl DataModelBuilder { let account_permissions = host .query(FindPermissionsByAccountId::new(account.id().clone())) .execute() - .unwrap() - .into_iter(); + .unwrap(); for permission in account_permissions.map(|permission| permission.unwrap()) { if !self.permissions.contains(permission.name()) { diff --git a/crates/iroha_executor_derive/src/entrypoint.rs b/crates/iroha_executor_derive/src/entrypoint.rs index 5f75d2f789e..77674da33ea 100644 --- a/crates/iroha_executor_derive/src/entrypoint.rs +++ b/crates/iroha_executor_derive/src/entrypoint.rs @@ -13,9 +13,9 @@ mod export { } mod import { - pub const DECODE_EXECUTE_TRANSACTION_CONTEXT: &str = "decode_execute_transaction_context"; - pub const DECODE_EXECUTE_INSTRUCTION_CONTEXT: &str = "decode_execute_instruction_context"; - pub const DECODE_VALIDATE_QUERY_CONTEXT: &str = "decode_validate_query_context"; + pub const DECODE_EXECUTE_TRANSACTION_CONTEXT: &str = "__decode_execute_transaction_context"; + pub const DECODE_EXECUTE_INSTRUCTION_CONTEXT: &str = "__decode_execute_instruction_context"; + pub const DECODE_VALIDATE_QUERY_CONTEXT: &str = "__decode_validate_query_context"; } /// [`executor_entrypoint`](crate::executor_entrypoint()) macro implementation @@ -140,7 +140,7 @@ pub fn impl_migrate_entrypoint(fn_item: syn::ItemFn) -> TokenStream { #[doc(hidden)] unsafe extern "C" fn #migrate_fn_name(context: *const u8) { let host = ::iroha_executor::smart_contract::Iroha; - let context = ::iroha_executor::utils::decode_migrate_context(context); + let context = ::iroha_executor::utils::__decode_migrate_context(context); #fn_name(host, context); } diff --git a/crates/iroha_p2p/src/peer.rs b/crates/iroha_p2p/src/peer.rs index 6e6b787bdd9..8740b510322 100644 --- a/crates/iroha_p2p/src/peer.rs +++ b/crates/iroha_p2p/src/peer.rs @@ -197,7 +197,7 @@ mod run { ping_period=?ping_interval.period(), "The connection has been idle, pinging to check if it's alive" ); - if let Err(error) = message_sender.prepare_message(Message::::Ping) { + if let Err(error) = message_sender.prepare_message(&Message::::Ping) { iroha_logger::error!(%error, "Failed to encrypt message."); break; } @@ -219,7 +219,7 @@ mod run { if post_receiver_len > 100 { iroha_logger::warn!(size=post_receiver_len, "Peer post messages are pilling up"); } - if let Err(error) = message_sender.prepare_message(Message::Data(msg)) { + if let Err(error) = message_sender.prepare_message(&Message::Data(msg)) { iroha_logger::error!(%error, "Failed to encrypt message."); break; } @@ -241,7 +241,7 @@ mod run { match msg { Message::Ping => { iroha_logger::trace!("Received peer ping"); - if let Err(error) = message_sender.prepare_message(Message::::Pong) { + if let Err(error) = message_sender.prepare_message(&Message::::Pong) { iroha_logger::error!(%error, "Failed to encrypt message."); break; } @@ -406,7 +406,7 @@ mod run { /// /// # Errors /// - If encryption fail. - fn prepare_message(&mut self, msg: T) -> Result<(), Error> { + fn prepare_message(&mut self, msg: &T) -> Result<(), Error> { // Start with fresh buffer self.buffer.clear(); msg.encode_to(&mut self.buffer); diff --git a/crates/iroha_smart_contract/src/lib.rs b/crates/iroha_smart_contract/src/lib.rs index cf3de235de3..d9754948ad9 100644 --- a/crates/iroha_smart_contract/src/lib.rs +++ b/crates/iroha_smart_contract/src/lib.rs @@ -4,7 +4,9 @@ extern crate alloc; -use alloc::{boxed::Box, format}; +use alloc::boxed::Box; +#[cfg(feature = "debug")] +use alloc::format; use core::fmt::Debug; use data_model::{ @@ -29,6 +31,20 @@ pub mod utils { //! Crate with utilities pub use iroha_smart_contract_utils::register_getrandom_err_callback; + + /// Get context for smart contract `main()` entrypoint. + /// + /// # Safety + /// + /// It's safe to call this function as long as it's safe to construct, from the given + /// pointer, byte array of prefix length and `Box<[u8]>` containing the encoded object + #[doc(hidden)] + #[cfg(not(test))] + pub unsafe fn __decode_smart_contract_context( + context: *const u8, + ) -> crate::data_model::smart_contract::payloads::SmartContractContext { + iroha_smart_contract_utils::decode_with_length_prefix_from_raw(context) + } } pub mod log { @@ -200,13 +216,6 @@ unsafe extern "C" fn _iroha_smart_contract_dealloc(offset: *mut u8, len: usize) let _box = Box::from_raw(core::slice::from_raw_parts_mut(offset, len)); } -/// Get context for smart contract `main()` entrypoint. -#[cfg(not(test))] -pub fn get_smart_contract_context() -> data_model::smart_contract::payloads::SmartContractContext { - // Safety: ownership of the returned result is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(host::get_smart_contract_context()) } -} - #[cfg(not(test))] mod host { #[link(wasm_import_module = "iroha")] @@ -228,12 +237,6 @@ mod host { /// This function doesn't take ownership of the provided allocation /// but it does transfer ownership of the result to the caller pub(super) fn execute_instruction(ptr: *const u8, len: usize) -> *const u8; - - /// Get context for smart contract `main()` entrypoint. - /// # Warning - /// - /// This function transfers ownership of the result to the caller - pub(super) fn get_smart_contract_context() -> *const u8; } } diff --git a/crates/iroha_smart_contract_derive/src/entrypoint.rs b/crates/iroha_smart_contract_derive/src/entrypoint.rs index 76b75279f97..812f298f0e7 100644 --- a/crates/iroha_smart_contract_derive/src/entrypoint.rs +++ b/crates/iroha_smart_contract_derive/src/entrypoint.rs @@ -36,9 +36,9 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream /// Smart contract entrypoint #[no_mangle] #[doc(hidden)] - unsafe extern "C" fn #main_fn_name() { + unsafe extern "C" fn #main_fn_name(context: *const u8) { let host = ::iroha_smart_contract::Iroha; - let context = ::iroha_smart_contract::get_smart_contract_context(); + let context = ::iroha_smart_contract::utils::__decode_smart_contract_context(context); #fn_name(host, context) } diff --git a/crates/iroha_smart_contract_utils/src/dbg.rs b/crates/iroha_smart_contract_utils/src/dbg.rs index 7418efa47ba..8ae2c40f27e 100644 --- a/crates/iroha_smart_contract_utils/src/dbg.rs +++ b/crates/iroha_smart_contract_utils/src/dbg.rs @@ -7,6 +7,7 @@ use core::fmt::Debug; use cfg_if::cfg_if; #[cfg(target_family = "wasm")] +#[cfg(feature = "debug")] #[cfg(not(test))] mod host { #[link(wasm_import_module = "iroha")] @@ -29,7 +30,8 @@ mod host { /// /// When running outside of wasm, always prints the output to stderr #[doc(hidden)] -pub fn dbg(obj: &T) { +#[allow(unused_variables)] +pub fn __dbg(obj: &T) { cfg_if! { if #[cfg(not(target_family = "wasm"))] { // when not on wasm - just print it @@ -56,7 +58,7 @@ pub fn dbg(obj: &T) { macro_rules! dbg { () => { #[cfg(feature = "debug")] - $crate::debug::dbg(concat!("[{}:{}:{}]", core::file!(), core::line!(), core::column!())); + $crate::__dbg(concat!("[{}:{}:{}]", core::file!(), core::line!(), core::column!())); }; ($val:expr $(,)?) => {{ #[cfg(feature = "debug")] @@ -64,7 +66,7 @@ macro_rules! dbg { tmp => { let location = concat!("[{}:{}:{}]", core::file!(), core::line!(), core::column!()); let location = format!("{location} {} = {tmp:#?}", stringify!($val)); - $crate::dbg(&location); + $crate::__dbg(&location); } } }}; diff --git a/crates/iroha_smart_contract_utils/src/lib.rs b/crates/iroha_smart_contract_utils/src/lib.rs index d5b266a7e4c..9e907a15d6c 100644 --- a/crates/iroha_smart_contract_utils/src/lib.rs +++ b/crates/iroha_smart_contract_utils/src/lib.rs @@ -125,6 +125,7 @@ pub unsafe fn encode_and_execute( /// Encode the given `val` as a vector of bytes with the size of the object at the beginning // // TODO: Write a separate crate for codec/protocol between Iroha and smartcontract +#[doc(hidden)] pub fn encode_with_length_prefix(val: &T) -> Box<[u8]> { let len_size_bytes = core::mem::size_of::(); diff --git a/crates/iroha_smart_contract_utils/src/log.rs b/crates/iroha_smart_contract_utils/src/log.rs index 4acf81f975b..a31d482c607 100644 --- a/crates/iroha_smart_contract_utils/src/log.rs +++ b/crates/iroha_smart_contract_utils/src/log.rs @@ -24,7 +24,7 @@ mod host { /// When running as a wasm smart contract, prints to the host logging system with the corresponding level. /// When running outside of wasm, prints the output along with its level to stderr #[doc(hidden)] -pub fn log(log_level: Level, obj: &T) { +pub fn __log(log_level: Level, obj: &T) { cfg_if! { if #[cfg(not(target_family = "wasm"))] { // when not on wasm - just print it @@ -51,7 +51,7 @@ pub fn log(log_level: Level, obj: &T) { #[macro_export] macro_rules! event { ($log_level:path, $msg:expr) => { - $crate::log::log($log_level, $msg) + $crate::log::__log($log_level, $msg) }; } diff --git a/crates/iroha_telemetry_derive/src/lib.rs b/crates/iroha_telemetry_derive/src/lib.rs index b2c63305ac2..792ab136a01 100644 --- a/crates/iroha_telemetry_derive/src/lib.rs +++ b/crates/iroha_telemetry_derive/src/lib.rs @@ -145,9 +145,10 @@ impl ToTokens for MetricSpec { /// # Examples /// /// ```rust -/// use iroha_core::state::{StateTransaction, World}; /// use iroha_telemetry_derive::metrics; /// +/// # struct StateTransaction; +/// /// #[metrics(+"test_query", "another_test_query_without_timing")] /// fn execute(state: &StateTransaction) -> Result<(), ()> { /// Ok(()) diff --git a/crates/iroha_trigger/src/lib.rs b/crates/iroha_trigger/src/lib.rs index a6916b9afce..aee20081848 100644 --- a/crates/iroha_trigger/src/lib.rs +++ b/crates/iroha_trigger/src/lib.rs @@ -12,6 +12,20 @@ pub mod utils { //! Crate with utilities pub use iroha_smart_contract_utils::register_getrandom_err_callback; + + /// Get context for smart contract `main()` entrypoint. + /// + /// # Safety + /// + /// It's safe to call this function as long as it's safe to construct, from the given + /// pointer, byte array of prefix length and `Box<[u8]>` containing the encoded object + #[doc(hidden)] + #[cfg(not(test))] + pub unsafe fn __decode_trigger_context( + context: *const u8, + ) -> crate::data_model::smart_contract::payloads::TriggerContext { + iroha_smart_contract_utils::decode_with_length_prefix_from_raw(context) + } } pub mod log { @@ -19,28 +33,6 @@ pub mod log { pub use iroha_smart_contract_utils::{debug, error, event, info, trace, warn}; } -#[cfg(not(test))] -mod host { - #[link(wasm_import_module = "iroha")] - extern "C" { - /// Get context for trigger `main()` entrypoint. - /// - /// # Warning - /// - /// This function does transfer ownership of the result to the caller - pub(super) fn get_trigger_context() -> *const u8; - } -} - -/// Get context for trigger `main()` entrypoint. -#[cfg(not(test))] -pub fn get_trigger_context() -> data_model::smart_contract::payloads::TriggerContext { - // Safety: ownership of the returned result is transferred into `_decode_from_raw` - unsafe { - iroha_smart_contract_utils::decode_with_length_prefix_from_raw(host::get_trigger_context()) - } -} - pub mod prelude { //! Common imports used by triggers pub use crate::{ diff --git a/crates/iroha_trigger_derive/src/entrypoint.rs b/crates/iroha_trigger_derive/src/entrypoint.rs index a7bad47e1f1..8b4a56985ef 100644 --- a/crates/iroha_trigger_derive/src/entrypoint.rs +++ b/crates/iroha_trigger_derive/src/entrypoint.rs @@ -36,9 +36,9 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream /// Smart contract entrypoint #[no_mangle] #[doc(hidden)] - unsafe extern "C" fn #main_fn_name() { + unsafe extern "C" fn #main_fn_name(context: *const u8) { let host = ::iroha_trigger::Iroha; - let context = ::iroha_trigger::get_trigger_context(); + let context = ::iroha_trigger::utils::__decode_trigger_context(context); #fn_name(host, context) }