diff --git a/Cargo.lock b/Cargo.lock index bd767492c67..f273833c325 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2931,6 +2931,7 @@ dependencies = [ "iroha_test_samples", "iroha_torii_const", "iroha_version", + "mint_rose_trigger_data_model", "nonzero_ext", "parity-scale-codec", "rand", @@ -3493,7 +3494,6 @@ version = "2.0.0-rc.1.0" dependencies = [ "derive_more", "displaydoc", - "getrandom", "iroha_data_model", "iroha_macro", "iroha_smart_contract_derive", @@ -3519,6 +3519,7 @@ name = "iroha_smart_contract_utils" version = "2.0.0-rc.1.0" dependencies = [ "cfg-if", + "getrandom", "iroha_data_model", "parity-scale-codec", "webassembly-test", @@ -4166,6 +4167,15 @@ dependencies = [ "adler2", ] +[[package]] +name = "mint_rose_trigger_data_model" +version = "2.0.0-rc.1.0" +dependencies = [ + "iroha_data_model", + "serde", + "serde_json", +] + [[package]] name = "mio" version = "0.8.11" diff --git a/Cargo.toml b/Cargo.toml index 9dc7f75c3e1..f0e087d5966 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,6 @@ iroha_macro_utils = { version = "=2.0.0-rc.1.0", path = "crates/iroha_macro_util iroha_telemetry = { version = "=2.0.0-rc.1.0", path = "crates/iroha_telemetry" } iroha_p2p = { version = "=2.0.0-rc.1.0", path = "crates/iroha_p2p" } iroha_primitives = { version = "=2.0.0-rc.1.0", path = "crates/iroha_primitives", default-features = false } -iroha_data_model = { version = "=2.0.0-rc.1.0", path = "crates/iroha_data_model", default-features = false } iroha_config = { version = "=2.0.0-rc.1.0", path = "crates/iroha_config" } iroha_config_base = { version = "=2.0.0-rc.1.0", path = "crates/iroha_config_base" } iroha_schema_gen = { version = "=2.0.0-rc.1.0", path = "crates/iroha_schema_gen" } @@ -42,11 +41,11 @@ iroha_wasm_builder = { version = "=2.0.0-rc.1.0", path = "crates/iroha_wasm_buil iroha_smart_contract = { version = "=2.0.0-rc.1.0", path = "crates/iroha_smart_contract" } iroha_smart_contract_utils = { version = "=2.0.0-rc.1.0", path = "crates/iroha_smart_contract_utils" } - iroha_executor = { version = "=2.0.0-rc.1.0", path = "crates/iroha_executor" } -iroha_executor_data_model = { version = "=2.0.0-rc.1.0", path = "crates/iroha_executor_data_model" } -iroha_multisig_data_model = { version = "=2.0.0-rc.1.0", path = "crates/iroha_multisig_data_model" } +iroha_data_model = { version = "=2.0.0-rc.1.0", path = "crates/iroha_data_model", default-features = false } +iroha_multisig_data_model = { version = "=2.0.0-rc.1.0", path = "data_model/libs/iroha_multisig_data_model" } +iroha_executor_data_model = { version = "=2.0.0-rc.1.0", path = "crates/iroha_executor_data_model" } iroha_test_network = { version = "=2.0.0-rc.1.0", path = "crates/iroha_test_network" } iroha_test_samples = { version = "=2.0.0-rc.1.0", path = "crates/iroha_test_samples" } @@ -199,7 +198,9 @@ clippy.wildcard_dependencies = "deny" [workspace] resolver = "2" members = [ - "crates/*" + "crates/*", + "data_model/libs/*", + "data_model/samples/*" ] [profile.deploy] diff --git a/crates/iroha/Cargo.toml b/crates/iroha/Cargo.toml index 8b029bb9ff2..6990b70d363 100644 --- a/crates/iroha/Cargo.toml +++ b/crates/iroha/Cargo.toml @@ -51,12 +51,13 @@ tls-rustls-webpki-roots = [ iroha_config = { workspace = true } iroha_config_base = { workspace = true } iroha_crypto = { workspace = true } -iroha_data_model = { workspace = true, features = ["http"] } iroha_primitives = { workspace = true } iroha_logger = { workspace = true } iroha_telemetry = { workspace = true } iroha_torii_const = { workspace = true } iroha_version = { workspace = true } + +iroha_data_model = { workspace = true, features = ["http"] } iroha_multisig_data_model = { workspace = true } attohttpc = { version = "0.28.0", default-features = false } @@ -84,8 +85,10 @@ nonzero_ext = { workspace = true } iroha_genesis = { workspace = true } iroha_test_samples = { workspace = true } iroha_test_network = { workspace = true } + +mint_rose_trigger_data_model = { path = "../../data_model/samples/mint_rose_trigger_data_model" } +executor_custom_data_model = { path = "../../data_model/samples/executor_custom_data_model" } iroha_executor_data_model = { workspace = true } -executor_custom_data_model = { version = "=2.0.0-rc.1.0", path = "../../wasm/samples/executor_custom_data_model" } tokio = { workspace = true, features = ["rt-multi-thread"] } reqwest = { version = "0.12.7", features = ["json"] } 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/tests/triggers/by_call_trigger.rs b/crates/iroha/tests/triggers/by_call_trigger.rs index 81dd9adcfee..f16fa25c380 100644 --- a/crates/iroha/tests/triggers/by_call_trigger.rs +++ b/crates/iroha/tests/triggers/by_call_trigger.rs @@ -1,6 +1,5 @@ use std::{sync::mpsc, thread, time::Duration}; -use executor_custom_data_model::mint_rose_args::MintRoseArgs; use eyre::{eyre, Result, WrapErr}; use iroha::{ crypto::KeyPair, @@ -13,6 +12,7 @@ use iroha::{ use iroha_executor_data_model::permission::trigger::CanRegisterTrigger; use iroha_test_network::*; use iroha_test_samples::{load_sample_wasm, ALICE_ID}; +use mint_rose_trigger_data_model::MintRoseArgs; use crate::triggers::get_asset_value; @@ -621,7 +621,7 @@ fn call_execute_trigger_with_args() -> Result<()> { let trigger = Trigger::new( trigger_id.clone(), Action::new( - load_sample_wasm("mint_rose_trigger_args"), + load_sample_wasm("mint_rose_trigger"), Repeats::Indefinitely, account_id.clone(), ExecuteTriggerEventFilter::new() 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 450621f5fdc..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"; @@ -688,8 +686,7 @@ impl Runtime { /// /// # Warning /// - /// This function doesn't take ownership of the provided - /// allocation + /// This function doesn't take ownership of the provided allocation /// /// # Errors /// @@ -697,7 +694,7 @@ impl Runtime { #[allow(clippy::needless_pass_by_value)] #[codec::wrap(state = "S")] fn dbg(msg: String) { - println!("{msg}"); + eprintln!("{msg}"); } } @@ -771,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 = @@ -797,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) } } @@ -944,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(); @@ -956,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) } } @@ -1019,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(); @@ -1032,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) } } @@ -1302,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) } } @@ -1436,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) }) @@ -1456,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) }) @@ -1659,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 @@ -1705,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 @@ -1751,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, @@ -1788,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/default.rs b/crates/iroha_executor/src/default.rs index d3a3fa20029..19fe09bb666 100644 --- a/crates/iroha_executor/src/default.rs +++ b/crates/iroha_executor/src/default.rs @@ -1222,7 +1222,7 @@ pub mod role { } fn find_account_roles(account_id: AccountId, host: &Iroha) -> impl Iterator { - use iroha_smart_contract::debug::DebugExpectExt as _; + use iroha_smart_contract::DebugExpectExt as _; host.query(FindRolesByAccountId::new(account_id)) .execute() @@ -1273,7 +1273,7 @@ pub mod role { } for permission in role.inner().permissions() { - iroha_smart_contract::debug!(&format!("Checking `{permission:?}`")); + iroha_smart_contract::log::debug!(&format!("Checking `{permission:?}`")); if let Ok(any_permission) = AnyPermission::try_from(permission) { if !executor.context().curr_block.is_genesis() { diff --git a/crates/iroha_executor/src/lib.rs b/crates/iroha_executor/src/lib.rs index a35f01f0ec2..a6146e50b82 100644 --- a/crates/iroha_executor/src/lib.rs +++ b/crates/iroha_executor/src/lib.rs @@ -10,56 +10,86 @@ use data_model::{executor::Result, ValidationFail}; #[cfg(not(test))] use data_model::{prelude::*, query::AnyQueryBox, smart_contract::payloads}; use iroha_executor_data_model::{parameter::Parameter, permission::Permission}; +pub use iroha_executor_derive::{entrypoint, migrate}; use iroha_schema::{Ident, MetaMap}; pub use iroha_smart_contract as smart_contract; -pub use iroha_smart_contract_utils::{debug, encode_with_length_prefix}; -#[cfg(not(test))] -use iroha_smart_contract_utils::{decode_with_length_prefix_from_raw, encode_and_execute}; -pub use smart_contract::{data_model, stub_getrandom, Iroha}; +pub use iroha_smart_contract_utils::{dbg, dbg_panic, DebugExpectExt, DebugUnwrapExt}; +pub use smart_contract::{data_model, Iroha}; pub mod default; pub mod permission; -pub mod utils { - //! Crate with utilities for implementing smart contract FFI - pub use iroha_smart_contract_utils::encode_with_length_prefix; -} - pub mod log { //! WASM logging utilities - pub use iroha_smart_contract_utils::{debug, error, event, info, log::*, trace, warn}; + pub use iroha_smart_contract_utils::{debug, error, event, info, trace, warn}; } -/// Get context for `validate_transaction()` entrypoint. -#[cfg(not(test))] -pub 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) } -} +#[doc(hidden)] +pub mod utils { + //! Crate with utilities -/// Get context for `validate_instruction()` entrypoint. -#[cfg(not(test))] -pub 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) } -} + #[cfg(not(test))] + use iroha_smart_contract_utils::decode_with_length_prefix_from_raw; + pub use iroha_smart_contract_utils::{ + encode_with_length_prefix, register_getrandom_err_callback, + }; -/// Get context for `validate_query()` entrypoint. -#[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) } -} + #[cfg(not(test))] + use super::*; -/// Get context for `migrate()` entrypoint. -#[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) } + /// 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 unsafe fn __decode_execute_transaction_context( + context: *const u8, + ) -> payloads::Validate { + 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 unsafe fn __decode_execute_instruction_context( + context: *const u8, + ) -> payloads::Validate { + 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 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 unsafe fn __decode_migrate_context(context: *const u8) -> payloads::ExecutorContext { + decode_with_length_prefix_from_raw(context) + } } /// Set new [`ExecutorDataModel`]. @@ -75,7 +105,7 @@ pub fn decode_migrate_context(context: *const u8) -> payloads::ExecutorContext { #[cfg(not(test))] pub fn set_data_model(data_model: &ExecutorDataModel) { // Safety: - ownership of the returned result is transferred into `_decode_from_raw` - unsafe { encode_and_execute(&data_model, host::set_data_model) } + unsafe { iroha_smart_contract_utils::encode_and_execute(&data_model, host::set_data_model) } } #[cfg(not(test))] @@ -227,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()) { @@ -277,14 +306,14 @@ pub mod prelude { pub use alloc::vec::Vec; - pub use iroha_executor_derive::{entrypoint, Entrypoints, Execute, Visit}; - pub use iroha_smart_contract::prelude::*; + pub use iroha_executor_derive::{Entrypoints, Execute, Visit}; - pub use super::{ + pub use crate::{ data_model::{ - executor::Result, smart_contract::payloads::ExecutorContext as Context, visit::Visit, - ValidationFail, + executor::Result, prelude::*, smart_contract::payloads::ExecutorContext as Context, + visit::Visit, }, - deny, execute, DataModelBuilder, Execute, + dbg, dbg_panic, deny, execute, DataModelBuilder, DebugExpectExt, DebugUnwrapExt, Execute, + Iroha, }; } diff --git a/crates/iroha_executor/src/permission.rs b/crates/iroha_executor/src/permission.rs index ed65e8185a0..f39cc199d71 100644 --- a/crates/iroha_executor/src/permission.rs +++ b/crates/iroha_executor/src/permission.rs @@ -8,8 +8,7 @@ use crate::{ prelude::Context, smart_contract::{ data_model::{executor::Result, permission::Permission as PermissionObject, prelude::*}, - debug::DebugExpectExt as _, - Iroha, + prelude::*, }, }; diff --git a/crates/iroha_executor_derive/src/default.rs b/crates/iroha_executor_derive/src/default.rs index c5def5c00b6..ca9e0abc80a 100644 --- a/crates/iroha_executor_derive/src/default.rs +++ b/crates/iroha_executor_derive/src/default.rs @@ -51,7 +51,7 @@ pub fn impl_derive_entrypoints(emitter: &mut Emitter, input: &syn::DeriveInput) let mut entrypoint_fns: Vec = vec![ parse_quote! { - #[::iroha_executor::prelude::entrypoint] + #[::iroha_executor::entrypoint] pub fn execute_transaction( transaction: ::iroha_executor::prelude::SignedTransaction, host: ::iroha_executor::prelude::Iroha, @@ -64,7 +64,7 @@ pub fn impl_derive_entrypoints(emitter: &mut Emitter, input: &syn::DeriveInput) } }, parse_quote! { - #[::iroha_executor::prelude::entrypoint] + #[::iroha_executor::entrypoint] pub fn execute_instruction( instruction: ::iroha_executor::prelude::InstructionBox, host: ::iroha_executor::prelude::Iroha, @@ -77,7 +77,7 @@ pub fn impl_derive_entrypoints(emitter: &mut Emitter, input: &syn::DeriveInput) } }, parse_quote! { - #[::iroha_executor::prelude::entrypoint] + #[::iroha_executor::entrypoint] pub fn validate_query( query: ::iroha_executor::data_model::query::AnyQueryBox, host: ::iroha_executor::prelude::Iroha, diff --git a/crates/iroha_executor_derive/src/entrypoint.rs b/crates/iroha_executor_derive/src/entrypoint.rs index 2527b8b20be..77674da33ea 100644 --- a/crates/iroha_executor_derive/src/entrypoint.rs +++ b/crates/iroha_executor_derive/src/entrypoint.rs @@ -13,40 +13,33 @@ 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 #[allow(clippy::needless_pass_by_value)] -pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream { +pub fn impl_validate_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream { macro_rules! match_entrypoints { (validate: { $($user_entrypoint_name:ident => $generated_entrypoint_name:ident ($decode_validation_context_fn_name:ident)),* $(,)? - } - other: { - $($other_user_entrypoint_name:ident => $branch:block),* $(,)? }) => { match &item.sig.ident { $(fn_name if fn_name == stringify!($user_entrypoint_name) => { - impl_validate_entrypoint( + impl_validate_entrypoint_priv( item, stringify!($user_entrypoint_name), export::$generated_entrypoint_name, import::$decode_validation_context_fn_name, ) })* - $(fn_name if fn_name == stringify!($other_user_entrypoint_name) => $branch),* _ => { emit!( emitter, "Executor entrypoint name must be one of: {:?}", - [ - $(stringify!($user_entrypoint_name),)* - $(stringify!($other_user_entrypoint_name),)* - ] + [$(stringify!($user_entrypoint_name),)*] ); return quote!(); }, @@ -60,13 +53,10 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream execute_instruction => EXECUTOR_EXECUTE_INSTRUCTION(DECODE_EXECUTE_INSTRUCTION_CONTEXT), validate_query => EXECUTOR_VALIDATE_QUERY(DECODE_VALIDATE_QUERY_CONTEXT), } - other: { - migrate => { impl_migrate_entrypoint(item) } - } } } -fn impl_validate_entrypoint( +fn impl_validate_entrypoint_priv( fn_item: syn::ItemFn, user_entrypoint_name: &'static str, generated_entrypoint_name: &'static str, @@ -103,9 +93,9 @@ fn impl_validate_entrypoint( #[no_mangle] #[doc(hidden)] unsafe extern "C" fn #generated_entrypoint_ident(context: *const u8) -> *const u8 { - let host = ::iroha_executor::smart_contract::Iroha; + let host = ::iroha_executor::Iroha; - let context = ::iroha_executor::#decode_validation_context_fn_ident(context); + let context = ::iroha_executor::utils::#decode_validation_context_fn_ident(context); let verdict = #fn_name(context.target, host, context.context); let bytes_box = ::core::mem::ManuallyDrop::new( @@ -124,7 +114,7 @@ fn impl_validate_entrypoint( } } -fn impl_migrate_entrypoint(fn_item: syn::ItemFn) -> TokenStream { +pub fn impl_migrate_entrypoint(fn_item: syn::ItemFn) -> TokenStream { let syn::ItemFn { attrs, vis, @@ -139,6 +129,8 @@ fn impl_migrate_entrypoint(fn_item: syn::ItemFn) -> TokenStream { ); quote! { + iroha_executor::utils::register_getrandom_err_callback!(); + /// Executor `migrate` entrypoint /// /// # Memory safety @@ -148,7 +140,7 @@ 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::decode_migrate_context(context); + let context = ::iroha_executor::utils::__decode_migrate_context(context); #fn_name(host, context); } diff --git a/crates/iroha_executor_derive/src/lib.rs b/crates/iroha_executor_derive/src/lib.rs index e89b95f2817..b5d401e05dc 100644 --- a/crates/iroha_executor_derive/src/lib.rs +++ b/crates/iroha_executor_derive/src/lib.rs @@ -16,10 +16,40 @@ mod entrypoint; /// ```ignore /// use iroha_executor::prelude::*; /// -/// #[entrypoint] +/// #[migrate] /// fn migrate(host: Iroha, context: Context) { /// todo!() /// } +/// ``` +#[manyhow] +#[proc_macro_attribute] +pub fn migrate(attr: TokenStream, item: TokenStream) -> TokenStream { + let mut emitter = Emitter::new(); + + if !attr.is_empty() { + emit!( + emitter, + "`#[migrate]` macro for Executor accepts no attributes" + ); + } + + let Some(item) = emitter.handle(syn::parse2(item)) else { + return emitter.finish_token_stream(); + }; + + let result = entrypoint::impl_migrate_entrypoint(item); + + emitter.finish_token_stream_with(result) +} + +/// Annotate the user-defined function that starts the execution of a executor. +/// +/// There are 4 acceptable forms of this macro usage. See examples. +/// +/// # Examples +/// +/// ```ignore +/// use iroha_executor::prelude::*; /// /// #[entrypoint] /// fn execute_transaction(transaction: SignedTransaction, host: Iroha, context: Context) -> Result { @@ -52,7 +82,7 @@ pub fn entrypoint(attr: TokenStream, item: TokenStream) -> TokenStream { return emitter.finish_token_stream(); }; - let result = entrypoint::impl_entrypoint(&mut emitter, item); + let result = entrypoint::impl_validate_entrypoint(&mut emitter, item); emitter.finish_token_stream_with(result) } 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/Cargo.toml b/crates/iroha_smart_contract/Cargo.toml index 7aaf2b04d6b..684bd81c806 100644 --- a/crates/iroha_smart_contract/Cargo.toml +++ b/crates/iroha_smart_contract/Cargo.toml @@ -26,11 +26,6 @@ derive_more.workspace = true displaydoc.workspace = true -getrandom = "0.2" - [dev-dependencies] webassembly-test = "0.1.0" -# Not used directly but required for compilation -getrandom = { version = "0.2", features = ["custom"] } - trybuild = { workspace = true } diff --git a/crates/iroha_smart_contract/src/lib.rs b/crates/iroha_smart_contract/src/lib.rs index 08131cde857..d9754948ad9 100644 --- a/crates/iroha_smart_contract/src/lib.rs +++ b/crates/iroha_smart_contract/src/lib.rs @@ -5,6 +5,8 @@ extern crate alloc; use alloc::boxed::Box; +#[cfg(feature = "debug")] +use alloc::format; use core::fmt::Debug; use data_model::{ @@ -20,13 +22,36 @@ use iroha_data_model::query::{ SingularQueryBox, SingularQueryOutputBox, }; pub use iroha_smart_contract_derive::main; -pub use iroha_smart_contract_utils::{debug, error, info, log, warn}; -use iroha_smart_contract_utils::{ - debug::{dbg_panic, DebugExpectExt as _}, - decode_with_length_prefix_from_raw, encode_and_execute, -}; +pub use iroha_smart_contract_utils::{dbg, dbg_panic, DebugExpectExt, DebugUnwrapExt}; +use iroha_smart_contract_utils::{decode_with_length_prefix_from_raw, encode_and_execute}; use parity_scale_codec::{Decode, Encode}; +#[doc(hidden)] +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 { + //! WASM logging utilities + pub use iroha_smart_contract_utils::{debug, error, event, info, trace, warn}; +} + /// An iterable query cursor for use in smart contracts. #[derive(Debug, Clone, Encode, Decode)] pub struct QueryCursor { @@ -130,7 +155,7 @@ impl QueryExecutor for Iroha { ) -> Result { let QueryResponse::Singular(output) = Self::execute_query(&QueryRequest::Singular(query))? else { - dbg_panic("BUG: iroha returned unexpected type in singular query"); + dbg_panic!("BUG: iroha returned unexpected type in singular query"); }; Ok(output) @@ -142,7 +167,7 @@ impl QueryExecutor for Iroha { ) -> Result<(QueryOutputBatchBox, u64, Option), Self::Error> { let QueryResponse::Iterable(output) = Self::execute_query(&QueryRequest::Start(query))? else { - dbg_panic("BUG: iroha returned unexpected type in iterable query"); + dbg_panic!("BUG: iroha returned unexpected type in iterable query"); }; let (batch, remaining_items, cursor) = output.into_parts(); @@ -160,7 +185,7 @@ impl QueryExecutor for Iroha { let QueryResponse::Iterable(output) = Self::execute_query(&QueryRequest::Continue(cursor.cursor))? else { - dbg_panic("BUG: iroha returned unexpected type in iterable query"); + dbg_panic!("BUG: iroha returned unexpected type in iterable query"); }; let (batch, remaining_items, cursor) = output.into_parts(); @@ -176,7 +201,7 @@ impl QueryExecutor for Iroha { #[no_mangle] extern "C" fn _iroha_smart_contract_alloc(len: usize) -> *const u8 { if len == 0 { - iroha_smart_contract_utils::debug::dbg_panic("Cannot allocate 0 bytes"); + dbg_panic!("Cannot allocate 0 bytes"); } let layout = core::alloc::Layout::array::(len).dbg_expect("Cannot allocate layout"); // Safety: safe because `layout` is guaranteed to have non-zero size @@ -191,47 +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)); } -/// Stub for [`getrandom::getrandom()`] for Iroha smart contracts. -/// Prints a log message with [`error!`] and panics. -/// -/// Required in order to crates like `iroha_crypto` to compile. Should never be called. -/// -/// # Panics -/// -/// Always Panics with [`unimplemented!()`]; -/// -/// # Errors -/// -/// No errors, always panics. -/// -/// # Example -/// -/// ``` -/// // Cargo.toml -/// // getrandom = { version = "0.2", features = ["custom"] } -/// -/// getrandom::register_custom_getrandom!(iroha_smart_contract::stub_getrandom); -/// ``` -pub fn stub_getrandom(_dest: &mut [u8]) -> Result<(), getrandom::Error> { - const ERROR_MESSAGE: &str = - "`getrandom()` is not implemented. To provide your custom function \ - see https://docs.rs/getrandom/latest/getrandom/macro.register_custom_getrandom.html. \ - Be aware that your function must give the same result on different peers at the same execution round, - and keep in mind the consequences of purely implemented random function."; - - // we don't support logging in our current wasm test runner implementation - #[cfg(not(test))] - error!(ERROR_MESSAGE); - unimplemented!("{ERROR_MESSAGE}") -} - -/// 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")] @@ -253,23 +237,14 @@ 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; } } /// Most used items pub mod prelude { - pub use iroha_smart_contract_derive::main; - pub use iroha_smart_contract_utils::debug::DebugUnwrapExt; - pub use crate::{ data_model::{prelude::*, smart_contract::payloads::SmartContractContext as Context}, - Iroha, + dbg, dbg_panic, DebugExpectExt, DebugUnwrapExt, Iroha, }; } @@ -283,8 +258,6 @@ mod tests { use super::*; - getrandom::register_custom_getrandom!(super::stub_getrandom); - const QUERY_RESULT: Result = Ok(numeric!(1234)); const ISI_RESULT: Result<(), ValidationFail> = Ok(()); diff --git a/crates/iroha_smart_contract_derive/src/entrypoint.rs b/crates/iroha_smart_contract_derive/src/entrypoint.rs index 4184c4b2c3f..812f298f0e7 100644 --- a/crates/iroha_smart_contract_derive/src/entrypoint.rs +++ b/crates/iroha_smart_contract_derive/src/entrypoint.rs @@ -31,12 +31,14 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream let main_fn_name = syn::Ident::new(export::SMART_CONTRACT_MAIN, proc_macro2::Span::call_site()); quote! { + iroha_smart_contract::utils::register_getrandom_err_callback!(); + /// 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/Cargo.toml b/crates/iroha_smart_contract_utils/Cargo.toml index 349839eea2d..4daa75c1bea 100644 --- a/crates/iroha_smart_contract_utils/Cargo.toml +++ b/crates/iroha_smart_contract_utils/Cargo.toml @@ -14,10 +14,11 @@ workspace = true debug = [] [dependencies] -cfg-if.workspace = true iroha_data_model.workspace = true +getrandom = { version = "0.2", features = ["custom"] } parity-scale-codec.workspace = true +cfg-if.workspace = true [dev-dependencies] webassembly-test = "0.1.0" diff --git a/crates/iroha_smart_contract_utils/src/debug.rs b/crates/iroha_smart_contract_utils/src/dbg.rs similarity index 67% rename from crates/iroha_smart_contract_utils/src/debug.rs rename to crates/iroha_smart_contract_utils/src/dbg.rs index ef1780accd3..8ae2c40f27e 100644 --- a/crates/iroha_smart_contract_utils/src/debug.rs +++ b/crates/iroha_smart_contract_utils/src/dbg.rs @@ -7,9 +7,9 @@ use core::fmt::Debug; use cfg_if::cfg_if; #[cfg(target_family = "wasm")] +#[cfg(feature = "debug")] #[cfg(not(test))] mod host { - #[cfg(feature = "debug")] #[link(wasm_import_module = "iroha")] extern "C" { /// Prints string to the standard output by providing offset and length @@ -29,8 +29,9 @@ mod host { /// Does nothing unless `debug` feature is enabled. /// /// When running outside of wasm, always prints the output to stderr +#[doc(hidden)] #[allow(unused_variables)] -pub fn dbg(obj: &T) { +pub fn __dbg(obj: &T) { cfg_if! { if #[cfg(not(target_family = "wasm"))] { // when not on wasm - just print it @@ -44,20 +45,57 @@ pub fn dbg(obj: &T) { let s = format!("{obj:?}"); // Safety: `host_dbg` doesn't take ownership of it's pointer parameter - unsafe { crate::encode_and_execute(&s, host_dbg) } + unsafe { crate::encode_and_execute(&s, host_dbg); } } } } -/// Print `msg` and call [`panic!`]. +/// Print `obj` in debug representation. Does nothing unless `debug` feature is enabled. /// -/// Only call [`panic!`] if `debug` feature is not specified. +/// When running as a wasm smart contract, prints to host's stdout. +/// When running outside of wasm, always prints the output to stderr +#[macro_export] +macro_rules! dbg { + () => { + #[cfg(feature = "debug")] + $crate::__dbg(concat!("[{}:{}:{}]", core::file!(), core::line!(), core::column!())); + }; + ($val:expr $(,)?) => {{ + #[cfg(feature = "debug")] + match $val { + tmp => { + let location = concat!("[{}:{}:{}]", core::file!(), core::line!(), core::column!()); + let location = format!("{location} {} = {tmp:#?}", stringify!($val)); + $crate::__dbg(&location); + } + } + }}; + ($($val:expr),+ $(,)?) => { + ($($crate::dbg!($val)),+,) + }; +} + +/// Print `obj` in debug representation. Does nothing unless `debug` feature is enabled. /// -/// # Panics -/// Always -pub fn dbg_panic(msg: &str) -> ! { - dbg(msg); - panic!("{msg}") +/// When running as a wasm smart contract, prints to host's stderr. +/// When running outside of wasm, always prints the output to stderr +#[macro_export] +macro_rules! dbg_panic { + () => { + dbg!(); + panic(); + }; + ($val:expr $(,)?) => {{ + match $val { + tmp => { + dbg!(tmp); + panic!("{tmp:?}"); + } + } + }}; + ($($val:expr),+ $(,)?) => { + ($($crate::dbg!($val)),+,) + }; } /// Extension implemented for `Result` and `Option` to provide unwrapping with error message, @@ -84,10 +122,10 @@ impl DebugUnwrapExt for Result { match self { Ok(out) => out, Err(err) => { - dbg(&format!( - "WASM execution panicked at `called Result::dbg_unwrap()` on an `Err` value: {err:?}", - )); - panic!(""); + let msg = format!("WASM execution panicked at `called Result::dbg_unwrap()` on an `Err` value: {err:?}"); + + dbg!(&msg); + panic!("{msg}"); } } } @@ -107,8 +145,10 @@ impl DebugUnwrapExt for Option { match self { Some(out) => out, None => { - dbg("WASM execution panicked at 'called `Option::dbg_unwrap()` on a `None` value'"); - panic!(""); + let msg = "WASM execution panicked at 'called `Option::dbg_unwrap()` on a `None` value'"; + + dbg!(msg); + panic!("{msg}"); } } } @@ -140,8 +180,10 @@ impl DebugExpectExt for Result { match self { Ok(out) => out, Err(err) => { - dbg(&format!("WASM execution panicked at `{msg}: {err:?}`",)); - panic!(""); + let msg = format!("WASM execution panicked at `{msg}: {err:?}`"); + + dbg!(&msg); + panic!("{msg}"); } } } @@ -161,8 +203,10 @@ impl DebugExpectExt for Option { match self { Some(out) => out, None => { - dbg(&format!("WASM execution panicked at `{msg}`",)); - panic!(""); + let msg = format!("WASM execution panicked at `{msg}`",); + + dbg!(&msg); + panic!("{msg}"); } } } @@ -190,6 +234,6 @@ mod tests { #[webassembly_test] fn dbg_call() { - super::dbg(get_dbg_message()); + dbg!(get_dbg_message()); } } diff --git a/crates/iroha_smart_contract_utils/src/lib.rs b/crates/iroha_smart_contract_utils/src/lib.rs index 971177c09fe..9e907a15d6c 100644 --- a/crates/iroha_smart_contract_utils/src/lib.rs +++ b/crates/iroha_smart_contract_utils/src/lib.rs @@ -9,23 +9,45 @@ extern crate alloc; use alloc::{boxed::Box, format, vec::Vec}; use core::ops::RangeFrom; +pub use dbg::*; +pub use getrandom; pub use parity_scale_codec::{DecodeAll, Encode}; -pub mod debug; +mod dbg; pub mod log; -/// Decode the object from given pointer and length -/// -/// # Warning -/// -/// This method takes ownership of the given pointer -/// -/// # Safety -/// -/// It's safe to call this function as long as it's safe to construct, from the given -/// pointer, `Box<[u8]>` containing the encoded object -unsafe fn _decode_from_raw(ptr: *const u8, len: usize) -> T { - _decode_from_raw_in_range(ptr, len, 0..) +/// Registers a custom `getrandom` function that: +/// +/// 1. prints `error` message to the log +/// 2. panics with the same message +#[doc(hidden)] +#[macro_export] +macro_rules! register_getrandom_err_callback { + () => { + /// Prints a log message with [`error!`] and panics. + /// + /// # Panics + /// + /// Always Panics with [`unimplemented!()`]; + /// + /// # Errors + /// + /// No errors, always panics. + fn stub_getrandom(_dest: &mut [u8]) -> Result<(), $crate::getrandom::Error> { + const ERROR_MESSAGE: &str = + "`getrandom()` is not implemented. To provide your custom function \ + see https://docs.rs/getrandom/latest/getrandom/macro.register_custom_getrandom.html. \ + Be aware that your function must give the same result on different peers at the same execution round, + and keep in mind the consequences of purely implemented random function."; + + // we don't support logging in our current wasm test runner implementation + #[cfg(not(test))] + $crate::error!(ERROR_MESSAGE); + unimplemented!("{ERROR_MESSAGE}") + } + + $crate::getrandom::register_custom_getrandom!(stub_getrandom); + }; } /// Decode the object from given pointer and length in the given range @@ -66,6 +88,7 @@ unsafe fn _decode_from_raw_in_range( /// /// 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)] pub unsafe fn decode_with_length_prefix_from_raw(ptr: *const u8) -> T { let len_size_bytes = core::mem::size_of::(); @@ -87,6 +110,7 @@ pub unsafe fn decode_with_length_prefix_from_raw(ptr: *const u8) - /// # Safety /// /// The given function must not take ownership of the pointer argument +#[doc(hidden)] pub unsafe fn encode_and_execute( obj: &T, fun: unsafe extern "C" fn(*const u8, usize) -> O, @@ -101,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 d42255aee72..a31d482c607 100644 --- a/crates/iroha_smart_contract_utils/src/log.rs +++ b/crates/iroha_smart_contract_utils/src/log.rs @@ -21,11 +21,10 @@ mod host { /// Log `obj` with desired log level /// -/// When running as a wasm smart contract, -/// prints to the host logging system with the corresponding level. -/// +/// 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 -pub fn log(log_level: Level, obj: &T) { +#[doc(hidden)] +pub fn __log(log_level: Level, obj: &T) { cfg_if! { if #[cfg(not(target_family = "wasm"))] { // when not on wasm - just print it @@ -52,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 5abca0a5d79..f376f38f7f0 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 ffa36a49186..aee20081848 100644 --- a/crates/iroha_trigger/src/lib.rs +++ b/crates/iroha_trigger/src/lib.rs @@ -3,43 +3,40 @@ #![allow(unsafe_code)] pub use iroha_smart_contract as smart_contract; -pub use iroha_smart_contract_utils::debug; +pub use iroha_smart_contract_utils::{dbg, dbg_panic, DebugExpectExt, DebugUnwrapExt}; pub use iroha_trigger_derive::main; -pub use smart_contract::{data_model, stub_getrandom}; +pub use smart_contract::{data_model, Iroha}; -pub mod log { - //! WASM logging utilities - pub use iroha_smart_contract_utils::{debug, error, event, info, log::*, trace, warn}; -} +#[doc(hidden)] +pub mod utils { + //! Crate with utilities -#[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; + 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) } } -/// 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 log { + //! WASM logging utilities + pub use iroha_smart_contract_utils::{debug, error, event, info, trace, warn}; } pub mod prelude { //! Common imports used by triggers - - pub use iroha_smart_contract::prelude::*; - pub use iroha_smart_contract_utils::debug::DebugUnwrapExt; - pub use iroha_trigger_derive::main; - - pub use crate::data_model::smart_contract::payloads::TriggerContext as Context; + pub use crate::{ + data_model::{prelude::*, smart_contract::payloads::TriggerContext as Context}, + dbg, dbg_panic, DebugExpectExt, DebugUnwrapExt, Iroha, + }; } diff --git a/crates/iroha_trigger_derive/src/entrypoint.rs b/crates/iroha_trigger_derive/src/entrypoint.rs index 2337268151d..8b4a56985ef 100644 --- a/crates/iroha_trigger_derive/src/entrypoint.rs +++ b/crates/iroha_trigger_derive/src/entrypoint.rs @@ -31,12 +31,14 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream let main_fn_name = syn::Ident::new(export::TRIGGER_MAIN, proc_macro2::Span::call_site()); quote! { + iroha_trigger::utils::register_getrandom_err_callback!(); + /// Smart contract entrypoint #[no_mangle] #[doc(hidden)] - unsafe extern "C" fn #main_fn_name() { - let host = ::iroha_trigger::smart_contract::Iroha; - let context = ::iroha_trigger::get_trigger_context(); + unsafe extern "C" fn #main_fn_name(context: *const u8) { + let host = ::iroha_trigger::Iroha; + let context = ::iroha_trigger::utils::__decode_trigger_context(context); #fn_name(host, context) } diff --git a/crates/iroha_multisig_data_model/Cargo.toml b/data_model/libs/iroha_multisig_data_model/Cargo.toml similarity index 100% rename from crates/iroha_multisig_data_model/Cargo.toml rename to data_model/libs/iroha_multisig_data_model/Cargo.toml diff --git a/crates/iroha_multisig_data_model/src/lib.rs b/data_model/libs/iroha_multisig_data_model/src/lib.rs similarity index 100% rename from crates/iroha_multisig_data_model/src/lib.rs rename to data_model/libs/iroha_multisig_data_model/src/lib.rs diff --git a/wasm/samples/executor_custom_data_model/Cargo.toml b/data_model/samples/executor_custom_data_model/Cargo.toml similarity index 100% rename from wasm/samples/executor_custom_data_model/Cargo.toml rename to data_model/samples/executor_custom_data_model/Cargo.toml diff --git a/wasm/samples/executor_custom_data_model/src/complex_isi.rs b/data_model/samples/executor_custom_data_model/src/complex_isi.rs similarity index 99% rename from wasm/samples/executor_custom_data_model/src/complex_isi.rs rename to data_model/samples/executor_custom_data_model/src/complex_isi.rs index f293c256f39..afbb8571c48 100644 --- a/wasm/samples/executor_custom_data_model/src/complex_isi.rs +++ b/data_model/samples/executor_custom_data_model/src/complex_isi.rs @@ -1,4 +1,5 @@ //! Example of custom expression system. +//! //! Only few expressions are implemented to show proof-of-concept. //! See `wasm/samples/executor_custom_instructions_complex`. //! This is simplified version of expression system from Iroha v2.0.0-pre-rc.20 diff --git a/wasm/samples/executor_custom_data_model/src/lib.rs b/data_model/samples/executor_custom_data_model/src/lib.rs similarity index 88% rename from wasm/samples/executor_custom_data_model/src/lib.rs rename to data_model/samples/executor_custom_data_model/src/lib.rs index ea920f09c12..4db9f68bde5 100644 --- a/wasm/samples/executor_custom_data_model/src/lib.rs +++ b/data_model/samples/executor_custom_data_model/src/lib.rs @@ -5,7 +5,6 @@ extern crate alloc; pub mod complex_isi; -pub mod mint_rose_args; pub mod parameters; pub mod permissions; pub mod simple_isi; diff --git a/wasm/samples/executor_custom_data_model/src/parameters.rs b/data_model/samples/executor_custom_data_model/src/parameters.rs similarity index 100% rename from wasm/samples/executor_custom_data_model/src/parameters.rs rename to data_model/samples/executor_custom_data_model/src/parameters.rs diff --git a/wasm/samples/executor_custom_data_model/src/permissions.rs b/data_model/samples/executor_custom_data_model/src/permissions.rs similarity index 100% rename from wasm/samples/executor_custom_data_model/src/permissions.rs rename to data_model/samples/executor_custom_data_model/src/permissions.rs diff --git a/wasm/samples/executor_custom_data_model/src/simple_isi.rs b/data_model/samples/executor_custom_data_model/src/simple_isi.rs similarity index 100% rename from wasm/samples/executor_custom_data_model/src/simple_isi.rs rename to data_model/samples/executor_custom_data_model/src/simple_isi.rs diff --git a/data_model/samples/mint_rose_trigger_data_model/Cargo.toml b/data_model/samples/mint_rose_trigger_data_model/Cargo.toml new file mode 100644 index 00000000000..3ac89bf6b2a --- /dev/null +++ b/data_model/samples/mint_rose_trigger_data_model/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "mint_rose_trigger_data_model" + +edition.workspace = true +version.workspace = true +authors.workspace = true + +license.workspace = true + +[dependencies] +iroha_data_model.workspace = true + +serde.workspace = true +serde_json.workspace = true diff --git a/wasm/samples/executor_custom_data_model/src/mint_rose_args.rs b/data_model/samples/mint_rose_trigger_data_model/src/lib.rs similarity index 98% rename from wasm/samples/executor_custom_data_model/src/mint_rose_args.rs rename to data_model/samples/mint_rose_trigger_data_model/src/lib.rs index d9a8da2724f..67f08036d15 100644 --- a/wasm/samples/executor_custom_data_model/src/mint_rose_args.rs +++ b/data_model/samples/mint_rose_trigger_data_model/src/lib.rs @@ -1,4 +1,5 @@ //! Arguments to mint rose with args trigger +#![no_std] use iroha_data_model::prelude::Json; use serde::{Deserialize, Serialize}; diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 8a4be9978dc..ad54dafcb30 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -24,21 +24,21 @@ opt-level = "z" # Optimize for size vs speed with "s"/"z"(removes vectorizat codegen-units = 1 # Further reduces binary size but increases compilation time [workspace.dependencies] -executor_custom_data_model = { path = "samples/executor_custom_data_model" } - iroha_smart_contract = { version = "=2.0.0-rc.1.0", path = "../crates/iroha_smart_contract", features = ["debug"] } iroha_trigger = { version = "=2.0.0-rc.1.0", path = "../crates/iroha_trigger", features = ["debug"] } iroha_executor = { version = "=2.0.0-rc.1.0", path = "../crates/iroha_executor", features = ["debug"] } iroha_schema = { version = "=2.0.0-rc.1.0", path = "../crates/iroha_schema" } + iroha_data_model = { version = "=2.0.0-rc.1.0", path = "../crates/iroha_data_model", default-features = false } +iroha_multisig_data_model = { version = "=2.0.0-rc.1.0", path = "../data_model/libs/iroha_multisig_data_model" } iroha_executor_data_model = { version = "=2.0.0-rc.1.0", path = "../crates/iroha_executor_data_model" } -iroha_multisig_data_model = { version = "=2.0.0-rc.1.0", path = "../crates/iroha_multisig_data_model" } +mint_rose_trigger_data_model = { path = "../data_model/samples/mint_rose_trigger_data_model" } +executor_custom_data_model = { path = "../data_model/samples/executor_custom_data_model" } parity-scale-codec = { version = "3.2.1", default-features = false } anyhow = { version = "1.0.71", default-features = false } serde = { version = "1.0.151", default-features = false } serde_json = { version = "1.0.91", default-features = false } -getrandom = { version = "0.2", features = ["custom"] } nonzero_ext = { version = "0.3.0", default-features = false } dlmalloc = { version = "0.2.6", features = ["global"] } diff --git a/wasm/libs/default_executor/Cargo.toml b/wasm/libs/default_executor/Cargo.toml index 3efbe8de352..c62989cb24f 100644 --- a/wasm/libs/default_executor/Cargo.toml +++ b/wasm/libs/default_executor/Cargo.toml @@ -14,4 +14,3 @@ iroha_executor.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/libs/default_executor/src/lib.rs b/wasm/libs/default_executor/src/lib.rs index 7b1fb13d3e8..f8475b05d1b 100644 --- a/wasm/libs/default_executor/src/lib.rs +++ b/wasm/libs/default_executor/src/lib.rs @@ -6,15 +6,11 @@ extern crate panic_halt; use dlmalloc::GlobalDlmalloc; -use iroha_executor::{ - data_model::block::BlockHeader, debug::dbg_panic, prelude::*, DataModelBuilder, -}; +use iroha_executor::{data_model::block::BlockHeader, prelude::*}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); - /// Executor that replaces some of [`Execute`]'s methods with sensible defaults /// /// # Warning @@ -30,7 +26,7 @@ struct Executor { impl Executor { fn ensure_genesis(curr_block: BlockHeader) { if !curr_block.is_genesis() { - dbg_panic( + dbg_panic!( "Default Executor is intended to be used only in genesis. \ Write your own executor if you need to upgrade executor on existing chain.", ); @@ -47,7 +43,7 @@ impl Executor { /// /// If `migrate()` entrypoint fails then the whole `Upgrade` instruction /// will be denied and previous executor will stay unchanged. -#[entrypoint] +#[iroha_executor::migrate] fn migrate(host: Iroha, context: Context) { Executor::ensure_genesis(context.curr_block); DataModelBuilder::with_default_permissions().build_and_set(&host); diff --git a/wasm/libs/multisig_accounts/Cargo.toml b/wasm/libs/multisig_accounts/Cargo.toml index 476b201367d..d8162aa48c9 100644 --- a/wasm/libs/multisig_accounts/Cargo.toml +++ b/wasm/libs/multisig_accounts/Cargo.toml @@ -17,7 +17,6 @@ iroha_multisig_data_model.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true, default-features = false } diff --git a/wasm/libs/multisig_accounts/src/lib.rs b/wasm/libs/multisig_accounts/src/lib.rs index 7ad18e3a2f7..24401b85916 100644 --- a/wasm/libs/multisig_accounts/src/lib.rs +++ b/wasm/libs/multisig_accounts/src/lib.rs @@ -11,16 +11,11 @@ use alloc::format; use dlmalloc::GlobalDlmalloc; use iroha_executor_data_model::permission::trigger::CanExecuteTrigger; use iroha_multisig_data_model::MultisigAccountArgs; -use iroha_trigger::{ - debug::{dbg_panic, DebugExpectExt as _}, - prelude::*, -}; +use iroha_trigger::prelude::*; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); - // Binary containing common logic to each multisig account for handling multisig transactions const MULTISIG_TRANSACTIONS_WASM: &[u8] = core::include_bytes!(concat!( core::env!("CARGO_MANIFEST_DIR"), @@ -30,7 +25,7 @@ const MULTISIG_TRANSACTIONS_WASM: &[u8] = core::include_bytes!(concat!( #[iroha_trigger::main] fn main(host: Iroha, context: Context) { let EventBox::ExecuteTrigger(event) = context.event else { - dbg_panic("trigger misused: must be triggered only by a call"); + dbg_panic!("trigger misused: must be triggered only by a call"); }; let args: MultisigAccountArgs = event .args() diff --git a/wasm/libs/multisig_domains/Cargo.toml b/wasm/libs/multisig_domains/Cargo.toml index ae37e394289..efbab17b923 100644 --- a/wasm/libs/multisig_domains/Cargo.toml +++ b/wasm/libs/multisig_domains/Cargo.toml @@ -16,7 +16,6 @@ iroha_executor_data_model.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true, default-features = false } diff --git a/wasm/libs/multisig_domains/src/lib.rs b/wasm/libs/multisig_domains/src/lib.rs index c60e3a9e802..9b93d096d7f 100644 --- a/wasm/libs/multisig_domains/src/lib.rs +++ b/wasm/libs/multisig_domains/src/lib.rs @@ -9,16 +9,11 @@ extern crate panic_halt; use alloc::format; use dlmalloc::GlobalDlmalloc; -use iroha_trigger::{ - debug::{dbg_panic, DebugExpectExt as _}, - prelude::*, -}; +use iroha_trigger::prelude::*; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); - // Binary containing common logic to each domain for handling multisig accounts const MULTISIG_ACCOUNTS_WASM: &[u8] = core::include_bytes!(concat!( core::env!("CARGO_MANIFEST_DIR"), @@ -28,7 +23,7 @@ const MULTISIG_ACCOUNTS_WASM: &[u8] = core::include_bytes!(concat!( #[iroha_trigger::main] fn main(host: Iroha, context: Context) { let EventBox::Data(DataEvent::Domain(event)) = context.event else { - dbg_panic("trigger misused: must be triggered only by a domain event"); + dbg_panic!("trigger misused: must be triggered only by a domain event"); }; let (domain_id, domain_owner, owner_changed) = match event { DomainEvent::Created(domain) => (domain.id().clone(), domain.owned_by().clone(), false), @@ -37,8 +32,8 @@ fn main(host: Iroha, context: Context) { owner_changed.new_owner().clone(), true, ), - _ => dbg_panic( - "trigger misused: must be triggered only when domain created or owner changed", + _ => dbg_panic!( + "trigger misused: must be triggered only when domain created or owner changed" ), }; diff --git a/wasm/libs/multisig_transactions/Cargo.toml b/wasm/libs/multisig_transactions/Cargo.toml index ab208ce239b..dd676e46c23 100644 --- a/wasm/libs/multisig_transactions/Cargo.toml +++ b/wasm/libs/multisig_transactions/Cargo.toml @@ -16,7 +16,6 @@ iroha_multisig_data_model.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true, default-features = false } diff --git a/wasm/libs/multisig_transactions/src/lib.rs b/wasm/libs/multisig_transactions/src/lib.rs index f4ac819cce4..d70c7fc870c 100644 --- a/wasm/libs/multisig_transactions/src/lib.rs +++ b/wasm/libs/multisig_transactions/src/lib.rs @@ -14,20 +14,15 @@ use alloc::{ use dlmalloc::GlobalDlmalloc; use iroha_multisig_data_model::MultisigTransactionArgs; -use iroha_trigger::{ - debug::{dbg_panic, DebugExpectExt as _}, - prelude::*, -}; +use iroha_trigger::prelude::*; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); - #[iroha_trigger::main] fn main(host: Iroha, context: Context) { let EventBox::ExecuteTrigger(event) = context.event else { - dbg_panic("trigger misused: must be triggered only by a call"); + dbg_panic!("trigger misused: must be triggered only by a call"); }; let trigger_id = context.id; let args: MultisigTransactionArgs = event diff --git a/wasm/samples/create_nft_for_every_user_trigger/Cargo.toml b/wasm/samples/create_nft_for_every_user_trigger/Cargo.toml index 58f3433a861..44d2f3908c8 100644 --- a/wasm/samples/create_nft_for_every_user_trigger/Cargo.toml +++ b/wasm/samples/create_nft_for_every_user_trigger/Cargo.toml @@ -15,4 +15,3 @@ iroha_trigger.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/create_nft_for_every_user_trigger/src/lib.rs b/wasm/samples/create_nft_for_every_user_trigger/src/lib.rs index 355261b4c7f..c345eb4c389 100644 --- a/wasm/samples/create_nft_for_every_user_trigger/src/lib.rs +++ b/wasm/samples/create_nft_for_every_user_trigger/src/lib.rs @@ -13,12 +13,13 @@ use iroha_trigger::prelude::*; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); - #[iroha_trigger::main] -fn main(host: Iroha, _context: Context) { +fn main(host: Iroha, context: Context) { iroha_trigger::log::info!("Executing trigger"); - let accounts_cursor = host.query(FindAccounts).execute().dbg_unwrap(); + + if !matches!(context.event, EventBox::Time(_)) { + dbg_panic!("Only work as a by call trigger"); + }; let bad_domain_ids: [DomainId; 3] = [ "system".parse().dbg_unwrap(), @@ -26,7 +27,7 @@ fn main(host: Iroha, _context: Context) { "garden_of_live_flowers".parse().dbg_unwrap(), ]; - for account in accounts_cursor { + for account in host.query(FindAccounts).execute().dbg_unwrap() { let account = account.dbg_unwrap(); if bad_domain_ids.contains(account.id().domain()) { diff --git a/wasm/samples/executor_custom_instructions_complex/Cargo.toml b/wasm/samples/executor_custom_instructions_complex/Cargo.toml index fc67ea62b04..35f8e3701fa 100644 --- a/wasm/samples/executor_custom_instructions_complex/Cargo.toml +++ b/wasm/samples/executor_custom_instructions_complex/Cargo.toml @@ -20,4 +20,3 @@ serde.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/executor_custom_instructions_complex/src/lib.rs b/wasm/samples/executor_custom_instructions_complex/src/lib.rs index 549c7e3c162..f75bc03538c 100644 --- a/wasm/samples/executor_custom_instructions_complex/src/lib.rs +++ b/wasm/samples/executor_custom_instructions_complex/src/lib.rs @@ -22,8 +22,6 @@ use iroha_executor::{ #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); - #[derive(Visit, Execute, Entrypoints)] #[visit(custom(visit_custom))] struct Executor { @@ -95,7 +93,7 @@ impl executor_custom_data_model::complex_isi::Context for Context<'_> { } } -#[entrypoint] +#[iroha_executor::migrate] fn migrate(host: Iroha, _context: iroha_executor::prelude::Context) { DataModelBuilder::with_default_permissions() .add_instruction::() diff --git a/wasm/samples/executor_custom_instructions_simple/Cargo.toml b/wasm/samples/executor_custom_instructions_simple/Cargo.toml index 7dd316c7878..6cea868cb8e 100644 --- a/wasm/samples/executor_custom_instructions_simple/Cargo.toml +++ b/wasm/samples/executor_custom_instructions_simple/Cargo.toml @@ -20,4 +20,3 @@ serde.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/executor_custom_instructions_simple/src/lib.rs b/wasm/samples/executor_custom_instructions_simple/src/lib.rs index 88afdac4eed..9a5db335edc 100644 --- a/wasm/samples/executor_custom_instructions_simple/src/lib.rs +++ b/wasm/samples/executor_custom_instructions_simple/src/lib.rs @@ -10,13 +10,11 @@ extern crate panic_halt; use dlmalloc::GlobalDlmalloc; use executor_custom_data_model::simple_isi::{CustomInstructionBox, MintAssetForAllAccounts}; -use iroha_executor::{data_model::isi::CustomInstruction, debug::DebugExpectExt, prelude::*}; +use iroha_executor::{data_model::isi::CustomInstruction, prelude::*}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); - #[derive(Visit, Execute, Entrypoints)] #[visit(custom(visit_custom))] struct Executor { @@ -64,7 +62,7 @@ fn execute_mint_asset_for_all_accounts( Ok(()) } -#[entrypoint] +#[iroha_executor::migrate] fn migrate(host: Iroha, _context: Context) { DataModelBuilder::with_default_permissions() .add_instruction::() diff --git a/wasm/samples/executor_remove_permission/Cargo.toml b/wasm/samples/executor_remove_permission/Cargo.toml index 6c5a58306f4..458249ad4fc 100644 --- a/wasm/samples/executor_remove_permission/Cargo.toml +++ b/wasm/samples/executor_remove_permission/Cargo.toml @@ -22,4 +22,3 @@ serde.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/executor_remove_permission/src/lib.rs b/wasm/samples/executor_remove_permission/src/lib.rs index 06196c32428..ec9272ae786 100644 --- a/wasm/samples/executor_remove_permission/src/lib.rs +++ b/wasm/samples/executor_remove_permission/src/lib.rs @@ -13,8 +13,6 @@ use iroha_executor_data_model::permission::domain::CanUnregisterDomain; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); - #[derive(Visit, Execute, Entrypoints)] struct Executor { host: Iroha, @@ -22,7 +20,7 @@ struct Executor { verdict: Result, } -#[entrypoint] +#[iroha_executor::migrate] fn migrate(host: Iroha, _context: Context) { // Note that actually migration will reset token schema to default (minus `CanUnregisterDomain`) // So any added custom permission tokens will be also removed diff --git a/wasm/samples/executor_with_admin/Cargo.toml b/wasm/samples/executor_with_admin/Cargo.toml index 808cb9d5594..a86fcf97703 100644 --- a/wasm/samples/executor_with_admin/Cargo.toml +++ b/wasm/samples/executor_with_admin/Cargo.toml @@ -16,4 +16,3 @@ iroha_schema.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/executor_with_admin/src/lib.rs b/wasm/samples/executor_with_admin/src/lib.rs index c41c063d401..857a9a950ca 100644 --- a/wasm/samples/executor_with_admin/src/lib.rs +++ b/wasm/samples/executor_with_admin/src/lib.rs @@ -12,8 +12,6 @@ use iroha_executor::prelude::*; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); - #[derive(Visit, Execute, Entrypoints)] #[visit(custom(visit_instruction))] struct Executor { @@ -34,5 +32,5 @@ fn visit_instruction(executor: &mut Executor, isi: &InstructionBox) { iroha_executor::default::visit_instruction(executor, isi); } -#[entrypoint] +#[iroha_executor::migrate] fn migrate(_host: Iroha, _context: Context) {} diff --git a/wasm/samples/executor_with_custom_parameter/Cargo.toml b/wasm/samples/executor_with_custom_parameter/Cargo.toml index 4fc114974f1..92888a254f6 100644 --- a/wasm/samples/executor_with_custom_parameter/Cargo.toml +++ b/wasm/samples/executor_with_custom_parameter/Cargo.toml @@ -23,4 +23,3 @@ serde.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/executor_with_custom_parameter/src/lib.rs b/wasm/samples/executor_with_custom_parameter/src/lib.rs index 7edb4412553..4a343bfa4b9 100644 --- a/wasm/samples/executor_with_custom_parameter/src/lib.rs +++ b/wasm/samples/executor_with_custom_parameter/src/lib.rs @@ -15,8 +15,6 @@ use iroha_executor_data_model::parameter::Parameter; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); - #[derive(Visit, Execute, Entrypoints)] #[visit(custom(visit_register_domain))] struct Executor { @@ -43,7 +41,7 @@ fn visit_register_domain(executor: &mut Executor, isi: &Register) { execute!(executor, isi); } -#[entrypoint] +#[iroha_executor::migrate] fn migrate(host: Iroha, _context: Context) { DataModelBuilder::with_default_permissions() .add_parameter(DomainLimits::default()) diff --git a/wasm/samples/executor_with_custom_permission/Cargo.toml b/wasm/samples/executor_with_custom_permission/Cargo.toml index 32cf35963c6..5dc5651d128 100644 --- a/wasm/samples/executor_with_custom_permission/Cargo.toml +++ b/wasm/samples/executor_with_custom_permission/Cargo.toml @@ -23,4 +23,3 @@ serde.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/executor_with_custom_permission/src/lib.rs b/wasm/samples/executor_with_custom_permission/src/lib.rs index 5ae332a8094..a55a985610f 100644 --- a/wasm/samples/executor_with_custom_permission/src/lib.rs +++ b/wasm/samples/executor_with_custom_permission/src/lib.rs @@ -25,8 +25,6 @@ use iroha_executor_data_model::permission::domain::CanUnregisterDomain; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); - #[derive(Visit, Execute, Entrypoints)] #[visit(custom( visit_register_domain, @@ -164,7 +162,7 @@ pub fn visit_revoke_account_permission( iroha_executor::default::visit_revoke_account_permission(executor, isi) } -#[entrypoint] +#[iroha_executor::migrate] pub fn migrate(host: Iroha, _context: Context) { let accounts = Executor::get_all_accounts_with_can_unregister_domain_permission(&host).collect::>(); diff --git a/wasm/samples/executor_with_migration_fail/Cargo.toml b/wasm/samples/executor_with_migration_fail/Cargo.toml index b6326eed261..36ee081b0b6 100644 --- a/wasm/samples/executor_with_migration_fail/Cargo.toml +++ b/wasm/samples/executor_with_migration_fail/Cargo.toml @@ -16,4 +16,3 @@ anyhow.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/executor_with_migration_fail/src/lib.rs b/wasm/samples/executor_with_migration_fail/src/lib.rs index 1bab3082384..9ef1296a6e9 100644 --- a/wasm/samples/executor_with_migration_fail/src/lib.rs +++ b/wasm/samples/executor_with_migration_fail/src/lib.rs @@ -6,13 +6,11 @@ extern crate panic_halt; use dlmalloc::GlobalDlmalloc; -use iroha_executor::{debug::dbg_panic, prelude::*}; +use iroha_executor::prelude::*; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); - #[derive(Visit, Execute, Entrypoints)] struct Executor { host: Iroha, @@ -20,7 +18,7 @@ struct Executor { verdict: Result, } -#[entrypoint] +#[iroha_executor::migrate] fn migrate(host: Iroha, _context: Context) { // Performing side-effects to check in the test that it won't be applied after failure @@ -29,5 +27,5 @@ fn migrate(host: Iroha, _context: Context) { host.submit(&Register::domain(Domain::new(domain_id))) .unwrap(); - dbg_panic("This executor always fails to migrate"); + dbg_panic!("This executor always fails to migrate"); } diff --git a/wasm/samples/mint_rose_trigger/Cargo.toml b/wasm/samples/mint_rose_trigger/Cargo.toml index 2a8bc1163f0..2ceb93a8810 100644 --- a/wasm/samples/mint_rose_trigger/Cargo.toml +++ b/wasm/samples/mint_rose_trigger/Cargo.toml @@ -11,8 +11,8 @@ license.workspace = true crate-type = ['cdylib'] [dependencies] +mint_rose_trigger_data_model = { version = "=2.0.0-rc.1.0", path = "../../../data_model/samples/mint_rose_trigger_data_model" } iroha_trigger.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true diff --git a/wasm/samples/mint_rose_trigger/src/lib.rs b/wasm/samples/mint_rose_trigger/src/lib.rs index 3aab88a3c7f..ef1fe988d29 100644 --- a/wasm/samples/mint_rose_trigger/src/lib.rs +++ b/wasm/samples/mint_rose_trigger/src/lib.rs @@ -6,23 +6,34 @@ extern crate panic_halt; use dlmalloc::GlobalDlmalloc; -use iroha_trigger::{debug::DebugExpectExt as _, prelude::*}; +use iroha_trigger::prelude::*; +use mint_rose_trigger_data_model::MintRoseArgs; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); - /// Mint 1 rose for owner #[iroha_trigger::main] fn main(host: Iroha, context: Context) { - let rose_id = AssetId::new("rose#wonderland".parse().unwrap(), context.authority); - - let val: u32 = host - .query_single(FindTriggerMetadata::new(context.id, "VAL".parse().unwrap())) - .dbg_unwrap() - .try_into_any() - .dbg_unwrap(); + let EventBox::ExecuteTrigger(event) = context.event else { + dbg_panic!("Only work as a by call trigger"); + }; + + let val = event + .args() + .try_into_any::() + .map_or_else( + |_| { + host.query_single(FindTriggerMetadata::new(context.id, "VAL".parse().unwrap())) + .dbg_unwrap() + .try_into_any::() + }, + |args| Ok(args.val), + ) + .dbg_expect("Failed get mint value"); + + let rose_definition_id = "rose#wonderland".parse().unwrap(); + let rose_id = AssetId::new(rose_definition_id, context.authority); host.submit(&Mint::asset_numeric(val, rose_id)) .dbg_expect("Failed to mint rose"); diff --git a/wasm/samples/mint_rose_trigger_args/Cargo.toml b/wasm/samples/mint_rose_trigger_args/Cargo.toml deleted file mode 100644 index 9fe349eac28..00000000000 --- a/wasm/samples/mint_rose_trigger_args/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "mint_rose_args" - -edition.workspace = true -version.workspace = true -authors.workspace = true - -license.workspace = true - -[lib] -crate-type = ['cdylib'] - -[dependencies] -iroha_trigger.workspace = true -executor_custom_data_model.workspace = true - -panic-halt.workspace = true -dlmalloc.workspace = true -getrandom.workspace = true - -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true, default-features = false } diff --git a/wasm/samples/mint_rose_trigger_args/src/lib.rs b/wasm/samples/mint_rose_trigger_args/src/lib.rs deleted file mode 100644 index 37e57b57ba2..00000000000 --- a/wasm/samples/mint_rose_trigger_args/src/lib.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! trigger which mints rose for its owner based on input args. - -#![no_std] - -#[cfg(not(test))] -extern crate panic_halt; - -use dlmalloc::GlobalDlmalloc; -use executor_custom_data_model::mint_rose_args::MintRoseArgs; -use iroha_trigger::{ - debug::{dbg_panic, DebugExpectExt as _}, - prelude::*, -}; - -#[global_allocator] -static ALLOC: GlobalDlmalloc = GlobalDlmalloc; - -getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); - -/// Mint 1 rose for owner -#[iroha_trigger::main] -fn main(host: Iroha, context: Context) { - let EventBox::ExecuteTrigger(event) = context.event else { - dbg_panic("Only work as by call trigger"); - }; - - let args: MintRoseArgs = event - .args() - .try_into_any() - .dbg_expect("Failed to parse args"); - - let rose_definition_id = "rose#wonderland".parse().unwrap(); - let rose_id = AssetId::new(rose_definition_id, context.authority); - - host.submit(&Mint::asset_numeric(args.val, rose_id)) - .dbg_expect("Failed to mint rose"); -} diff --git a/wasm/samples/query_assets_and_save_cursor/Cargo.toml b/wasm/samples/query_assets_and_save_cursor/Cargo.toml index 41c9da685c8..61d3d1f8233 100644 --- a/wasm/samples/query_assets_and_save_cursor/Cargo.toml +++ b/wasm/samples/query_assets_and_save_cursor/Cargo.toml @@ -15,7 +15,6 @@ iroha_smart_contract.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true parity-scale-codec.workspace = true nonzero_ext.workspace = true serde_json = { version = "1.0.108", default-features = false } diff --git a/wasm/samples/query_assets_and_save_cursor/src/lib.rs b/wasm/samples/query_assets_and_save_cursor/src/lib.rs index 81ed71a94fe..e7261d9b9b4 100644 --- a/wasm/samples/query_assets_and_save_cursor/src/lib.rs +++ b/wasm/samples/query_assets_and_save_cursor/src/lib.rs @@ -13,7 +13,6 @@ use iroha_smart_contract::{ predicate::CompoundPredicate, QueryWithFilter, QueryWithParams, }, - debug::DebugExpectExt as _, prelude::*, }; use nonzero_ext::nonzero; @@ -22,8 +21,6 @@ use parity_scale_codec::{Decode, DecodeAll, Encode}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_smart_contract::stub_getrandom); - /// Execute [`FindAssets`] and save cursor to the owner's metadata. /// NOTE: DON'T TAKE THIS AS AN EXAMPLE, THIS IS ONLY FOR TESTING INTERNALS OF IROHA #[iroha_smart_contract::main] diff --git a/wasm/samples/smart_contract_can_filter_queries/Cargo.toml b/wasm/samples/smart_contract_can_filter_queries/Cargo.toml index 33a478ddfad..69c95d6a026 100644 --- a/wasm/samples/smart_contract_can_filter_queries/Cargo.toml +++ b/wasm/samples/smart_contract_can_filter_queries/Cargo.toml @@ -15,7 +15,6 @@ iroha_smart_contract.workspace = true panic-halt.workspace = true dlmalloc.workspace = true -getrandom.workspace = true parity-scale-codec.workspace = true nonzero_ext.workspace = true serde_json = { workspace = true, default-features = false } diff --git a/wasm/samples/smart_contract_can_filter_queries/src/lib.rs b/wasm/samples/smart_contract_can_filter_queries/src/lib.rs index 2501f27fac0..798f719629c 100644 --- a/wasm/samples/smart_contract_can_filter_queries/src/lib.rs +++ b/wasm/samples/smart_contract_can_filter_queries/src/lib.rs @@ -15,8 +15,6 @@ use iroha_smart_contract::{prelude::*, Iroha}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; -getrandom::register_custom_getrandom!(iroha_smart_contract::stub_getrandom); - /// Create two asset definitions in the looking_glass domain, query all asset definitions, filter them to only be in the looking_glass domain, check that the results are consistent #[iroha_smart_contract::main] fn main(host: Iroha, _context: Context) {