diff --git a/crates/iroha/benches/torii.rs b/crates/iroha/benches/torii.rs index a9e5ded3523..3b9e989d2b8 100644 --- a/crates/iroha/benches/torii.rs +++ b/crates/iroha/benches/torii.rs @@ -73,10 +73,10 @@ fn query_requests(criterion: &mut Criterion) { format!("http://{}", peer.api_address).parse().unwrap(), ); - let iroha = Client::new(client_config); + let client = Client::new(client_config); thread::sleep(std::time::Duration::from_millis(5000)); - let _ = iroha + let _ = client .submit_all::([ create_domain.into(), create_account.into(), @@ -85,7 +85,7 @@ fn query_requests(criterion: &mut Criterion) { ]) .expect("Failed to prepare state"); - let query = iroha + let query = client .query(asset::all()) .filter_with(|asset| asset.id.account.eq(account_id)); thread::sleep(std::time::Duration::from_millis(1500)); @@ -155,9 +155,9 @@ fn instruction_submits(criterion: &mut Criterion) { get_key_pair(iroha_test_network::Signatory::Alice), format!("http://{}", peer.api_address).parse().unwrap(), ); - let iroha = Client::new(client_config); + let client = Client::new(client_config); thread::sleep(std::time::Duration::from_millis(5000)); - let _ = iroha + let _ = client .submit_all::([create_domain.into(), create_account.into()]) .expect("Failed to create role."); thread::sleep(std::time::Duration::from_millis(500)); @@ -169,7 +169,7 @@ fn instruction_submits(criterion: &mut Criterion) { 200u32, AssetId::new(asset_definition_id.clone(), account_id.clone()), ); - match iroha.submit(mint_asset) { + match client.submit(mint_asset) { Ok(_) => success_count += 1, Err(e) => { eprintln!("Failed to execute instruction: {e}"); diff --git a/crates/iroha/examples/register_1000_triggers.rs b/crates/iroha/examples/register_1000_triggers.rs index c54a9df41c8..851f43d4c0b 100644 --- a/crates/iroha/examples/register_1000_triggers.rs +++ b/crates/iroha/examples/register_1000_triggers.rs @@ -6,9 +6,12 @@ use std::num::NonZeroU64; use iroha::{ client::Client, crypto::KeyPair, - data_model::{prelude::*, trigger::TriggerId}, + data_model::{ + parameter::{Parameter, SmartContractParameter}, + prelude::*, + trigger::TriggerId, + }, }; -use iroha_data_model::parameter::{Parameter, SmartContractParameter}; use iroha_genesis::{GenesisBlock, GenesisBuilder}; use iroha_primitives::unique_vec; use iroha_test_network::{ diff --git a/crates/iroha/examples/tutorial.rs b/crates/iroha/examples/tutorial.rs index 28a882e0518..75238e76b00 100644 --- a/crates/iroha/examples/tutorial.rs +++ b/crates/iroha/examples/tutorial.rs @@ -52,19 +52,19 @@ fn domain_registration_test(config: Config) -> Result<(), Error> { // #region rust_client_create // Create an Iroha client - let iroha = Client::new(config); + let client = Client::new(config); // #endregion rust_client_create // #region domain_register_example_prepare_tx // Prepare a transaction let metadata = Metadata::default(); let instructions: Vec = vec![create_looking_glass.into()]; - let tx = iroha.build_transaction(instructions, metadata); + let tx = client.build_transaction(instructions, metadata); // #endregion domain_register_example_prepare_tx // #region domain_register_example_submit_tx // Submit a prepared domain registration transaction - iroha + client .submit_transaction(&tx) .wrap_err("Failed to submit transaction")?; // #endregion domain_register_example_submit_tx @@ -108,7 +108,7 @@ fn account_registration_test(config: Config) -> Result<(), Error> { // #endregion register_account_crates // Create an Iroha client - let iroha = Client::new(config); + let client = Client::new(config); // #region register_account_create // Generate a new public key for a new account @@ -129,12 +129,12 @@ fn account_registration_test(config: Config) -> Result<(), Error> { // Account's RegisterBox let metadata = Metadata::default(); let instructions: Vec = vec![create_account.into()]; - let tx = iroha.build_transaction(instructions, metadata); + let tx = client.build_transaction(instructions, metadata); // #endregion register_account_prepare_tx // #region register_account_submit_tx // Submit a prepared account registration transaction - iroha.submit_transaction(&tx)?; + client.submit_transaction(&tx)?; // #endregion register_account_submit_tx // Finish the test successfully @@ -153,7 +153,7 @@ fn asset_registration_test(config: Config) -> Result<(), Error> { // #endregion register_asset_crates // Create an Iroha client - let iroha = Client::new(config); + let client = Client::new(config); // #region register_asset_create_asset // Create an asset @@ -167,7 +167,7 @@ fn asset_registration_test(config: Config) -> Result<(), Error> { Register::asset_definition(AssetDefinition::numeric(asset_def_id.clone()).mintable_once()); // Submit a registration time - iroha.submit(register_time)?; + client.submit(register_time)?; // #endregion register_asset_init_submit // Generate a new public key for a new account @@ -182,7 +182,7 @@ fn asset_registration_test(config: Config) -> Result<(), Error> { let mint = Mint::asset_numeric(numeric!(12.34), AssetId::new(asset_def_id, account_id)); // Submit a minting transaction - iroha.submit_all([mint])?; + client.submit_all([mint])?; // #endregion register_asset_mint_submit // Finish the test successfully @@ -198,7 +198,7 @@ fn asset_minting_test(config: Config) -> Result<(), Error> { // #endregion mint_asset_crates // Create an Iroha client - let iroha = Client::new(config); + let client = Client::new(config); // Define the instances of an Asset and Account // #region mint_asset_define_asset_account @@ -214,7 +214,7 @@ fn asset_minting_test(config: Config) -> Result<(), Error> { // #endregion mint_asset_mint // #region mint_asset_submit_tx - iroha + client .submit(mint_roses) .wrap_err("Failed to submit transaction")?; // #endregion mint_asset_submit_tx @@ -232,7 +232,7 @@ fn asset_minting_test(config: Config) -> Result<(), Error> { // #endregion mint_asset_mint_alt // #region mint_asset_submit_tx_alt - iroha + client .submit(mint_roses_alt) .wrap_err("Failed to submit transaction")?; // #endregion mint_asset_submit_tx_alt @@ -250,7 +250,7 @@ fn asset_burning_test(config: Config) -> Result<(), Error> { // #endregion burn_asset_crates // Create an Iroha client - let iroha = Client::new(config); + let client = Client::new(config); // #region burn_asset_define_asset_account // Define the instances of an Asset and Account @@ -266,7 +266,7 @@ fn asset_burning_test(config: Config) -> Result<(), Error> { // #endregion burn_asset_burn // #region burn_asset_submit_tx - iroha + client .submit(burn_roses) .wrap_err("Failed to submit transaction")?; // #endregion burn_asset_submit_tx @@ -284,7 +284,7 @@ fn asset_burning_test(config: Config) -> Result<(), Error> { // #endregion burn_asset_burn_alt // #region burn_asset_submit_tx_alt - iroha + client .submit(burn_roses_alt) .wrap_err("Failed to submit transaction")?; // #endregion burn_asset_submit_tx_alt diff --git a/crates/iroha/src/client.rs b/crates/iroha/src/client.rs index dfcf644b0d3..8ddd7f22977 100644 --- a/crates/iroha/src/client.rs +++ b/crates/iroha/src/client.rs @@ -230,8 +230,7 @@ impl Client { /// /// # Errors /// Fails if sending transaction to peer fails or if it response with error - pub fn submit(&self, instruction: I) -> Result> { - let isi = instruction.into(); + pub fn submit(&self, isi: I) -> Result> { self.submit_all([isi]) } diff --git a/crates/iroha/tests/integration/multisig.rs b/crates/iroha/tests/integration/multisig.rs index 55e61bbec36..62ea4b7939f 100644 --- a/crates/iroha/tests/integration/multisig.rs +++ b/crates/iroha/tests/integration/multisig.rs @@ -84,7 +84,7 @@ fn mutlisig() -> Result<()> { .map(Register::account), )?; - let call_trigger = ExecuteTrigger::new(multisig_register_trigger_id).with_args(&args); + let call_trigger = ExecuteTrigger::new(multisig_register_trigger_id).with_args(args); test_client.submit_blocking(call_trigger)?; // Check that multisig account exist @@ -120,7 +120,7 @@ fn mutlisig() -> Result<()> { if let Some((signatory, key_pair)) = signatories_iter.next() { let args = MultisigArgs::Instructions(isi); - let call_trigger = ExecuteTrigger::new(multisig_trigger_id.clone()).with_args(&args); + let call_trigger = ExecuteTrigger::new(multisig_trigger_id.clone()).with_args(args); test_client.submit_transaction_blocking( &TransactionBuilder::new(test_client.chain.clone(), signatory) .with_instructions([call_trigger]) @@ -138,7 +138,7 @@ fn mutlisig() -> Result<()> { for (signatory, key_pair) in signatories_iter { let args = MultisigArgs::Vote(isi_hash); - let call_trigger = ExecuteTrigger::new(multisig_trigger_id.clone()).with_args(&args); + let call_trigger = ExecuteTrigger::new(multisig_trigger_id.clone()).with_args(args); test_client.submit_transaction_blocking( &TransactionBuilder::new(test_client.chain.clone(), signatory) .with_instructions([call_trigger]) diff --git a/crates/iroha/tests/integration/triggers/by_call_trigger.rs b/crates/iroha/tests/integration/triggers/by_call_trigger.rs index 063a96e05eb..247b3b32a75 100644 --- a/crates/iroha/tests/integration/triggers/by_call_trigger.rs +++ b/crates/iroha/tests/integration/triggers/by_call_trigger.rs @@ -7,11 +7,10 @@ use iroha::{ crypto::KeyPair, data_model::{ prelude::*, - query::error::FindError, + query::{builder::SingleQueryError, error::FindError, trigger::FindTriggers}, transaction::{Executable, WasmSmartContract}, }, }; -use iroha_data_model::query::{builder::SingleQueryError, trigger::FindTriggers}; use iroha_executor_data_model::permission::trigger::CanRegisterTrigger; use iroha_genesis::GenesisBlock; use iroha_logger::info; @@ -696,7 +695,7 @@ fn call_execute_trigger_with_args() -> Result<()> { test_client.submit_blocking(Register::trigger(trigger))?; let args: MintRoseArgs = MintRoseArgs { val: 42 }; - let call_trigger = ExecuteTrigger::new(trigger_id).with_args(&args); + let call_trigger = ExecuteTrigger::new(trigger_id).with_args(args); test_client.submit_blocking(call_trigger)?; let new_value = get_asset_value(&mut test_client, asset_id); diff --git a/crates/iroha/tests/integration/triggers/orphans.rs b/crates/iroha/tests/integration/triggers/orphans.rs index 41dfc874f3d..19b497a4e74 100644 --- a/crates/iroha/tests/integration/triggers/orphans.rs +++ b/crates/iroha/tests/integration/triggers/orphans.rs @@ -1,5 +1,7 @@ -use iroha::{client::Client, data_model::prelude::*}; -use iroha_data_model::query::trigger::FindTriggers; +use iroha::{ + client::Client, + data_model::{prelude::*, query::trigger::FindTriggers}, +}; use iroha_test_network::{wait_for_genesis_committed, Peer, PeerBuilder}; use iroha_test_samples::gen_account_in; use tokio::runtime::Runtime; @@ -7,7 +9,7 @@ use tokio::runtime::Runtime; fn find_trigger(iroha: &Client, trigger_id: TriggerId) -> Option { iroha .query(FindTriggers::new()) - .filter_with(|trigger| trigger.id.eq(trigger_id.clone())) + .filter_with(|trigger| trigger.id.eq(trigger_id)) .execute_single() .ok() .map(|trigger| trigger.id) diff --git a/crates/iroha_cli/src/main.rs b/crates/iroha_cli/src/main.rs index 5c06ab8d6b5..48d7367e516 100644 --- a/crates/iroha_cli/src/main.rs +++ b/crates/iroha_cli/src/main.rs @@ -233,15 +233,15 @@ fn submit( metadata: Metadata, context: &mut dyn RunContext, ) -> Result<()> { - let iroha = context.client_from_config(); + let client = context.client_from_config(); let instructions = instructions.into(); - let tx = iroha.build_transaction(instructions, metadata); + let tx = client.build_transaction(instructions, metadata); #[cfg(not(debug_assertions))] let err_msg = "Failed to submit transaction."; #[cfg(debug_assertions)] let err_msg = format!("Failed to submit transaction {tx:?}"); - let hash = iroha.submit_transaction_blocking(&tx).wrap_err(err_msg)?; + let hash = client.submit_transaction_blocking(&tx).wrap_err(err_msg)?; context.print_data(&hash)?; Ok(()) @@ -333,9 +333,9 @@ mod events { fn listen(filter: impl Into, context: &mut dyn RunContext) -> Result<()> { let filter = filter.into(); - let iroha = context.client_from_config(); + let client = context.client_from_config(); eprintln!("Listening to events with filter: {filter:?}"); - iroha + client .listen_for_events([filter]) .wrap_err("Failed to listen for events.")? .try_for_each(|event| context.print_data(&event?))?; @@ -363,9 +363,9 @@ mod blocks { } fn listen(height: NonZeroU64, context: &mut dyn RunContext) -> Result<()> { - let iroha = context.client_from_config(); + let client = context.client_from_config(); eprintln!("Listening to blocks from height: {height}"); - iroha + client .listen_for_blocks(height) .wrap_err("Failed to listen for blocks.")? .try_for_each(|event| context.print_data(&event?))?; @@ -909,8 +909,8 @@ mod asset { impl RunArgs for Get { fn run(self, context: &mut dyn RunContext) -> Result<()> { let Self { id: asset_id } = self; - let iroha = context.client_from_config(); - let asset = iroha + let client = context.client_from_config(); + let asset = client .query(asset::all()) .filter_with(|asset| asset.id.eq(asset_id)) .execute_single() diff --git a/crates/iroha_core/src/executor.rs b/crates/iroha_core/src/executor.rs index bbdc58f1596..69469901004 100644 --- a/crates/iroha_core/src/executor.rs +++ b/crates/iroha_core/src/executor.rs @@ -110,20 +110,20 @@ impl<'de> DeserializeSeed<'de> for WasmSeed<'_, Executor> { } impl Executor { - /// Validate [`SignedTransaction`]. + /// Execute [`SignedTransaction`]. /// /// # Errors /// /// - Failed to prepare runtime for WASM execution; /// - Failed to execute the entrypoint of the WASM blob; /// - Executor denied the operation. - pub fn validate_transaction( + pub fn execute_transaction( &self, state_transaction: &mut StateTransaction<'_, '_>, authority: &AccountId, transaction: SignedTransaction, ) -> Result<(), ValidationFail> { - trace!("Running transaction validation"); + trace!("Running transaction execution"); match self { Self::Initial => { @@ -141,12 +141,12 @@ impl Executor { } Self::UserProvided(loaded_executor) => { let runtime = - wasm::RuntimeBuilder::::new() + wasm::RuntimeBuilder::::new() .with_engine(state_transaction.engine.clone()) // Cloning engine is cheap, see [`wasmtime::Engine`] docs .with_config(state_transaction.world.parameters().executor) .build()?; - runtime.execute_executor_validate_transaction( + runtime.execute_executor_execute_transaction( state_transaction, authority, &loaded_executor.module, @@ -156,20 +156,20 @@ impl Executor { } } - /// Validate [`InstructionExpr`]. + /// Execute [`Instruction`]. /// /// # Errors /// /// - Failed to prepare runtime for WASM execution; /// - Failed to execute the entrypoint of the WASM blob; /// - Executor denied the operation. - pub fn validate_instruction( + pub fn execute_instruction( &self, state_transaction: &mut StateTransaction<'_, '_>, authority: &AccountId, instruction: InstructionBox, ) -> Result<(), ValidationFail> { - trace!("Running instruction validation"); + trace!("Running instruction execution"); match self { Self::Initial => instruction @@ -177,12 +177,12 @@ impl Executor { .map_err(Into::into), Self::UserProvided(loaded_executor) => { let runtime = - wasm::RuntimeBuilder::::new() + wasm::RuntimeBuilder::::new() .with_engine(state_transaction.engine.clone()) // Cloning engine is cheap, see [`wasmtime::Engine`] docs .with_config(state_transaction.world.parameters().executor) .build()?; - runtime.execute_executor_validate_instruction( + runtime.execute_executor_execute_instruction( state_transaction, authority, &loaded_executor.module, diff --git a/crates/iroha_core/src/smartcontracts/wasm.rs b/crates/iroha_core/src/smartcontracts/wasm.rs index b121ae0f966..c18ec61ed4d 100644 --- a/crates/iroha_core/src/smartcontracts/wasm.rs +++ b/crates/iroha_core/src/smartcontracts/wasm.rs @@ -5,7 +5,7 @@ use std::{borrow::Borrow, num::NonZeroU64}; use error::*; -use import::traits::{ExecuteOperations as _, GetExecutorPayloads as _, SetDataModel as _}; +use import::traits::{ExecuteOperations as _, GetExecutorContexts as _, SetDataModel as _}; use iroha_data_model::{ account::AccountId, executor::{self, ExecutorDataModel}, @@ -13,7 +13,7 @@ use iroha_data_model::{ parameter::SmartContractParameters as Config, prelude::*, query::{parameters::QueryId, AnyQueryBox, QueryOutput, QueryRequest, QueryResponse}, - smart_contract::payloads::{self, Validate}, + smart_contract::payloads::{self, ExecutorContext, Validate}, Level as LogLevel, ValidationFail, }; use iroha_logger::debug; @@ -38,12 +38,12 @@ 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_PAYLOAD: &str = "get_smart_contract_payload"; - pub const GET_TRIGGER_PAYLOAD: &str = "get_trigger_payload"; - pub const GET_MIGRATE_PAYLOAD: &str = "get_migrate_payload"; - pub const GET_VALIDATE_TRANSACTION_PAYLOAD: &str = "get_validate_transaction_payload"; - pub const GET_VALIDATE_INSTRUCTION_PAYLOAD: &str = "get_validate_instruction_payload"; - pub const GET_VALIDATE_QUERY_PAYLOAD: &str = "get_validate_query_payload"; + pub const GET_SMART_CONTRACT_CONTEXT: &str = "get_smart_contract_context"; + pub const GET_TRIGGER_CONTEXT: &str = "get_trigger_context"; + pub const GET_MIGRATE_CONTEXT: &str = "get_migrate_context"; + pub const GET_EXECUTE_TRANSACTION_CONTEXT: &str = "get_execute_transaction_context"; + pub const GET_EXECUTE_INSTRUCTION_CONTEXT: &str = "get_execute_instruction_context"; + pub const GET_VALIDATE_QUERY_CONTEXT: &str = "get_validate_query_context"; pub const SET_DATA_MODEL: &str = "set_data_model"; pub const DBG: &str = "dbg"; @@ -57,8 +57,8 @@ mod import { pub const TRIGGER_MAIN: &str = "_iroha_trigger_main"; - pub const EXECUTOR_VALIDATE_TRANSACTION: &str = "_iroha_executor_validate_transaction"; - pub const EXECUTOR_VALIDATE_INSTRUCTION: &str = "_iroha_executor_validate_instruction"; + pub const EXECUTOR_EXECUTE_TRANSACTION: &str = "_iroha_executor_execute_transaction"; + pub const EXECUTOR_EXECUTE_INSTRUCTION: &str = "_iroha_executor_execute_instruction"; pub const EXECUTOR_VALIDATE_QUERY: &str = "_iroha_executor_validate_query"; pub const EXECUTOR_MIGRATE: &str = "_iroha_executor_migrate"; @@ -88,18 +88,18 @@ mod import { ) -> Result<(), ValidationFail>; } - pub trait GetExecutorPayloads { + pub trait GetExecutorContexts { #[codec::wrap_trait_fn] - fn get_migrate_payload(state: &S) -> payloads::Migrate; + fn get_migrate_context(state: &S) -> payloads::ExecutorContext; #[codec::wrap_trait_fn] - fn get_validate_transaction_payload(state: &S) -> Validate; + fn get_execute_transaction_context(state: &S) -> Validate; #[codec::wrap_trait_fn] - fn get_validate_instruction_payload(state: &S) -> Validate; + fn get_execute_instruction_context(state: &S) -> Validate; #[codec::wrap_trait_fn] - fn get_validate_query_payload(state: &S) -> Validate; + fn get_validate_query_context(state: &S) -> Validate; } pub trait SetDataModel { @@ -481,14 +481,14 @@ pub mod state { pub(in super::super::super::super) to_validate: T, } - /// State kind for executing `validate_transaction()` entrypoint of executor - pub type ValidateTransaction = Validate; + /// State kind for executing `execute_transaction()` entrypoint of executor + pub type ExecuteTransaction = Validate; /// State kind for executing `validate_query()` entrypoint of executor pub type ValidateQuery = Validate; - /// State kind for executing `validate_instruction()` entrypoint of executor - pub type ValidateInstruction = Validate; + /// State kind for executing `execute_instruction()` entrypoint of executor + pub type ExecuteInstruction = Validate; /// State kind for executing `migrate()` entrypoint of executor #[derive(Copy, Clone)] @@ -537,20 +537,20 @@ pub mod state { use super::*; - /// State for executing `validate_transaction()` entrypoint - pub type ValidateTransaction<'wrld, 'block, 'state> = CommonState< + /// State for executing `execute_transaction()` entrypoint + pub type ExecuteTransaction<'wrld, 'block, 'state> = CommonState< chain_state::WithMut<'wrld, 'block, 'state>, - specific::executor::ValidateTransaction, + specific::executor::ExecuteTransaction, >; /// State for executing `validate_query()` entrypoint pub type ValidateQuery<'wrld, S> = CommonState, specific::executor::ValidateQuery>; - /// State for executing `validate_instruction()` entrypoint - pub type ValidateInstruction<'wrld, 'block, 'state> = CommonState< + /// State for executing `execute_instruction()` entrypoint + pub type ExecuteInstruction<'wrld, 'block, 'state> = CommonState< chain_state::WithMut<'wrld, 'block, 'state>, - specific::executor::ValidateInstruction, + specific::executor::ExecuteInstruction, >; /// State for executing `migrate()` entrypoint @@ -572,8 +572,8 @@ pub mod state { } impl_blank_validate_operations!( - ValidateTransaction<'_, '_, '_>, - ValidateInstruction<'_, '_, '_>, + ExecuteTransaction<'_, '_, '_>, + ExecuteInstruction<'_, '_, '_>, Migrate<'_, '_, '_>, ); @@ -613,7 +613,7 @@ impl Runtime { .ok_or_else(|| ExportError::not_found(import::SMART_CONTRACT_ALLOC))? .into_func() .ok_or_else(|| ExportError::not_a_function(import::SMART_CONTRACT_ALLOC))? - .typed::(caller) + .typed(caller) .map_err(|_error| { ExportError::wrong_signature::(import::SMART_CONTRACT_ALLOC) }) @@ -627,7 +627,7 @@ impl Runtime { instance .get_func(&mut store, func_name) .ok_or_else(|| ExportError::not_found(func_name))? - .typed::(&mut store) + .typed(&mut store) .map_err(|_error| ExportError::wrong_signature::(func_name)) } @@ -750,7 +750,7 @@ impl Runtime> { } impl Runtime> { - fn execute_executor_validate_internal( + fn execute_executor_execute_internal( &self, module: &wasmtime::Module, state: state::CommonState, @@ -851,7 +851,7 @@ impl<'wrld, 'state, 'block, S> .world .executor .clone() // Cloning executor is a cheap operation - .validate_instruction(state.state.0, &authority, instruction) + .execute_instruction(state.state.0, &authority, instruction) } } @@ -915,7 +915,7 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime = + let main_fn: TypedFunc<_, ()> = Self::get_typed_func(&smart_contract, &mut store, import::SMART_CONTRACT_MAIN)?; // NOTE: This function takes ownership of the pointer @@ -930,9 +930,9 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime payloads::SmartContract { - payloads::SmartContract { - owner: state.authority.clone(), + fn get_smart_contract_context(state: &state::SmartContract) -> payloads::SmartContractContext { + payloads::SmartContractContext { + authority: state.authority.clone(), } } } @@ -989,7 +989,7 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime = + let main_fn: TypedFunc<_, ()> = Self::get_typed_func(&instance, &mut store, import::TRIGGER_MAIN)?; // NOTE: This function takes ownership of the pointer @@ -1005,10 +1005,10 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime payloads::Trigger { - payloads::Trigger { + fn get_trigger_context(state: &state::Trigger) -> payloads::TriggerContext { + payloads::TriggerContext { id: state.specific_state.id.clone(), - owner: state.authority.clone(), + authority: state.authority.clone(), event: state.specific_state.triggering_event.clone(), } } @@ -1096,8 +1096,8 @@ where } } -impl<'wrld, 'block, 'state> Runtime> { - /// Execute `validate_transaction()` entrypoint of the given module of runtime executor +impl<'wrld, 'block, 'state> Runtime> { + /// Execute `execute_transaction()` entrypoint of the given module of runtime executor /// /// # Errors /// @@ -1105,79 +1105,81 @@ impl<'wrld, 'block, 'state> Runtime, authority: &AccountId, module: &wasmtime::Module, transaction: SignedTransaction, ) -> Result { - let span = wasm_log_span!("Running `validate_transaction()`"); - - self.execute_executor_validate_internal( - module, - state::executor::ValidateTransaction::new( - authority.clone(), - self.config, - span, - state::chain_state::WithMut(state_transaction), - state::specific::executor::ValidateTransaction::new(transaction), - ), - import::EXECUTOR_VALIDATE_TRANSACTION, - ) + let span = wasm_log_span!("Running `execute_transaction()`"); + + let state = state::executor::ExecuteTransaction::new( + authority.clone(), + self.config, + span, + state::chain_state::WithMut(state_transaction), + state::specific::executor::ExecuteTransaction::new(transaction), + ); + + self.execute_executor_execute_internal(module, state, import::EXECUTOR_EXECUTE_TRANSACTION) } } -impl<'wrld> ExecuteOperationsAsExecutorMut> - for Runtime> +impl<'wrld> ExecuteOperationsAsExecutorMut> + for Runtime> { } impl<'wrld, 'block, 'state> - import::traits::GetExecutorPayloads> - for Runtime> + import::traits::GetExecutorContexts> + for Runtime> { #[codec::wrap] - fn get_migrate_payload( - _state: &state::executor::ValidateTransaction<'wrld, 'block, 'state>, - ) -> payloads::Migrate { - panic!("Executor `validate_transaction()` entrypoint should not query payload for `migrate()` entrypoint") + fn get_migrate_context( + _state: &state::executor::ExecuteTransaction<'wrld, 'block, 'state>, + ) -> payloads::ExecutorContext { + panic!("Executor `execute_transaction()` entrypoint should not query context for `migrate()` entrypoint") } #[codec::wrap] - fn get_validate_transaction_payload( - state: &state::executor::ValidateTransaction<'wrld, 'block, 'state>, + fn get_execute_transaction_context( + state: &state::executor::ExecuteTransaction<'wrld, 'block, 'state>, ) -> Validate { - Validate { + let context = ExecutorContext { authority: state.authority.clone(), block_height: state.state.0.height() as u64, + }; + + Validate { + context, target: state.specific_state.to_validate.clone(), } } #[codec::wrap] - fn get_validate_instruction_payload( - _state: &state::executor::ValidateTransaction<'wrld, 'block, 'state>, + fn get_execute_instruction_context( + _state: &state::executor::ExecuteTransaction<'wrld, 'block, 'state>, ) -> Validate { - panic!("Executor `validate_transaction()` entrypoint should not query payload for `validate_instruction()` entrypoint") + panic!("Executor `execute_transaction()` entrypoint should not query context for `execute_instruction()` entrypoint") } #[codec::wrap] - fn get_validate_query_payload( - _state: &state::executor::ValidateTransaction<'wrld, 'block, 'state>, + fn get_validate_query_context( + _state: &state::executor::ExecuteTransaction<'wrld, 'block, 'state>, ) -> Validate { - panic!("Executor `validate_transaction()` entrypoint should not query payload for `validate_query()` entrypoint") + panic!("Executor `execute_transaction()` entrypoint should not query context for `execute_query()` entrypoint") } } -impl<'wrld> FakeSetExecutorDataModel> - for Runtime> +impl<'wrld> FakeSetExecutorDataModel> + for Runtime> { - const ENTRYPOINT_FN_NAME: &'static str = "validate_transaction"; + const ENTRYPOINT_FN_NAME: &'static str = "execute_transaction"; } -impl<'wrld, 'block, 'state> Runtime> { - /// Execute `validate_instruction()` entrypoint of the given module of runtime executor +impl<'wrld, 'block, 'state> Runtime> { + /// Execute `execute_instruction()` entrypoint of the given module of runtime executor /// /// # Errors /// @@ -1185,75 +1187,77 @@ impl<'wrld, 'block, 'state> Runtime, authority: &AccountId, module: &wasmtime::Module, instruction: InstructionBox, ) -> Result { - let span = wasm_log_span!("Running `validate_instruction()`"); - - self.execute_executor_validate_internal( - module, - state::executor::ValidateInstruction::new( - authority.clone(), - self.config, - span, - state::chain_state::WithMut(state_transaction), - state::specific::executor::ValidateInstruction::new(instruction), - ), - import::EXECUTOR_VALIDATE_INSTRUCTION, - ) + let span = wasm_log_span!("Running `execute_instruction()`"); + + let state = state::executor::ExecuteInstruction::new( + authority.clone(), + self.config, + span, + state::chain_state::WithMut(state_transaction), + state::specific::executor::ExecuteInstruction::new(instruction), + ); + + self.execute_executor_execute_internal(module, state, import::EXECUTOR_EXECUTE_INSTRUCTION) } } -impl<'wrld> ExecuteOperationsAsExecutorMut> - for Runtime> +impl<'wrld> ExecuteOperationsAsExecutorMut> + for Runtime> { } impl<'wrld, 'block, 'state> - import::traits::GetExecutorPayloads> - for Runtime> + import::traits::GetExecutorContexts> + for Runtime> { #[codec::wrap] - fn get_migrate_payload( - _state: &state::executor::ValidateInstruction<'wrld, 'block, 'state>, - ) -> payloads::Migrate { - panic!("Executor `validate_instruction()` entrypoint should not query payload for `migrate()` entrypoint") + fn get_migrate_context( + _state: &state::executor::ExecuteInstruction<'wrld, 'block, 'state>, + ) -> payloads::ExecutorContext { + panic!("Executor `execute_instruction()` entrypoint should not query context for `migrate()` entrypoint") } #[codec::wrap] - fn get_validate_transaction_payload( - _state: &state::executor::ValidateInstruction<'wrld, 'block, 'state>, + fn get_execute_transaction_context( + _state: &state::executor::ExecuteInstruction<'wrld, 'block, 'state>, ) -> Validate { - panic!("Executor `validate_instruction()` entrypoint should not query payload for `validate_transaction()` entrypoint") + panic!("Executor `execute_instruction()` entrypoint should not query context for `execute_transaction()` entrypoint") } #[codec::wrap] - fn get_validate_instruction_payload( - state: &state::executor::ValidateInstruction<'wrld, 'block, 'state>, + fn get_execute_instruction_context( + state: &state::executor::ExecuteInstruction<'wrld, 'block, 'state>, ) -> Validate { - Validate { + let context = ExecutorContext { authority: state.authority.clone(), block_height: state.state.0.height() as u64, + }; + + Validate { + context, target: state.specific_state.to_validate.clone(), } } #[codec::wrap] - fn get_validate_query_payload( - _state: &state::executor::ValidateInstruction<'wrld, 'block, 'state>, + fn get_validate_query_context( + _state: &state::executor::ExecuteInstruction<'wrld, 'block, 'state>, ) -> Validate { - panic!("Executor `validate_instruction()` entrypoint should not query payload for `validate_query()` entrypoint") + panic!("Executor `execute_instruction()` entrypoint should not query context for `execute_query()` entrypoint") } } -impl<'wrld> FakeSetExecutorDataModel> - for Runtime> +impl<'wrld> FakeSetExecutorDataModel> + for Runtime> { - const ENTRYPOINT_FN_NAME: &'static str = "validate_instruction"; + const ENTRYPOINT_FN_NAME: &'static str = "execute_instruction"; } impl<'wrld, S: StateReadOnly> Runtime> { @@ -1274,17 +1278,15 @@ impl<'wrld, S: StateReadOnly> Runtime> ) -> Result { let span = wasm_log_span!("Running `validate_query()`"); - self.execute_executor_validate_internal( - module, - state::executor::ValidateQuery::new( - authority.clone(), - self.config, - span, - state::chain_state::WithConst(state_ro), - state::specific::executor::ValidateQuery::new(query), - ), - import::EXECUTOR_VALIDATE_QUERY, - ) + let state = state::executor::ValidateQuery::new( + authority.clone(), + self.config, + span, + state::chain_state::WithConst(state_ro), + state::specific::executor::ValidateQuery::new(query), + ); + + self.execute_executor_execute_internal(module, state, import::EXECUTOR_VALIDATE_QUERY) } } @@ -1312,35 +1314,41 @@ impl<'wrld, S: StateReadOnly> } impl<'wrld, S: StateReadOnly> - import::traits::GetExecutorPayloads> + import::traits::GetExecutorContexts> for Runtime> { #[codec::wrap] - fn get_migrate_payload(_state: &state::executor::ValidateQuery<'wrld, S>) -> payloads::Migrate { - panic!("Executor `validate_query()` entrypoint should not query payload for `migrate()` entrypoint") + fn get_migrate_context( + _state: &state::executor::ValidateQuery<'wrld, S>, + ) -> payloads::ExecutorContext { + panic!("Executor `validate_query()` entrypoint should not query context for `migrate()` entrypoint") } #[codec::wrap] - fn get_validate_transaction_payload( + fn get_execute_transaction_context( _state: &state::executor::ValidateQuery<'wrld, S>, ) -> Validate { - panic!("Executor `validate_query()` entrypoint should not query payload for `validate_transaction()` entrypoint") + panic!("Executor `validate_query()` entrypoint should not query context for `execute_transaction()` entrypoint") } #[codec::wrap] - fn get_validate_instruction_payload( + fn get_execute_instruction_context( _state: &state::executor::ValidateQuery<'wrld, S>, ) -> Validate { - panic!("Executor `validate_query()` entrypoint should not query payload for `validate_instruction()` entrypoint") + panic!("Executor `validate_query()` entrypoint should not query context for `execute_instruction()` entrypoint") } #[codec::wrap] - fn get_validate_query_payload( + fn get_validate_query_context( state: &state::executor::ValidateQuery<'wrld, S>, ) -> Validate { - Validate { + let context = ExecutorContext { authority: state.authority.clone(), block_height: state.state.0.height() as u64, + }; + + Validate { + context, target: state.specific_state.to_validate.clone(), } } @@ -1378,7 +1386,7 @@ impl<'wrld, 'block, 'state> Runtime = + let migrate_fn: TypedFunc<_, ()> = Self::get_typed_func(&instance, &mut store, import::EXECUTOR_MIGRATE)?; migrate_fn @@ -1394,47 +1402,48 @@ impl<'wrld> ExecuteOperationsAsExecutorMut - import::traits::GetExecutorPayloads> + import::traits::GetExecutorContexts> for Runtime> { #[codec::wrap] - fn get_migrate_payload( + fn get_migrate_context( state: &state::executor::Migrate<'wrld, 'block, 'state>, - ) -> payloads::Migrate { - payloads::Migrate { + ) -> payloads::ExecutorContext { + payloads::ExecutorContext { + authority: state.authority.clone(), block_height: state.state.0.height() as u64, } } #[codec::wrap] - fn get_validate_transaction_payload( + fn get_execute_transaction_context( _state: &state::executor::Migrate<'wrld, 'block, 'state>, ) -> Validate { - panic!("Executor `migrate()` entrypoint should not query payload for `validate_transaction()` entrypoint") + panic!("Executor `migrate()` entrypoint should not query context for `execute_transaction()` entrypoint") } #[codec::wrap] - fn get_validate_instruction_payload( + fn get_execute_instruction_context( _state: &state::executor::Migrate<'wrld, 'block, 'state>, ) -> Validate { - panic!("Executor `migrate()` entrypoint should not query payload for `validate_instruction()` entrypoint") + panic!("Executor `migrate()` entrypoint should not query context for `execute_instruction()` entrypoint") } #[codec::wrap] - fn get_validate_query_payload( + fn get_validate_query_context( _state: &state::executor::Migrate<'wrld, 'block, 'state>, ) -> Validate { - panic!("Executor `migrate()` entrypoint should not query payload for `validate_query()` entrypoint") + panic!("Executor `migrate()` entrypoint should not query context for `validate_query()` entrypoint") } } @@ -1546,7 +1555,7 @@ 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_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_smart_contract_payload(caller), + export::GET_SMART_CONTRACT_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_smart_contract_context(caller), )?; Ok(linker) }) @@ -1566,7 +1575,7 @@ 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_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_trigger_payload(caller), + export::GET_TRIGGER_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_trigger_context(caller), )?; Ok(linker) }) @@ -1574,27 +1583,27 @@ impl<'wrld, 'block, 'state> RuntimeBuilder } impl<'wrld, 'block, 'state> - RuntimeBuilder> + RuntimeBuilder> { - /// Builds the [`Runtime`] for *Executor* `validate_transaction()` execution + /// Builds the [`Runtime`] for *Executor* `execute_transaction()` execution /// /// # Errors /// /// Fails if failed to create default linker. pub fn build( self, - ) -> Result>> { + ) -> Result>> { self.finalize(|engine| { let mut linker = Linker::new(engine); - create_imports!(linker, state::executor::ValidateTransaction<'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_MIGRATE_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_migrate_payload(caller), - export::GET_VALIDATE_TRANSACTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_transaction_payload(caller), - export::GET_VALIDATE_INSTRUCTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_instruction_payload(caller), - export::GET_VALIDATE_QUERY_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_payload(caller), - export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), + create_imports!(linker, state::executor::ExecuteTransaction<'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_MIGRATE_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_migrate_context(caller), + export::GET_EXECUTE_TRANSACTION_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_execute_transaction_context(caller), + export::GET_EXECUTE_INSTRUCTION_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_execute_instruction_context(caller), + export::GET_VALIDATE_QUERY_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_context(caller), + export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), )?; Ok(linker) }) @@ -1602,27 +1611,27 @@ impl<'wrld, 'block, 'state> } impl<'wrld, 'block, 'state> - RuntimeBuilder> + RuntimeBuilder> { - /// Builds the [`Runtime`] for *Executor* `validate_instruction()` execution + /// Builds the [`Runtime`] for *Executor* `execute_instruction()` execution /// /// # Errors /// /// Fails if failed to create default linker. pub fn build( self, - ) -> Result>> { + ) -> Result>> { self.finalize(|engine| { let mut linker = Linker::new(engine); - create_imports!(linker, state::executor::ValidateInstruction<'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_MIGRATE_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_migrate_payload(caller), - export::GET_VALIDATE_TRANSACTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_transaction_payload(caller), - export::GET_VALIDATE_INSTRUCTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_instruction_payload(caller), - export::GET_VALIDATE_QUERY_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_payload(caller), - export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), + create_imports!(linker, state::executor::ExecuteInstruction<'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_MIGRATE_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_migrate_context(caller), + export::GET_EXECUTE_TRANSACTION_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_execute_transaction_context(caller), + export::GET_EXECUTE_INSTRUCTION_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_execute_instruction_context(caller), + export::GET_VALIDATE_QUERY_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_context(caller), + export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), )?; Ok(linker) }) @@ -1643,10 +1652,10 @@ impl<'wrld, S: StateReadOnly> 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_MIGRATE_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_migrate_payload(caller), - export::GET_VALIDATE_TRANSACTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_transaction_payload(caller), - export::GET_VALIDATE_INSTRUCTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_instruction_payload(caller), - export::GET_VALIDATE_QUERY_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_payload(caller), + export::GET_MIGRATE_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_migrate_context(caller), + export::GET_EXECUTE_TRANSACTION_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_execute_transaction_context(caller), + export::GET_EXECUTE_INSTRUCTION_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_execute_instruction_context(caller), + export::GET_VALIDATE_QUERY_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_context(caller), export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), )?; Ok(linker) @@ -1668,10 +1677,10 @@ 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_MIGRATE_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_migrate_payload(caller), - export::GET_VALIDATE_TRANSACTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_transaction_payload(caller), - export::GET_VALIDATE_INSTRUCTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_instruction_payload(caller), - export::GET_VALIDATE_QUERY_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_payload(caller), + export::GET_MIGRATE_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_migrate_context(caller), + export::GET_EXECUTE_TRANSACTION_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_execute_transaction_context(caller), + export::GET_EXECUTE_INSTRUCTION_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_execute_instruction_context(caller), + export::GET_VALIDATE_QUERY_CONTEXT => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_context(caller), export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), )?; Ok(linker) @@ -2025,7 +2034,7 @@ mod tests { drop)) "#, main_fn_name = import::SMART_CONTRACT_MAIN, - get_trigger_payload_fn_name = export::GET_TRIGGER_PAYLOAD, + get_trigger_payload_fn_name = export::GET_TRIGGER_CONTEXT, // this test doesn't use the memory memory_and_alloc = memory_and_alloc(""), ); diff --git a/crates/iroha_core/src/tx.rs b/crates/iroha_core/src/tx.rs index 44fe92aed46..fe51896b572 100644 --- a/crates/iroha_core/src/tx.rs +++ b/crates/iroha_core/src/tx.rs @@ -278,7 +278,7 @@ impl StateBlock<'_> { .world .executor .clone() // Cloning executor is a cheap operation - .validate_transaction(state_transaction, &authority, tx) + .execute_transaction(state_transaction, &authority, tx) .map_err(|error| { if let ValidationFail::InternalError(msg) = &error { error!( diff --git a/crates/iroha_data_model/src/events/execute_trigger.rs b/crates/iroha_data_model/src/events/execute_trigger.rs index 59324f91329..66bd26885bb 100644 --- a/crates/iroha_data_model/src/events/execute_trigger.rs +++ b/crates/iroha_data_model/src/events/execute_trigger.rs @@ -35,7 +35,7 @@ mod model { pub authority: AccountId, /// Args to pass for trigger execution #[getset(skip)] - pub args: Option, + pub args: JsonString, } /// Filter for trigger execution [`Event`] @@ -64,8 +64,8 @@ mod model { impl ExecuteTriggerEvent { /// Args to pass for trigger execution - pub fn args(&self) -> Option<&JsonString> { - self.args.as_ref() + pub fn args(&self) -> &JsonString { + &self.args } } diff --git a/crates/iroha_data_model/src/isi.rs b/crates/iroha_data_model/src/isi.rs index 1d6a7e16f0a..add44d87124 100644 --- a/crates/iroha_data_model/src/isi.rs +++ b/crates/iroha_data_model/src/isi.rs @@ -930,7 +930,7 @@ mod transparent { /// Id of a trigger to execute pub trigger: TriggerId, /// Arguments to trigger execution - pub args: Option, + pub args: JsonString, } } @@ -939,14 +939,14 @@ mod transparent { pub fn new(trigger: TriggerId) -> Self { Self { trigger, - args: None, + args: JsonString::default(), } } /// Add trigger execution args #[must_use] - pub fn with_args(mut self, args: &T) -> Self { - self.args = Some(JsonString::new(args)); + pub fn with_args(mut self, args: impl Into) -> Self { + self.args = args.into(); self } } diff --git a/crates/iroha_data_model/src/smart_contract.rs b/crates/iroha_data_model/src/smart_contract.rs index d7957b8ad4c..aa27818711d 100644 --- a/crates/iroha_data_model/src/smart_contract.rs +++ b/crates/iroha_data_model/src/smart_contract.rs @@ -1,33 +1,35 @@ //! This module contains data and structures related only to smart contract execution pub mod payloads { - //! Payloads with function arguments for different entrypoints + //! Contexts with function arguments for different entrypoints use parity_scale_codec::{Decode, Encode}; use crate::prelude::*; - /// Payload for smart contract entrypoint + /// Context for smart contract entrypoint #[derive(Debug, Clone, Encode, Decode)] - pub struct SmartContract { - /// Smart contract owner who submitted transaction with it - pub owner: AccountId, + pub struct SmartContractContext { + /// Account that submitted the transaction containing the smart contract + pub authority: AccountId, } - /// Payload for trigger entrypoint + /// Context for trigger entrypoint #[derive(Debug, Clone, Encode, Decode)] - pub struct Trigger { + pub struct TriggerContext { /// Id of this trigger pub id: TriggerId, - /// Trigger owner who registered the trigger - pub owner: AccountId, + /// Account that registered the trigger + pub authority: AccountId, /// Event which triggered the execution pub event: EventBox, } - /// Payload for migrate entrypoint - #[derive(Debug, Clone, Copy, Encode, Decode)] - pub struct Migrate { + /// Context for migrate entrypoint + #[derive(Debug, Clone, Encode, Decode)] + pub struct ExecutorContext { + /// Account that is executing the operation + pub authority: AccountId, /// Height of the latest block in the blockchain pub block_height: u64, } @@ -35,10 +37,8 @@ pub mod payloads { /// Generic payload for `validate_*()` entrypoints of executor. #[derive(Debug, Clone, Encode, Decode)] pub struct Validate { - /// Authority which executed the operation to be validated - pub authority: AccountId, - /// Height of the latest block in the blockchain - pub block_height: u64, + /// Context of the executor + pub context: ExecutorContext, /// Operation to be validated pub target: T, } diff --git a/crates/iroha_data_model/src/visit.rs b/crates/iroha_data_model/src/visit.rs index 102ce612686..92b8709c618 100644 --- a/crates/iroha_data_model/src/visit.rs +++ b/crates/iroha_data_model/src/visit.rs @@ -13,8 +13,8 @@ use crate::{ macro_rules! delegate { ( $($visitor:ident $(<$param:ident $(: $bound:path)?>)?($operation:ty)),+ $(,)? ) => { $( - fn $visitor$(<$param $(: $bound)?>)?(&mut self, authority: &AccountId, operation: $operation) { - $visitor(self, authority, operation); + fn $visitor$(<$param $(: $bound)?>)?(&mut self, operation: $operation) { + $visitor(self, operation); } )+ }; } @@ -137,30 +137,22 @@ pub trait Visit { } } -pub fn visit_transaction( - visitor: &mut V, - authority: &AccountId, - transaction: &SignedTransaction, -) { +pub fn visit_transaction(visitor: &mut V, transaction: &SignedTransaction) { match transaction.instructions() { - Executable::Wasm(wasm) => visitor.visit_wasm(authority, wasm), + Executable::Wasm(wasm) => visitor.visit_wasm(wasm), Executable::Instructions(instructions) => { for isi in instructions { - visitor.visit_instruction(authority, isi); + visitor.visit_instruction(isi); } } } } -pub fn visit_singular_query( - visitor: &mut V, - authority: &AccountId, - query: &SingularQueryBox, -) { +pub fn visit_singular_query(visitor: &mut V, query: &SingularQueryBox) { macro_rules! singular_query_visitors { ( $($visitor:ident($query:ident)),+ $(,)? ) => { match query { $( - SingularQueryBox::$query(query) => visitor.$visitor(authority, &query), )+ + SingularQueryBox::$query(query) => visitor.$visitor(&query), )+ } }; } @@ -177,15 +169,11 @@ pub fn visit_singular_query( } } -pub fn visit_iter_query( - visitor: &mut V, - authority: &AccountId, - query: &QueryWithParams, -) { +pub fn visit_iter_query(visitor: &mut V, query: &QueryWithParams) { macro_rules! iterable_query_visitors { ( $($visitor:ident($query:ident)),+ $(,)? ) => { match &query.query { $( - QueryBox::$query(query) => visitor.$visitor(authority, &query), )+ + QueryBox::$query(query) => visitor.$visitor(&query), )+ } }; } @@ -209,176 +197,133 @@ pub fn visit_iter_query( } } -pub fn visit_query(visitor: &mut V, authority: &AccountId, query: &AnyQueryBox) { +pub fn visit_query(visitor: &mut V, query: &AnyQueryBox) { match query { - AnyQueryBox::Singular(query) => visitor.visit_singular_query(authority, query), - AnyQueryBox::Iterable(query) => visitor.visit_iter_query(authority, query), + AnyQueryBox::Singular(query) => visitor.visit_singular_query(query), + AnyQueryBox::Iterable(query) => visitor.visit_iter_query(query), } } -pub fn visit_wasm( - _visitor: &mut V, - _authority: &AccountId, - _wasm: &WasmSmartContract, -) { -} +pub fn visit_wasm(_visitor: &mut V, _wasm: &WasmSmartContract) {} /// Default validation for [`InstructionBox`]. /// /// # Warning /// /// Instruction is executed following successful validation -pub fn visit_instruction( - visitor: &mut V, - authority: &AccountId, - isi: &InstructionBox, -) { +pub fn visit_instruction(visitor: &mut V, isi: &InstructionBox) { match isi { - InstructionBox::SetParameter(variant_value) => { - visitor.visit_set_parameter(authority, variant_value) - } + InstructionBox::SetParameter(variant_value) => visitor.visit_set_parameter(variant_value), InstructionBox::ExecuteTrigger(variant_value) => { - visitor.visit_execute_trigger(authority, variant_value) + visitor.visit_execute_trigger(variant_value) } - InstructionBox::Log(variant_value) => visitor.visit_log(authority, variant_value), - InstructionBox::Burn(variant_value) => visitor.visit_burn(authority, variant_value), - InstructionBox::Grant(variant_value) => visitor.visit_grant(authority, variant_value), - InstructionBox::Mint(variant_value) => visitor.visit_mint(authority, variant_value), - InstructionBox::Register(variant_value) => visitor.visit_register(authority, variant_value), + InstructionBox::Log(variant_value) => visitor.visit_log(variant_value), + InstructionBox::Burn(variant_value) => visitor.visit_burn(variant_value), + InstructionBox::Grant(variant_value) => visitor.visit_grant(variant_value), + InstructionBox::Mint(variant_value) => visitor.visit_mint(variant_value), + InstructionBox::Register(variant_value) => visitor.visit_register(variant_value), InstructionBox::RemoveKeyValue(variant_value) => { - visitor.visit_remove_key_value(authority, variant_value) - } - InstructionBox::Revoke(variant_value) => visitor.visit_revoke(authority, variant_value), - InstructionBox::SetKeyValue(variant_value) => { - visitor.visit_set_key_value(authority, variant_value) - } - InstructionBox::Transfer(variant_value) => visitor.visit_transfer(authority, variant_value), - InstructionBox::Unregister(variant_value) => { - visitor.visit_unregister(authority, variant_value) + visitor.visit_remove_key_value(variant_value) } - InstructionBox::Upgrade(variant_value) => visitor.visit_upgrade(authority, variant_value), - InstructionBox::Custom(custom) => visitor.visit_custom(authority, custom), + InstructionBox::Revoke(variant_value) => visitor.visit_revoke(variant_value), + InstructionBox::SetKeyValue(variant_value) => visitor.visit_set_key_value(variant_value), + InstructionBox::Transfer(variant_value) => visitor.visit_transfer(variant_value), + InstructionBox::Unregister(variant_value) => visitor.visit_unregister(variant_value), + InstructionBox::Upgrade(variant_value) => visitor.visit_upgrade(variant_value), + InstructionBox::Custom(custom) => visitor.visit_custom(custom), } } -pub fn visit_register( - visitor: &mut V, - authority: &AccountId, - isi: &RegisterBox, -) { +pub fn visit_register(visitor: &mut V, isi: &RegisterBox) { match isi { - RegisterBox::Peer(obj) => visitor.visit_register_peer(authority, obj), - RegisterBox::Domain(obj) => visitor.visit_register_domain(authority, obj), - RegisterBox::Account(obj) => visitor.visit_register_account(authority, obj), - RegisterBox::AssetDefinition(obj) => { - visitor.visit_register_asset_definition(authority, obj) - } - RegisterBox::Asset(obj) => visitor.visit_register_asset(authority, obj), - RegisterBox::Role(obj) => visitor.visit_register_role(authority, obj), - RegisterBox::Trigger(obj) => visitor.visit_register_trigger(authority, obj), + RegisterBox::Peer(obj) => visitor.visit_register_peer(obj), + RegisterBox::Domain(obj) => visitor.visit_register_domain(obj), + RegisterBox::Account(obj) => visitor.visit_register_account(obj), + RegisterBox::AssetDefinition(obj) => visitor.visit_register_asset_definition(obj), + RegisterBox::Asset(obj) => visitor.visit_register_asset(obj), + RegisterBox::Role(obj) => visitor.visit_register_role(obj), + RegisterBox::Trigger(obj) => visitor.visit_register_trigger(obj), } } -pub fn visit_unregister( - visitor: &mut V, - authority: &AccountId, - isi: &UnregisterBox, -) { +pub fn visit_unregister(visitor: &mut V, isi: &UnregisterBox) { match isi { - UnregisterBox::Peer(obj) => visitor.visit_unregister_peer(authority, obj), - UnregisterBox::Domain(obj) => visitor.visit_unregister_domain(authority, obj), - UnregisterBox::Account(obj) => visitor.visit_unregister_account(authority, obj), - UnregisterBox::AssetDefinition(obj) => { - visitor.visit_unregister_asset_definition(authority, obj) - } - UnregisterBox::Asset(obj) => visitor.visit_unregister_asset(authority, obj), - UnregisterBox::Role(obj) => visitor.visit_unregister_role(authority, obj), - UnregisterBox::Trigger(obj) => visitor.visit_unregister_trigger(authority, obj), + UnregisterBox::Peer(obj) => visitor.visit_unregister_peer(obj), + UnregisterBox::Domain(obj) => visitor.visit_unregister_domain(obj), + UnregisterBox::Account(obj) => visitor.visit_unregister_account(obj), + UnregisterBox::AssetDefinition(obj) => visitor.visit_unregister_asset_definition(obj), + UnregisterBox::Asset(obj) => visitor.visit_unregister_asset(obj), + UnregisterBox::Role(obj) => visitor.visit_unregister_role(obj), + UnregisterBox::Trigger(obj) => visitor.visit_unregister_trigger(obj), } } -pub fn visit_mint(visitor: &mut V, authority: &AccountId, isi: &MintBox) { +pub fn visit_mint(visitor: &mut V, isi: &MintBox) { match isi { - MintBox::Asset(obj) => visitor.visit_mint_asset_numeric(authority, obj), - MintBox::TriggerRepetitions(obj) => visitor.visit_mint_trigger_repetitions(authority, obj), + MintBox::Asset(obj) => visitor.visit_mint_asset_numeric(obj), + MintBox::TriggerRepetitions(obj) => visitor.visit_mint_trigger_repetitions(obj), } } -pub fn visit_burn(visitor: &mut V, authority: &AccountId, isi: &BurnBox) { +pub fn visit_burn(visitor: &mut V, isi: &BurnBox) { match isi { - BurnBox::Asset(obj) => visitor.visit_burn_asset_numeric(authority, obj), - BurnBox::TriggerRepetitions(obj) => visitor.visit_burn_trigger_repetitions(authority, obj), + BurnBox::Asset(obj) => visitor.visit_burn_asset_numeric(obj), + BurnBox::TriggerRepetitions(obj) => visitor.visit_burn_trigger_repetitions(obj), } } -pub fn visit_transfer( - visitor: &mut V, - authority: &AccountId, - isi: &TransferBox, -) { +pub fn visit_transfer(visitor: &mut V, isi: &TransferBox) { match isi { - TransferBox::Domain(obj) => visitor.visit_transfer_domain(authority, obj), - TransferBox::AssetDefinition(obj) => { - visitor.visit_transfer_asset_definition(authority, obj) - } + TransferBox::Domain(obj) => visitor.visit_transfer_domain(obj), + TransferBox::AssetDefinition(obj) => visitor.visit_transfer_asset_definition(obj), TransferBox::Asset(transfer_asset) => match transfer_asset { - AssetTransferBox::Numeric(obj) => visitor.visit_transfer_asset_numeric(authority, obj), - AssetTransferBox::Store(obj) => visitor.visit_transfer_asset_store(authority, obj), + AssetTransferBox::Numeric(obj) => visitor.visit_transfer_asset_numeric(obj), + AssetTransferBox::Store(obj) => visitor.visit_transfer_asset_store(obj), }, } } -pub fn visit_set_key_value( - visitor: &mut V, - authority: &AccountId, - isi: &SetKeyValueBox, -) { +pub fn visit_set_key_value(visitor: &mut V, isi: &SetKeyValueBox) { match isi { - SetKeyValueBox::Domain(obj) => visitor.visit_set_domain_key_value(authority, obj), - SetKeyValueBox::Account(obj) => visitor.visit_set_account_key_value(authority, obj), - SetKeyValueBox::AssetDefinition(obj) => { - visitor.visit_set_asset_definition_key_value(authority, obj) - } - SetKeyValueBox::Asset(obj) => visitor.visit_set_asset_key_value(authority, obj), - SetKeyValueBox::Trigger(obj) => visitor.visit_set_trigger_key_value(authority, obj), + SetKeyValueBox::Domain(obj) => visitor.visit_set_domain_key_value(obj), + SetKeyValueBox::Account(obj) => visitor.visit_set_account_key_value(obj), + SetKeyValueBox::AssetDefinition(obj) => visitor.visit_set_asset_definition_key_value(obj), + SetKeyValueBox::Asset(obj) => visitor.visit_set_asset_key_value(obj), + SetKeyValueBox::Trigger(obj) => visitor.visit_set_trigger_key_value(obj), } } -pub fn visit_remove_key_value( - visitor: &mut V, - authority: &AccountId, - isi: &RemoveKeyValueBox, -) { +pub fn visit_remove_key_value(visitor: &mut V, isi: &RemoveKeyValueBox) { match isi { - RemoveKeyValueBox::Domain(obj) => visitor.visit_remove_domain_key_value(authority, obj), - RemoveKeyValueBox::Account(obj) => visitor.visit_remove_account_key_value(authority, obj), + RemoveKeyValueBox::Domain(obj) => visitor.visit_remove_domain_key_value(obj), + RemoveKeyValueBox::Account(obj) => visitor.visit_remove_account_key_value(obj), RemoveKeyValueBox::AssetDefinition(obj) => { - visitor.visit_remove_asset_definition_key_value(authority, obj) + visitor.visit_remove_asset_definition_key_value(obj) } - RemoveKeyValueBox::Asset(obj) => visitor.visit_remove_asset_key_value(authority, obj), - RemoveKeyValueBox::Trigger(obj) => visitor.visit_remove_trigger_key_value(authority, obj), + RemoveKeyValueBox::Asset(obj) => visitor.visit_remove_asset_key_value(obj), + RemoveKeyValueBox::Trigger(obj) => visitor.visit_remove_trigger_key_value(obj), } } -pub fn visit_grant(visitor: &mut V, authority: &AccountId, isi: &GrantBox) { +pub fn visit_grant(visitor: &mut V, isi: &GrantBox) { match isi { - GrantBox::Permission(obj) => visitor.visit_grant_account_permission(authority, obj), - GrantBox::Role(obj) => visitor.visit_grant_account_role(authority, obj), - GrantBox::RolePermission(obj) => visitor.visit_grant_role_permission(authority, obj), + GrantBox::Permission(obj) => visitor.visit_grant_account_permission(obj), + GrantBox::Role(obj) => visitor.visit_grant_account_role(obj), + GrantBox::RolePermission(obj) => visitor.visit_grant_role_permission(obj), } } -pub fn visit_revoke(visitor: &mut V, authority: &AccountId, isi: &RevokeBox) { +pub fn visit_revoke(visitor: &mut V, isi: &RevokeBox) { match isi { - RevokeBox::Permission(obj) => visitor.visit_revoke_account_permission(authority, obj), - RevokeBox::Role(obj) => visitor.visit_revoke_account_role(authority, obj), - RevokeBox::RolePermission(obj) => visitor.visit_revoke_role_permission(authority, obj), + RevokeBox::Permission(obj) => visitor.visit_revoke_account_permission(obj), + RevokeBox::Role(obj) => visitor.visit_revoke_account_role(obj), + RevokeBox::RolePermission(obj) => visitor.visit_revoke_role_permission(obj), } } macro_rules! leaf_visitors { ( $($visitor:ident($operation:ty)),+ $(,)? ) => { $( - pub fn $visitor(_visitor: &mut V, _authority: &AccountId, _operation: $operation) { + pub fn $visitor(_visitor: &mut V, _operation: $operation) { } )+ }; diff --git a/crates/iroha_executor/src/default.rs b/crates/iroha_executor/src/default.rs index 178c3b619e5..c2814a04a82 100644 --- a/crates/iroha_executor/src/default.rs +++ b/crates/iroha_executor/src/default.rs @@ -1,4 +1,4 @@ -//! Definition of Iroha default executor and accompanying validation functions +//! Definition of Iroha default executor and accompanying execute functions #![allow(missing_docs, clippy::missing_errors_doc)] use alloc::format; @@ -41,7 +41,7 @@ pub use trigger::{ use crate::{ deny, execute, permission::{AnyPermission, ExecutorPermission as _}, - Validate, + Execute, }; // NOTE: If any new `visit_..` functions are introduced in this module, one should @@ -49,81 +49,75 @@ use crate::{ // `iroha_executor::derive::default::impl_derive_visit` function // signature list. -/// Default validation for [`SignedTransaction`]. +/// Execute [`SignedTransaction`]. +/// +/// Transaction is executed following successful validation. /// /// # Warning /// -/// Each instruction is executed in sequence following successful validation. /// [`Executable::Wasm`] is not executed because it is validated on the host side. -pub fn visit_transaction( +pub fn visit_transaction( executor: &mut V, - authority: &AccountId, transaction: &SignedTransaction, ) { match transaction.instructions() { - Executable::Wasm(wasm) => executor.visit_wasm(authority, wasm), + Executable::Wasm(wasm) => executor.visit_wasm(wasm), Executable::Instructions(instructions) => { for isi in instructions { if executor.verdict().is_ok() { - executor.visit_instruction(authority, isi); + executor.visit_instruction(isi); } } } } } -/// Default validation for [`InstructionBox`]. -/// -/// # Warning +/// Execute [`InstructionBox`]. /// /// Instruction is executed following successful validation -pub fn visit_instruction( - executor: &mut V, - authority: &AccountId, - isi: &InstructionBox, -) { +pub fn visit_instruction(executor: &mut V, isi: &InstructionBox) { match isi { InstructionBox::SetParameter(isi) => { - executor.visit_set_parameter(authority, isi); + executor.visit_set_parameter(isi); } InstructionBox::Log(isi) => { - executor.visit_log(authority, isi); + executor.visit_log(isi); } InstructionBox::ExecuteTrigger(isi) => { - executor.visit_execute_trigger(authority, isi); + executor.visit_execute_trigger(isi); } InstructionBox::Burn(isi) => { - executor.visit_burn(authority, isi); + executor.visit_burn(isi); } InstructionBox::Grant(isi) => { - executor.visit_grant(authority, isi); + executor.visit_grant(isi); } InstructionBox::Mint(isi) => { - executor.visit_mint(authority, isi); + executor.visit_mint(isi); } InstructionBox::Register(isi) => { - executor.visit_register(authority, isi); + executor.visit_register(isi); } InstructionBox::RemoveKeyValue(isi) => { - executor.visit_remove_key_value(authority, isi); + executor.visit_remove_key_value(isi); } InstructionBox::Revoke(isi) => { - executor.visit_revoke(authority, isi); + executor.visit_revoke(isi); } InstructionBox::SetKeyValue(isi) => { - executor.visit_set_key_value(authority, isi); + executor.visit_set_key_value(isi); } InstructionBox::Transfer(isi) => { - executor.visit_transfer(authority, isi); + executor.visit_transfer(isi); } InstructionBox::Unregister(isi) => { - executor.visit_unregister(authority, isi); + executor.visit_unregister(isi); } InstructionBox::Upgrade(isi) => { - executor.visit_upgrade(authority, isi); + executor.visit_upgrade(isi); } InstructionBox::Custom(isi) => { - executor.visit_custom(authority, isi); + executor.visit_custom(isi); } } } @@ -133,30 +127,28 @@ pub mod peer { use super::*; - pub fn visit_register_peer( + pub fn visit_register_peer( executor: &mut V, - authority: &AccountId, isi: &Register, ) { if is_genesis(executor) { execute!(executor, isi); } - if CanManagePeers.is_owned_by(authority) { + if CanManagePeers.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } deny!(executor, "Can't register peer"); } - pub fn visit_unregister_peer( + pub fn visit_unregister_peer( executor: &mut V, - authority: &AccountId, isi: &Unregister, ) { if is_genesis(executor) { execute!(executor, isi); } - if CanManagePeers.is_owned_by(authority) { + if CanManagePeers.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } @@ -175,30 +167,28 @@ pub mod domain { account::is_account_owner, accounts_permissions, domain::is_domain_owner, roles_permissions, }; - pub fn visit_register_domain( + pub fn visit_register_domain( executor: &mut V, - authority: &AccountId, isi: &Register, ) { if is_genesis(executor) { execute!(executor, isi); } - if CanRegisterDomain.is_owned_by(authority) { + if CanRegisterDomain.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } deny!(executor, "Can't register domain"); } - pub fn visit_unregister_domain( + pub fn visit_unregister_domain( executor: &mut V, - authority: &AccountId, isi: &Unregister, ) { let domain_id = isi.object(); if is_genesis(executor) - || match is_domain_owner(domain_id, authority) { + || match is_domain_owner(domain_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(is_domain_owner) => is_domain_owner, } @@ -206,23 +196,30 @@ pub mod domain { let can_unregister_domain_token = CanUnregisterDomain { domain: domain_id.clone(), }; - can_unregister_domain_token.is_owned_by(authority) + can_unregister_domain_token + .is_owned_by(&executor.context().authority, executor.host()) } { - use iroha_smart_contract::ExecuteOnHost as _; - - for (owner_id, permission) in accounts_permissions() { + let mut err = None; + for (owner_id, permission) in accounts_permissions(executor.host()) { if is_permission_domain_associated(&permission, domain_id) { - let isi = Revoke::account_permission(permission, owner_id.clone()); - if let Err(err) = isi.execute() { - deny!(executor, err); + let isi = &Revoke::account_permission(permission, owner_id.clone()); + + if let Err(error) = executor.host().submit(isi) { + err = Some(error); + break; } } } - for (role_id, permission) in roles_permissions() { + if let Some(err) = err { + deny!(executor, err); + } + + for (role_id, permission) in roles_permissions(executor.host()) { if is_permission_domain_associated(&permission, domain_id) { - let isi = Revoke::role_permission(permission, role_id.clone()); - if let Err(err) = isi.execute() { + let isi = &Revoke::role_permission(permission, role_id.clone()); + + if let Err(err) = executor.host().submit(isi) { deny!(executor, err); } } @@ -232,9 +229,8 @@ pub mod domain { deny!(executor, "Can't unregister domain"); } - pub fn visit_transfer_domain( + pub fn visit_transfer_domain( executor: &mut V, - authority: &AccountId, isi: &Transfer, ) { let source_id = isi.source(); @@ -243,12 +239,12 @@ pub mod domain { if is_genesis(executor) { execute!(executor, isi); } - match is_account_owner(source_id, authority) { + match is_account_owner(source_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} } - match is_domain_owner(domain_id, authority) { + match is_domain_owner(domain_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -257,9 +253,8 @@ pub mod domain { deny!(executor, "Can't transfer domain of another account"); } - pub fn visit_set_domain_key_value( + pub fn visit_set_domain_key_value( executor: &mut V, - authority: &AccountId, isi: &SetKeyValue, ) { let domain_id = isi.object(); @@ -267,7 +262,7 @@ pub mod domain { if is_genesis(executor) { execute!(executor, isi); } - match is_domain_owner(domain_id, authority) { + match is_domain_owner(domain_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -275,16 +270,17 @@ pub mod domain { let can_set_key_value_in_domain_token = CanModifyDomainMetadata { domain: domain_id.clone(), }; - if can_set_key_value_in_domain_token.is_owned_by(authority) { + if can_set_key_value_in_domain_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } deny!(executor, "Can't set key value in domain metadata"); } - pub fn visit_remove_domain_key_value( + pub fn visit_remove_domain_key_value( executor: &mut V, - authority: &AccountId, isi: &RemoveKeyValue, ) { let domain_id = isi.object(); @@ -292,7 +288,7 @@ pub mod domain { if is_genesis(executor) { execute!(executor, isi); } - match is_domain_owner(domain_id, authority) { + match is_domain_owner(domain_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -300,7 +296,9 @@ pub mod domain { let can_remove_key_value_in_domain_token = CanModifyDomainMetadata { domain: domain_id.clone(), }; - if can_remove_key_value_in_domain_token.is_owned_by(authority) { + if can_remove_key_value_in_domain_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -331,13 +329,13 @@ pub mod domain { AnyPermission::CanUnregisterAssetWithDefinition(permission) => { permission.asset_definition.domain() == domain_id } - AnyPermission::CanMintAssetsWithDefinition(permission) => { + AnyPermission::CanMintAssetWithDefinition(permission) => { permission.asset_definition.domain() == domain_id } - AnyPermission::CanBurnAssetsWithDefinition(permission) => { + AnyPermission::CanBurnAssetWithDefinition(permission) => { permission.asset_definition.domain() == domain_id } - AnyPermission::CanTransferAssetsWithDefinition(permission) => { + AnyPermission::CanTransferAssetWithDefinition(permission) => { permission.asset_definition.domain() == domain_id } AnyPermission::CanRegisterAsset(permission) => permission.owner.domain() == domain_id, @@ -391,14 +389,17 @@ pub mod account { use super::*; use crate::permission::{account::is_account_owner, accounts_permissions, roles_permissions}; - pub fn visit_register_account( + pub fn visit_register_account( executor: &mut V, - authority: &AccountId, isi: &Register, ) { let domain_id = isi.object().id().domain(); - match crate::permission::domain::is_domain_owner(domain_id, authority) { + match crate::permission::domain::is_domain_owner( + domain_id, + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -407,7 +408,9 @@ pub mod account { let can_register_account_in_domain = CanRegisterAccount { domain: domain_id.clone(), }; - if can_register_account_in_domain.is_owned_by(authority) { + if can_register_account_in_domain + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -417,15 +420,14 @@ pub mod account { ); } - pub fn visit_unregister_account( + pub fn visit_unregister_account( executor: &mut V, - authority: &AccountId, isi: &Unregister, ) { let account_id = isi.object(); if is_genesis(executor) - || match is_account_owner(account_id, authority) { + || match is_account_owner(account_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(is_account_owner) => is_account_owner, } @@ -433,23 +435,30 @@ pub mod account { let can_unregister_user_account = CanUnregisterAccount { account: account_id.clone(), }; - can_unregister_user_account.is_owned_by(authority) + can_unregister_user_account + .is_owned_by(&executor.context().authority, executor.host()) } { - use iroha_smart_contract::ExecuteOnHost as _; - - for (owner_id, permission) in accounts_permissions() { + let mut err = None; + for (owner_id, permission) in accounts_permissions(executor.host()) { if is_permission_account_associated(&permission, account_id) { - let isi = Revoke::account_permission(permission, owner_id.clone()); - if let Err(err) = isi.execute() { - deny!(executor, err); + let isi = &Revoke::account_permission(permission, owner_id.clone()); + + if let Err(error) = executor.host().submit(isi) { + err = Some(error); + break; } } } - for (role_id, permission) in roles_permissions() { + if let Some(err) = err { + deny!(executor, err); + } + + for (role_id, permission) in roles_permissions(executor.host()) { if is_permission_account_associated(&permission, account_id) { - let isi = Revoke::role_permission(permission, role_id.clone()); - if let Err(err) = isi.execute() { + let isi = &Revoke::role_permission(permission, role_id.clone()); + + if let Err(err) = executor.host().submit(isi) { deny!(executor, err); } } @@ -459,9 +468,8 @@ pub mod account { deny!(executor, "Can't unregister another account"); } - pub fn visit_set_account_key_value( + pub fn visit_set_account_key_value( executor: &mut V, - authority: &AccountId, isi: &SetKeyValue, ) { let account_id = isi.object(); @@ -469,7 +477,7 @@ pub mod account { if is_genesis(executor) { execute!(executor, isi); } - match is_account_owner(account_id, authority) { + match is_account_owner(account_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -477,7 +485,9 @@ pub mod account { let can_set_key_value_in_user_account_token = CanModifyAccountMetadata { account: account_id.clone(), }; - if can_set_key_value_in_user_account_token.is_owned_by(authority) { + if can_set_key_value_in_user_account_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -487,9 +497,8 @@ pub mod account { ); } - pub fn visit_remove_account_key_value( + pub fn visit_remove_account_key_value( executor: &mut V, - authority: &AccountId, isi: &RemoveKeyValue, ) { let account_id = isi.object(); @@ -497,7 +506,7 @@ pub mod account { if is_genesis(executor) { execute!(executor, isi); } - match is_account_owner(account_id, authority) { + match is_account_owner(account_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -505,7 +514,9 @@ pub mod account { let can_remove_key_value_in_user_account_token = CanModifyAccountMetadata { account: account_id.clone(), }; - if can_remove_key_value_in_user_account_token.is_owned_by(authority) { + if can_remove_key_value_in_user_account_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -549,9 +560,9 @@ pub mod account { | AnyPermission::CanModifyAssetDefinitionMetadata(_) | AnyPermission::CanRegisterAssetWithDefinition(_) | AnyPermission::CanUnregisterAssetWithDefinition(_) - | AnyPermission::CanMintAssetsWithDefinition(_) - | AnyPermission::CanBurnAssetsWithDefinition(_) - | AnyPermission::CanTransferAssetsWithDefinition(_) + | AnyPermission::CanMintAssetWithDefinition(_) + | AnyPermission::CanBurnAssetWithDefinition(_) + | AnyPermission::CanTransferAssetWithDefinition(_) | AnyPermission::CanSetParameters(_) | AnyPermission::CanManageRoles(_) | AnyPermission::CanUpgradeExecutor(_) => false, @@ -571,14 +582,17 @@ pub mod asset_definition { asset_definition::is_asset_definition_owner, roles_permissions, }; - pub fn visit_register_asset_definition( + pub fn visit_register_asset_definition( executor: &mut V, - authority: &AccountId, isi: &Register, ) { let domain_id = isi.object().id().domain(); - match crate::permission::domain::is_domain_owner(domain_id, authority) { + match crate::permission::domain::is_domain_owner( + domain_id, + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -587,7 +601,9 @@ pub mod asset_definition { let can_register_asset_definition_in_domain_token = CanRegisterAssetDefinition { domain: domain_id.clone(), }; - if can_register_asset_definition_in_domain_token.is_owned_by(authority) { + if can_register_asset_definition_in_domain_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -597,15 +613,18 @@ pub mod asset_definition { ); } - pub fn visit_unregister_asset_definition( + pub fn visit_unregister_asset_definition( executor: &mut V, - authority: &AccountId, isi: &Unregister, ) { let asset_definition_id = isi.object(); if is_genesis(executor) - || match is_asset_definition_owner(asset_definition_id, authority) { + || match is_asset_definition_owner( + asset_definition_id, + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(is_asset_definition_owner) => is_asset_definition_owner, } @@ -613,23 +632,30 @@ pub mod asset_definition { let can_unregister_asset_definition_token = CanUnregisterAssetDefinition { asset_definition: asset_definition_id.clone(), }; - can_unregister_asset_definition_token.is_owned_by(authority) + can_unregister_asset_definition_token + .is_owned_by(&executor.context().authority, executor.host()) } { - use iroha_smart_contract::ExecuteOnHost as _; - - for (owner_id, permission) in accounts_permissions() { + let mut err = None; + for (owner_id, permission) in accounts_permissions(executor.host()) { if is_permission_asset_definition_associated(&permission, asset_definition_id) { - let isi = Revoke::account_permission(permission, owner_id.clone()); - if let Err(err) = isi.execute() { - deny!(executor, err); + let isi = &Revoke::account_permission(permission, owner_id.clone()); + + if let Err(error) = executor.host().submit(isi) { + err = Some(error); + break; } } } - for (role_id, permission) in roles_permissions() { + if let Some(err) = err { + deny!(executor, err); + } + + for (role_id, permission) in roles_permissions(executor.host()) { if is_permission_asset_definition_associated(&permission, asset_definition_id) { - let isi = Revoke::role_permission(permission, role_id.clone()); - if let Err(err) = isi.execute() { + let isi = &Revoke::role_permission(permission, role_id.clone()); + + if let Err(err) = executor.host().submit(isi) { deny!(executor, err); } } @@ -642,9 +668,8 @@ pub mod asset_definition { ); } - pub fn visit_transfer_asset_definition( + pub fn visit_transfer_asset_definition( executor: &mut V, - authority: &AccountId, isi: &Transfer, ) { let source_id = isi.source(); @@ -653,12 +678,16 @@ pub mod asset_definition { if is_genesis(executor) { execute!(executor, isi); } - match is_account_owner(source_id, authority) { + match is_account_owner(source_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} } - match is_asset_definition_owner(asset_definition_id, authority) { + match is_asset_definition_owner( + asset_definition_id, + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -670,9 +699,8 @@ pub mod asset_definition { ); } - pub fn visit_set_asset_definition_key_value( + pub fn visit_set_asset_definition_key_value( executor: &mut V, - authority: &AccountId, isi: &SetKeyValue, ) { let asset_definition_id = isi.object(); @@ -680,7 +708,11 @@ pub mod asset_definition { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_definition_owner(asset_definition_id, authority) { + match is_asset_definition_owner( + asset_definition_id, + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -688,7 +720,9 @@ pub mod asset_definition { let can_set_key_value_in_asset_definition_token = CanModifyAssetDefinitionMetadata { asset_definition: asset_definition_id.clone(), }; - if can_set_key_value_in_asset_definition_token.is_owned_by(authority) { + if can_set_key_value_in_asset_definition_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -698,9 +732,8 @@ pub mod asset_definition { ); } - pub fn visit_remove_asset_definition_key_value( + pub fn visit_remove_asset_definition_key_value( executor: &mut V, - authority: &AccountId, isi: &RemoveKeyValue, ) { let asset_definition_id = isi.object(); @@ -708,7 +741,11 @@ pub mod asset_definition { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_definition_owner(asset_definition_id, authority) { + match is_asset_definition_owner( + asset_definition_id, + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -716,7 +753,9 @@ pub mod asset_definition { let can_remove_key_value_in_asset_definition_token = CanModifyAssetDefinitionMetadata { asset_definition: asset_definition_id.clone(), }; - if can_remove_key_value_in_asset_definition_token.is_owned_by(authority) { + if can_remove_key_value_in_asset_definition_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -746,13 +785,13 @@ pub mod asset_definition { AnyPermission::CanUnregisterAssetWithDefinition(permission) => { &permission.asset_definition == asset_definition_id } - AnyPermission::CanMintAssetsWithDefinition(permission) => { + AnyPermission::CanMintAssetWithDefinition(permission) => { &permission.asset_definition == asset_definition_id } - AnyPermission::CanBurnAssetsWithDefinition(permission) => { + AnyPermission::CanBurnAssetWithDefinition(permission) => { &permission.asset_definition == asset_definition_id } - AnyPermission::CanTransferAssetsWithDefinition(permission) => { + AnyPermission::CanTransferAssetWithDefinition(permission) => { &permission.asset_definition == asset_definition_id } AnyPermission::CanUnregisterAsset(permission) => { @@ -793,9 +832,10 @@ pub mod asset_definition { pub mod asset { use iroha_executor_data_model::permission::asset::{ - CanBurnAsset, CanBurnAssetsWithDefinition, CanMintAsset, CanMintAssetsWithDefinition, - CanModifyAssetMetadata, CanRegisterAsset, CanRegisterAssetWithDefinition, CanTransferAsset, - CanTransferAssetsWithDefinition, CanUnregisterAsset, CanUnregisterAssetWithDefinition, + CanBurnAsset, CanBurnAssetWithDefinition, CanMintAsset, CanMintAssetWithDefinition, + CanModifyAssetMetadata, CanRegisterAsset, CanRegisterAssetWithDefinition, + CanTransferAsset, CanTransferAssetWithDefinition, CanUnregisterAsset, + CanUnregisterAssetWithDefinition, }; use iroha_smart_contract::data_model::{ asset::AssetValue, isi::BuiltInInstruction, metadata::Metadata, @@ -805,9 +845,8 @@ pub mod asset { use super::*; use crate::permission::{asset::is_asset_owner, asset_definition::is_asset_definition_owner}; - pub fn visit_register_asset( + pub fn visit_register_asset( executor: &mut V, - authority: &AccountId, isi: &Register, ) { let asset = isi.object(); @@ -815,7 +854,11 @@ pub mod asset { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_definition_owner(asset.id().definition(), authority) { + match is_asset_definition_owner( + asset.id().definition(), + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -823,13 +866,16 @@ pub mod asset { let can_register_assets_with_definition_token = CanRegisterAssetWithDefinition { asset_definition: asset.id().definition().clone(), }; - if can_register_assets_with_definition_token.is_owned_by(authority) { + if can_register_assets_with_definition_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } let can_register_user_asset_token = CanRegisterAsset { owner: asset.id().account().clone(), }; - if can_register_user_asset_token.is_owned_by(authority) { + if can_register_user_asset_token.is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -839,9 +885,8 @@ pub mod asset { ); } - pub fn visit_unregister_asset( + pub fn visit_unregister_asset( executor: &mut V, - authority: &AccountId, isi: &Unregister, ) { let asset_id = isi.object(); @@ -849,12 +894,16 @@ pub mod asset { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_owner(asset_id, authority) { + match is_asset_owner(asset_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} } - match is_asset_definition_owner(asset_id.definition(), authority) { + match is_asset_definition_owner( + asset_id.definition(), + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -862,22 +911,26 @@ pub mod asset { let can_unregister_assets_with_definition_token = CanUnregisterAssetWithDefinition { asset_definition: asset_id.definition().clone(), }; - if can_unregister_assets_with_definition_token.is_owned_by(authority) { + if can_unregister_assets_with_definition_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } let can_unregister_user_asset_token = CanUnregisterAsset { asset: asset_id.clone(), }; - if can_unregister_user_asset_token.is_owned_by(authority) { + if can_unregister_user_asset_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } deny!(executor, "Can't unregister asset from another account"); } - fn validate_mint_asset(executor: &mut V, authority: &AccountId, isi: &Mint) + fn execute_mint_asset(executor: &mut V, isi: &Mint) where - V: Validate + Visit + ?Sized, + V: Execute + Visit + ?Sized, Q: Into, Mint: BuiltInInstruction + Encode, { @@ -885,21 +938,27 @@ pub mod asset { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_definition_owner(asset_id.definition(), authority) { + match is_asset_definition_owner( + asset_id.definition(), + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_mint_assets_with_definition_token = CanMintAssetsWithDefinition { + let can_mint_assets_with_definition_token = CanMintAssetWithDefinition { asset_definition: asset_id.definition().clone(), }; - if can_mint_assets_with_definition_token.is_owned_by(authority) { + if can_mint_assets_with_definition_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } let can_mint_user_asset_token = CanMintAsset { asset: asset_id.clone(), }; - if can_mint_user_asset_token.is_owned_by(authority) { + if can_mint_user_asset_token.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } @@ -909,17 +968,16 @@ pub mod asset { ); } - pub fn visit_mint_asset_numeric( + pub fn visit_mint_asset_numeric( executor: &mut V, - authority: &AccountId, isi: &Mint, ) { - validate_mint_asset(executor, authority, isi); + execute_mint_asset(executor, isi); } - fn validate_burn_asset(executor: &mut V, authority: &AccountId, isi: &Burn) + fn execute_burn_asset(executor: &mut V, isi: &Burn) where - V: Validate + Visit + ?Sized, + V: Execute + Visit + ?Sized, Q: Into, Burn: BuiltInInstruction + Encode, { @@ -927,41 +985,48 @@ pub mod asset { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_definition_owner(asset_id.definition(), authority) { + match is_asset_owner(asset_id, &executor.context().authority, executor.host()) { + Err(err) => deny!(executor, err), + Ok(true) => execute!(executor, isi), + Ok(false) => {} + } + match is_asset_definition_owner( + asset_id.definition(), + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_burn_assets_with_definition_token = CanBurnAssetsWithDefinition { + let can_burn_assets_with_definition_token = CanBurnAssetWithDefinition { asset_definition: asset_id.definition().clone(), }; - if can_burn_assets_with_definition_token.is_owned_by(authority) { + if can_burn_assets_with_definition_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } let can_burn_user_asset_token = CanBurnAsset { asset: asset_id.clone(), }; - if can_burn_user_asset_token.is_owned_by(authority) { + if can_burn_user_asset_token.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } deny!(executor, "Can't burn assets from another account"); } - pub fn visit_burn_asset_numeric( + pub fn visit_burn_asset_numeric( executor: &mut V, - authority: &AccountId, isi: &Burn, ) { - validate_burn_asset(executor, authority, isi); + execute_burn_asset(executor, isi); } - fn validate_transfer_asset( - executor: &mut V, - authority: &AccountId, - isi: &Transfer, - ) where - V: Validate + Visit + ?Sized, + fn execute_transfer_asset(executor: &mut V, isi: &Transfer) + where + V: Execute + Visit + ?Sized, Q: Into, Transfer: BuiltInInstruction + Encode, { @@ -969,51 +1034,55 @@ pub mod asset { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_owner(asset_id, authority) { + match is_asset_owner(asset_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} } - match is_asset_definition_owner(asset_id.definition(), authority) { + match is_asset_definition_owner( + asset_id.definition(), + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_transfer_assets_with_definition_token = CanTransferAssetsWithDefinition { + let can_transfer_assets_with_definition_token = CanTransferAssetWithDefinition { asset_definition: asset_id.definition().clone(), }; - if can_transfer_assets_with_definition_token.is_owned_by(authority) { + if can_transfer_assets_with_definition_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } let can_transfer_user_asset_token = CanTransferAsset { asset: asset_id.clone(), }; - if can_transfer_user_asset_token.is_owned_by(authority) { + if can_transfer_user_asset_token.is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } deny!(executor, "Can't transfer assets of another account"); } - pub fn visit_transfer_asset_numeric( + pub fn visit_transfer_asset_numeric( executor: &mut V, - authority: &AccountId, isi: &Transfer, ) { - validate_transfer_asset(executor, authority, isi); + execute_transfer_asset(executor, isi); } - pub fn visit_transfer_asset_store( + pub fn visit_transfer_asset_store( executor: &mut V, - authority: &AccountId, isi: &Transfer, ) { - validate_transfer_asset(executor, authority, isi); + execute_transfer_asset(executor, isi); } - pub fn visit_set_asset_key_value( + pub fn visit_set_asset_key_value( executor: &mut V, - authority: &AccountId, isi: &SetKeyValue, ) { let asset_id = isi.object(); @@ -1021,7 +1090,7 @@ pub mod asset { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_owner(asset_id, authority) { + match is_asset_owner(asset_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -1030,7 +1099,9 @@ pub mod asset { let can_set_key_value_in_user_asset_token = CanModifyAssetMetadata { asset: asset_id.clone(), }; - if can_set_key_value_in_user_asset_token.is_owned_by(authority) { + if can_set_key_value_in_user_asset_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -1040,9 +1111,8 @@ pub mod asset { ); } - pub fn visit_remove_asset_key_value( + pub fn visit_remove_asset_key_value( executor: &mut V, - authority: &AccountId, isi: &RemoveKeyValue, ) { let asset_id = isi.object(); @@ -1050,7 +1120,7 @@ pub mod asset { if is_genesis(executor) { execute!(executor, isi); } - match is_asset_owner(asset_id, authority) { + match is_asset_owner(asset_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -1058,7 +1128,9 @@ pub mod asset { let can_remove_key_value_in_user_asset_token = CanModifyAssetMetadata { asset: asset_id.clone(), }; - if can_remove_key_value_in_user_asset_token.is_owned_by(authority) { + if can_remove_key_value_in_user_asset_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -1074,15 +1146,11 @@ pub mod parameter { use super::*; - pub fn visit_set_parameter( - executor: &mut V, - authority: &AccountId, - isi: &SetParameter, - ) { + pub fn visit_set_parameter(executor: &mut V, isi: &SetParameter) { if is_genesis(executor) { execute!(executor, isi); } - if CanSetParameters.is_owned_by(authority) { + if CanSetParameters.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } @@ -1095,16 +1163,16 @@ pub mod parameter { pub mod role { use iroha_executor_data_model::permission::role::CanManageRoles; - use iroha_smart_contract::data_model::role::Role; + use iroha_smart_contract::{data_model::role::Role, Iroha}; use super::*; - macro_rules! impl_validate_grant_revoke_account_role { - ($executor:ident, $isi:ident, $authority:ident) => { + macro_rules! impl_execute_grant_revoke_account_role { + ($executor:ident, $isi:ident) => { let role_id = $isi.object(); if is_genesis($executor) - || find_account_roles($authority.clone()) + || find_account_roles($executor.context().authority.clone(), $executor.host()) .any(|authority_role_id| authority_role_id == *role_id) { execute!($executor, $isi) @@ -1114,14 +1182,14 @@ pub mod role { }; } - macro_rules! impl_validate_grant_revoke_role_permission { - ($executor:ident, $isi:ident, $authority:ident, $method:ident, $isi_type:ty) => { + macro_rules! impl_execute_grant_revoke_role_permission { + ($executor:ident, $isi:ident, $method:ident, $isi_type:ty) => { let role_id = $isi.destination().clone(); let permission = $isi.object(); if let Ok(any_permission) = AnyPermission::try_from(permission) { if !is_genesis($executor) { - if !find_account_roles($authority.clone()) + if !find_account_roles($executor.context().authority.clone(), $executor.host()) .any(|authority_role_id| authority_role_id == role_id) { deny!($executor, "Can't modify role"); @@ -1129,14 +1197,15 @@ pub mod role { if let Err(error) = crate::permission::ValidateGrantRevoke::$method( &any_permission, - $authority, - $executor.block_height(), + &$executor.context().authority, + $executor.context(), + $executor.host(), ) { deny!($executor, error); } } - let isi = <$isi_type>::role_permission(any_permission, role_id); + let isi = &<$isi_type>::role_permission(any_permission, role_id); execute!($executor, isi); } @@ -1147,22 +1216,19 @@ pub mod role { }; } - fn find_account_roles(account_id: AccountId) -> impl Iterator { - use iroha_smart_contract_utils::debug::DebugExpectExt as _; + fn find_account_roles(account_id: AccountId, host: &Iroha) -> impl Iterator { + use iroha_smart_contract::debug::DebugExpectExt as _; - iroha_smart_contract::query(FindRolesByAccountId::new(account_id)) + host.query(FindRolesByAccountId::new(account_id)) .execute() .dbg_expect("INTERNAL BUG: `FindRolesByAccountId` must never fail") .map(|role| role.dbg_expect("Failed to get role from cursor")) } - pub fn visit_register_role( + pub fn visit_register_role( executor: &mut V, - authority: &AccountId, isi: &Register, ) { - use crate::smart_contract::ExecuteOnHost as _; - let role = isi.object(); let mut new_role = Role::new(role.id().clone(), role.grant_to().clone()); @@ -1174,7 +1240,8 @@ pub mod role { if let Err(error) = crate::permission::ValidateGrantRevoke::validate_grant( &any_permission, role.grant_to(), - executor.block_height(), + executor.context(), + executor.host(), ) { deny!(executor, error); } @@ -1189,11 +1256,13 @@ pub mod role { } } - let isi = Register::role(new_role); - if is_genesis(executor) || CanManageRoles.is_owned_by(authority) { - let grant_role = Grant::account_role(role.id().clone(), role.grant_to().clone()); + if is_genesis(executor) + || CanManageRoles.is_owned_by(&executor.context().authority, executor.host()) + { + let grant_role = &Grant::account_role(role.id().clone(), role.grant_to().clone()); - if let Err(err) = isi.execute() { + let isi = &Register::role(new_role); + if let Err(err) = executor.host().submit(isi) { executor.deny(err); } @@ -1203,51 +1272,46 @@ pub mod role { deny!(executor, "Can't register role"); } - pub fn visit_unregister_role( + pub fn visit_unregister_role( executor: &mut V, - authority: &AccountId, isi: &Unregister, ) { if is_genesis(executor) { execute!(executor, isi); } - if CanManageRoles.is_owned_by(authority) { + if CanManageRoles.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } deny!(executor, "Can't unregister role"); } - pub fn visit_grant_account_role( + pub fn visit_grant_account_role( executor: &mut V, - authority: &AccountId, isi: &Grant, ) { - impl_validate_grant_revoke_account_role!(executor, isi, authority); + impl_execute_grant_revoke_account_role!(executor, isi); } - pub fn visit_revoke_account_role( + pub fn visit_revoke_account_role( executor: &mut V, - authority: &AccountId, isi: &Revoke, ) { - impl_validate_grant_revoke_account_role!(executor, isi, authority); + impl_execute_grant_revoke_account_role!(executor, isi); } - pub fn visit_grant_role_permission( + pub fn visit_grant_role_permission( executor: &mut V, - authority: &AccountId, isi: &Grant, ) { - impl_validate_grant_revoke_role_permission!(executor, isi, authority, validate_grant, Grant); + impl_execute_grant_revoke_role_permission!(executor, isi, validate_grant, Grant); } - pub fn visit_revoke_role_permission( + pub fn visit_revoke_role_permission( executor: &mut V, - authority: &AccountId, isi: &Revoke, ) { - impl_validate_grant_revoke_role_permission!(executor, isi, authority, validate_revoke, Revoke); + impl_execute_grant_revoke_role_permission!(executor, isi, validate_revoke, Revoke); } } @@ -1263,16 +1327,19 @@ pub mod trigger { accounts_permissions, domain::is_domain_owner, roles_permissions, trigger::is_trigger_owner, }; - pub fn visit_register_trigger( + pub fn visit_register_trigger( executor: &mut V, - authority: &AccountId, isi: &Register, ) { let trigger = isi.object(); if is_genesis(executor) || { - match is_domain_owner(trigger.action().authority().domain(), authority) { + match is_domain_owner( + trigger.action().authority().domain(), + &executor.context().authority, + executor.host(), + ) { Err(err) => deny!(executor, err), Ok(is_domain_owner) => is_domain_owner, } @@ -1281,7 +1348,8 @@ pub mod trigger { let can_register_user_trigger_token = CanRegisterTrigger { authority: isi.object().action().authority().clone(), }; - can_register_user_trigger_token.is_owned_by(authority) + can_register_user_trigger_token + .is_owned_by(&executor.context().authority, executor.host()) } { execute!(executor, isi) @@ -1289,15 +1357,14 @@ pub mod trigger { deny!(executor, "Can't register trigger owned by another account"); } - pub fn visit_unregister_trigger( + pub fn visit_unregister_trigger( executor: &mut V, - authority: &AccountId, isi: &Unregister, ) { let trigger_id = isi.object(); if is_genesis(executor) - || match is_trigger_owner(trigger_id, authority) { + || match is_trigger_owner(trigger_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(is_trigger_owner) => is_trigger_owner, } @@ -1305,27 +1372,34 @@ pub mod trigger { let can_unregister_user_trigger_token = CanUnregisterTrigger { trigger: trigger_id.clone(), }; - can_unregister_user_trigger_token.is_owned_by(authority) + can_unregister_user_trigger_token + .is_owned_by(&executor.context().authority, executor.host()) } { - use iroha_smart_contract::ExecuteOnHost as _; - - for (owner_id, permission) in accounts_permissions() { + let mut err = None; + for (owner_id, permission) in accounts_permissions(executor.host()) { if is_permission_trigger_associated(&permission, trigger_id) { - let isi = Revoke::account_permission(permission, owner_id.clone()); - if let Err(err) = isi.execute() { - deny!(executor, err); + let isi = &Revoke::account_permission(permission, owner_id.clone()); + + if let Err(error) = executor.host().submit(isi) { + err = Some(error); + break; } } } - for (role_id, permission) in roles_permissions() { + if let Some(err) = err { + deny!(executor, err); + } + + for (role_id, permission) in roles_permissions(executor.host()) { if is_permission_trigger_associated(&permission, trigger_id) { - let isi = Revoke::role_permission(permission, role_id.clone()); - if let Err(err) = isi.execute() { + let isi = &Revoke::role_permission(permission, role_id.clone()); + if let Err(err) = executor.host().submit(isi) { deny!(executor, err); } } } + execute!(executor, isi); } deny!( @@ -1334,9 +1408,8 @@ pub mod trigger { ); } - pub fn visit_mint_trigger_repetitions( + pub fn visit_mint_trigger_repetitions( executor: &mut V, - authority: &AccountId, isi: &Mint, ) { let trigger_id = isi.destination(); @@ -1344,7 +1417,7 @@ pub mod trigger { if is_genesis(executor) { execute!(executor, isi); } - match is_trigger_owner(trigger_id, authority) { + match is_trigger_owner(trigger_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -1352,7 +1425,7 @@ pub mod trigger { let can_mint_user_trigger_token = CanModifyTrigger { trigger: trigger_id.clone(), }; - if can_mint_user_trigger_token.is_owned_by(authority) { + if can_mint_user_trigger_token.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } @@ -1362,9 +1435,8 @@ pub mod trigger { ); } - pub fn visit_burn_trigger_repetitions( + pub fn visit_burn_trigger_repetitions( executor: &mut V, - authority: &AccountId, isi: &Burn, ) { let trigger_id = isi.destination(); @@ -1372,7 +1444,7 @@ pub mod trigger { if is_genesis(executor) { execute!(executor, isi); } - match is_trigger_owner(trigger_id, authority) { + match is_trigger_owner(trigger_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -1380,7 +1452,7 @@ pub mod trigger { let can_mint_user_trigger_token = CanModifyTrigger { trigger: trigger_id.clone(), }; - if can_mint_user_trigger_token.is_owned_by(authority) { + if can_mint_user_trigger_token.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } @@ -1390,9 +1462,8 @@ pub mod trigger { ); } - pub fn visit_execute_trigger( + pub fn visit_execute_trigger( executor: &mut V, - authority: &AccountId, isi: &ExecuteTrigger, ) { let trigger_id = isi.trigger(); @@ -1400,7 +1471,7 @@ pub mod trigger { if is_genesis(executor) { execute!(executor, isi); } - match is_trigger_owner(trigger_id, authority) { + match is_trigger_owner(trigger_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -1408,16 +1479,15 @@ pub mod trigger { let can_execute_trigger_token = CanExecuteTrigger { trigger: trigger_id.clone(), }; - if can_execute_trigger_token.is_owned_by(authority) { + if can_execute_trigger_token.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } deny!(executor, "Can't execute trigger owned by another account"); } - pub fn visit_set_trigger_key_value( + pub fn visit_set_trigger_key_value( executor: &mut V, - authority: &AccountId, isi: &SetKeyValue, ) { let trigger_id = isi.object(); @@ -1425,7 +1495,7 @@ pub mod trigger { if is_genesis(executor) { execute!(executor, isi); } - match is_trigger_owner(trigger_id, authority) { + match is_trigger_owner(trigger_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -1433,7 +1503,9 @@ pub mod trigger { let can_set_key_value_in_user_trigger_token = CanModifyTriggerMetadata { trigger: trigger_id.clone(), }; - if can_set_key_value_in_user_trigger_token.is_owned_by(authority) { + if can_set_key_value_in_user_trigger_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -1443,9 +1515,8 @@ pub mod trigger { ); } - pub fn visit_remove_trigger_key_value( + pub fn visit_remove_trigger_key_value( executor: &mut V, - authority: &AccountId, isi: &RemoveKeyValue, ) { let trigger_id = isi.object(); @@ -1453,7 +1524,7 @@ pub mod trigger { if is_genesis(executor) { execute!(executor, isi); } - match is_trigger_owner(trigger_id, authority) { + match is_trigger_owner(trigger_id, &executor.context().authority, executor.host()) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -1461,7 +1532,9 @@ pub mod trigger { let can_remove_key_value_in_trigger_token = CanModifyTriggerMetadata { trigger: trigger_id.clone(), }; - if can_remove_key_value_in_trigger_token.is_owned_by(authority) { + if can_remove_key_value_in_trigger_token + .is_owned_by(&executor.context().authority, executor.host()) + { execute!(executor, isi); } @@ -1497,9 +1570,9 @@ pub mod trigger { | AnyPermission::CanUnregisterAssetWithDefinition(_) | AnyPermission::CanRegisterAsset(_) | AnyPermission::CanUnregisterAsset(_) - | AnyPermission::CanMintAssetsWithDefinition(_) - | AnyPermission::CanBurnAssetsWithDefinition(_) - | AnyPermission::CanTransferAssetsWithDefinition(_) + | AnyPermission::CanMintAssetWithDefinition(_) + | AnyPermission::CanBurnAssetWithDefinition(_) + | AnyPermission::CanTransferAssetWithDefinition(_) | AnyPermission::CanModifyAssetMetadata(_) | AnyPermission::CanMintAsset(_) | AnyPermission::CanBurnAsset(_) @@ -1514,23 +1587,21 @@ pub mod trigger { pub mod permission { use super::*; - macro_rules! impl_validate { - ($executor:ident, $authority:ident, $isi:ident, $method:ident, $isi_type:ty) => { + macro_rules! impl_execute { + ($executor:ident, $isi:ident, $method:ident, $isi_type:ty) => { let account_id = $isi.destination().clone(); let permission = $isi.object(); if let Ok(any_permission) = AnyPermission::try_from(permission) { if !is_genesis($executor) { - if let Err(error) = crate::permission::ValidateGrantRevoke::$method( - &any_permission, - $authority, - $executor.block_height(), - ) { + if let Err(error) = + crate::permission::ValidateGrantRevoke::$method(&any_permission, &$executor.context().authority, $executor.context(), $executor.host()) + { deny!($executor, error); } } - let isi = <$isi_type>::account_permission(any_permission, account_id); + let isi = &<$isi_type>::account_permission(any_permission, account_id); execute!($executor, isi); } @@ -1541,32 +1612,18 @@ pub mod permission { }; } - pub fn visit_grant_account_permission( + pub fn visit_grant_account_permission( executor: &mut V, - authority: &AccountId, isi: &Grant, ) { - impl_validate!( - executor, - authority, - isi, - validate_grant, - Grant - ); + impl_execute!(executor, isi, validate_grant, Grant); } - pub fn visit_revoke_account_permission( + pub fn visit_revoke_account_permission( executor: &mut V, - authority: &AccountId, isi: &Revoke, ) { - impl_validate!( - executor, - authority, - isi, - validate_revoke, - Revoke - ); + impl_execute!(executor, isi, validate_revoke, Revoke); } } @@ -1575,15 +1632,11 @@ pub mod executor { use super::*; - pub fn visit_upgrade( - executor: &mut V, - authority: &AccountId, - isi: &Upgrade, - ) { + pub fn visit_upgrade(executor: &mut V, isi: &Upgrade) { if is_genesis(executor) { execute!(executor, isi); } - if CanUpgradeExecutor.is_owned_by(authority) { + if CanUpgradeExecutor.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } @@ -1594,11 +1647,7 @@ pub mod executor { pub mod log { use super::*; - pub fn visit_log( - executor: &mut V, - _authority: &AccountId, - isi: &Log, - ) { + pub fn visit_log(executor: &mut V, isi: &Log) { execute!(executor, isi) } } @@ -1606,11 +1655,7 @@ pub mod log { pub mod custom { use super::*; - pub fn visit_custom( - executor: &mut V, - _authority: &AccountId, - _isi: &CustomInstruction, - ) { + pub fn visit_custom(executor: &mut V, _isi: &CustomInstruction) { deny!( executor, "Custom instructions should be handled in custom executor" @@ -1618,6 +1663,6 @@ pub mod custom { } } -fn is_genesis(executor: &V) -> bool { - executor.block_height() == 0 +fn is_genesis(executor: &V) -> bool { + executor.context().block_height == 0 } diff --git a/crates/iroha_executor/src/lib.rs b/crates/iroha_executor/src/lib.rs index 11f7ccda712..d8675d4dc5f 100644 --- a/crates/iroha_executor/src/lib.rs +++ b/crates/iroha_executor/src/lib.rs @@ -15,7 +15,7 @@ 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}; +pub use smart_contract::{data_model, stub_getrandom, Iroha}; pub mod default; pub mod permission; @@ -30,52 +30,52 @@ pub mod log { pub use iroha_smart_contract_utils::{debug, error, event, info, log::*, trace, warn}; } -/// Get payload for `validate_transaction()` entrypoint. +/// Get context for `execute_transaction()` entrypoint. /// /// # Traps /// /// Host side will generate a trap if this function was called not from a -/// executor `validate_transaction()` entrypoint. +/// executor `execute_transaction()` entrypoint. #[cfg(not(test))] -pub fn get_validate_transaction_payload() -> payloads::Validate { +pub fn get_execute_transaction_context() -> payloads::Validate { // Safety: ownership of the returned result is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(host::get_validate_transaction_payload()) } + unsafe { decode_with_length_prefix_from_raw(host::get_execute_transaction_context()) } } -/// Get payload for `validate_instruction()` entrypoint. +/// Get context for `execute_instruction()` entrypoint. /// /// # Traps /// /// Host side will generate a trap if this function was called not from a -/// executor `validate_instruction()` entrypoint. +/// executor `execute_instruction()` entrypoint. #[cfg(not(test))] -pub fn get_validate_instruction_payload() -> payloads::Validate { +pub fn get_execute_instruction_context() -> payloads::Validate { // Safety: ownership of the returned result is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(host::get_validate_instruction_payload()) } + unsafe { decode_with_length_prefix_from_raw(host::get_execute_instruction_context()) } } -/// Get payload for `validate_query()` entrypoint. +/// Get context for `validate_query()` entrypoint. /// /// # Traps /// /// Host side will generate a trap if this function was called not from a /// executor `validate_query()` entrypoint. #[cfg(not(test))] -pub fn get_validate_query_payload() -> payloads::Validate { +pub fn get_validate_query_context() -> payloads::Validate { // Safety: ownership of the returned result is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(host::get_validate_query_payload()) } + unsafe { decode_with_length_prefix_from_raw(host::get_validate_query_context()) } } -/// Get payload for `migrate()` entrypoint. +/// Get context for `migrate()` entrypoint. /// /// # Traps /// /// Host side will generate a trap if this function was called not from a /// executor `migrate()` entrypoint. #[cfg(not(test))] -pub fn get_migrate_payload() -> payloads::Migrate { +pub fn get_migrate_context() -> prelude::Context { // Safety: ownership of the returned result is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(host::get_migrate_payload()) } + unsafe { decode_with_length_prefix_from_raw(host::get_migrate_context()) } } /// Set new [`ExecutorDataModel`]. @@ -98,33 +98,33 @@ pub fn set_data_model(data_model: &ExecutorDataModel) { mod host { #[link(wasm_import_module = "iroha")] extern "C" { - /// Get payload for `validate_transaction()` entrypoint. + /// Get context for `execute_transaction()` entrypoint. /// /// # Warning /// /// This function does transfer ownership of the result to the caller - pub(super) fn get_validate_transaction_payload() -> *const u8; + pub(super) fn get_execute_transaction_context() -> *const u8; - /// Get payload for `validate_instruction()` entrypoint. + /// Get context for `execute_instruction()` entrypoint. /// /// # Warning /// /// This function does transfer ownership of the result to the caller - pub(super) fn get_validate_instruction_payload() -> *const u8; + pub(super) fn get_execute_instruction_context() -> *const u8; - /// Get payload for `validate_query()` entrypoint. + /// Get context for `validate_query()` entrypoint. /// /// # Warning /// /// This function does transfer ownership of the result to the caller - pub(super) fn get_validate_query_payload() -> *const u8; + pub(super) fn get_validate_query_context() -> *const u8; - /// Get payload for `migrate()` entrypoint. + /// Get context for `migrate()` entrypoint. /// /// # Warning /// /// This function does transfer ownership of the result to the caller - pub(super) fn get_migrate_payload() -> *const u8; + pub(super) fn get_migrate_context() -> *const u8; /// Set new [`ExecutorDataModel`]. pub(super) fn set_data_model(ptr: *const u8, len: usize); @@ -142,12 +142,8 @@ macro_rules! execute { unreachable!("Executor already denied"); } - { - use $crate::smart_contract::ExecuteOnHost as _; - - if let Err(err) = $isi.execute() { - $executor.deny(err); - } + if let Err(err) = $executor.host().submit($isi) { + $executor.deny(err); } return; @@ -255,35 +251,36 @@ impl DataModelBuilder { /// Set the data model of the executor via [`set_data_model`] #[cfg(not(test))] - pub fn build_and_set(self) { - use iroha_smart_contract::query; - - use crate::smart_contract::ExecuteOnHost as _; - - let all_accounts = query(FindAccounts::new()).execute().unwrap(); - let all_roles = query(FindRoles::new()).execute().unwrap(); + pub fn build_and_set(self, host: &Iroha) { + let all_accounts = host.query(FindAccounts::new()).execute().unwrap(); + let all_roles = host.query(FindRoles::new()).execute().unwrap(); for role in all_roles.into_iter().map(|role| role.unwrap()) { for permission in role.permissions() { if !self.permissions.contains(permission.name()) { - Revoke::role_permission(permission.clone(), role.id().clone()) - .execute() - .unwrap(); + host.submit(&Revoke::role_permission( + permission.clone(), + role.id().clone(), + )) + .unwrap(); } } } for account in all_accounts.into_iter().map(|account| account.unwrap()) { - let account_permissions = query(FindPermissionsByAccountId::new(account.id().clone())) + let account_permissions = host + .query(FindPermissionsByAccountId::new(account.id().clone())) .execute() .unwrap() .into_iter(); for permission in account_permissions.map(|permission| permission.unwrap()) { if !self.permissions.contains(permission.name()) { - Revoke::account_permission(permission, account.id().clone()) - .execute() - .unwrap(); + host.submit(&Revoke::account_permission( + permission, + account.id().clone(), + )) + .unwrap(); } } } @@ -303,13 +300,18 @@ impl DataModelBuilder { } /// Executor of Iroha operations -pub trait Validate { +pub trait Execute { + /// Handle to the host environment. + fn host(&self) -> &Iroha; + + /// Context of the execution. + /// + /// Represents the current state of the world + fn context(&self) -> &prelude::Context; + /// Executor verdict. fn verdict(&self) -> &Result; - /// Current block height. - fn block_height(&self) -> u64; - /// Set executor verdict to deny fn deny(&mut self, reason: ValidationFail); } @@ -319,13 +321,14 @@ pub mod prelude { pub use alloc::vec::Vec; - pub use iroha_executor_derive::{ - entrypoint, Constructor, Validate, ValidateEntrypoints, Visit, - }; + pub use iroha_executor_derive::{entrypoint, Constructor, Entrypoints, Execute, Visit}; pub use iroha_smart_contract::prelude::*; pub use super::{ - data_model::{executor::Result, visit::Visit, ValidationFail}, - deny, execute, DataModelBuilder, Validate, + data_model::{ + executor::Result, smart_contract::payloads::ExecutorContext as Context, visit::Visit, + ValidationFail, + }, + deny, execute, DataModelBuilder, Execute, }; } diff --git a/crates/iroha_executor/src/permission.rs b/crates/iroha_executor/src/permission.rs index ded0a1094b2..26b7b52fdb8 100644 --- a/crates/iroha_executor/src/permission.rs +++ b/crates/iroha_executor/src/permission.rs @@ -3,11 +3,15 @@ use alloc::{borrow::ToOwned as _, vec::Vec}; use iroha_executor_data_model::permission::Permission; -use iroha_smart_contract::{ - data_model::{executor::Result, permission::Permission as PermissionObject, prelude::*}, - query, + +use crate::{ + prelude::Context, + smart_contract::{ + data_model::{executor::Result, permission::Permission as PermissionObject, prelude::*}, + debug::DebugExpectExt as _, + Iroha, + }, }; -use iroha_smart_contract_utils::debug::DebugExpectExt as _; /// Declare permission types of current module. Use it with a full path to the permission. /// Used to iterate over tokens to validate `Grant` and `Revoke` instructions. @@ -60,15 +64,15 @@ macro_rules! declare_permissions { } impl ValidateGrantRevoke for AnyPermission { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { match self { $( - AnyPermission::$token_ty(permission) => permission.validate_grant(authority, block_height), )* + AnyPermission::$token_ty(permission) => permission.validate_grant(authority, context, host), )* } } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { + fn validate_revoke(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { match self { $( - AnyPermission::$token_ty(permission) => permission.validate_revoke(authority, block_height), )* + AnyPermission::$token_ty(permission) => permission.validate_revoke(authority, context, host), )* } } } @@ -100,9 +104,9 @@ declare_permissions! { iroha_executor_data_model::permission::asset::{CanRegisterAssetWithDefinition}, iroha_executor_data_model::permission::asset::{CanUnregisterAssetWithDefinition}, - iroha_executor_data_model::permission::asset::{CanMintAssetsWithDefinition}, - iroha_executor_data_model::permission::asset::{CanBurnAssetsWithDefinition}, - iroha_executor_data_model::permission::asset::{CanTransferAssetsWithDefinition}, + iroha_executor_data_model::permission::asset::{CanMintAssetWithDefinition}, + iroha_executor_data_model::permission::asset::{CanBurnAssetWithDefinition}, + iroha_executor_data_model::permission::asset::{CanTransferAssetWithDefinition}, iroha_executor_data_model::permission::asset::{CanRegisterAsset}, iroha_executor_data_model::permission::asset::{CanUnregisterAsset}, iroha_executor_data_model::permission::asset::{CanMintAsset}, @@ -125,11 +129,12 @@ declare_permissions! { /// Trait that enables using permissions on the blockchain pub trait ExecutorPermission: Permission + PartialEq { /// Check if the account owns this permission - fn is_owned_by(&self, account_id: &AccountId) -> bool + fn is_owned_by(&self, authority: &AccountId, host: &Iroha) -> bool where for<'a> Self: TryFrom<&'a crate::data_model::permission::Permission>, { - if query(FindPermissionsByAccountId::new(account_id.clone())) + if host + .query(FindPermissionsByAccountId::new(authority.clone())) .execute() .expect("INTERNAL BUG: `FindPermissionsByAccountId` must never fail") .map(|res| res.dbg_expect("Failed to get permission from cursor")) @@ -140,7 +145,8 @@ pub trait ExecutorPermission: Permission + PartialEq { } // build a big OR predicate over all roles we are interested in - let role_predicate = query(FindRolesByAccountId::new(account_id.clone())) + let role_predicate = host + .query(FindRolesByAccountId::new(authority.clone())) .execute() .expect("INTERNAL BUG: `FindRolesByAccountId` must never fail") .map(|role_id| role_id.dbg_expect("Failed to get role from cursor")) @@ -149,7 +155,7 @@ pub trait ExecutorPermission: Permission + PartialEq { }); // check if any of the roles have the permission we need - query(FindRoles) + host.query(FindRoles) .filter(role_predicate) .execute() .expect("INTERNAL BUG: `FindRoles` must never fail") @@ -168,17 +174,15 @@ impl ExecutorPermission for T {} /// Provides a function to check validity of [`Grant`] and [`Revoke`] /// instructions containing implementing permission. pub(super) trait ValidateGrantRevoke { - #[allow(missing_docs, clippy::missing_errors_doc)] - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result; + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result; - #[allow(missing_docs, clippy::missing_errors_doc)] - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result; + fn validate_revoke(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result; } /// Predicate-like trait used for pass conditions to identify if [`Grant`] or [`Revoke`] should be allowed. pub(crate) trait PassCondition { #[allow(missing_docs, clippy::missing_errors_doc)] - fn validate(&self, authority: &AccountId, block_height: u64) -> Result; + fn validate(&self, authority: &AccountId, host: &Iroha, context: &Context) -> Result; } mod executor { @@ -187,11 +191,16 @@ mod executor { use super::*; impl ValidateGrantRevoke for CanUpgradeExecutor { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - OnlyGenesis::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + OnlyGenesis::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - OnlyGenesis::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + OnlyGenesis::from(self).validate(authority, host, context) } } } @@ -202,11 +211,16 @@ mod peer { use super::*; impl ValidateGrantRevoke for CanManagePeers { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - OnlyGenesis::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + OnlyGenesis::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - OnlyGenesis::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + OnlyGenesis::from(self).validate(authority, host, context) } } } @@ -217,11 +231,16 @@ mod role { use super::*; impl ValidateGrantRevoke for CanManageRoles { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - OnlyGenesis::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + OnlyGenesis::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - OnlyGenesis::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + OnlyGenesis::from(self).validate(authority, host, context) } } } @@ -233,8 +252,13 @@ mod parameter { use super::*; impl ValidateGrantRevoke for CanSetParameters { - fn validate_grant(&self, authority: &AccountId, _block_height: u64) -> Result { - if CanSetParameters.is_owned_by(authority) { + fn validate_grant( + &self, + authority: &AccountId, + _context: &Context, + host: &Iroha, + ) -> Result { + if CanSetParameters.is_owned_by(authority, host) { return Ok(()); } @@ -244,8 +268,13 @@ mod parameter { )) } - fn validate_revoke(&self, authority: &AccountId, _block_height: u64) -> Result { - if CanSetParameters.is_owned_by(authority) { + fn validate_revoke( + &self, + authority: &AccountId, + _context: &Context, + host: &Iroha, + ) -> Result { + if CanSetParameters.is_owned_by(authority, host) { return Ok(()); } @@ -261,9 +290,10 @@ pub mod asset { //! Module with pass conditions for asset related tokens use iroha_executor_data_model::permission::asset::{ - CanBurnAsset, CanBurnAssetsWithDefinition, CanMintAsset, CanMintAssetsWithDefinition, - CanModifyAssetMetadata, CanRegisterAsset, CanRegisterAssetWithDefinition, CanTransferAsset, - CanTransferAssetsWithDefinition, CanUnregisterAsset, CanUnregisterAssetWithDefinition, + CanBurnAsset, CanBurnAssetWithDefinition, CanMintAsset, CanMintAssetWithDefinition, + CanModifyAssetMetadata, CanRegisterAsset, CanRegisterAssetWithDefinition, + CanTransferAsset, CanTransferAssetWithDefinition, CanUnregisterAsset, + CanUnregisterAssetWithDefinition, }; use super::*; @@ -277,8 +307,8 @@ pub mod asset { /// # Errors /// /// Fails if `is_account_owner` fails - pub fn is_asset_owner(asset_id: &AssetId, authority: &AccountId) -> Result { - crate::permission::account::is_account_owner(asset_id.account(), authority) + pub fn is_asset_owner(asset_id: &AssetId, authority: &AccountId, host: &Iroha) -> Result { + crate::permission::account::is_account_owner(asset_id.account(), authority, host) } /// Pass condition that checks if `authority` is the owner of asset. @@ -289,8 +319,8 @@ pub mod asset { } impl PassCondition for Owner<'_> { - fn validate(&self, authority: &AccountId, _block_height: u64) -> Result { - if is_asset_owner(self.asset, authority)? { + fn validate(&self, authority: &AccountId, host: &Iroha, _context: &Context) -> Result { + if is_asset_owner(self.asset, authority, host)? { return Ok(()); } @@ -301,101 +331,156 @@ pub mod asset { } impl ValidateGrantRevoke for CanRegisterAssetWithDefinition { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanUnregisterAssetWithDefinition { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } } - impl ValidateGrantRevoke for CanMintAssetsWithDefinition { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + impl ValidateGrantRevoke for CanMintAssetWithDefinition { + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } } - impl ValidateGrantRevoke for CanBurnAssetsWithDefinition { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + impl ValidateGrantRevoke for CanBurnAssetWithDefinition { + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } } - impl ValidateGrantRevoke for CanTransferAssetsWithDefinition { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + impl ValidateGrantRevoke for CanTransferAssetWithDefinition { + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::asset_definition::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::asset_definition::Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanRegisterAsset { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::account::Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::account::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::account::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::account::Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanUnregisterAsset { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanMintAsset { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanBurnAsset { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanTransferAsset { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanModifyAssetMetadata { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } @@ -432,15 +517,15 @@ pub mod asset_definition { use iroha_executor_data_model::permission::asset_definition::{ CanModifyAssetDefinitionMetadata, CanRegisterAssetDefinition, CanUnregisterAssetDefinition, }; - use iroha_smart_contract::data_model::{ - isi::error::InstructionExecutionError, - query::{ - builder::{QueryBuilderExt, SingleQueryError}, - error::FindError, - }, - }; use super::*; + use crate::smart_contract::{ + data_model::{ + isi::error::InstructionExecutionError, + query::{builder::SingleQueryError, error::FindError}, + }, + Iroha, + }; /// Check if `authority` is the owner of asset definition @@ -454,8 +539,10 @@ pub mod asset_definition { pub fn is_asset_definition_owner( asset_definition_id: &AssetDefinitionId, authority: &AccountId, + host: &Iroha, ) -> Result { - let asset_definition = query(FindAssetsDefinitions) + let asset_definition = host + .query(FindAssetsDefinitions) .filter_with(|asset_definition| asset_definition.id.eq(asset_definition_id.clone())) .execute_single() .map_err(|e| match e { @@ -471,7 +558,11 @@ pub mod asset_definition { if asset_definition.owned_by() == authority { Ok(true) } else { - crate::permission::domain::is_domain_owner(asset_definition_id.domain(), authority) + crate::permission::domain::is_domain_owner( + asset_definition_id.domain(), + authority, + host, + ) } } @@ -483,8 +574,8 @@ pub mod asset_definition { } impl PassCondition for Owner<'_> { - fn validate(&self, authority: &AccountId, _block_height: u64) -> Result { - if is_asset_definition_owner(self.asset_definition, authority)? { + fn validate(&self, authority: &AccountId, host: &Iroha, _context: &Context) -> Result { + if is_asset_definition_owner(self.asset_definition, authority, host)? { return Ok(()); } @@ -495,29 +586,44 @@ pub mod asset_definition { } impl ValidateGrantRevoke for CanRegisterAssetDefinition { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::domain::Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::domain::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::domain::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::domain::Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanUnregisterAssetDefinition { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanModifyAssetDefinitionMetadata { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } @@ -536,9 +642,9 @@ pub mod asset_definition { CanModifyAssetDefinitionMetadata, iroha_executor_data_model::permission::asset::CanRegisterAssetWithDefinition, iroha_executor_data_model::permission::asset::CanUnregisterAssetWithDefinition, - iroha_executor_data_model::permission::asset::CanMintAssetsWithDefinition, - iroha_executor_data_model::permission::asset::CanBurnAssetsWithDefinition, - iroha_executor_data_model::permission::asset::CanTransferAssetsWithDefinition, + iroha_executor_data_model::permission::asset::CanMintAssetWithDefinition, + iroha_executor_data_model::permission::asset::CanBurnAssetWithDefinition, + iroha_executor_data_model::permission::asset::CanTransferAssetWithDefinition, ); } @@ -560,11 +666,15 @@ pub mod account { /// # Errors /// /// Fails if `is_domain_owner` fails - pub fn is_account_owner(account_id: &AccountId, authority: &AccountId) -> Result { + pub fn is_account_owner( + account_id: &AccountId, + authority: &AccountId, + host: &Iroha, + ) -> Result { if account_id == authority { Ok(true) } else { - crate::permission::domain::is_domain_owner(account_id.domain(), authority) + crate::permission::domain::is_domain_owner(account_id.domain(), authority, host) } } @@ -576,8 +686,8 @@ pub mod account { } impl PassCondition for Owner<'_> { - fn validate(&self, authority: &AccountId, _block_height: u64) -> Result { - if is_account_owner(self.account, authority)? { + fn validate(&self, authority: &AccountId, host: &Iroha, _context: &Context) -> Result { + if is_account_owner(self.account, authority, host)? { return Ok(()); } @@ -588,29 +698,44 @@ pub mod account { } impl ValidateGrantRevoke for CanRegisterAccount { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::domain::Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::domain::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::domain::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::domain::Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanUnregisterAccount { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanModifyAccountMetadata { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } @@ -652,15 +777,19 @@ pub mod trigger { /// # Errors /// - `FindTrigger` fails /// - `is_domain_owner` fails - pub fn is_trigger_owner(trigger_id: &TriggerId, authority: &AccountId) -> Result { - let trigger = find_trigger(trigger_id)?; + pub fn is_trigger_owner( + trigger_id: &TriggerId, + authority: &AccountId, + host: &Iroha, + ) -> Result { + let trigger = find_trigger(trigger_id, host)?; Ok(trigger.action().authority() == authority - || is_domain_owner(trigger.action().authority().domain(), authority)?) + || is_domain_owner(trigger.action().authority().domain(), authority, host)?) } /// Returns the trigger. - fn find_trigger(trigger_id: &TriggerId) -> Result { - query(FindTriggers::new()) + pub(crate) fn find_trigger(trigger_id: &TriggerId, host: &Iroha) -> Result { + host.query(FindTriggers::new()) .filter_with(|trigger| trigger.id.eq(trigger_id.clone())) .execute_single() .map_err(|e| match e { @@ -680,8 +809,8 @@ pub mod trigger { } impl PassCondition for Owner<'_> { - fn validate(&self, authority: &AccountId, _block_height: u64) -> Result { - if is_trigger_owner(self.trigger, authority)? { + fn validate(&self, authority: &AccountId, host: &Iroha, _context: &Context) -> Result { + if is_trigger_owner(self.trigger, authority, host)? { return Ok(()); } @@ -692,47 +821,72 @@ pub mod trigger { } impl ValidateGrantRevoke for CanRegisterTrigger { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - super::account::Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + super::account::Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - super::account::Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + super::account::Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanExecuteTrigger { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanUnregisterTrigger { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanModifyTrigger { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanModifyTriggerMetadata { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } @@ -769,10 +923,7 @@ pub mod domain { }; use iroha_smart_contract::data_model::{ isi::error::InstructionExecutionError, - query::{ - builder::{QueryBuilderExt, SingleQueryError}, - error::FindError, - }, + query::{builder::SingleQueryError, error::FindError}, }; use super::*; @@ -781,8 +932,12 @@ pub mod domain { /// /// # Errors /// Fails if query fails - pub fn is_domain_owner(domain_id: &DomainId, authority: &AccountId) -> Result { - query(FindDomains) + pub fn is_domain_owner( + domain_id: &DomainId, + authority: &AccountId, + host: &Iroha, + ) -> Result { + host.query(FindDomains) .filter_with(|domain| domain.id.eq(domain_id.clone())) .execute_single() .map(|domain| domain.owned_by() == authority) @@ -806,8 +961,8 @@ pub mod domain { } impl PassCondition for Owner<'_> { - fn validate(&self, authority: &AccountId, _block_height: u64) -> Result { - if is_domain_owner(self.domain, authority)? { + fn validate(&self, authority: &AccountId, host: &Iroha, _context: &Context) -> Result { + if is_domain_owner(self.domain, authority, host)? { return Ok(()); } @@ -818,29 +973,43 @@ pub mod domain { } impl ValidateGrantRevoke for CanRegisterDomain { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - OnlyGenesis::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + OnlyGenesis::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - OnlyGenesis::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + OnlyGenesis::from(self).validate(authority, host, context) } } - impl ValidateGrantRevoke for CanUnregisterDomain { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } impl ValidateGrantRevoke for CanModifyDomainMetadata { - fn validate_grant(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_grant(&self, authority: &AccountId, context: &Context, host: &Iroha) -> Result { + Owner::from(self).validate(authority, host, context) } - fn validate_revoke(&self, authority: &AccountId, block_height: u64) -> Result { - Owner::from(self).validate(authority, block_height) + fn validate_revoke( + &self, + authority: &AccountId, + context: &Context, + host: &Iroha, + ) -> Result { + Owner::from(self).validate(authority, host, context) } } @@ -869,8 +1038,8 @@ pub mod domain { pub(crate) struct OnlyGenesis; impl PassCondition for OnlyGenesis { - fn validate(&self, _: &AccountId, block_height: u64) -> Result { - if block_height == 0 { + fn validate(&self, _authority: &AccountId, _host: &Iroha, context: &Context) -> Result { + if context.block_height == 0 { Ok(()) } else { Err(ValidationFail::NotPermitted( @@ -887,13 +1056,15 @@ impl From<&T> for OnlyGenesis { } /// Iterator over all accounts and theirs permission tokens -pub(crate) fn accounts_permissions() -> impl Iterator { - query(FindAccounts) +pub(crate) fn accounts_permissions( + host: &Iroha, +) -> impl Iterator + '_ { + host.query(FindAccounts) .execute() .dbg_expect("INTERNAL BUG: `FindAllAccounts` must never fail") .map(|account| account.dbg_expect("Failed to get account from cursor")) .flat_map(|account| { - query(FindPermissionsByAccountId::new(account.id().clone())) + host.query(FindPermissionsByAccountId::new(account.id().clone())) .execute() .dbg_expect("INTERNAL BUG: `FindPermissionsByAccountId` must never fail") .map(|permission| permission.dbg_expect("Failed to get permission from cursor")) @@ -902,8 +1073,8 @@ pub(crate) fn accounts_permissions() -> impl Iterator impl Iterator { - query(FindRoles) +pub(crate) fn roles_permissions(host: &Iroha) -> impl Iterator { + host.query(FindRoles) .execute() .dbg_expect("INTERNAL BUG: `FindAllRoles` must never fail") .map(|role| role.dbg_expect("Failed to get role from cursor")) diff --git a/crates/iroha_executor_data_model/src/permission.rs b/crates/iroha_executor_data_model/src/permission.rs index 3614807bdfd..27778496268 100644 --- a/crates/iroha_executor_data_model/src/permission.rs +++ b/crates/iroha_executor_data_model/src/permission.rs @@ -121,19 +121,19 @@ pub mod asset { } permission! { - pub struct CanMintAssetsWithDefinition { + pub struct CanMintAssetWithDefinition { pub asset_definition: AssetDefinitionId, } } permission! { - pub struct CanBurnAssetsWithDefinition { + pub struct CanBurnAssetWithDefinition { pub asset_definition: AssetDefinitionId, } } permission! { - pub struct CanTransferAssetsWithDefinition { + pub struct CanTransferAssetWithDefinition { pub asset_definition: AssetDefinitionId, } } diff --git a/crates/iroha_executor_data_model_derive/src/lib.rs b/crates/iroha_executor_data_model_derive/src/lib.rs index b4890922c64..14f6cc6f17d 100644 --- a/crates/iroha_executor_data_model_derive/src/lib.rs +++ b/crates/iroha_executor_data_model_derive/src/lib.rs @@ -30,7 +30,7 @@ pub fn derive_parameter(input: TokenStream) -> Result { /// } /// /// #[entrypoint(params = "[authority, operation]")] -/// fn validate(authority: AccountId, operation: NeedsValidationBox) -> Result { +/// fn validate(authority: AccountId, operation: NeedsValidationBox) -> Result { /// let NeedsValidationBox::Instruction(instruction) = operation else { /// pass!(); /// }; diff --git a/crates/iroha_executor_derive/src/default.rs b/crates/iroha_executor_derive/src/default.rs index 45b1af66ea6..2fcab70738d 100644 --- a/crates/iroha_executor_derive/src/default.rs +++ b/crates/iroha_executor_derive/src/default.rs @@ -52,42 +52,42 @@ pub fn impl_derive_entrypoints(emitter: &mut Emitter, input: &syn::DeriveInput) let mut entrypoint_fns: Vec = vec![ parse_quote! { #[::iroha_executor::prelude::entrypoint] - pub fn validate_instruction( - authority: ::iroha_executor::prelude::AccountId, - instruction: ::iroha_executor::prelude::InstructionBox, - block_height: u64, + pub fn execute_transaction( + transaction: ::iroha_executor::prelude::SignedTransaction, + host: ::iroha_executor::prelude::Iroha, + context: ::iroha_executor::prelude::Context, #(#custom_args),* ) -> ::iroha_executor::prelude::Result { - let mut executor = #ident::new(block_height, #(#custom_idents),*); - executor.visit_instruction(&authority, &instruction); - ::core::mem::forget(instruction); + let mut executor = #ident::new(host, context, #(#custom_idents),*); + executor.visit_transaction(&transaction); + ::core::mem::forget(transaction); executor.verdict } }, parse_quote! { #[::iroha_executor::prelude::entrypoint] - pub fn validate_transaction( - authority: ::iroha_executor::prelude::AccountId, - transaction: ::iroha_executor::prelude::SignedTransaction, - block_height: u64, + pub fn execute_instruction( + instruction: ::iroha_executor::prelude::InstructionBox, + host: ::iroha_executor::prelude::Iroha, + context: ::iroha_executor::prelude::Context, #(#custom_args),* ) -> ::iroha_executor::prelude::Result { - let mut executor = #ident::new(block_height, #(#custom_idents),*); - executor.visit_transaction(&authority, &transaction); - ::core::mem::forget(transaction); + let mut executor = #ident::new(host, context, #(#custom_idents),*); + executor.visit_instruction(&instruction); + ::core::mem::forget(instruction); executor.verdict } }, parse_quote! { #[::iroha_executor::prelude::entrypoint] pub fn validate_query( - authority: ::iroha_executor::prelude::AccountId, query: ::iroha_executor::data_model::query::AnyQueryBox, - block_height: u64, + host: ::iroha_executor::prelude::Iroha, + context: ::iroha_executor::prelude::Context, #(#custom_args),* ) -> ::iroha_executor::prelude::Result { - let mut executor = #ident::new(block_height, #(#custom_idents),*); - executor.visit_query(&authority, &query); + let mut executor = #ident::new(host, context, #(#custom_idents),*); + executor.visit_query(&query); ::core::mem::forget(query); executor.verdict } @@ -165,9 +165,7 @@ pub fn impl_derive_visit(emitter: &mut Emitter, input: &syn::DeriveInput) -> Tok let mut sig: syn::Signature = syn::parse_str(item).expect("Function names and operation signatures should be valid"); let recv_arg: syn::Receiver = parse_quote!(&mut self); - let auth_arg: syn::FnArg = parse_quote!(authority: &AccountId); sig.inputs.insert(0, recv_arg.into()); - sig.inputs.insert(1, auth_arg); sig }) .collect(); @@ -193,12 +191,12 @@ pub fn impl_derive_visit(emitter: &mut Emitter, input: &syn::DeriveInput) -> Tok let curr_fn_name = &visit_sig.ident; let local_override_fn = quote! { #visit_sig { - #curr_fn_name(self, authority, operation) + #curr_fn_name(self, operation) } }; let default_override_fn = quote! { #visit_sig { - ::iroha_executor::default::#curr_fn_name(self, authority, operation) + ::iroha_executor::default::#curr_fn_name(self, operation) } }; if let Some(fns_to_exclude) = custom { @@ -224,20 +222,24 @@ pub fn impl_derive_visit(emitter: &mut Emitter, input: &syn::DeriveInput) -> Tok } } -pub fn impl_derive_validate(emitter: &mut Emitter, input: &syn::DeriveInput) -> TokenStream2 { +pub fn impl_derive_execute(emitter: &mut Emitter, input: &syn::DeriveInput) -> TokenStream2 { let Some(input) = emitter.handle(ExecutorDeriveInput::from_derive_input(input)) else { return quote!(); }; let ExecutorDeriveInput { ident, data, .. } = &input; check_required_fields(data, emitter); quote! { - impl ::iroha_executor::Validate for #ident { - fn verdict(&self) -> &::iroha_executor::prelude::Result { - &self.verdict + impl ::iroha_executor::Execute for #ident { + fn host(&self) -> &::iroha_executor::smart_contract::Iroha { + &self.host + } + + fn context(&self) -> &::iroha_executor::prelude::Context { + &self.context } - fn block_height(&self) -> u64 { - self.block_height + fn verdict(&self) -> &::iroha_executor::prelude::Result { + &self.verdict } fn deny(&mut self, reason: ::iroha_executor::prelude::ValidationFail) { @@ -260,21 +262,24 @@ pub fn impl_derive_constructor(emitter: &mut Emitter, input: &syn::DeriveInput) // Returning an inherent impl is okay here as there can be multiple quote! { impl #ident { - pub fn new(block_height: u64, #(#custom_args),*) -> Self { + pub fn new(host: ::iroha_executor::prelude::Iroha, context: ::iroha_executor::prelude::Context, #(#custom_args),*) -> Self { Self { + host, + context, verdict: Ok(()), - block_height, #(#custom_idents),* } } } - } } fn check_required_fields(ast: &ExecutorData, emitter: &mut Emitter) { - let required_fields: syn::FieldsNamed = - parse_quote!({ verdict: ::iroha_executor::prelude::Result, block_height: u64 }); + let required_fields: syn::FieldsNamed = parse_quote!({ + host: ::iroha_executor::prelude::Iroha, + context: iroha_executor::prelude::Context, + verdict: ::iroha_executor::prelude::Result, + }); let struct_fields = ast .as_ref() .take_struct() @@ -324,7 +329,7 @@ fn check_type_equivalence(full_ty: &syn::Type, given_ty: &syn::Type) -> bool { /// Processes an `Executor` by draining it of default fields and returning the idents of the /// custom fields and the corresponding function arguments for use in the constructor fn custom_field_idents_and_fn_args(ast: &ExecutorData) -> (Vec<&Ident>, Vec) { - let required_idents: Vec = ["verdict", "block_height"] + let required_idents: Vec = ["host", "context", "verdict"] .iter() .map(|s| Ident::new(s, Span::call_site())) .collect(); diff --git a/crates/iroha_executor_derive/src/entrypoint.rs b/crates/iroha_executor_derive/src/entrypoint.rs index c833407e687..b87455762f9 100644 --- a/crates/iroha_executor_derive/src/entrypoint.rs +++ b/crates/iroha_executor_derive/src/entrypoint.rs @@ -4,19 +4,18 @@ use iroha_macro_utils::Emitter; use manyhow::emit; use proc_macro2::TokenStream; use quote::quote; -use syn::parse_quote; mod export { - pub const EXECUTOR_VALIDATE_TRANSACTION: &str = "_iroha_executor_validate_transaction"; - pub const EXECUTOR_VALIDATE_INSTRUCTION: &str = "_iroha_executor_validate_instruction"; + pub const EXECUTOR_EXECUTE_TRANSACTION: &str = "_iroha_executor_execute_transaction"; + pub const EXECUTOR_EXECUTE_INSTRUCTION: &str = "_iroha_executor_execute_instruction"; pub const EXECUTOR_VALIDATE_QUERY: &str = "_iroha_executor_validate_query"; - pub const EXECUTOR_MIGRATE: &str = "_iroha_executor_migrate"; + pub const EXECUTOR_MIGRATE_CONTEXT: &str = "_iroha_executor_migrate"; } mod import { - pub const GET_VALIDATE_TRANSACTION_PAYLOAD: &str = "get_validate_transaction_payload"; - pub const GET_VALIDATE_INSTRUCTION_PAYLOAD: &str = "get_validate_instruction_payload"; - pub const GET_VALIDATE_QUERY_PAYLOAD: &str = "get_validate_query_payload"; + pub const GET_EXECUTE_TRANSACTION_CONTEXT: &str = "get_execute_transaction_context"; + pub const GET_EXECUTE_INSTRUCTION_CONTEXT: &str = "get_execute_instruction_context"; + pub const GET_VALIDATE_QUERY_CONTEXT: &str = "get_validate_query_context"; } /// [`executor_entrypoint`](crate::executor_entrypoint()) macro implementation @@ -57,9 +56,9 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream match_entrypoints! { validate: { - validate_transaction => EXECUTOR_VALIDATE_TRANSACTION(GET_VALIDATE_TRANSACTION_PAYLOAD), - validate_instruction => EXECUTOR_VALIDATE_INSTRUCTION(GET_VALIDATE_INSTRUCTION_PAYLOAD), - validate_query => EXECUTOR_VALIDATE_QUERY(GET_VALIDATE_QUERY_PAYLOAD), + execute_transaction => EXECUTOR_EXECUTE_TRANSACTION(GET_EXECUTE_TRANSACTION_CONTEXT), + execute_instruction => EXECUTOR_EXECUTE_INSTRUCTION(GET_EXECUTE_INSTRUCTION_CONTEXT), + validate_query => EXECUTOR_VALIDATE_QUERY(GET_VALIDATE_QUERY_CONTEXT), } other: { migrate => { impl_migrate_entrypoint(item) } @@ -71,13 +70,13 @@ fn impl_validate_entrypoint( fn_item: syn::ItemFn, user_entrypoint_name: &'static str, generated_entrypoint_name: &'static str, - get_validation_payload_fn_name: &'static str, + get_execute_context_fn_name: &'static str, ) -> TokenStream { let syn::ItemFn { attrs, vis, sig, - mut block, + block, } = fn_item; let fn_name = &sig.ident; @@ -86,23 +85,16 @@ fn impl_validate_entrypoint( "Executor `{user_entrypoint_name}` entrypoint must have `Result` return type" ); - block.stmts.insert( - 0, - parse_quote!( - use ::iroha_executor::smart_contract::{ExecuteOnHost as _}; - ), - ); - let generated_entrypoint_ident: syn::Ident = syn::parse_str(generated_entrypoint_name) .expect("Provided entrypoint name to generate is not a valid Ident, this is a bug"); - let get_validation_payload_fn_ident: syn::Ident = - syn::parse_str(get_validation_payload_fn_name).expect( + let get_execute_context_fn_ident: syn::Ident = syn::parse_str(get_execute_context_fn_name) + .expect( "Provided function name to query validating object is not a valid Ident, this is a bug", ); quote! { - /// Executor `validate` entrypoint + /// Executor entrypoint /// /// # Memory safety /// @@ -111,10 +103,14 @@ fn impl_validate_entrypoint( #[no_mangle] #[doc(hidden)] unsafe extern "C" fn #generated_entrypoint_ident() -> *const u8 { - let payload = ::iroha_executor::#get_validation_payload_fn_ident(); - let verdict: ::iroha_executor::data_model::executor::Result = - #fn_name(payload.authority, payload.target, payload.block_height); - let bytes_box = ::core::mem::ManuallyDrop::new(::iroha_executor::utils::encode_with_length_prefix(&verdict)); + let host = ::iroha_executor::smart_contract::Iroha; + + let context = ::iroha_executor::#get_execute_context_fn_ident(); + let verdict = #fn_name(context.target, host, context.context); + + let bytes_box = ::core::mem::ManuallyDrop::new( + ::iroha_executor::utils::encode_with_length_prefix(&verdict) + ); bytes_box.as_ptr() } @@ -137,7 +133,10 @@ fn impl_migrate_entrypoint(fn_item: syn::ItemFn) -> TokenStream { } = fn_item; let fn_name = &sig.ident; - let migrate_fn_name = syn::Ident::new(export::EXECUTOR_MIGRATE, proc_macro2::Span::call_site()); + let migrate_fn_name = syn::Ident::new( + export::EXECUTOR_MIGRATE_CONTEXT, + proc_macro2::Span::call_site(), + ); quote! { /// Executor `migrate` entrypoint @@ -148,8 +147,9 @@ fn impl_migrate_entrypoint(fn_item: syn::ItemFn) -> TokenStream { #[no_mangle] #[doc(hidden)] unsafe extern "C" fn #migrate_fn_name() { - let payload = ::iroha_executor::get_migrate_payload(); - #fn_name(payload.block_height); + let host = ::iroha_executor::smart_contract::Iroha; + let context = ::iroha_executor::get_migrate_context(); + #fn_name(host, context); } // NOTE: False positive diff --git a/crates/iroha_executor_derive/src/lib.rs b/crates/iroha_executor_derive/src/lib.rs index a76a4a4168d..905d4d5c450 100644 --- a/crates/iroha_executor_derive/src/lib.rs +++ b/crates/iroha_executor_derive/src/lib.rs @@ -17,26 +17,22 @@ mod entrypoint; /// use iroha_executor::prelude::*; /// /// #[entrypoint] -/// pub fn migrate(block_height: u64) { +/// fn migrate(host: Iroha, context: Context) { /// todo!() /// } /// /// #[entrypoint] -/// pub fn validate_transaction( -/// authority: AccountId, -/// transaction: SignedTransaction, -/// block_height: u64, -/// ) -> Result { +/// fn execute_transaction(host: Iroha, context: Context, transaction: SignedTransaction) -> Result { /// todo!() /// } /// /// #[entrypoint] -/// pub fn validate_instruction(authority: AccountId, instruction: InstructionBox, block_height: u64) -> Result { +/// fn execute_instruction(host: Iroha, context: Context, instruction: InstructionBox) -> Result { /// todo!() /// } /// /// #[entrypoint] -/// pub fn validate_query(authority: AccountId, query: QueryBox, block_height: u64) -> Result { +/// fn validate_query(host: Iroha, context: Context, query: QueryBox) -> Result { /// todo!() /// } /// ``` @@ -64,19 +60,17 @@ pub fn entrypoint(attr: TokenStream, item: TokenStream) -> TokenStream { /// Implements the `iroha_executor::Validate` trait for the given `Executor` struct. As /// this trait has a `iroha_executor::prelude::Visit` at least this one should be implemented as well. /// -/// Emits a compile error if the struct didn't have all the expected fields with corresponding -/// types, i.e. `verdict`: `iroha_executor::prelude::Result` and `block_height`: `u64`. -/// The types can be unqualified, but not aliased. +/// Emits a compile error if the struct didn't have all the expected fields with corresponding types. #[manyhow] -#[proc_macro_derive(Validate)] -pub fn derive_validate(input: TokenStream) -> TokenStream { +#[proc_macro_derive(Execute)] +pub fn derive_execute(input: TokenStream) -> TokenStream { let mut emitter = Emitter::new(); let Some(input) = emitter.handle(syn::parse2(input)) else { return emitter.finish_token_stream(); }; - let result = default::impl_derive_validate(&mut emitter, &input); + let result = default::impl_derive_execute(&mut emitter, &input); emitter.finish_token_stream_with(result) } @@ -87,24 +81,23 @@ pub fn derive_validate(input: TokenStream) -> TokenStream { /// supplying corresponding visit function names inside of it, otherwise a default /// implementation from `iroha_executor::default` module is used. /// -/// Emits a compile error if the struct didn't have all the expected fields with corresponding -/// types, i.e. `verdict`: `iroha_executor::prelude::Result` and `block_height`: `u64`, -/// though technically only `verdict` is needed. The types can be unqualified, but not aliased. +/// Emits a compile error if the struct didn't have all the expected fields with corresponding types. /// /// # Example /// /// ```ignore /// use iroha_executor::prelude::*; /// -/// #[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +/// #[derive(Constructor, Visit, Execute, Entrypoints)] /// #[visit(custom(visit_query)] -/// pub struct Executor { +/// struct Executor { +/// host: Iroha, +/// context: Context, /// verdict: Result, -/// block_height: u64, /// } /// /// // Custom visit function should supply a `&mut Executor` as first argument -/// fn visit_query(executor: &mut Executor, _authority: &AccountId, _query: &AnyQueryBox) { +/// fn visit_query(executor: &mut Executor, _query: &AnyQueryBox) { /// executor.deny(ValidationFail::NotPermitted( /// "All queries are forbidden".to_owned(), /// )); @@ -124,32 +117,31 @@ pub fn derive_visit(input: TokenStream) -> TokenStream { emitter.finish_token_stream_with(result) } -/// Implements three default entrypoints on a given `Executor` struct: `validate_transaction`, -/// `validate_query` and `validate_instruction`. The `migrate` entrypoint is implied to be +/// Implements three default entrypoints on a given `Executor` struct: `execute_transaction`, +/// `validate_query` and `execute_instruction`. The `migrate` entrypoint is implied to be /// implemented manually by the user at all times. /// /// Users can supply custom overrides for any of the entrypoint functions as freestanding functions /// in the same module via the `#[entrypoints(custom(...))]` attribute by /// supplying corresponding entrypoint function names inside of it. /// -/// Emits a compile error if the struct didn't have all the expected fields with corresponding -/// types, i.e. `verdict`: `iroha_executor::prelude::Result` and `block_height`: `u64`, -/// though technically only `verdict` is needed. The types can be unqualified, but not aliased. +/// Emits a compile error if the struct didn't have all the expected fields with corresponding types. /// /// # Example /// /// ```ignore /// use iroha_executor::prelude::*; /// -/// #[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +/// #[derive(Constructor, Visit, Validate, Entrypoints)] /// #[entrypoints(custom(validate_query))] /// pub struct Executor { +/// context: Context, /// verdict: Result, -/// block_height: u64, +/// host: Iroha, /// } /// ``` #[manyhow] -#[proc_macro_derive(ValidateEntrypoints, attributes(entrypoints))] +#[proc_macro_derive(Entrypoints, attributes(entrypoints))] pub fn derive_entrypoints(input: TokenStream) -> TokenStream { let mut emitter = Emitter::new(); @@ -164,11 +156,9 @@ pub fn derive_entrypoints(input: TokenStream) -> TokenStream { /// Implements a constructor for the given `Executor` struct. If the `Executor` has any custom fields /// (i.e. different from the expected fields listed below), they will be included into the constructor -/// automatically and will need to be passed into `new()` function explicitly. In the default case, -/// only the `block_height` needs to be supplied manually. +/// automatically and will need to be passed into `new()` function explicitly. /// -/// Emits a compile error if the struct didn't have all the expected fields with corresponding -/// types, i.e. `verdict`: `iroha_executor::prelude::Result` and `block_height`: `u64`. +/// Emits a compile error if the struct didn't have all the expected fields with corresponding types. /// The types can be unqualified, but not aliased. #[manyhow] #[proc_macro_derive(Constructor)] diff --git a/crates/iroha_genesis/src/lib.rs b/crates/iroha_genesis/src/lib.rs index 1bd448168a5..70649c91ebd 100644 --- a/crates/iroha_genesis/src/lib.rs +++ b/crates/iroha_genesis/src/lib.rs @@ -336,6 +336,7 @@ fn convert_parameters(parameters: Vec) -> Option { for parameter in parameters { result.set_parameter(parameter); } + Some(result) } @@ -512,6 +513,7 @@ mod tests { "instructions": [] }}"# ); + let _genesis: RawGenesisTransaction = serde_json::from_str(&genesis_json).expect("Failed to deserialize"); } diff --git a/crates/iroha_primitives/src/const_vec.rs b/crates/iroha_primitives/src/const_vec.rs index 54f7c628b28..3cf7287cd5c 100644 --- a/crates/iroha_primitives/src/const_vec.rs +++ b/crates/iroha_primitives/src/const_vec.rs @@ -98,7 +98,7 @@ impl<'a, T> IntoIterator for &'a ConstVec { type IntoIter = <&'a [T] as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + self.0.iter() } } diff --git a/crates/iroha_schema_gen/src/lib.rs b/crates/iroha_schema_gen/src/lib.rs index a6d22807cb9..4051bb2a883 100644 --- a/crates/iroha_schema_gen/src/lib.rs +++ b/crates/iroha_schema_gen/src/lib.rs @@ -75,7 +75,7 @@ pub fn build_schemas() -> MetaMap { permission::asset_definition::CanModifyAssetDefinitionMetadata, permission::asset::CanRegisterAssetWithDefinition, permission::asset::CanUnregisterAssetWithDefinition, - permission::asset::CanTransferAssetsWithDefinition, + permission::asset::CanTransferAssetWithDefinition, permission::asset::CanRegisterAsset, permission::asset::CanUnregisterAsset, permission::asset::CanMintAsset, @@ -315,7 +315,6 @@ types!( Option>, Option>, Option, - Option, Option, Option, Option, @@ -614,7 +613,7 @@ mod tests { iroha_executor_data_model::permission::asset::CanUnregisterAssetWithDefinition ); insert_into_test_map!( - iroha_executor_data_model::permission::asset::CanTransferAssetsWithDefinition + iroha_executor_data_model::permission::asset::CanTransferAssetWithDefinition ); insert_into_test_map!(iroha_executor_data_model::permission::asset::CanRegisterAsset); insert_into_test_map!(iroha_executor_data_model::permission::asset::CanUnregisterAsset); diff --git a/crates/iroha_smart_contract/src/lib.rs b/crates/iroha_smart_contract/src/lib.rs index f0fc3d7ba6f..08131cde857 100644 --- a/crates/iroha_smart_contract/src/lib.rs +++ b/crates/iroha_smart_contract/src/lib.rs @@ -7,8 +7,6 @@ extern crate alloc; use alloc::boxed::Box; use core::fmt::Debug; -#[cfg(not(test))] -use data_model::smart_contract::payloads; use data_model::{ isi::BuiltInInstruction, prelude::*, @@ -29,109 +27,100 @@ use iroha_smart_contract_utils::{ }; use parity_scale_codec::{Decode, Encode}; -#[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"); - } - let layout = core::alloc::Layout::array::(len).dbg_expect("Cannot allocate layout"); - // Safety: safe because `layout` is guaranteed to have non-zero size - unsafe { alloc::alloc::alloc_zeroed(layout) } +/// An iterable query cursor for use in smart contracts. +#[derive(Debug, Clone, Encode, Decode)] +pub struct QueryCursor { + cursor: ForwardCursor, } -/// # Safety -/// - `offset` is a pointer to a `[u8; len]` which is allocated in the WASM memory. -/// - This function can't call destructor of the encoded object. -#[no_mangle] -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)); -} +/// Client for the host environment +#[derive(Debug, Clone, Encode, Decode)] +#[allow(missing_copy_implementations)] +pub struct Iroha; -/// 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."; +impl Iroha { + /// Submits one Iroha Special Instruction + /// + /// # Errors + /// Fails if sending transaction to peer fails or if it response with error + pub fn submit(&self, isi: &I) -> Result<(), ValidationFail> { + self.submit_all([isi]) + } - // we don't support logging in our current wasm test runner implementation - #[cfg(not(test))] - error!(ERROR_MESSAGE); - unimplemented!("{ERROR_MESSAGE}") -} + /// Submits several Iroha Special Instructions + /// + /// # Errors + /// Fails if sending transaction to peer fails or if it response with error + #[expect(clippy::unused_self)] + pub fn submit_all<'isi, I: BuiltInInstruction + Encode + 'isi>( + &self, + instructions: impl IntoIterator, + ) -> Result<(), ValidationFail> { + instructions.into_iter().try_for_each(|isi| { + #[cfg(not(test))] + use host::execute_instruction as host_execute_instruction; + #[cfg(test)] + use tests::_iroha_smart_contract_execute_instruction_mock as host_execute_instruction; + + let bytes = isi.encode_as_instruction_box(); + // Safety: `host_execute_instruction` doesn't take ownership of it's pointer parameter + unsafe { + decode_with_length_prefix_from_raw::>( + host_execute_instruction(bytes.as_ptr(), bytes.len()), + ) + } + })?; + + Ok(()) + } + + /// Build an iterable query for execution in a smart contract. + pub fn query( + &self, + query: Q, + ) -> QueryBuilder::Item as HasPredicateBox>::PredicateBoxType> + where + Q: Query, + { + QueryBuilder::new(self, query) + } -/// Implementing instructions can be executed on the host -pub trait ExecuteOnHost { - /// Execute instruction on the host + /// Run a singular query in a smart contract. /// /// # Errors /// - /// - If instruction validation failed - /// - If instruction execution failed - fn execute(&self) -> Result<(), ValidationFail>; -} + /// Returns an error if the query execution fails. + pub fn query_single(&self, query: Q) -> Result + where + Q: SingularQuery, + SingularQueryBox: From, + Q::Output: TryFrom, + >::Error: Debug, + { + let query = SingularQueryBox::from(query); + + let result = self.execute_singular_query(query)?; + + Ok(result + .try_into() + .expect("BUG: iroha returned unexpected type in singular query")) + } -impl ExecuteOnHost for I { - fn execute(&self) -> Result<(), ValidationFail> { + fn execute_query(query: &QueryRequest) -> Result { #[cfg(not(test))] - use host::execute_instruction as host_execute_instruction; + use host::execute_query as host_execute_query; #[cfg(test)] - use tests::_iroha_smart_contract_execute_instruction_mock as host_execute_instruction; + use tests::_iroha_smart_contract_execute_query_mock as host_execute_query; - let bytes = self.encode_as_instruction_box(); - // Safety: `host_execute_instruction` doesn't take ownership of it's pointer parameter + // Safety: - `host_execute_query` doesn't take ownership of it's pointer parameter + // - ownership of the returned result is transferred into `_decode_from_raw` unsafe { - decode_with_length_prefix_from_raw(host_execute_instruction( - bytes.as_ptr(), - bytes.len(), - )) + decode_with_length_prefix_from_raw(encode_and_execute(&query, host_execute_query)) } } } -/// An iterable query cursor for use in smart contracts. -#[derive(Clone, Debug, Encode, Decode)] -pub struct QueryCursor { - cursor: ForwardCursor, -} - -fn execute_query(query: &QueryRequest) -> Result { - #[cfg(not(test))] - use host::execute_query as host_execute_query; - #[cfg(test)] - use tests::_iroha_smart_contract_execute_query_mock as host_execute_query; - - // Safety: - `host_execute_query` doesn't take ownership of it's pointer parameter - // - ownership of the returned result is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(encode_and_execute(&query, host_execute_query)) } -} - -/// A [`QueryExecutor`] for use in smart contracts. -#[derive(Copy, Clone, Debug)] -pub struct SmartContractQueryExecutor; - -impl QueryExecutor for SmartContractQueryExecutor { +impl QueryExecutor for Iroha { type Cursor = QueryCursor; type Error = ValidationFail; @@ -139,7 +128,8 @@ impl QueryExecutor for SmartContractQueryExecutor { &self, query: SingularQueryBox, ) -> Result { - let QueryResponse::Singular(output) = execute_query(&QueryRequest::Singular(query))? else { + let QueryResponse::Singular(output) = Self::execute_query(&QueryRequest::Singular(query))? + else { dbg_panic("BUG: iroha returned unexpected type in singular query"); }; @@ -150,7 +140,8 @@ impl QueryExecutor for SmartContractQueryExecutor { &self, query: QueryWithParams, ) -> Result<(QueryOutputBatchBox, u64, Option), Self::Error> { - let QueryResponse::Iterable(output) = execute_query(&QueryRequest::Start(query))? else { + let QueryResponse::Iterable(output) = Self::execute_query(&QueryRequest::Start(query))? + else { dbg_panic("BUG: iroha returned unexpected type in iterable query"); }; @@ -167,7 +158,7 @@ impl QueryExecutor for SmartContractQueryExecutor { cursor: Self::Cursor, ) -> Result<(QueryOutputBatchBox, u64, Option), Self::Error> { let QueryResponse::Iterable(output) = - execute_query(&QueryRequest::Continue(cursor.cursor))? + Self::execute_query(&QueryRequest::Continue(cursor.cursor))? else { dbg_panic("BUG: iroha returned unexpected type in iterable query"); }; @@ -182,48 +173,63 @@ impl QueryExecutor for SmartContractQueryExecutor { } } -/// Build an iterable query for execution in a smart contract. -pub fn query( - query: Q, -) -> QueryBuilder< - 'static, - SmartContractQueryExecutor, - Q, - ::PredicateBoxType, -> -where - Q: Query, - Q::Item: HasPredicateBox, -{ - QueryBuilder::new(&SmartContractQueryExecutor, query) +#[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"); + } + let layout = core::alloc::Layout::array::(len).dbg_expect("Cannot allocate layout"); + // Safety: safe because `layout` is guaranteed to have non-zero size + unsafe { alloc::alloc::alloc_zeroed(layout) } +} + +/// # Safety +/// - `offset` is a pointer to a `[u8; len]` which is allocated in the WASM memory. +/// - This function can't call destructor of the encoded object. +#[no_mangle] +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)); } -/// Run a singular query in a smart contract. +/// 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 /// -/// Returns an error if the query execution fails. -pub fn query_single(query: Q) -> Result -where - Q: SingularQuery, - SingularQueryBox: From, - Q::Output: TryFrom, - >::Error: Debug, -{ - let query = SingularQueryBox::from(query); - - let result = SmartContractQueryExecutor.execute_singular_query(query)?; - - Ok(result - .try_into() - .expect("BUG: iroha returned unexpected type in singular query")) +/// 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 payload for smart contract `main()` entrypoint. +/// Get context for smart contract `main()` entrypoint. #[cfg(not(test))] -pub fn get_smart_contract_payload() -> payloads::SmartContract { +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_payload()) } + unsafe { decode_with_length_prefix_from_raw(host::get_smart_contract_context()) } } #[cfg(not(test))] @@ -248,11 +254,11 @@ mod host { /// but it does transfer ownership of the result to the caller pub(super) fn execute_instruction(ptr: *const u8, len: usize) -> *const u8; - /// Get payload for smart contract `main()` entrypoint. + /// Get context for smart contract `main()` entrypoint. /// # Warning /// - /// This function does transfer ownership of the result to the caller - pub(super) fn get_smart_contract_payload() -> *const u8; + /// This function transfers ownership of the result to the caller + pub(super) fn get_smart_contract_context() -> *const u8; } } @@ -261,7 +267,10 @@ pub mod prelude { pub use iroha_smart_contract_derive::main; pub use iroha_smart_contract_utils::debug::DebugUnwrapExt; - pub use crate::{data_model::prelude::*, ExecuteOnHost}; + pub use crate::{ + data_model::{prelude::*, smart_contract::payloads::SmartContractContext as Context}, + Iroha, + }; } #[cfg(test)] @@ -321,11 +330,13 @@ mod tests { #[webassembly_test] fn execute_instruction() { - get_test_instruction().execute().unwrap(); + let host = Iroha; + host.submit(&get_test_instruction()).unwrap(); } #[webassembly_test] fn execute_query() { - assert_eq!(query_single(get_test_query()), QUERY_RESULT); + let host = Iroha; + assert_eq!(host.query_single(get_test_query()), QUERY_RESULT); } } diff --git a/crates/iroha_smart_contract_derive/src/entrypoint.rs b/crates/iroha_smart_contract_derive/src/entrypoint.rs index b0ce6d8c40b..4184c4b2c3f 100644 --- a/crates/iroha_smart_contract_derive/src/entrypoint.rs +++ b/crates/iroha_smart_contract_derive/src/entrypoint.rs @@ -6,7 +6,6 @@ use iroha_macro_utils::Emitter; use manyhow::emit; use proc_macro2::TokenStream; use quote::quote; -use syn::parse_quote; mod export { pub const SMART_CONTRACT_MAIN: &str = "_iroha_smart_contract_main"; @@ -18,7 +17,7 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream attrs, vis, sig, - mut block, + block, } = item; if sig.output != syn::ReturnType::Default { @@ -29,14 +28,6 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream } let fn_name = &sig.ident; - - block.stmts.insert( - 0, - parse_quote!( - use ::iroha_smart_contract::{debug::DebugExpectExt as _, ExecuteOnHost as _}; - ), - ); - let main_fn_name = syn::Ident::new(export::SMART_CONTRACT_MAIN, proc_macro2::Span::call_site()); quote! { @@ -44,8 +35,9 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream #[no_mangle] #[doc(hidden)] unsafe extern "C" fn #main_fn_name() { - let payload = ::iroha_smart_contract::get_smart_contract_payload(); - #fn_name(payload.owner) + let host = ::iroha_smart_contract::Iroha; + let context = ::iroha_smart_contract::get_smart_contract_context(); + #fn_name(host, context) } // NOTE: Host objects are always passed by value to wasm diff --git a/crates/iroha_smart_contract_derive/src/lib.rs b/crates/iroha_smart_contract_derive/src/lib.rs index 1e6a19e10b1..5ae0577fa5e 100644 --- a/crates/iroha_smart_contract_derive/src/lib.rs +++ b/crates/iroha_smart_contract_derive/src/lib.rs @@ -8,20 +8,22 @@ mod entrypoint; /// Annotate the user-defined function that starts the execution of the smart contract. /// -/// Requires function to accept one argument of type `AccountId`, which represents the smart contract owner. +/// Requires function to accept two arguments of types: +/// 1. `host: Iroha` - handle to the host system (use it to execute instructions and queries) +/// 2. `context: Context` - context of the execution (authority, triggering event, et) /// /// # Panics /// /// - If function has a return type /// /// # Examples -// `ignore` because this macro idiomatically should be imported from `iroha_wasm` crate. // -/// Using without parameters: -/// ```ignore -/// #[iroha_smart_contract::main] -/// fn main(owner: AccountId) { -/// todo!() +/// ``` +/// use iroha_smart_contract::prelude::*; +/// +/// #[main] +/// fn main(host: Iroha, context: Context) { +/// todo!() /// } /// ``` #[manyhow] diff --git a/crates/iroha_test_network/src/lib.rs b/crates/iroha_test_network/src/lib.rs index 7f144779343..84b61667dae 100644 --- a/crates/iroha_test_network/src/lib.rs +++ b/crates/iroha_test_network/src/lib.rs @@ -14,7 +14,7 @@ pub use iroha_core::state::StateReadOnly; use iroha_crypto::{ExposedPrivateKey, KeyPair}; use iroha_data_model::{asset::AssetDefinitionId, isi::InstructionBox, ChainId}; use iroha_executor_data_model::permission::{ - asset::CanMintAssetsWithDefinition, domain::CanUnregisterDomain, executor::CanUpgradeExecutor, + asset::CanMintAssetWithDefinition, domain::CanUnregisterDomain, executor::CanUpgradeExecutor, peer::CanManagePeers, role::CanManageRoles, }; use iroha_futures::supervisor::ShutdownSignal; @@ -97,7 +97,7 @@ impl TestGenesis for GenesisBlock { let rose_definition_id = "rose#wonderland".parse::().unwrap(); let grant_modify_rose_permission = Grant::account_permission( - CanMintAssetsWithDefinition { + CanMintAssetWithDefinition { asset_definition: rose_definition_id.clone(), }, ALICE_ID.clone(), diff --git a/crates/iroha_trigger/src/lib.rs b/crates/iroha_trigger/src/lib.rs index 413f6f2be77..ffa36a49186 100644 --- a/crates/iroha_trigger/src/lib.rs +++ b/crates/iroha_trigger/src/lib.rs @@ -2,12 +2,8 @@ #![no_std] #![allow(unsafe_code)] -#[cfg(not(test))] -use data_model::smart_contract::payloads; pub use iroha_smart_contract as smart_contract; pub use iroha_smart_contract_utils::debug; -#[cfg(not(test))] -use iroha_smart_contract_utils::decode_with_length_prefix_from_raw; pub use iroha_trigger_derive::main; pub use smart_contract::{data_model, stub_getrandom}; @@ -20,26 +16,30 @@ pub mod log { mod host { #[link(wasm_import_module = "iroha")] extern "C" { - /// Get payload for trigger `main()` entrypoint. + /// Get context for trigger `main()` entrypoint. /// /// # Warning /// /// This function does transfer ownership of the result to the caller - pub(super) fn get_trigger_payload() -> *const u8; + pub(super) fn get_trigger_context() -> *const u8; } } -/// Get payload for trigger `main()` entrypoint. +/// Get context for trigger `main()` entrypoint. #[cfg(not(test))] -pub fn get_trigger_payload() -> payloads::Trigger { +pub fn get_trigger_context() -> data_model::smart_contract::payloads::TriggerContext { // Safety: ownership of the returned result is transferred into `_decode_from_raw` - unsafe { decode_with_length_prefix_from_raw(host::get_trigger_payload()) } + 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 iroha_smart_contract::{data_model::prelude::*, prelude::*}; + 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; } diff --git a/crates/iroha_trigger_derive/src/entrypoint.rs b/crates/iroha_trigger_derive/src/entrypoint.rs index 3307fd6a7d0..2337268151d 100644 --- a/crates/iroha_trigger_derive/src/entrypoint.rs +++ b/crates/iroha_trigger_derive/src/entrypoint.rs @@ -4,7 +4,6 @@ use iroha_macro_utils::Emitter; use manyhow::emit; use proc_macro2::TokenStream; use quote::quote; -use syn::parse_quote; mod export { pub const TRIGGER_MAIN: &str = "_iroha_trigger_main"; @@ -17,7 +16,7 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream attrs, vis, sig, - mut block, + block, } = item; if sig.output != syn::ReturnType::Default { @@ -29,14 +28,6 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream } let fn_name = &sig.ident; - - block.stmts.insert( - 0, - parse_quote!( - use ::iroha_trigger::smart_contract::{debug::DebugExpectExt as _, ExecuteOnHost as _}; - ), - ); - let main_fn_name = syn::Ident::new(export::TRIGGER_MAIN, proc_macro2::Span::call_site()); quote! { @@ -44,8 +35,9 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream #[no_mangle] #[doc(hidden)] unsafe extern "C" fn #main_fn_name() { - let payload = ::iroha_trigger::get_trigger_payload(); - #fn_name(payload.id, payload.owner, payload.event) + let host = ::iroha_trigger::smart_contract::Iroha; + let context = ::iroha_trigger::get_trigger_context(); + #fn_name(host, context) } // NOTE: Host objects are always passed by value to wasm diff --git a/crates/iroha_trigger_derive/src/lib.rs b/crates/iroha_trigger_derive/src/lib.rs index 8e05e163f87..f3745abb97c 100644 --- a/crates/iroha_trigger_derive/src/lib.rs +++ b/crates/iroha_trigger_derive/src/lib.rs @@ -9,16 +9,20 @@ mod entrypoint; /// Annotate the user-defined function that starts the execution of the trigger. /// /// Requires function to accept two arguments of types: -/// 1. `AccountId`, which represents the trigger owner -/// 2. `Event`, which represents the event which triggered this trigger execution +/// 1. `host: Iroha` - handle to the host system (use it to execute instructions and queries) +/// 2. `context: Context` - context of the execution (authority, triggering event, et) +/// +/// # Panics +/// +/// - If function has a return type /// /// # Examples /// -/// ```ignore +/// ``` /// use iroha_trigger::prelude::*; /// /// #[main] -/// fn main(owner: AccountId, event: Event) { +/// fn main(host: Iroha, context: Context) { /// todo!() /// } /// ``` diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index de724c14da0..1cc000a4fa1 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -925,7 +925,7 @@ } ] }, - "CanTransferAssetsWithDefinition": { + "CanTransferAssetWithDefinition": { "Struct": [ { "name": "asset_definition", @@ -1699,7 +1699,7 @@ }, { "name": "args", - "type": "Option" + "type": "JsonString" } ] }, @@ -1715,7 +1715,7 @@ }, { "name": "args", - "type": "Option" + "type": "JsonString" } ] }, @@ -2685,9 +2685,6 @@ "Option": { "Option": "IpfsPath" }, - "Option": { - "Option": "JsonString" - }, "Option": { "Option": "Name" }, 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 221ab7d4226..415329d8a0f 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 @@ -8,7 +8,7 @@ extern crate panic_halt; use alloc::{format, string::ToString}; use dlmalloc::GlobalDlmalloc; -use iroha_trigger::{prelude::*, smart_contract::query}; +use iroha_trigger::prelude::*; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; @@ -16,10 +16,9 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); #[iroha_trigger::main] -fn main(_id: TriggerId, _owner: AccountId, _event: EventBox) { +fn main(host: Iroha, _context: Context) { iroha_trigger::log::info!("Executing trigger"); - - let accounts_cursor = query(FindAccounts).execute().dbg_unwrap(); + let accounts_cursor = host.query(FindAccounts).execute().dbg_unwrap(); let bad_domain_ids: [DomainId; 2] = [ "genesis".parse().dbg_unwrap(), @@ -43,24 +42,24 @@ fn main(_id: TriggerId, _owner: AccountId, _event: EventBox) { .dbg_unwrap(); metadata.insert(name, true); - let nft_id = generate_new_nft_id(account.id()); + let nft_id = generate_new_nft_id(&host, account.id()); let nft_definition = AssetDefinition::store(nft_id.clone()) .mintable_once() .with_metadata(metadata); let account_nft_id = AssetId::new(nft_id, account.id().clone()); let account_nft = Asset::new(account_nft_id, Metadata::default()); - Register::asset_definition(nft_definition) - .execute() + host.submit(&Register::asset_definition(nft_definition)) .dbg_unwrap(); - Register::asset(account_nft).execute().dbg_unwrap(); + host.submit(&Register::asset(account_nft)).dbg_unwrap(); } iroha_trigger::log::info!("Smart contract executed successfully"); } -fn generate_new_nft_id(account_id: &AccountId) -> AssetDefinitionId { - let assets = query(FindAssets) +fn generate_new_nft_id(host: &Iroha, account_id: &AccountId) -> AssetDefinitionId { + let assets = host + .query(FindAssets) .filter_with(|asset| asset.id.account.eq(account_id.clone())) .execute() .dbg_unwrap(); diff --git a/wasm_samples/default_executor/src/lib.rs b/wasm_samples/default_executor/src/lib.rs index 9fc90729682..9d14bd1e409 100644 --- a/wasm_samples/default_executor/src/lib.rs +++ b/wasm_samples/default_executor/src/lib.rs @@ -14,15 +14,16 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); -/// Executor that replaces some of [`Validate`]'s methods with sensible defaults +/// Executor that replaces some of [`Execute`]'s methods with sensible defaults /// /// # Warning /// /// The defaults are not guaranteed to be stable. -#[derive(Debug, Clone, Constructor, Visit, Validate, ValidateEntrypoints)] +#[derive(Debug, Clone, Constructor, Visit, Execute, Entrypoints)] pub struct Executor { + host: Iroha, + context: Context, verdict: Result, - block_height: u64, } impl Executor { @@ -46,7 +47,7 @@ impl Executor { /// If `migrate()` entrypoint fails then the whole `Upgrade` instruction /// will be denied and previous executor will stay unchanged. #[entrypoint] -fn migrate(block_height: u64) { - Executor::ensure_genesis(block_height); - DataModelBuilder::with_default_permissions().build_and_set(); +fn migrate(host: Iroha, context: Context) { + Executor::ensure_genesis(context.block_height); + DataModelBuilder::with_default_permissions().build_and_set(&host); } diff --git a/wasm_samples/executor_custom_data_model/src/mint_rose_args.rs b/wasm_samples/executor_custom_data_model/src/mint_rose_args.rs index a07fb859706..501c3810bf0 100644 --- a/wasm_samples/executor_custom_data_model/src/mint_rose_args.rs +++ b/wasm_samples/executor_custom_data_model/src/mint_rose_args.rs @@ -1,5 +1,6 @@ //! Arguments to mint rose with args trigger +use iroha_data_model::prelude::JsonString; use serde::{Deserialize, Serialize}; /// Arguments to mint rose with args trigger @@ -8,3 +9,17 @@ pub struct MintRoseArgs { // Amount to mint pub val: u32, } + +impl From for JsonString { + fn from(details: MintRoseArgs) -> Self { + JsonString::new(details) + } +} + +impl TryFrom<&JsonString> for MintRoseArgs { + type Error = serde_json::Error; + + fn try_from(payload: &JsonString) -> serde_json::Result { + serde_json::from_str::(payload.as_ref()) + } +} diff --git a/wasm_samples/executor_custom_data_model/src/multisig.rs b/wasm_samples/executor_custom_data_model/src/multisig.rs index 916fa06eaf6..5a42c2494bd 100644 --- a/wasm_samples/executor_custom_data_model/src/multisig.rs +++ b/wasm_samples/executor_custom_data_model/src/multisig.rs @@ -22,3 +22,31 @@ pub enum MultisigArgs { /// Accept vote for certain instructions Vote(HashOf>), } + +impl From for JsonString { + fn from(details: MultisigRegisterArgs) -> Self { + JsonString::new(details) + } +} + +impl TryFrom<&JsonString> for MultisigRegisterArgs { + type Error = serde_json::Error; + + fn try_from(payload: &JsonString) -> serde_json::Result { + serde_json::from_str::(payload.as_ref()) + } +} + +impl From for JsonString { + fn from(details: MultisigArgs) -> Self { + JsonString::new(details) + } +} + +impl TryFrom<&JsonString> for MultisigArgs { + type Error = serde_json::Error; + + fn try_from(payload: &JsonString) -> serde_json::Result { + serde_json::from_str::(payload.as_ref()) + } +} diff --git a/wasm_samples/executor_custom_instructions_complex/src/lib.rs b/wasm_samples/executor_custom_instructions_complex/src/lib.rs index 7668553fa71..2d4ee5492df 100644 --- a/wasm_samples/executor_custom_instructions_complex/src/lib.rs +++ b/wasm_samples/executor_custom_instructions_complex/src/lib.rs @@ -24,18 +24,19 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); -#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +#[derive(Constructor, Visit, Execute, Entrypoints)] #[visit(custom(visit_custom))] struct Executor { + context: iroha_executor::prelude::Context, verdict: Result, - block_height: u64, + host: Iroha, } -fn visit_custom(executor: &mut Executor, _authority: &AccountId, isi: &CustomInstruction) { +fn visit_custom(executor: &mut Executor, isi: &CustomInstruction) { let Ok(isi) = CustomInstructionExpr::try_from(isi.payload()) else { deny!(executor, "Failed to parse custom instruction"); }; - match execute_custom_instruction(isi) { + match execute_custom_instruction(isi, executor.host()) { Ok(()) => return, Err(err) => { deny!(executor, err); @@ -43,44 +44,48 @@ fn visit_custom(executor: &mut Executor, _authority: &AccountId, isi: &CustomIns } } -fn execute_custom_instruction(isi: CustomInstructionExpr) -> Result<(), ValidationFail> { +fn execute_custom_instruction( + isi: CustomInstructionExpr, + host: &Iroha, +) -> Result<(), ValidationFail> { match isi { - CustomInstructionExpr::Core(isi) => execute_core(isi), - CustomInstructionExpr::If(isi) => execute_if(*isi), + CustomInstructionExpr::Core(isi) => execute_core(isi, host), + CustomInstructionExpr::If(isi) => execute_if(*isi, host), } } -fn execute_core(isi: CoreExpr) -> Result<(), ValidationFail> { - let isi = isi.object.evaluate(&Context)?; - isi.execute() +fn execute_core(isi: CoreExpr, host: &Iroha) -> Result<(), ValidationFail> { + let isi = &isi.object.evaluate(&Context { host })?; + host.submit(isi) } -fn execute_if(isi: ConditionalExpr) -> Result<(), ValidationFail> { - let condition = isi.condition.evaluate(&Context)?; +fn execute_if(isi: ConditionalExpr, host: &Iroha) -> Result<(), ValidationFail> { + let condition = isi.condition.evaluate(&Context { host })?; if condition { - execute_custom_instruction(isi.then) + execute_custom_instruction(isi.then, host) } else { Ok(()) } } -struct Context; +struct Context<'i> { + host: &'i Iroha, +} -impl executor_custom_data_model::complex_isi::Context for Context { +impl executor_custom_data_model::complex_isi::Context for Context<'_> { fn query(&self, q: &NumericQuery) -> Result { let result = match q.clone() { - NumericQuery::FindAssetQuantityById(q) => { - iroha_executor::smart_contract::query_single(q) - } + NumericQuery::FindAssetQuantityById(q) => self.host.query_single(q), NumericQuery::FindTotalAssetQuantityByAssetDefinitionId(asset_definition_id) => { - let asset_definition = - iroha_executor::smart_contract::query(FindAssetsDefinitions::new()) - .filter_with(|asset_definition| asset_definition.id.eq(asset_definition_id)) - .execute_single() - .map_err(|e| match e { - SingleQueryError::QueryError(e) => e, - _ => unreachable!(), - })?; + let asset_definition = self + .host + .query(FindAssetsDefinitions::new()) + .filter_with(|asset_definition| asset_definition.id.eq(asset_definition_id)) + .execute_single() + .map_err(|e| match e { + SingleQueryError::QueryError(e) => e, + _ => unreachable!(), + })?; Ok(*asset_definition.total_quantity()) } @@ -91,10 +96,10 @@ impl executor_custom_data_model::complex_isi::Context for Context { } #[entrypoint] -fn migrate(_block_height: u64) { +fn migrate(host: Iroha, _context: iroha_executor::prelude::Context) { DataModelBuilder::with_default_permissions() .add_instruction::() .add_instruction::() .add_instruction::() - .build_and_set(); + .build_and_set(&host); } diff --git a/wasm_samples/executor_custom_instructions_simple/src/lib.rs b/wasm_samples/executor_custom_instructions_simple/src/lib.rs index bc1d3f4a0a8..c13956bed5c 100644 --- a/wasm_samples/executor_custom_instructions_simple/src/lib.rs +++ b/wasm_samples/executor_custom_instructions_simple/src/lib.rs @@ -10,27 +10,26 @@ 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::*, smart_contract::query, -}; +use iroha_executor::{data_model::isi::CustomInstruction, debug::DebugExpectExt, prelude::*}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); -#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +#[derive(Constructor, Visit, Execute, Entrypoints)] #[visit(custom(visit_custom))] struct Executor { + context: Context, verdict: Result, - block_height: u64, + host: Iroha, } -fn visit_custom(executor: &mut Executor, _authority: &AccountId, isi: &CustomInstruction) { +fn visit_custom(executor: &mut Executor, isi: &CustomInstruction) { let Ok(isi) = CustomInstructionBox::try_from(isi.payload()) else { deny!(executor, "Failed to parse custom instruction"); }; - match execute_custom_instruction(isi) { + match execute_custom_instruction(isi, executor.host()) { Ok(()) => return, Err(err) => { deny!(executor, err); @@ -38,29 +37,37 @@ fn visit_custom(executor: &mut Executor, _authority: &AccountId, isi: &CustomIns } } -fn execute_custom_instruction(isi: CustomInstructionBox) -> Result<(), ValidationFail> { +fn execute_custom_instruction( + isi: CustomInstructionBox, + host: &Iroha, +) -> Result<(), ValidationFail> { match isi { CustomInstructionBox::MintAssetForAllAccounts(isi) => { - execute_mint_asset_for_all_accounts(isi) + execute_mint_asset_for_all_accounts(isi, host) } } } -fn execute_mint_asset_for_all_accounts(isi: MintAssetForAllAccounts) -> Result<(), ValidationFail> { - let accounts = query(FindAccountsWithAsset::new(isi.asset_definition.clone())).execute()?; +fn execute_mint_asset_for_all_accounts( + isi: MintAssetForAllAccounts, + host: &Iroha, +) -> Result<(), ValidationFail> { + let accounts = host + .query(FindAccountsWithAsset::new(isi.asset_definition.clone())) + .execute()?; for account in accounts { let account = account.dbg_expect("Failed to get accounts with asset"); let asset_id = AssetId::new(isi.asset_definition.clone(), account.id().clone()); - Mint::asset_numeric(isi.quantity, asset_id).execute()?; + host.submit(&Mint::asset_numeric(isi.quantity, asset_id))?; } Ok(()) } #[entrypoint] -fn migrate(_block_height: u64) { +fn migrate(host: Iroha, _context: Context) { DataModelBuilder::with_default_permissions() .add_instruction::() .add_instruction::() - .build_and_set(); + .build_and_set(&host); } diff --git a/wasm_samples/executor_remove_permission/src/lib.rs b/wasm_samples/executor_remove_permission/src/lib.rs index d93b76c2ceb..e1f9b93820d 100644 --- a/wasm_samples/executor_remove_permission/src/lib.rs +++ b/wasm_samples/executor_remove_permission/src/lib.rs @@ -15,17 +15,18 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); -#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +#[derive(Constructor, Visit, Execute, Entrypoints)] struct Executor { + host: Iroha, + context: Context, verdict: Result, - block_height: u64, } #[entrypoint] -fn migrate(_block_height: u64) { +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 DataModelBuilder::with_default_permissions() .remove_permission::() - .build_and_set(); + .build_and_set(&host); } diff --git a/wasm_samples/executor_with_admin/src/lib.rs b/wasm_samples/executor_with_admin/src/lib.rs index d4466d1783a..3451a5f9112 100644 --- a/wasm_samples/executor_with_admin/src/lib.rs +++ b/wasm_samples/executor_with_admin/src/lib.rs @@ -14,24 +14,25 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); -#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +#[derive(Constructor, Visit, Execute, Entrypoints)] #[visit(custom(visit_instruction))] struct Executor { + host: Iroha, + context: Context, verdict: Result, - block_height: u64, } -fn visit_instruction(executor: &mut Executor, authority: &AccountId, isi: &InstructionBox) { +fn visit_instruction(executor: &mut Executor, isi: &InstructionBox) { // multihash equals to integration::upgrade::ADMIN_PUBLIC_KEY_MULTIHASH let admin_id = "ed012076E5CA9698296AF9BE2CA45F525CB3BCFDEB7EE068BA56F973E9DD90564EF4FC@admin" .parse() .unwrap(); - if *authority == admin_id { + if executor.context().authority == admin_id { execute!(executor, isi); } - iroha_executor::default::visit_instruction(executor, authority, isi); + iroha_executor::default::visit_instruction(executor, isi); } #[entrypoint] -fn migrate(_block_height: u64) {} +fn migrate(_host: Iroha, _context: Context) {} diff --git a/wasm_samples/executor_with_custom_parameter/src/lib.rs b/wasm_samples/executor_with_custom_parameter/src/lib.rs index c270cad2d15..b5c71a43bcf 100644 --- a/wasm_samples/executor_with_custom_parameter/src/lib.rs +++ b/wasm_samples/executor_with_custom_parameter/src/lib.rs @@ -9,7 +9,7 @@ use alloc::format; use dlmalloc::GlobalDlmalloc; use executor_custom_data_model::parameters::DomainLimits; -use iroha_executor::{prelude::*, smart_contract::query_single, DataModelBuilder}; +use iroha_executor::{prelude::*, smart_contract::Iroha, DataModelBuilder}; use iroha_executor_data_model::parameter::Parameter; #[global_allocator] @@ -17,15 +17,16 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); -#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +#[derive(Constructor, Visit, Execute, Entrypoints)] #[visit(custom(visit_register_domain))] struct Executor { + host: Iroha, + context: Context, verdict: Result, - block_height: u64, } -fn visit_register_domain(executor: &mut Executor, _authority: &AccountId, isi: &Register) { - let parameters = query_single(FindParameters).dbg_unwrap(); +fn visit_register_domain(executor: &mut Executor, isi: &Register) { + let parameters = executor.host().query_single(FindParameters).dbg_unwrap(); let domain_limits: DomainLimits = parameters .custom() @@ -43,8 +44,8 @@ fn visit_register_domain(executor: &mut Executor, _authority: &AccountId, isi: & } #[entrypoint] -fn migrate(_block_height: u64) { +fn migrate(host: Iroha, _context: Context) { DataModelBuilder::with_default_permissions() .add_parameter(DomainLimits::default()) - .build_and_set(); + .build_and_set(&host); } diff --git a/wasm_samples/executor_with_custom_permission/src/lib.rs b/wasm_samples/executor_with_custom_permission/src/lib.rs index 132ddf55b4d..0b9567db0f2 100644 --- a/wasm_samples/executor_with_custom_permission/src/lib.rs +++ b/wasm_samples/executor_with_custom_permission/src/lib.rs @@ -19,8 +19,7 @@ extern crate panic_halt; use dlmalloc::GlobalDlmalloc; use executor_custom_data_model::permissions::CanControlDomainLives; use iroha_executor::{ - data_model::prelude::*, permission::ExecutorPermission as _, prelude::*, smart_contract::query, - DataModelBuilder, + data_model::prelude::*, permission::ExecutorPermission as _, prelude::*, DataModelBuilder, }; use iroha_executor_data_model::permission::domain::CanUnregisterDomain; @@ -29,7 +28,7 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); -#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +#[derive(Constructor, Visit, Execute, Entrypoints)] #[visit(custom( visit_register_domain, visit_unregister_domain, @@ -41,19 +40,23 @@ getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); visit_revoke_role_permission ))] struct Executor { + host: Iroha, + context: Context, verdict: Result, - block_height: u64, } impl Executor { - fn get_all_accounts_with_can_unregister_domain_permission() -> impl Iterator { - query(FindAccounts) + fn get_all_accounts_with_can_unregister_domain_permission( + host: &Iroha, + ) -> impl Iterator + '_ { + host.query(FindAccounts) .execute() .expect("INTERNAL BUG: Failed to execute `FindAllAccounts`") .filter_map(|res| { let account = res.dbg_unwrap(); - if query(FindPermissionsByAccountId::new(account.id().clone())) + if host + .query(FindPermissionsByAccountId::new(account.id().clone())) .execute() .expect("INTERNAL BUG: Failed to execute `FindPermissionsByAccountId`") .filter_map(|res| { @@ -70,20 +73,22 @@ impl Executor { }) } - fn replace_token(accounts: &[Account]) { + fn replace_token(accounts: &[Account], host: &Iroha) { for account in accounts { - Grant::account_permission(CanControlDomainLives, account.id().clone()) - .execute() - .dbg_unwrap(); + host.submit(&Grant::account_permission( + CanControlDomainLives, + account.id().clone(), + )) + .dbg_unwrap(); } } } -fn visit_register_domain(executor: &mut Executor, authority: &AccountId, isi: &Register) { - if executor.block_height() == 0 { +fn visit_register_domain(executor: &mut Executor, isi: &Register) { + if executor.context().block_height == 0 { execute!(executor, isi); } - if CanControlDomainLives.is_owned_by(authority) { + if CanControlDomainLives.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } @@ -93,90 +98,82 @@ fn visit_register_domain(executor: &mut Executor, authority: &AccountId, isi: &R ); } -fn visit_unregister_domain( - executor: &mut Executor, - authority: &AccountId, - isi: &Unregister, -) { - if executor.block_height() == 0 { +fn visit_unregister_domain(executor: &mut Executor, isi: &Unregister) { + if executor.context().block_height == 0 { execute!(executor, isi); } - if CanControlDomainLives.is_owned_by(authority) { + if CanControlDomainLives.is_owned_by(&executor.context().authority, executor.host()) { execute!(executor, isi); } deny!(executor, "You don't have permission to unregister domain"); } -pub fn visit_grant_role_permission( +pub fn visit_grant_role_permission( executor: &mut V, - authority: &AccountId, isi: &Grant, ) { let role_id = isi.destination().clone(); if let Ok(permission) = CanControlDomainLives::try_from(isi.object()) { - let isi = Grant::role_permission(permission, role_id); + let isi = &Grant::role_permission(permission, role_id); execute!(executor, isi); } - iroha_executor::default::visit_grant_role_permission(executor, authority, isi) + iroha_executor::default::visit_grant_role_permission(executor, isi) } -pub fn visit_revoke_role_permission( +pub fn visit_revoke_role_permission( executor: &mut V, - authority: &AccountId, isi: &Revoke, ) { let role_id = isi.destination().clone(); if let Ok(permission) = CanControlDomainLives::try_from(isi.object()) { - let isi = Revoke::role_permission(permission, role_id); + let isi = &Revoke::role_permission(permission, role_id); execute!(executor, isi); } - iroha_executor::default::visit_revoke_role_permission(executor, authority, isi) + iroha_executor::default::visit_revoke_role_permission(executor, isi) } -pub fn visit_grant_account_permission( +pub fn visit_grant_account_permission( executor: &mut V, - authority: &AccountId, isi: &Grant, ) { let account_id = isi.destination().clone(); if let Ok(permission) = CanControlDomainLives::try_from(isi.object()) { - let isi = Grant::account_permission(permission, account_id); + let isi = &Grant::account_permission(permission, account_id); execute!(executor, isi); } - iroha_executor::default::visit_grant_account_permission(executor, authority, isi) + iroha_executor::default::visit_grant_account_permission(executor, isi) } -pub fn visit_revoke_account_permission( +pub fn visit_revoke_account_permission( executor: &mut V, - authority: &AccountId, isi: &Revoke, ) { let account_id = isi.destination().clone(); if let Ok(permission) = CanControlDomainLives::try_from(isi.object()) { - let isi = Revoke::account_permission(permission, account_id); + let isi = &Revoke::account_permission(permission, account_id); execute!(executor, isi); } - iroha_executor::default::visit_revoke_account_permission(executor, authority, isi) + iroha_executor::default::visit_revoke_account_permission(executor, isi) } #[entrypoint] -pub fn migrate(_block_height: u64) { +pub fn migrate(host: Iroha, _context: Context) { let accounts = - Executor::get_all_accounts_with_can_unregister_domain_permission().collect::>(); + Executor::get_all_accounts_with_can_unregister_domain_permission(&host).collect::>(); DataModelBuilder::with_default_permissions() .remove_permission::() .add_permission::() - .build_and_set(); + .build_and_set(&host); - Executor::replace_token(&accounts); + Executor::replace_token(&accounts, &host); } diff --git a/wasm_samples/executor_with_migration_fail/src/lib.rs b/wasm_samples/executor_with_migration_fail/src/lib.rs index 169a91e7882..5cde4e854b2 100644 --- a/wasm_samples/executor_with_migration_fail/src/lib.rs +++ b/wasm_samples/executor_with_migration_fail/src/lib.rs @@ -1,4 +1,4 @@ -//! Runtime Executor which copies default validation logic but forbids any queries and fails to migrate. +//! Runtime Executor which copies default logic but forbids any queries and fails to migrate. #![no_std] @@ -14,19 +14,21 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); -#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +#[derive(Constructor, Visit, Execute, Entrypoints)] struct Executor { + host: Iroha, + context: Context, verdict: Result, - block_height: u64, } #[entrypoint] -fn migrate(_block_height: u64) { +fn migrate(host: Iroha, _context: Context) { // Performing side-effects to check in the test that it won't be applied after failure // Registering a new domain (using ISI) let domain_id = "failed_migration_test_domain".parse().unwrap(); - Register::domain(Domain::new(domain_id)).execute().unwrap(); + host.submit(&Register::domain(Domain::new(domain_id))) + .unwrap(); dbg_panic("This executor always fails to migrate"); } diff --git a/wasm_samples/mint_rose_trigger/src/lib.rs b/wasm_samples/mint_rose_trigger/src/lib.rs index c2d89e45734..3aab88a3c7f 100644 --- a/wasm_samples/mint_rose_trigger/src/lib.rs +++ b/wasm_samples/mint_rose_trigger/src/lib.rs @@ -6,7 +6,7 @@ extern crate panic_halt; use dlmalloc::GlobalDlmalloc; -use iroha_trigger::{prelude::*, smart_contract::query_single}; +use iroha_trigger::{debug::DebugExpectExt as _, prelude::*}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; @@ -15,16 +15,15 @@ getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); /// Mint 1 rose for owner #[iroha_trigger::main] -fn main(id: TriggerId, owner: AccountId, _event: EventBox) { - let rose_definition_id = "rose#wonderland".parse().unwrap(); - let rose_id = AssetId::new(rose_definition_id, owner); +fn main(host: Iroha, context: Context) { + let rose_id = AssetId::new("rose#wonderland".parse().unwrap(), context.authority); - let val: u32 = query_single(FindTriggerMetadata::new(id, "VAL".parse().unwrap())) + let val: u32 = host + .query_single(FindTriggerMetadata::new(context.id, "VAL".parse().unwrap())) .dbg_unwrap() .try_into_any() .dbg_unwrap(); - Mint::asset_numeric(val, rose_id) - .execute() + host.submit(&Mint::asset_numeric(val, rose_id)) .dbg_expect("Failed to mint rose"); } diff --git a/wasm_samples/mint_rose_trigger_args/src/lib.rs b/wasm_samples/mint_rose_trigger_args/src/lib.rs index c9999ea2069..37e57b57ba2 100644 --- a/wasm_samples/mint_rose_trigger_args/src/lib.rs +++ b/wasm_samples/mint_rose_trigger_args/src/lib.rs @@ -7,7 +7,10 @@ extern crate panic_halt; use dlmalloc::GlobalDlmalloc; use executor_custom_data_model::mint_rose_args::MintRoseArgs; -use iroha_trigger::{debug::dbg_panic, prelude::*}; +use iroha_trigger::{ + debug::{dbg_panic, DebugExpectExt as _}, + prelude::*, +}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; @@ -16,22 +19,19 @@ getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); /// Mint 1 rose for owner #[iroha_trigger::main] -fn main(_id: TriggerId, owner: AccountId, event: EventBox) { - let rose_definition_id = "rose#wonderland".parse().unwrap(); - let rose_id = AssetId::new(rose_definition_id, owner); - - let args: MintRoseArgs = match event { - EventBox::ExecuteTrigger(event) => event - .args() - .dbg_expect("Trigger expect parameters") - .try_into_any() - .dbg_expect("Failed to parse args"), - _ => dbg_panic("Only work as by call trigger"), +fn main(host: Iroha, context: Context) { + let EventBox::ExecuteTrigger(event) = context.event else { + dbg_panic("Only work as by call trigger"); }; - let val = args.val; + 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); - Mint::asset_numeric(val, rose_id) - .execute() + host.submit(&Mint::asset_numeric(args.val, rose_id)) .dbg_expect("Failed to mint rose"); } diff --git a/wasm_samples/multisig/src/lib.rs b/wasm_samples/multisig/src/lib.rs index b3c7cf95ad8..646a79b9e19 100644 --- a/wasm_samples/multisig/src/lib.rs +++ b/wasm_samples/multisig/src/lib.rs @@ -10,7 +10,10 @@ use alloc::{collections::btree_set::BTreeSet, format, vec::Vec}; use dlmalloc::GlobalDlmalloc; use executor_custom_data_model::multisig::MultisigArgs; -use iroha_trigger::{debug::dbg_panic, prelude::*, smart_contract::query_single}; +use iroha_trigger::{ + debug::{dbg_panic, DebugExpectExt as _}, + prelude::*, +}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; @@ -18,19 +21,19 @@ static ALLOC: GlobalDlmalloc = GlobalDlmalloc; getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); #[iroha_trigger::main] -fn main(id: TriggerId, _owner: AccountId, event: EventBox) { - let (args, signatory): (MultisigArgs, AccountId) = match event { - EventBox::ExecuteTrigger(event) => ( - event - .args() - .dbg_expect("trigger expect args") - .try_into_any() - .dbg_expect("failed to parse arguments"), - event.authority().clone(), - ), - _ => dbg_panic("only work as by call trigger"), +fn main(host: Iroha, context: Context) { + let trigger_id = context.id; + + let EventBox::ExecuteTrigger(event) = context.event else { + dbg_panic("only work as by call trigger"); }; + let args: MultisigArgs = event + .args() + .try_into_any() + .dbg_expect("failed to parse arguments"); + + let signatory = event.authority().clone(); let instructions_hash = match &args { MultisigArgs::Instructions(instructions) => HashOf::new(instructions), MultisigArgs::Vote(instructions_hash) => *instructions_hash, @@ -41,84 +44,88 @@ fn main(id: TriggerId, _owner: AccountId, event: EventBox) { let (votes, instructions) = match args { MultisigArgs::Instructions(instructions) => { - query_single(FindTriggerMetadata::new( - id.clone(), + host.query_single(FindTriggerMetadata::new( + trigger_id.clone(), votes_metadata_key.clone(), )) .expect_err("instructions are already submitted"); let votes = BTreeSet::from([signatory.clone()]); - SetKeyValue::trigger( - id.clone(), + host.submit(&SetKeyValue::trigger( + trigger_id.clone(), instructions_metadata_key.clone(), JsonString::new(&instructions), - ) - .execute() + )) .dbg_unwrap(); - SetKeyValue::trigger( - id.clone(), + host.submit(&SetKeyValue::trigger( + trigger_id.clone(), votes_metadata_key.clone(), JsonString::new(&votes), - ) - .execute() + )) .dbg_unwrap(); (votes, instructions) } MultisigArgs::Vote(_instructions_hash) => { - let mut votes: BTreeSet = query_single(FindTriggerMetadata::new( - id.clone(), - votes_metadata_key.clone(), - )) - .dbg_expect("instructions should be submitted first") - .try_into_any() - .dbg_unwrap(); + let mut votes: BTreeSet = host + .query_single(FindTriggerMetadata::new( + trigger_id.clone(), + votes_metadata_key.clone(), + )) + .dbg_expect("instructions should be submitted first") + .try_into_any() + .dbg_unwrap(); votes.insert(signatory.clone()); - SetKeyValue::trigger( - id.clone(), + host.submit(&SetKeyValue::trigger( + trigger_id.clone(), votes_metadata_key.clone(), JsonString::new(&votes), - ) - .execute() - .dbg_unwrap(); - - let instructions: Vec = query_single(FindTriggerMetadata::new( - id.clone(), - instructions_metadata_key.clone(), )) - .dbg_unwrap() - .try_into_any() .dbg_unwrap(); + let instructions: Vec = host + .query_single(FindTriggerMetadata::new( + trigger_id.clone(), + instructions_metadata_key.clone(), + )) + .dbg_unwrap() + .try_into_any() + .dbg_unwrap(); + (votes, instructions) } }; - let signatories: BTreeSet = query_single(FindTriggerMetadata::new( - id.clone(), - "signatories".parse().unwrap(), - )) - .dbg_unwrap() - .try_into_any() - .dbg_unwrap(); + let signatories: BTreeSet = host + .query_single(FindTriggerMetadata::new( + trigger_id.clone(), + "signatories".parse().unwrap(), + )) + .dbg_unwrap() + .try_into_any() + .dbg_unwrap(); // Require N of N signatures if votes.is_superset(&signatories) { // Cleanup votes and instructions - RemoveKeyValue::trigger(id.clone(), votes_metadata_key) - .execute() - .dbg_unwrap(); - RemoveKeyValue::trigger(id.clone(), instructions_metadata_key) - .execute() - .dbg_unwrap(); + host.submit(&RemoveKeyValue::trigger( + trigger_id.clone(), + votes_metadata_key, + )) + .dbg_unwrap(); + host.submit(&RemoveKeyValue::trigger( + trigger_id.clone(), + instructions_metadata_key, + )) + .dbg_unwrap(); // Execute instructions proposal which collected enough votes - for isi in instructions { - isi.execute().dbg_unwrap(); + for isi in &instructions { + host.submit(isi).dbg_unwrap(); } } } diff --git a/wasm_samples/multisig_register/src/lib.rs b/wasm_samples/multisig_register/src/lib.rs index 97782e419db..dc097485829 100644 --- a/wasm_samples/multisig_register/src/lib.rs +++ b/wasm_samples/multisig_register/src/lib.rs @@ -11,7 +11,10 @@ use alloc::format; use dlmalloc::GlobalDlmalloc; use executor_custom_data_model::multisig::MultisigRegisterArgs; use iroha_executor_data_model::permission::trigger::CanExecuteTrigger; -use iroha_trigger::{debug::dbg_panic, prelude::*}; +use iroha_trigger::{ + debug::{dbg_panic, DebugExpectExt as _}, + prelude::*, +}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; @@ -22,20 +25,18 @@ getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); const WASM: &[u8] = core::include_bytes!(concat!(core::env!("OUT_DIR"), "/multisig.wasm")); #[iroha_trigger::main] -fn main(_id: TriggerId, owner: AccountId, event: EventBox) { - let args: MultisigRegisterArgs = match event { - EventBox::ExecuteTrigger(event) => event - .args() - .dbg_expect("trigger expect args") - .try_into_any() - .dbg_expect("failed to parse args"), - _ => dbg_panic("Only work as by call trigger"), +fn main(host: Iroha, context: Context) { + let EventBox::ExecuteTrigger(event) = context.event else { + dbg_panic("Only work as by call trigger"); }; - let account_id = args.account.id().clone(); + let args: MultisigRegisterArgs = event + .args() + .try_into_any() + .dbg_expect("failed to parse args"); - Register::account(args.account.clone()) - .execute() + let account_id = args.account.id().clone(); + host.submit(&Register::account(args.account)) .dbg_expect("failed to register multisig account"); let trigger_id: TriggerId = format!( @@ -57,8 +58,7 @@ fn main(_id: TriggerId, owner: AccountId, event: EventBox) { ), ); - Register::trigger(trigger) - .execute() + host.submit(&Register::trigger(trigger)) .dbg_expect("failed to register multisig trigger"); let role_id: RoleId = format!( @@ -73,25 +73,22 @@ fn main(_id: TriggerId, owner: AccountId, event: EventBox) { trigger: trigger_id.clone(), }; - Register::role( + host.submit(&Register::role( // FIX: args.account.id() should be used but I can't // execute an instruction from a different account - Role::new(role_id.clone(), owner).add_permission(can_execute_multisig_trigger), - ) - .execute() + Role::new(role_id.clone(), context.authority).add_permission(can_execute_multisig_trigger), + )) .dbg_expect("failed to register multisig role"); - SetKeyValue::trigger( + host.submit(&SetKeyValue::trigger( trigger_id, "signatories".parse().unwrap(), JsonString::new(&args.signatories), - ) - .execute() + )) .dbg_unwrap(); for signatory in args.signatories { - Grant::account_role(role_id.clone(), signatory) - .execute() + host.submit(&Grant::account_role(role_id.clone(), signatory)) .dbg_expect("failed to grant multisig role to account"); } } 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 e4a03191a6e..7026bdf506a 100644 --- a/wasm_samples/query_assets_and_save_cursor/src/lib.rs +++ b/wasm_samples/query_assets_and_save_cursor/src/lib.rs @@ -15,8 +15,8 @@ use iroha_smart_contract::{ predicate::CompoundPredicate, QueryWithFilter, QueryWithParams, }, + debug::DebugExpectExt as _, prelude::*, - SmartContractQueryExecutor, }; use nonzero_ext::nonzero; use parity_scale_codec::{Decode, DecodeAll, Encode}; @@ -29,13 +29,13 @@ 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] -fn main(owner: AccountId) { +fn main(host: Iroha, context: Context) { #[derive(Clone, Debug, Decode)] pub struct SmartContractQueryCursor { pub cursor: ForwardCursor, } - let (_batch, _remaining_items, cursor) = SmartContractQueryExecutor + let (_batch, _remaining_items, cursor) = host .start_query(QueryWithParams::new( QueryWithFilter::new(FindAssets, CompoundPredicate::PASS).into(), QueryParams::new( @@ -50,11 +50,10 @@ fn main(owner: AccountId) { let asset_cursor = SmartContractQueryCursor::decode_all(&mut &cursor.dbg_unwrap().encode()[..]).dbg_unwrap(); - SetKeyValue::account( - owner, + host.submit(&SetKeyValue::account( + context.authority, "cursor".parse().unwrap(), JsonString::new(asset_cursor.cursor), - ) - .execute() + )) .dbg_expect("Failed to save cursor to the owner's metadata"); } 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 d6a69f10653..2501f27fac0 100644 --- a/wasm_samples/smart_contract_can_filter_queries/src/lib.rs +++ b/wasm_samples/smart_contract_can_filter_queries/src/lib.rs @@ -10,7 +10,7 @@ extern crate alloc; use alloc::collections::BTreeSet; use dlmalloc::GlobalDlmalloc; -use iroha_smart_contract::{prelude::*, query}; +use iroha_smart_contract::{prelude::*, Iroha}; #[global_allocator] static ALLOC: GlobalDlmalloc = GlobalDlmalloc; @@ -19,34 +19,30 @@ 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(_owner: AccountId) { +fn main(host: Iroha, _context: Context) { let domain_id: DomainId = "looking_glass".parse().unwrap(); - - // create the "looking_glass" domain - Register::domain(Domain::new(domain_id.clone())) - .execute() + host.submit(&Register::domain(Domain::new(domain_id.clone()))) .dbg_unwrap(); // create two asset definitions inside the `looking_glass` domain let time_id: AssetDefinitionId = "time#looking_glass".parse().dbg_unwrap(); let space_id: AssetDefinitionId = "space#looking_glass".parse().dbg_unwrap(); - Register::asset_definition(AssetDefinition::new( + host.submit(&Register::asset_definition(AssetDefinition::new( time_id.clone(), AssetType::Numeric(NumericSpec::default()), - )) - .execute() + ))) .dbg_unwrap(); - Register::asset_definition(AssetDefinition::new( + host.submit(&Register::asset_definition(AssetDefinition::new( space_id.clone(), AssetType::Numeric(NumericSpec::default()), - )) - .execute() + ))) .dbg_unwrap(); // genesis registers some more asset definitions, but we apply a filter to find only the ones from the `looking_glass` domain - let cursor = query(FindAssetsDefinitions) + let cursor = host + .query(FindAssetsDefinitions) .filter_with(|asset_definition| asset_definition.id.domain_id.eq(domain_id)) .execute() .dbg_unwrap();