diff --git a/Cargo.lock b/Cargo.lock index d71bbe9df90..ff9e1f49ce9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2934,20 +2934,6 @@ dependencies = [ "trybuild", ] -[[package]] -name = "iroha_dsl" -version = "2.0.0-pre-rc.20" -dependencies = [ - "iroha_client", - "iroha_config", - "iroha_crypto", - "iroha_data_model", - "litrs", - "proc-macro2", - "quote", - "serde_json", -] - [[package]] name = "iroha_executor" version = "2.0.0-pre-rc.20" @@ -3582,15 +3568,6 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" -[[package]] -name = "litrs" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f17c3668f3cc1132437cdadc93dab05e52d592f06948d3f64828430c36e4a70" -dependencies = [ - "proc-macro2", -] - [[package]] name = "lock_api" version = "0.4.10" diff --git a/Cargo.toml b/Cargo.toml index 73b53e5a8bc..3da58f35d73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -218,7 +218,6 @@ members = [ "genesis", "primitives", "primitives/derive", - "dsl", "ffi", "ffi/derive", "futures", diff --git a/cli/src/torii/mod.rs b/cli/src/torii/mod.rs index a20f2c3f11a..7780d4e5b74 100644 --- a/cli/src/torii/mod.rs +++ b/cli/src/torii/mod.rs @@ -112,9 +112,7 @@ impl Error { QueryFailed(query_error) | InstructionFailed(InstructionExecutionError::Query(query_error)) => match query_error { - Evaluate(_) | Conversion(_) | UnknownCursor | FetchSizeTooBig => { - StatusCode::BAD_REQUEST - } + Conversion(_) | UnknownCursor | FetchSizeTooBig => StatusCode::BAD_REQUEST, Signature(_) => StatusCode::UNAUTHORIZED, Find(_) => StatusCode::NOT_FOUND, }, diff --git a/client/benches/torii.rs b/client/benches/torii.rs index b8906f52504..95b6be46304 100644 --- a/client/benches/torii.rs +++ b/client/benches/torii.rs @@ -9,6 +9,7 @@ use iroha_client::{ data_model::prelude::*, }; use iroha_crypto::KeyPair; +use iroha_data_model::isi::InstructionBox; use iroha_genesis::{GenesisNetwork, RawGenesisBlockBuilder}; use iroha_primitives::unique_vec; use iroha_version::Encode; @@ -51,18 +52,19 @@ fn query_requests(criterion: &mut Criterion) { }); let mut group = criterion.benchmark_group("query-requests"); let domain_id: DomainId = "domain".parse().expect("Valid"); - let create_domain = RegisterExpr::new(Domain::new(domain_id.clone())); + let create_domain = Register::domain(Domain::new(domain_id.clone())); let account_id = AccountId::new("account".parse().expect("Valid"), domain_id.clone()); let (public_key, _) = KeyPair::generate() .expect("Failed to generate KeyPair") .into(); - let create_account = RegisterExpr::new(Account::new(account_id.clone(), [public_key])); + let create_account = Register::account(Account::new(account_id.clone(), [public_key])); let asset_definition_id = AssetDefinitionId::new("xor".parse().expect("Valid"), domain_id); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); let quantity: u32 = 200; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new(asset_definition_id, account_id.clone())), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id, account_id.clone()), ); let mut client_config = iroha_client::samples::get_client_config(&get_key_pair()); @@ -71,7 +73,7 @@ fn query_requests(criterion: &mut Criterion) { let iroha_client = Client::new(&client_config).expect("Invalid client configuration"); thread::sleep(std::time::Duration::from_millis(5000)); - let instructions: [InstructionExpr; 4] = [ + let instructions: [InstructionBox; 4] = [ create_domain.into(), create_account.into(), create_asset.into(), @@ -140,12 +142,12 @@ fn instruction_submits(criterion: &mut Criterion) { rt.block_on(builder.start_with_peer(&mut peer)); let mut group = criterion.benchmark_group("instruction-requests"); let domain_id: DomainId = "domain".parse().expect("Valid"); - let create_domain = RegisterExpr::new(Domain::new(domain_id.clone())); + let create_domain: InstructionBox = Register::domain(Domain::new(domain_id.clone())).into(); let account_id = AccountId::new("account".parse().expect("Valid"), domain_id.clone()); let (public_key, _) = KeyPair::generate() .expect("Failed to generate Key-pair.") .into(); - let create_account = RegisterExpr::new(Account::new(account_id.clone(), [public_key])); + let create_account = Register::account(Account::new(account_id.clone(), [public_key])).into(); let asset_definition_id = AssetDefinitionId::new("xor".parse().expect("Valid"), domain_id); let mut client_config = iroha_client::samples::get_client_config(&get_key_pair()); client_config.torii_api_url = format!("http://{}", peer.api_address).parse().unwrap(); @@ -160,12 +162,9 @@ fn instruction_submits(criterion: &mut Criterion) { let _dropable = group.bench_function("instructions", |b| { b.iter(|| { let quantity: u32 = 200; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); match iroha_client.submit(mint_asset) { Ok(_) => success_count += 1, diff --git a/client/benches/tps/utils.rs b/client/benches/tps/utils.rs index d21611f7d53..39c2ee5103a 100644 --- a/client/benches/tps/utils.rs +++ b/client/benches/tps/utils.rs @@ -61,7 +61,7 @@ impl Config { let clients = network.clients(); wait_for_genesis_committed(&clients, 0); - client.submit_blocking( + client.submit_all_blocking( ParametersBuilder::new() .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, self.max_txs_per_block)? .into_set_parameters(), @@ -70,13 +70,12 @@ impl Config { let unit_names = (UnitName::MIN..).take(self.peers as usize); let units = clients .into_iter() - .zip(unit_names.clone().zip(unit_names.cycle().skip(1))) - .map(|(client, pair)| { + .zip(unit_names) + .map(|(client, name)| { let unit = MeasurerUnit { config: self, client, - name: pair.0, - next_name: pair.1, + name, }; unit.ready() }) @@ -155,7 +154,6 @@ struct MeasurerUnit { pub config: Config, pub client: Client, pub name: UnitName, - pub next_name: UnitName, } type UnitName = u32; @@ -172,7 +170,7 @@ impl MeasurerUnit { let alice_id = AccountId::from_str("alice@wonderland")?; let asset_id = asset_id(self.name); - let register_me = RegisterExpr::new(Account::new( + let register_me = Register::account(Account::new( account_id.clone(), [keypair.public_key().clone()], )); @@ -182,12 +180,14 @@ impl MeasurerUnit { "CanBurnUserAsset".parse().unwrap(), &json!({ "asset_id": asset_id }), ); - let allow_alice_to_burn_my_asset = GrantExpr::new(can_burn_my_asset, alice_id.clone()); + let allow_alice_to_burn_my_asset = + Grant::permission_token(can_burn_my_asset, alice_id.clone()); let can_transfer_my_asset = PermissionToken::new( "CanTransferUserAsset".parse().unwrap(), &json!({ "asset_id": asset_id }), ); - let allow_alice_to_transfer_my_asset = GrantExpr::new(can_transfer_my_asset, alice_id); + let allow_alice_to_transfer_my_asset = + Grant::permission_token(can_transfer_my_asset, alice_id); let grant_tx = TransactionBuilder::new(account_id) .with_instructions([ allow_alice_to_burn_my_asset, @@ -196,7 +196,7 @@ impl MeasurerUnit { .sign(keypair)?; self.client.submit_transaction_blocking(&grant_tx)?; - let mint_a_rose = MintExpr::new(1_u32, asset_id); + let mint_a_rose = Mint::asset_quantity(1_u32, asset_id); self.client.submit_blocking(mint_a_rose)?; Ok(self) @@ -267,42 +267,12 @@ impl MeasurerUnit { }) } - fn instructions(&self) -> impl Iterator { - [self.mint_or_burn(), self.relay_a_rose()] - .into_iter() - .cycle() - } - - fn mint_or_burn(&self) -> InstructionExpr { - let is_running_out = Less::new( - EvaluatesTo::new_unchecked(Expression::Query( - FindAssetQuantityById::new(asset_id(self.name)).into(), - )), - 100_u32, - ); - let supply_roses = MintExpr::new(100_u32.to_value(), asset_id(self.name)); - let burn_a_rose = BurnExpr::new(1_u32.to_value(), asset_id(self.name)); - - ConditionalExpr::with_otherwise(is_running_out, supply_roses, burn_a_rose).into() + fn instructions(&self) -> impl Iterator { + std::iter::once(self.mint()).cycle() } - fn relay_a_rose(&self) -> InstructionExpr { - // Save at least one rose - // because if asset value hits 0 it's automatically deleted from account - // and query `FindAssetQuantityById` return error - let enough_to_transfer = Greater::new( - EvaluatesTo::new_unchecked(Expression::Query( - FindAssetQuantityById::new(asset_id(self.name)).into(), - )), - 1_u32, - ); - let transfer_rose = TransferExpr::new( - asset_id(self.name), - 1_u32.to_value(), - account_id(self.next_name), - ); - - ConditionalExpr::new(enough_to_transfer, transfer_rose).into() + fn mint(&self) -> InstructionBox { + Mint::asset_quantity(1_u32, asset_id(self.name)).into() } } diff --git a/client/examples/million_accounts_genesis.rs b/client/examples/million_accounts_genesis.rs index 079c0ecc7e5..57993c1a972 100644 --- a/client/examples/million_accounts_genesis.rs +++ b/client/examples/million_accounts_genesis.rs @@ -3,6 +3,7 @@ use std::{thread, time::Duration}; use iroha::samples::{construct_executor, get_config}; use iroha_client::data_model::prelude::*; +use iroha_data_model::isi::InstructionBox; use iroha_genesis::{GenesisNetwork, RawGenesisBlock, RawGenesisBlockBuilder}; use iroha_primitives::unique_vec; use test_network::{ @@ -64,8 +65,8 @@ fn create_million_accounts_directly() { format!("bob-{i}").parse().expect("Valid"), domain_id.clone(), ); - let create_domain = RegisterExpr::new(Domain::new(domain_id)); - let create_account = RegisterExpr::new(Account::new(normal_account_id.clone(), [])); + let create_domain: InstructionBox = Register::domain(Domain::new(domain_id)).into(); + let create_account = Register::account(Account::new(normal_account_id.clone(), [])).into(); if test_client .submit_all([create_domain, create_account]) .is_err() diff --git a/client/examples/tutorial.rs b/client/examples/tutorial.rs index a961a1932e7..5cc86cd8495 100644 --- a/client/examples/tutorial.rs +++ b/client/examples/tutorial.rs @@ -3,7 +3,6 @@ use std::fs::File; use eyre::{Error, WrapErr}; -use iroha_client::data_model::TryToValue; // #region rust_config_crates use iroha_config::client::Configuration; // #endregion rust_config_crates @@ -51,7 +50,7 @@ fn domain_registration_test(config: &Configuration) -> Result<(), Error> { client::Client, data_model::{ metadata::UnlimitedMetadata, - prelude::{Domain, DomainId, InstructionExpr, RegisterExpr}, + prelude::{Domain, DomainId, InstructionBox, Register}, }, }; // #endregion domain_register_example_crates @@ -63,7 +62,7 @@ fn domain_registration_test(config: &Configuration) -> Result<(), Error> { // #region domain_register_example_create_isi // Create an ISI - let create_looking_glass = RegisterExpr::new(Domain::new(looking_glass)); + let create_looking_glass = Register::domain(Domain::new(looking_glass)); // #endregion domain_register_example_create_isi // #region rust_client_create @@ -74,7 +73,7 @@ fn domain_registration_test(config: &Configuration) -> Result<(), Error> { // #region domain_register_example_prepare_tx // Prepare a transaction let metadata = UnlimitedMetadata::default(); - let instructions: Vec = vec![create_looking_glass.into()]; + let instructions: Vec = vec![create_looking_glass.into()]; let tx = iroha_client .build_transaction(instructions, metadata) .wrap_err("Error building a domain registration transaction")?; @@ -117,7 +116,7 @@ fn account_registration_test(config: &Configuration) -> Result<(), Error> { client::Client, data_model::{ metadata::UnlimitedMetadata, - prelude::{Account, AccountId, InstructionExpr, RegisterExpr}, + prelude::{Account, AccountId, InstructionBox, Register}, }, }; use iroha_crypto::KeyPair; @@ -141,14 +140,14 @@ fn account_registration_test(config: &Configuration) -> Result<(), Error> { // #region register_account_generate // Generate a new account - let create_account = RegisterExpr::new(Account::new(account_id, [public_key])); + let create_account = Register::account(Account::new(account_id, [public_key])); // #endregion register_account_generate // #region register_account_prepare_tx // Prepare a transaction using the - // Account's RegisterExpr + // Account's RegisterBox let metadata = UnlimitedMetadata::new(); - let instructions: Vec = vec![create_account.into()]; + let instructions: Vec = vec![create_account.into()]; let tx = iroha_client.build_transaction(instructions, metadata)?; // #endregion register_account_prepare_tx @@ -168,7 +167,7 @@ fn asset_registration_test(config: &Configuration) -> Result<(), Error> { use iroha_client::{ client::Client, data_model::prelude::{ - AccountId, AssetDefinition, AssetDefinitionId, AssetId, IdBox, MintExpr, RegisterExpr, + AccountId, AssetDefinition, AssetDefinitionId, AssetId, Mint, Register, }, }; // #endregion register_asset_crates @@ -185,7 +184,7 @@ fn asset_registration_test(config: &Configuration) -> Result<(), Error> { // #region register_asset_init_submit // Initialise the registration time let register_time = - RegisterExpr::new(AssetDefinition::fixed(asset_def_id.clone()).mintable_once()); + Register::asset_definition(AssetDefinition::fixed(asset_def_id.clone()).mintable_once()); // Submit a registration time iroha_client.submit(register_time)?; @@ -197,10 +196,10 @@ fn asset_registration_test(config: &Configuration) -> Result<(), Error> { .expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after"); // #region register_asset_mint_submit - // Create a MintExpr using a previous asset and account - let mint = MintExpr::new( - 12.34_f64.try_to_value()?, - IdBox::AssetId(AssetId::new(asset_def_id, account_id)), + // Create a MintBox using a previous asset and account + let mint = Mint::asset_fixed( + 12.34_f64.try_into()?, + AssetId::new(asset_def_id, account_id), ); // Submit a minting transaction @@ -217,10 +216,7 @@ fn asset_minting_test(config: &Configuration) -> Result<(), Error> { use iroha_client::{ client::Client, - data_model::{ - prelude::{AccountId, AssetDefinitionId, AssetId, MintExpr, ToValue}, - IdBox, - }, + data_model::prelude::{AccountId, AssetDefinitionId, AssetId, Mint}, }; // #endregion mint_asset_crates @@ -237,10 +233,7 @@ fn asset_minting_test(config: &Configuration) -> Result<(), Error> { // Mint the Asset instance // #region mint_asset_mint - let mint_roses = MintExpr::new( - 42_u32.to_value(), - IdBox::AssetId(AssetId::new(roses, alice)), - ); + let mint_roses = Mint::asset_quantity(42_u32, AssetId::new(roses, alice)); // #endregion mint_asset_mint // #region mint_asset_submit_tx @@ -255,10 +248,7 @@ fn asset_minting_test(config: &Configuration) -> Result<(), Error> { // or `roses.to_string() + "#" + alice.to_string()`. // The `##` is a short-hand for the rose `which belongs to the same domain as the account // to which it belongs to. - let mint_roses_alt = MintExpr::new( - 10_u32.to_value(), - IdBox::AssetId("rose##alice@wonderland".parse()?), - ); + let mint_roses_alt = Mint::asset_quantity(10_u32, "rose##alice@wonderland".parse()?); // #endregion mint_asset_mint_alt // #region mint_asset_submit_tx_alt @@ -277,10 +267,7 @@ fn asset_burning_test(config: &Configuration) -> Result<(), Error> { use iroha_client::{ client::Client, - data_model::{ - prelude::{AccountId, AssetDefinitionId, AssetId, BurnExpr, ToValue}, - IdBox, - }, + data_model::prelude::{AccountId, AssetDefinitionId, AssetId, Burn}, }; // #endregion burn_asset_crates @@ -297,10 +284,7 @@ fn asset_burning_test(config: &Configuration) -> Result<(), Error> { // #region burn_asset_burn // Burn the Asset instance - let burn_roses = BurnExpr::new( - 10_u32.to_value(), - IdBox::AssetId(AssetId::new(roses, alice)), - ); + let burn_roses = Burn::asset_quantity(10_u32, AssetId::new(roses, alice)); // #endregion burn_asset_burn // #region burn_asset_submit_tx @@ -315,10 +299,7 @@ fn asset_burning_test(config: &Configuration) -> Result<(), Error> { // or `roses.to_string() + "#" + alice.to_string()`. // The `##` is a short-hand for the rose `which belongs to the same domain as the account // to which it belongs to. - let burn_roses_alt = BurnExpr::new( - 10_u32.to_value(), - IdBox::AssetId("rose##alice@wonderland".parse()?), - ); + let burn_roses_alt = Burn::asset_quantity(10_u32, "rose##alice@wonderland".parse()?); // #endregion burn_asset_burn_alt // #region burn_asset_submit_tx_alt diff --git a/client/src/client.rs b/client/src/client.rs index d4f7f383e30..e057a8c7c58 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -1472,14 +1472,12 @@ pub mod account { } /// Construct a query to get account by id - pub fn by_id(account_id: impl Into>) -> FindAccountById { + pub fn by_id(account_id: AccountId) -> FindAccountById { FindAccountById::new(account_id) } /// Construct a query to get all accounts containing specified asset - pub fn all_with_asset( - asset_definition_id: impl Into>, - ) -> FindAccountsWithAsset { + pub fn all_with_asset(asset_definition_id: AssetDefinitionId) -> FindAccountsWithAsset { FindAccountsWithAsset::new(asset_definition_id) } } @@ -1499,19 +1497,17 @@ pub mod asset { } /// Construct a query to get asset definition by its id - pub fn definition_by_id( - asset_definition_id: impl Into>, - ) -> FindAssetDefinitionById { + pub fn definition_by_id(asset_definition_id: AssetDefinitionId) -> FindAssetDefinitionById { FindAssetDefinitionById::new(asset_definition_id) } /// Construct a query to get all assets by account id - pub fn by_account_id(account_id: impl Into>) -> FindAssetsByAccountId { + pub fn by_account_id(account_id: AccountId) -> FindAssetsByAccountId { FindAssetsByAccountId::new(account_id) } /// Construct a query to get an asset by its id - pub fn by_id(asset_id: impl Into>) -> FindAssetById { + pub fn by_id(asset_id: AssetId) -> FindAssetById { FindAssetById::new(asset_id) } } @@ -1532,9 +1528,7 @@ pub mod block { } /// Construct a query to find block header by hash - pub fn header_by_hash( - hash: impl Into>>, - ) -> FindBlockHeaderByHash { + pub fn header_by_hash(hash: HashOf) -> FindBlockHeaderByHash { FindBlockHeaderByHash::new(hash) } } @@ -1549,7 +1543,7 @@ pub mod domain { } /// Construct a query to get all domain by id - pub fn by_id(domain_id: impl Into>) -> FindDomainById { + pub fn by_id(domain_id: DomainId) -> FindDomainById { FindDomainById::new(domain_id) } } @@ -1565,16 +1559,12 @@ pub mod transaction { } /// Construct a query to retrieve transactions for account - pub fn by_account_id( - account_id: impl Into>, - ) -> FindTransactionsByAccountId { + pub fn by_account_id(account_id: AccountId) -> FindTransactionsByAccountId { FindTransactionsByAccountId::new(account_id) } /// Construct a query to retrieve transaction by hash - pub fn by_hash( - hash: impl Into>>, - ) -> FindTransactionByHash { + pub fn by_hash(hash: HashOf) -> FindTransactionByHash { FindTransactionByHash::new(hash) } } @@ -1584,7 +1574,7 @@ pub mod trigger { use super::*; /// Construct a query to get triggers by domain id - pub fn by_domain_id(domain_id: impl Into>) -> FindTriggersByDomainId { + pub fn by_domain_id(domain_id: DomainId) -> FindTriggersByDomainId { FindTriggersByDomainId::new(domain_id) } } @@ -1600,10 +1590,8 @@ pub mod permission { /// Construct a query to get all [`PermissionToken`] granted /// to account with given [`Id`][AccountId] - pub fn by_account_id( - account_id: impl Into>, - ) -> FindPermissionTokensByAccountId { - FindPermissionTokensByAccountId::new(account_id.into()) + pub fn by_account_id(account_id: AccountId) -> FindPermissionTokensByAccountId { + FindPermissionTokensByAccountId::new(account_id) } } @@ -1622,12 +1610,12 @@ pub mod role { } /// Construct a query to retrieve a role by its id - pub fn by_id(role_id: impl Into>) -> FindRoleByRoleId { + pub fn by_id(role_id: RoleId) -> FindRoleByRoleId { FindRoleByRoleId::new(role_id) } /// Construct a query to retrieve all roles for an account - pub fn by_account_id(account_id: impl Into>) -> FindRolesByAccountId { + pub fn by_account_id(account_id: AccountId) -> FindRolesByAccountId { FindRolesByAccountId::new(account_id) } } @@ -1681,7 +1669,7 @@ mod tests { let build_transaction = || { client - .build_transaction(Vec::::new(), UnlimitedMetadata::new()) + .build_transaction(Vec::::new(), UnlimitedMetadata::new()) .unwrap() }; let tx1 = build_transaction(); @@ -1754,13 +1742,6 @@ mod tests { )), ), (StatusCode::UNPROCESSABLE_ENTITY, ValidationFail::TooComplex), - ( - StatusCode::NOT_FOUND, - // Here should be `Find`, but actually handler doesn't care - ValidationFail::QueryFailed(QueryExecutionFail::Evaluate( - "whatever".to_owned(), - )), - ), ]; for (status_code, err) in responses { let resp = Response::builder().status(status_code).body(err.encode())?; diff --git a/client/tests/integration/add_account.rs b/client/tests/integration/add_account.rs index f463266399e..bdec9441783 100644 --- a/client/tests/integration/add_account.rs +++ b/client/tests/integration/add_account.rs @@ -13,14 +13,14 @@ fn client_add_account_with_name_length_more_than_limit_should_not_commit_transac let pipeline_time = super::Configuration::pipeline_time(); let normal_account_id: AccountId = "bob@wonderland".parse().expect("Valid"); - let create_account = RegisterExpr::new(Account::new(normal_account_id.clone(), [])); + let create_account = Register::account(Account::new(normal_account_id.clone(), [])); test_client.submit(create_account)?; let too_long_account_name = "0".repeat(2_usize.pow(14)); let incorrect_account_id: AccountId = (too_long_account_name + "@wonderland") .parse() .expect("Valid"); - let create_account = RegisterExpr::new(Account::new(incorrect_account_id.clone(), [])); + let create_account = Register::account(Account::new(incorrect_account_id.clone(), [])); test_client.submit(create_account)?; thread::sleep(pipeline_time * 2); diff --git a/client/tests/integration/add_domain.rs b/client/tests/integration/add_domain.rs index f963fe31d10..09bf95bb90d 100644 --- a/client/tests/integration/add_domain.rs +++ b/client/tests/integration/add_domain.rs @@ -16,11 +16,11 @@ fn client_add_domain_with_name_length_more_than_limit_should_not_commit_transact // Given let normal_domain_id: DomainId = "sora".parse()?; - let create_domain = RegisterExpr::new(Domain::new(normal_domain_id.clone())); + let create_domain = Register::domain(Domain::new(normal_domain_id.clone())); test_client.submit(create_domain)?; let too_long_domain_name: DomainId = "0".repeat(2_usize.pow(14)).parse()?; - let create_domain = RegisterExpr::new(Domain::new(too_long_domain_name.clone())); + let create_domain = Register::domain(Domain::new(too_long_domain_name.clone())); test_client.submit(create_domain)?; thread::sleep(pipeline_time * 2); diff --git a/client/tests/integration/asset.rs b/client/tests/integration/asset.rs index 26e672fc857..2cd3cab768f 100644 --- a/client/tests/integration/asset.rs +++ b/client/tests/integration/asset.rs @@ -6,6 +6,7 @@ use iroha_client::{ data_model::prelude::*, }; use iroha_crypto::{KeyPair, PublicKey}; +use iroha_data_model::isi::InstructionBox; use iroha_primitives::fixed::Fixed; use serde_json::json; use test_network::*; @@ -21,11 +22,13 @@ fn client_register_asset_should_add_asset_once_but_not_twice() -> Result<()> { let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); let asset_definition_id = AssetDefinitionId::from_str("test_asset#wonderland").expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); - let register_asset = RegisterExpr::new(Asset::new( + let create_asset: InstructionBox = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())).into(); + let register_asset: InstructionBox = Register::asset(Asset::new( AssetId::new(asset_definition_id.clone(), account_id.clone()), AssetValue::Quantity(0), - )); + )) + .into(); test_client.submit_all([create_asset, register_asset.clone()])?; @@ -56,9 +59,11 @@ fn unregister_asset_should_remove_asset_from_account() -> Result<()> { let asset_definition_id = AssetDefinitionId::from_str("test_asset#wonderland").expect("Valid"); let asset_id = AssetId::new(asset_definition_id.clone(), account_id.clone()); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); - let register_asset = RegisterExpr::new(Asset::new(asset_id.clone(), AssetValue::Quantity(0))); - let unregister_asset = UnregisterExpr::new(asset_id); + let create_asset: InstructionBox = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())).into(); + let register_asset = + Register::asset(Asset::new(asset_id.clone(), AssetValue::Quantity(0))).into(); + let unregister_asset = Unregister::asset(asset_id); test_client.submit_all([create_asset, register_asset])?; @@ -93,18 +98,16 @@ fn client_add_asset_quantity_to_existing_asset_should_increase_asset_amount() -> // Given let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); let metadata = iroha_client::data_model::metadata::UnlimitedMetadata::default(); //When let quantity: u32 = 200; - let mint = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); - let instructions: [InstructionExpr; 2] = [create_asset.into(), mint.into()]; + let instructions: [InstructionBox; 2] = [create_asset.into(), mint.into()]; let tx = test_client.build_transaction(instructions, metadata)?; test_client.submit_transaction(&tx)?; test_client.poll_request(client::asset::by_account_id(account_id), |result| { @@ -127,18 +130,15 @@ fn client_add_big_asset_quantity_to_existing_asset_should_increase_asset_amount( let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset = - RegisterExpr::new(AssetDefinition::big_quantity(asset_definition_id.clone())); + Register::asset_definition(AssetDefinition::big_quantity(asset_definition_id.clone())); let metadata = iroha_client::data_model::metadata::UnlimitedMetadata::default(); //When let quantity: u128 = 2_u128.pow(65); - let mint = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint = Mint::asset_big_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); - let instructions: [InstructionExpr; 2] = [create_asset.into(), mint.into()]; + let instructions: [InstructionBox; 2] = [create_asset.into(), mint.into()]; let tx = test_client.build_transaction(instructions, metadata)?; test_client.submit_transaction(&tx)?; test_client.poll_request(client::asset::by_account_id(account_id), |result| { @@ -160,20 +160,17 @@ fn client_add_asset_with_decimal_should_increase_asset_amount() -> Result<()> { // Given let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); - let identifiable_box = AssetDefinition::fixed(asset_definition_id.clone()); - let create_asset = RegisterExpr::new(identifiable_box); + let asset_definition = AssetDefinition::fixed(asset_definition_id.clone()); + let create_asset = Register::asset_definition(asset_definition); let metadata = iroha_client::data_model::metadata::UnlimitedMetadata::default(); //When let quantity: Fixed = Fixed::try_from(123.456_f64).unwrap(); - let mint = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint = Mint::asset_fixed( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); - let instructions: [InstructionExpr; 2] = [create_asset.into(), mint.into()]; + let instructions: [InstructionBox; 2] = [create_asset.into(), mint.into()]; let tx = test_client.build_transaction(instructions, metadata)?; test_client.submit_transaction(&tx)?; test_client.poll_request(client::asset::by_account_id(account_id.clone()), |result| { @@ -187,12 +184,9 @@ fn client_add_asset_with_decimal_should_increase_asset_amount() -> Result<()> { // Add some fractional part let quantity2: Fixed = Fixed::try_from(0.55_f64).unwrap(); - let mint = MintExpr::new( - quantity2.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint = Mint::asset_fixed( + quantity2, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); // and check that it is added without errors let sum = quantity @@ -217,7 +211,7 @@ fn client_add_asset_with_name_length_more_than_limit_should_not_commit_transacti // Given let normal_asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::quantity( + let create_asset = Register::asset_definition(AssetDefinition::quantity( normal_asset_definition_id.clone(), )); test_client.submit(create_asset)?; @@ -226,7 +220,7 @@ fn client_add_asset_with_name_length_more_than_limit_should_not_commit_transacti let too_long_asset_name = "0".repeat(2_usize.pow(14)); let incorrect_asset_definition_id = AssetDefinitionId::from_str(&(too_long_asset_name + "#wonderland")).expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::quantity( + let create_asset = Register::asset_definition(AssetDefinition::quantity( incorrect_asset_definition_id.clone(), )); @@ -273,11 +267,11 @@ fn find_rate_and_make_exchange_isi_should_succeed() { let buyer_keypair = KeyPair::generate().expect("Failed to generate seller KeyPair."); let register_account = |account_id: AccountId, signature: PublicKey| { - RegisterExpr::new(Account::new(account_id, [signature])) + Register::account(Account::new(account_id, [signature])) }; let grant_alice_asset_transfer_permission = |asset_id: AssetId, owner_keypair: KeyPair| { - let allow_alice_to_transfer_asset = GrantExpr::new( + let allow_alice_to_transfer_asset = Grant::permission_token( PermissionToken::new( "CanTransferUserAsset".parse().unwrap(), &json!({ "asset_id": asset_id }), @@ -304,7 +298,7 @@ fn find_rate_and_make_exchange_isi_should_succeed() { "exchange", account_id_new("dex", "exchange"), ); - let instructions: [InstructionExpr; 12] = [ + let instructions: [InstructionBox; 12] = [ register::domain("exchange").into(), register::domain("company").into(), register::domain("crypto").into(), @@ -314,17 +308,17 @@ fn find_rate_and_make_exchange_isi_should_succeed() { register::asset_definition("btc", "crypto").into(), register::asset_definition("eth", "crypto").into(), register::asset_definition("btc2eth_rate", "exchange").into(), - MintExpr::new( - 200_u32.to_value(), - IdBox::AssetId(asset_id_new("eth", "crypto", buyer_account_id.clone())), + Mint::asset_quantity( + 200_u32, + asset_id_new("eth", "crypto", buyer_account_id.clone()), ) .into(), - MintExpr::new( - 20_u32.to_value(), - IdBox::AssetId(asset_id_new("btc", "crypto", seller_account_id.clone())), + Mint::asset_quantity( + 20_u32, + asset_id_new("btc", "crypto", seller_account_id.clone()), ) .into(), - MintExpr::new(20_u32.to_value(), IdBox::AssetId(asset_id.clone())).into(), + Mint::asset_quantity(20_u32, asset_id.clone()).into(), ]; test_client .submit_all_blocking(instructions) @@ -333,23 +327,26 @@ fn find_rate_and_make_exchange_isi_should_succeed() { grant_alice_asset_transfer_permission(seller_btc, seller_keypair); grant_alice_asset_transfer_permission(buyer_eth, buyer_keypair); + let to_transfer = test_client + .request(FindAssetQuantityById::new(asset_id)) + .expect("Failed to execute query to find asset quantity by id."); + let to_transfer = match to_transfer { + NumericValue::U32(value) => value, + _ => panic!("Wrong asset quantity type."), + }; test_client - .submit_all_blocking([PairExpr::new( - TransferExpr::new( - IdBox::AssetId(asset_id_new("btc", "crypto", seller_account_id.clone())), - EvaluatesTo::new_evaluates_to_value(Expression::Query( - FindAssetQuantityById::new(asset_id.clone()).into(), - )), - IdBox::AccountId(buyer_account_id.clone()), + .submit_all_blocking([ + Transfer::asset_quantity( + asset_id_new("btc", "crypto", seller_account_id.clone()), + to_transfer, + buyer_account_id.clone(), ), - TransferExpr::new( - IdBox::AssetId(asset_id_new("eth", "crypto", buyer_account_id)), - EvaluatesTo::new_evaluates_to_value(Expression::Query( - FindAssetQuantityById::new(asset_id).into(), - )), - IdBox::AccountId(seller_account_id), + Transfer::asset_quantity( + asset_id_new("eth", "crypto", buyer_account_id), + to_transfer, + seller_account_id, ), - )]) + ]) .expect("Failed to exchange eth for btc."); let expected_seller_eth = NumericValue::U32(20); @@ -403,7 +400,7 @@ fn transfer_asset_definition() { let asset_definition_id: AssetDefinitionId = "asset#wonderland".parse().expect("Valid"); test_client - .submit_blocking(RegisterExpr::new(AssetDefinition::quantity( + .submit_blocking(Register::asset_definition(AssetDefinition::quantity( asset_definition_id.clone(), ))) .expect("Failed to submit transaction"); @@ -414,7 +411,7 @@ fn transfer_asset_definition() { assert_eq!(asset_definition.owned_by(), &alice_id); test_client - .submit_blocking(TransferExpr::new( + .submit_blocking(Transfer::asset_definition( alice_id, asset_definition_id.clone(), bob_id.clone(), @@ -447,12 +444,12 @@ fn asset_id_new(definition_name: &str, definition_domain: &str, account_id: Acco mod register { use super::*; - pub fn domain(name: &str) -> RegisterExpr { - RegisterExpr::new(Domain::new(DomainId::from_str(name).expect("Valid"))) + pub fn domain(name: &str) -> Register { + Register::domain(Domain::new(DomainId::from_str(name).expect("Valid"))) } - pub fn account(account_name: &str, domain_name: &str) -> RegisterExpr { - RegisterExpr::new(Account::new( + pub fn account(account_name: &str, domain_name: &str) -> Register { + Register::account(Account::new( AccountId::new( account_name.parse().expect("Valid"), domain_name.parse().expect("Valid"), @@ -461,8 +458,8 @@ mod register { )) } - pub fn asset_definition(asset_name: &str, domain_name: &str) -> RegisterExpr { - RegisterExpr::new(AssetDefinition::quantity(AssetDefinitionId::new( + pub fn asset_definition(asset_name: &str, domain_name: &str) -> Register { + Register::asset_definition(AssetDefinition::quantity(AssetDefinitionId::new( asset_name.parse().expect("Valid"), domain_name.parse().expect("Valid"), ))) diff --git a/client/tests/integration/asset_propagation.rs b/client/tests/integration/asset_propagation.rs index fb50c5b3f2d..de7a5238418 100644 --- a/client/tests/integration/asset_propagation.rs +++ b/client/tests/integration/asset_propagation.rs @@ -9,6 +9,7 @@ use iroha_client::{ }, }; use iroha_crypto::KeyPair; +use iroha_data_model::isi::InstructionBox; use test_network::*; use super::Configuration; @@ -21,28 +22,27 @@ fn client_add_asset_quantity_to_existing_asset_should_increase_asset_amount_on_a wait_for_genesis_committed(&network.clients(), 0); let pipeline_time = Configuration::pipeline_time(); - client.submit_blocking( + client.submit_all_blocking( ParametersBuilder::new() .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? .into_set_parameters(), )?; - let create_domain = RegisterExpr::new(Domain::new(DomainId::from_str("domain")?)); + let create_domain: InstructionBox = + Register::domain(Domain::new(DomainId::from_str("domain")?)).into(); let account_id = AccountId::from_str("account@domain")?; let (public_key, _) = KeyPair::generate()?.into(); - let create_account = RegisterExpr::new(Account::new(account_id.clone(), [public_key])); + let create_account = Register::account(Account::new(account_id.clone(), [public_key])).into(); let asset_definition_id = AssetDefinitionId::from_str("xor#domain")?; - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())).into(); client.submit_all([create_domain, create_account, create_asset])?; thread::sleep(pipeline_time * 3); //When let quantity: u32 = 200; - client.submit(MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + client.submit(Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ))?; thread::sleep(pipeline_time); diff --git a/client/tests/integration/burn_public_keys.rs b/client/tests/integration/burn_public_keys.rs index 4c1431c0639..fb4c54b2251 100644 --- a/client/tests/integration/burn_public_keys.rs +++ b/client/tests/integration/burn_public_keys.rs @@ -29,7 +29,7 @@ fn submit( } fn get(client: &Client, hash: HashOf) -> TransactionValue { - client + *client .request(transaction::by_hash(hash)) .unwrap() .transaction @@ -51,7 +51,7 @@ fn public_keys_cannot_be_burned_to_nothing() { wait_for_genesis_committed(&vec![client.clone()], 0); let charlie_initial_keypair = KeyPair::generate().unwrap(); - let register_charlie = RegisterExpr::new(Account::new( + let register_charlie = Register::account(Account::new( charlie_id.clone(), [charlie_initial_keypair.public_key().clone()], )); @@ -64,7 +64,7 @@ fn public_keys_cannot_be_burned_to_nothing() { let mint_keys = (0..KEYS_COUNT - 1).map(|_| { let (public_key, _) = KeyPair::generate().unwrap().into(); - MintExpr::new(public_key, charlie_id.clone()) + Mint::account_public_key(public_key, charlie_id.clone()) }); let (tx_hash, res) = submit( @@ -79,7 +79,8 @@ fn public_keys_cannot_be_burned_to_nothing() { let charlie = client.request(account::by_id(charlie_id.clone())).unwrap(); let mut keys = charlie.signatories(); - let burn = |key: PublicKey| InstructionExpr::from(BurnExpr::new(key, charlie_id.clone())); + let burn = + |key: PublicKey| InstructionBox::from(Burn::account_public_key(key, charlie_id.clone())); let burn_keys_leaving_one = keys .by_ref() .filter(|pub_key| pub_key != &charlie_initial_keypair.public_key()) diff --git a/client/tests/integration/connected_peers.rs b/client/tests/integration/connected_peers.rs index 0ad808b20c2..91745b15ff8 100644 --- a/client/tests/integration/connected_peers.rs +++ b/client/tests/integration/connected_peers.rs @@ -37,7 +37,7 @@ fn connected_peers_with_f(faults: u64, start_port: Option) -> Result<()> { wait_for_genesis_committed(&network.clients(), 0); let pipeline_time = Configuration::pipeline_time(); - client.submit_blocking( + client.submit_all_blocking( ParametersBuilder::new() .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? .into_set_parameters(), @@ -52,7 +52,7 @@ fn connected_peers_with_f(faults: u64, start_port: Option) -> Result<()> { // then `status.peers` decrements let peer = network.peers.values().last().unwrap(); let peer_client = Client::test(&peer.api_address); - let unregister_peer = UnregisterExpr::new(IdBox::PeerId(peer.id.clone())); + let unregister_peer = Unregister::peer(peer.id.clone()); client.submit_blocking(unregister_peer)?; thread::sleep(pipeline_time * 2); // Wait for some time to allow peers to connect status = client.get_status()?; @@ -63,7 +63,7 @@ fn connected_peers_with_f(faults: u64, start_port: Option) -> Result<()> { // Re-register the peer: committed with f = `faults` - 1 then // `status.peers` increments - let register_peer = RegisterExpr::new(DataModelPeer::new(peer.id.clone())); + let register_peer = Register::peer(DataModelPeer::new(peer.id.clone())); client.submit_blocking(register_peer)?; thread::sleep(pipeline_time * 4); // Wait for some time to allow peers to connect status = client.get_status()?; diff --git a/client/tests/integration/domain_owner.rs b/client/tests/integration/domain_owner.rs index 608eb38bdba..b420d5e81c2 100644 --- a/client/tests/integration/domain_owner.rs +++ b/client/tests/integration/domain_owner.rs @@ -13,13 +13,13 @@ fn domain_owner_domain_permissions() -> Result<()> { // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id.clone()); - test_client.submit_blocking(RegisterExpr::new(kingdom))?; + test_client.submit_blocking(Register::domain(kingdom))?; // check that "alice@wonderland" as owner of domain can edit metadata in her domain let key: Name = "key".parse()?; let value: Name = "value".parse()?; - test_client.submit_blocking(SetKeyValueExpr::new(kingdom_id.clone(), key.clone(), value))?; - test_client.submit_blocking(RemoveKeyValueExpr::new(kingdom_id.clone(), key))?; + test_client.submit_blocking(SetKeyValue::domain(kingdom_id.clone(), key.clone(), value))?; + test_client.submit_blocking(RemoveKeyValue::domain(kingdom_id.clone(), key))?; // check that "alice@wonderland" as owner of domain can grant and revoke domain related permission tokens let bob_id: AccountId = "bob@wonderland".parse()?; @@ -27,11 +27,11 @@ fn domain_owner_domain_permissions() -> Result<()> { "CanUnregisterDomain".parse().unwrap(), &json!({ "domain_id": kingdom_id }), ); - test_client.submit_blocking(GrantExpr::new(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(RevokeExpr::new(token, bob_id))?; + test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; // check that "alice@wonderland" as owner of domain can unregister her domain - test_client.submit_blocking(UnregisterExpr::new(kingdom_id))?; + test_client.submit_blocking(Unregister::domain(kingdom_id))?; Ok(()) } @@ -46,28 +46,28 @@ fn domain_owner_account_permissions() -> Result<()> { // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id); - test_client.submit_blocking(RegisterExpr::new(kingdom))?; + test_client.submit_blocking(Register::domain(kingdom))?; let mad_hatter_keypair = KeyPair::generate()?; let mad_hatter = Account::new( mad_hatter_id.clone(), [mad_hatter_keypair.public_key().clone()], ); - test_client.submit_blocking(RegisterExpr::new(mad_hatter))?; + test_client.submit_blocking(Register::account(mad_hatter))?; // check that "alice@wonderland" as owner of domain can burn and mint public keys for accounts in her domain let mad_hatter_new_keypair = KeyPair::generate()?; - test_client.submit_blocking(MintExpr::new( + test_client.submit_blocking(Mint::account_public_key( mad_hatter_new_keypair.public_key().clone(), mad_hatter_id.clone(), ))?; - test_client.submit_blocking(BurnExpr::new( + test_client.submit_blocking(Burn::account_public_key( mad_hatter_new_keypair.public_key().clone(), mad_hatter_id.clone(), ))?; // check that "alice@wonderland" as owner of domain can change signature check condition for accounts in her domain - test_client.submit_blocking(MintExpr::new( + test_client.submit_blocking(Mint::account_signature_check_condition( SignatureCheckCondition::AnyAccountSignatureOr(Vec::new().into()), mad_hatter_id.clone(), ))?; @@ -75,12 +75,12 @@ fn domain_owner_account_permissions() -> Result<()> { // check that "alice@wonderland" as owner of domain can edit metadata of account in her domain let key: Name = "key".parse()?; let value: Name = "value".parse()?; - test_client.submit_blocking(SetKeyValueExpr::new( + test_client.submit_blocking(SetKeyValue::account( mad_hatter_id.clone(), key.clone(), value, ))?; - test_client.submit_blocking(RemoveKeyValueExpr::new(mad_hatter_id.clone(), key))?; + test_client.submit_blocking(RemoveKeyValue::account(mad_hatter_id.clone(), key))?; // check that "alice@wonderland" as owner of domain can grant and revoke account related permission tokens in her domain let bob_id: AccountId = "bob@wonderland".parse()?; @@ -88,11 +88,11 @@ fn domain_owner_account_permissions() -> Result<()> { "CanUnregisterAccount".parse().unwrap(), &json!({ "account_id": mad_hatter_id }), ); - test_client.submit_blocking(GrantExpr::new(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(RevokeExpr::new(token, bob_id))?; + test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; // check that "alice@wonderland" as owner of domain can unregister accounts in her domain - test_client.submit_blocking(UnregisterExpr::new(mad_hatter_id))?; + test_client.submit_blocking(Unregister::account(mad_hatter_id))?; Ok(()) } @@ -109,30 +109,38 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id); - test_client.submit_blocking(RegisterExpr::new(kingdom))?; + test_client.submit_blocking(Register::domain(kingdom))?; let bob_keypair = KeyPair::generate()?; let bob = Account::new(bob_id.clone(), [bob_keypair.public_key().clone()]); - test_client.submit_blocking(RegisterExpr::new(bob))?; + test_client.submit_blocking(Register::account(bob))?; let rabbit = Account::new(rabbit_id.clone(), []); - test_client.submit_blocking(RegisterExpr::new(rabbit))?; + test_client.submit_blocking(Register::account(rabbit))?; // register asset definitions by "bob@kingdom" so he is owner of it let coin = AssetDefinition::quantity(coin_id.clone()); let transaction = TransactionBuilder::new(bob_id.clone()) - .with_instructions([RegisterExpr::new(coin)]) + .with_instructions([Register::asset_definition(coin)]) .sign(bob_keypair)?; test_client.submit_transaction_blocking(&transaction)?; // check that "alice@wonderland" as owner of domain can transfer asset definitions in her domain - test_client.submit_blocking(TransferExpr::new(bob_id, coin_id.clone(), rabbit_id))?; + test_client.submit_blocking(Transfer::asset_definition( + bob_id, + coin_id.clone(), + rabbit_id, + ))?; // check that "alice@wonderland" as owner of domain can edit metadata of asset definition in her domain let key: Name = "key".parse()?; let value: Name = "value".parse()?; - test_client.submit_blocking(SetKeyValueExpr::new(coin_id.clone(), key.clone(), value))?; - test_client.submit_blocking(RemoveKeyValueExpr::new(coin_id.clone(), key))?; + test_client.submit_blocking(SetKeyValue::asset_definition( + coin_id.clone(), + key.clone(), + value, + ))?; + test_client.submit_blocking(RemoveKeyValue::asset_definition(coin_id.clone(), key))?; // check that "alice@wonderland" as owner of domain can grant and revoke asset definition related permission tokens in her domain let bob_id: AccountId = "bob@wonderland".parse()?; @@ -140,11 +148,11 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { "CanUnregisterAssetDefinition".parse().unwrap(), &json!({ "asset_definition_id": coin_id }), ); - test_client.submit_blocking(GrantExpr::new(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(RevokeExpr::new(token, bob_id))?; + test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; // check that "alice@wonderland" as owner of domain can unregister asset definitions in her domain - test_client.submit_blocking(UnregisterExpr::new(coin_id))?; + test_client.submit_blocking(Unregister::asset_definition(coin_id))?; Ok(()) } @@ -162,41 +170,40 @@ fn domain_owner_asset_permissions() -> Result<()> { // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id); - test_client.submit_blocking(RegisterExpr::new(kingdom))?; + test_client.submit_blocking(Register::domain(kingdom))?; let bob_keypair = KeyPair::generate()?; let bob = Account::new(bob_id.clone(), [bob_keypair.public_key().clone()]); - test_client.submit_blocking(RegisterExpr::new(bob))?; + test_client.submit_blocking(Register::account(bob))?; // register asset definitions by "bob@kingdom" so he is owner of it let coin = AssetDefinition::quantity(coin_id.clone()); let store = AssetDefinition::store(store_id.clone()); let transaction = TransactionBuilder::new(bob_id.clone()) - .with_instructions([RegisterExpr::new(coin), RegisterExpr::new(store)]) + .with_instructions([ + Register::asset_definition(coin), + Register::asset_definition(store), + ]) .sign(bob_keypair)?; test_client.submit_transaction_blocking(&transaction)?; // check that "alice@wonderland" as owner of domain can register and unregister assets in her domain let bob_coin_id = AssetId::new(coin_id, bob_id.clone()); let bob_coin = Asset::new(bob_coin_id.clone(), 30u32); - test_client.submit_blocking(RegisterExpr::new(bob_coin))?; - test_client.submit_blocking(UnregisterExpr::new(bob_coin_id.clone()))?; + test_client.submit_blocking(Register::asset(bob_coin))?; + test_client.submit_blocking(Unregister::asset(bob_coin_id.clone()))?; // check that "alice@wonderland" as owner of domain can burn, mint and transfer assets in her domain - test_client.submit_blocking(MintExpr::new(10u32.to_value(), bob_coin_id.clone()))?; - test_client.submit_blocking(BurnExpr::new(5u32.to_value(), bob_coin_id.clone()))?; - test_client.submit_blocking(TransferExpr::new(bob_coin_id, 5u32.to_value(), alice_id))?; + test_client.submit_blocking(Mint::asset_quantity(10u32, bob_coin_id.clone()))?; + test_client.submit_blocking(Burn::asset_quantity(5u32, bob_coin_id.clone()))?; + test_client.submit_blocking(Transfer::asset_quantity(bob_coin_id, 5u32, alice_id))?; // check that "alice@wonderland" as owner of domain can edit metadata of store asset in her domain let key: Name = "key".parse()?; let value: Name = "value".parse()?; let bob_store_id = AssetId::new(store_id, bob_id); - test_client.submit_blocking(SetKeyValueExpr::new( - bob_store_id.clone(), - key.clone(), - value, - ))?; - test_client.submit_blocking(RemoveKeyValueExpr::new(bob_store_id.clone(), key))?; + test_client.submit_blocking(SetKeyValue::asset(bob_store_id.clone(), key.clone(), value))?; + test_client.submit_blocking(RemoveKeyValue::asset(bob_store_id.clone(), key))?; // check that "alice@wonderland" as owner of domain can grant and revoke asset related permission tokens in her domain let bob_id: AccountId = "bob@wonderland".parse()?; @@ -204,8 +211,8 @@ fn domain_owner_asset_permissions() -> Result<()> { "CanUnregisterUserAsset".parse().unwrap(), &json!({ "asset_id": bob_store_id }), ); - test_client.submit_blocking(GrantExpr::new(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(RevokeExpr::new(token, bob_id))?; + test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; Ok(()) } @@ -221,18 +228,18 @@ fn domain_owner_trigger_permissions() -> Result<()> { // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id); - test_client.submit_blocking(RegisterExpr::new(kingdom))?; + test_client.submit_blocking(Register::domain(kingdom))?; let bob_keypair = KeyPair::generate()?; let bob = Account::new(bob_id.clone(), [bob_keypair.public_key().clone()]); - test_client.submit_blocking(RegisterExpr::new(bob))?; + test_client.submit_blocking(Register::account(bob))?; let asset_definition_id = "rose#wonderland".parse()?; let asset_id = AssetId::new(asset_definition_id, alice_id.clone()); let trigger_id: TriggerId = "trigger$kingdom".parse()?; - let trigger_instructions = vec![MintExpr::new(1_u32, asset_id)]; - let register_trigger = RegisterExpr::new(Trigger::new( + let trigger_instructions = vec![Mint::asset_quantity(1_u32, asset_id)]; + let register_trigger = Register::trigger(Trigger::new( trigger_id.clone(), Action::new( trigger_instructions, @@ -248,11 +255,11 @@ fn domain_owner_trigger_permissions() -> Result<()> { test_client.submit_blocking(register_trigger)?; // check that "alice@wonderland" as owner of domain can edit repetitions of triggers in her domain - test_client.submit_blocking(MintExpr::new(1_u32, trigger_id.clone()))?; - test_client.submit_blocking(BurnExpr::new(1_u32, trigger_id.clone()))?; + test_client.submit_blocking(Mint::trigger_repetitions(1_u32, trigger_id.clone()))?; + test_client.submit_blocking(Burn::trigger_repetitions(1_u32, trigger_id.clone()))?; // check that "alice@wonderland" as owner of domain can call triggers in her domain - let execute_trigger = ExecuteTriggerExpr::new(trigger_id.clone()); + let execute_trigger = ExecuteTrigger::new(trigger_id.clone()); let _result = test_client.submit_blocking(execute_trigger)?; // check that "alice@wonderland" as owner of domain can grant and revoke trigger related permission tokens in her domain @@ -261,19 +268,15 @@ fn domain_owner_trigger_permissions() -> Result<()> { "CanUnregisterUserTrigger".parse().unwrap(), &json!({ "trigger_id": trigger_id }), ); - test_client.submit_blocking(GrantExpr::new(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(RevokeExpr::new(token, bob_id))?; + test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; // check that "alice@wonderland" as owner of domain can unregister triggers in her domain - test_client.submit_blocking(UnregisterExpr::new(trigger_id))?; + test_client.submit_blocking(Unregister::trigger(trigger_id))?; Ok(()) } -#[deprecated( - since = "2.0.0-pre-rc.20", - note = "This test suite is deprecated, use test_transfer_domains.py instead" -)] #[ignore = "migrated to client cli python tests"] #[test] fn domain_owner_transfer() -> Result<()> { @@ -286,17 +289,17 @@ fn domain_owner_transfer() -> Result<()> { // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id.clone()); - test_client.submit_blocking(RegisterExpr::new(kingdom))?; + test_client.submit_blocking(Register::domain(kingdom))?; let bob_keypair = KeyPair::generate()?; let bob = Account::new(bob_id.clone(), [bob_keypair.public_key().clone()]); - test_client.submit_blocking(RegisterExpr::new(bob))?; + test_client.submit_blocking(Register::account(bob))?; let domain = test_client.request(FindDomainById::new(kingdom_id.clone()))?; assert_eq!(domain.owned_by(), &alice_id); test_client - .submit_blocking(TransferExpr::new( + .submit_blocking(Transfer::domain( alice_id, kingdom_id.clone(), bob_id.clone(), diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index 161ec489ac7..d3aa2a96834 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -8,37 +8,15 @@ use test_network::*; use crate::wasm::utils::wasm_template; -fn produce_instructions() -> Vec { +fn produce_instructions() -> Vec { let domains = (0..4) .map(|domain_index: usize| Domain::new(domain_index.to_string().parse().expect("Valid"))); - let registers: [InstructionExpr; 4] = domains + domains .into_iter() - .map(RegisterExpr::new) - .map(InstructionExpr::from) + .map(Register::domain) + .map(InstructionBox::from) .collect::>() - .try_into() - .unwrap(); - - // TODO: should we re-introduce the DSL? - vec![ - // domain "0" - // pair - // domain "1" - // if false fail else sequence - // domain "2" - // domain "3" - registers[0].clone(), - PairExpr::new( - registers[1].clone(), - ConditionalExpr::with_otherwise( - false, - Fail::new("unreachable"), - SequenceExpr::new([registers[2].clone(), registers[3].clone()]), - ), - ) - .into(), - ] } #[test] @@ -69,7 +47,7 @@ fn wasm_execution_should_produce_events() -> Result<()> { ptr_len = ptr_len / 2, )?; - ptr_offset = ptr_len; + ptr_offset += ptr_len; } let wat = format!( @@ -121,8 +99,10 @@ fn transaction_execution_should_produce_events( client.submit_transaction_blocking(&transaction)?; // assertion + iroha_logger::info!("Listening for events"); for i in 0..4_usize { let event: DataEvent = event_receiver.recv()??.try_into()?; + iroha_logger::info!("Event: {:?}", event); assert!(matches!(event, DataEvent::Domain(_))); if let DataEvent::Domain(domain_event) = event { assert!(matches!(domain_event, DomainEvent::Created(_))); @@ -174,16 +154,16 @@ fn produce_multiple_events() -> Result<()> { let role = iroha_client::data_model::role::Role::new(role_id.clone()) .add_permission(token_1.clone()) .add_permission(token_2.clone()); - let instructions = [RegisterExpr::new(role.clone())]; + let instructions = [Register::role(role.clone())]; client.submit_all_blocking(instructions)?; // Grants role to Bob let bob_id = AccountId::from_str("bob@wonderland")?; - let grant_role = GrantExpr::new(role_id.clone(), bob_id.clone()); + let grant_role = Grant::role(role_id.clone(), bob_id.clone()); client.submit_blocking(grant_role)?; // Unregister role - let unregister_role = UnregisterExpr::new(role_id.clone()); + let unregister_role = Unregister::role(role_id.clone()); client.submit_blocking(unregister_role)?; // Inspect produced events diff --git a/client/tests/integration/events/notification.rs b/client/tests/integration/events/notification.rs index 2c5cf522fd2..2cd033e2b7c 100644 --- a/client/tests/integration/events/notification.rs +++ b/client/tests/integration/events/notification.rs @@ -14,11 +14,11 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { let asset_id = AssetId::new(asset_definition_id, account_id); let trigger_id = TriggerId::from_str("mint_rose")?; - let instruction = MintExpr::new(1_u32, asset_id.clone()); - let register_trigger = RegisterExpr::new(Trigger::new( + let instruction = Mint::asset_quantity(1_u32, asset_id.clone()); + let register_trigger = Register::trigger(Trigger::new( trigger_id.clone(), Action::new( - vec![InstructionExpr::from(instruction)], + vec![InstructionBox::from(instruction)], Repeats::Indefinitely, asset_id.account_id.clone(), TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( @@ -29,7 +29,7 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { )); test_client.submit_blocking(register_trigger)?; - let call_trigger = ExecuteTriggerExpr::new(trigger_id.clone()); + let call_trigger = ExecuteTrigger::new(trigger_id.clone()); let thread_client = test_client.clone(); let (sender, receiver) = mpsc::channel(); @@ -63,11 +63,11 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { let account_id: AccountId = "alice@wonderland".parse()?; let trigger_id = TriggerId::from_str("fail_box")?; - let instruction = Fail::new("Fail box"); - let register_trigger = RegisterExpr::new(Trigger::new( + let instruction = Fail::new("Fail box".to_owned()); + let register_trigger = Register::trigger(Trigger::new( trigger_id.clone(), Action::new( - vec![InstructionExpr::from(instruction)], + vec![InstructionBox::from(instruction)], Repeats::Indefinitely, account_id.clone(), TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( @@ -78,7 +78,7 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { )); test_client.submit_blocking(register_trigger)?; - let call_trigger = ExecuteTriggerExpr::new(trigger_id.clone()); + let call_trigger = ExecuteTrigger::new(trigger_id.clone()); let thread_client = test_client.clone(); let (sender, receiver) = mpsc::channel(); diff --git a/client/tests/integration/events/pipeline.rs b/client/tests/integration/events/pipeline.rs index 8a9ce281d06..966a922f6e0 100644 --- a/client/tests/integration/events/pipeline.rs +++ b/client/tests/integration/events/pipeline.rs @@ -24,7 +24,7 @@ fn transaction_with_no_instructions_should_be_committed() -> Result<()> { // #[ignore = "Experiment"] #[test] fn transaction_with_fail_instruction_should_be_rejected() -> Result<()> { - let fail = Fail::new("Should be rejected"); + let fail = Fail::new("Should be rejected".to_owned()); test_with_instruction_and_status_and_port( Some(fail.into()), PipelineStatusKind::Rejected, @@ -34,7 +34,7 @@ fn transaction_with_fail_instruction_should_be_rejected() -> Result<()> { #[allow(dead_code, clippy::needless_range_loop, clippy::needless_pass_by_value)] fn test_with_instruction_and_status_and_port( - instruction: Option, + instruction: Option, should_be: PipelineStatusKind, port: u16, ) -> Result<()> { @@ -44,7 +44,7 @@ fn test_with_instruction_and_status_and_port( wait_for_genesis_committed(&clients, 0); let pipeline_time = Configuration::pipeline_time(); - client.submit_blocking( + client.submit_all_blocking( ParametersBuilder::new() .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? .into_set_parameters(), @@ -110,7 +110,7 @@ fn committed_block_must_be_available_in_kura() { .expect("Failed to subscribe for events"); client - .submit(Fail::new("Dummy instruction")) + .submit(Fail::new("Dummy instruction".to_owned())) .expect("Failed to submit transaction"); let event = event_iter.next().expect("Block must be committed"); diff --git a/client/tests/integration/multiple_blocks_created.rs b/client/tests/integration/multiple_blocks_created.rs index f2a13a8089b..aa3f3a551ba 100644 --- a/client/tests/integration/multiple_blocks_created.rs +++ b/client/tests/integration/multiple_blocks_created.rs @@ -9,6 +9,7 @@ use iroha_client::{ }, }; use iroha_crypto::KeyPair; +use iroha_data_model::isi::InstructionBox; use test_network::*; use super::Configuration; @@ -23,18 +24,19 @@ fn long_multiple_blocks_created() -> Result<()> { wait_for_genesis_committed(&network.clients(), 0); let pipeline_time = Configuration::pipeline_time(); - client.submit_blocking( + client.submit_all_blocking( ParametersBuilder::new() .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? .into_set_parameters(), )?; - let create_domain = RegisterExpr::new(Domain::new("domain".parse()?)); + let create_domain: InstructionBox = Register::domain(Domain::new("domain".parse()?)).into(); let account_id: AccountId = "account@domain".parse()?; let (public_key, _) = KeyPair::generate()?.into(); - let create_account = RegisterExpr::new(Account::new(account_id.clone(), [public_key])); + let create_account = Register::account(Account::new(account_id.clone(), [public_key])).into(); let asset_definition_id: AssetDefinitionId = "xor#domain".parse()?; - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())).into(); client.submit_all([create_domain, create_account, create_asset])?; @@ -44,12 +46,9 @@ fn long_multiple_blocks_created() -> Result<()> { //When for _ in 0..N_BLOCKS { let quantity: u32 = 1; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); client.submit(mint_asset)?; account_has_quantity += quantity; diff --git a/client/tests/integration/multisignature_account.rs b/client/tests/integration/multisignature_account.rs index 44f289dcfb1..9f35fb9bbfa 100644 --- a/client/tests/integration/multisignature_account.rs +++ b/client/tests/integration/multisignature_account.rs @@ -19,24 +19,19 @@ fn transaction_signed_by_new_signatory_of_account_should_pass() -> Result<()> { // Given let account_id: AccountId = "alice@wonderland".parse().expect("Valid"); let asset_definition_id: AssetDefinitionId = "xor#wonderland".parse().expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); let key_pair = KeyPair::generate()?; - let add_signatory = MintExpr::new( - key_pair.public_key().clone(), - IdBox::AccountId(account_id.clone()), - ); + let add_signatory = Mint::account_public_key(key_pair.public_key().clone(), account_id.clone()); - let instructions: [InstructionExpr; 2] = [create_asset.into(), add_signatory.into()]; + let instructions: [InstructionBox; 2] = [create_asset.into(), add_signatory.into()]; client.submit_all(instructions)?; thread::sleep(pipeline_time * 2); //When let quantity: u32 = 200; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); Client::test_with_key(&peer.api_address, key_pair).submit_till( mint_asset, diff --git a/client/tests/integration/multisignature_transaction.rs b/client/tests/integration/multisignature_transaction.rs index 4d999d5c920..280a07751f3 100644 --- a/client/tests/integration/multisignature_transaction.rs +++ b/client/tests/integration/multisignature_transaction.rs @@ -21,7 +21,7 @@ fn multisignature_transactions_should_wait_for_all_signatures() -> Result<()> { wait_for_genesis_committed(&network.clients(), 0); let pipeline_time = Configuration::pipeline_time(); - client.submit_blocking( + client.submit_all_blocking( ParametersBuilder::new() .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? .into_set_parameters(), @@ -31,23 +31,24 @@ fn multisignature_transactions_should_wait_for_all_signatures() -> Result<()> { let alice_key_pair = get_key_pair(); let key_pair_2 = KeyPair::generate()?; let asset_definition_id = AssetDefinitionId::from_str("camomile#wonderland")?; - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); - let set_signature_condition = MintExpr::new( + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); + let set_signature_condition = Mint::account_signature_check_condition( SignatureCheckCondition::AllAccountSignaturesAnd( vec![key_pair_2.public_key().clone()].into(), ), - IdBox::AccountId(alice_id.clone()), + alice_id.clone(), ); let mut client_configuration = ClientConfiguration::test(&network.genesis.api_address); let client = Client::new(&client_configuration)?; - let instructions: [InstructionExpr; 2] = [create_asset.into(), set_signature_condition.into()]; + let instructions: [InstructionBox; 2] = [create_asset.into(), set_signature_condition.into()]; client.submit_all_blocking(instructions)?; //When let quantity: u32 = 200; let asset_id = AssetId::new(asset_definition_id, alice_id.clone()); - let mint_asset = MintExpr::new(quantity.to_value(), IdBox::AssetId(asset_id.clone())); + let mint_asset = Mint::asset_quantity(quantity, asset_id.clone()); let (public_key1, private_key1) = alice_key_pair.into(); client_configuration.account_id = alice_id.clone(); diff --git a/client/tests/integration/non_mintable.rs b/client/tests/integration/non_mintable.rs index 1dca25910a2..c80be2ca4d9 100644 --- a/client/tests/integration/non_mintable.rs +++ b/client/tests/integration/non_mintable.rs @@ -5,6 +5,7 @@ use iroha_client::{ client::{self, QueryResult}, data_model::{metadata::UnlimitedMetadata, prelude::*}, }; +use iroha_data_model::isi::InstructionBox; use test_network::*; #[test] @@ -15,20 +16,18 @@ fn non_mintable_asset_can_be_minted_once_but_not_twice() -> Result<()> { // Given let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); - let create_asset = - RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone()).mintable_once()); + let create_asset = Register::asset_definition( + AssetDefinition::quantity(asset_definition_id.clone()).mintable_once(), + ); let metadata = UnlimitedMetadata::default(); - let mint = MintExpr::new( - 200_u32.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint = Mint::asset_quantity( + 200_u32, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); - let instructions: [InstructionExpr; 2] = [create_asset.into(), mint.clone().into()]; + let instructions: [InstructionBox; 2] = [create_asset.into(), mint.clone().into()]; let tx = test_client.build_transaction(instructions, metadata)?; // We can register and mint the non-mintable token @@ -65,11 +64,14 @@ fn non_mintable_asset_cannot_be_minted_if_registered_with_non_zero_value() -> Re // Given let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); - let create_asset = - RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone()).mintable_once()); + let create_asset: InstructionBox = Register::asset_definition( + AssetDefinition::quantity(asset_definition_id.clone()).mintable_once(), + ) + .into(); let asset_id = AssetId::new(asset_definition_id.clone(), account_id.clone()); - let register_asset = RegisterExpr::new(Asset::new(asset_id.clone(), 1_u32)); + let register_asset: InstructionBox = + Register::asset(Asset::new(asset_id.clone(), 1_u32)).into(); // We can register the non-mintable token test_client.submit_all([create_asset, register_asset.clone()])?; @@ -85,7 +87,7 @@ fn non_mintable_asset_cannot_be_minted_if_registered_with_non_zero_value() -> Re assert!(test_client.submit_blocking(register_asset).is_err()); // And can't be minted - let mint = MintExpr::new(1_u32.to_value(), IdBox::AssetId(asset_id)); + let mint = Mint::asset_quantity(1_u32, asset_id); assert!(test_client.submit_blocking(mint).is_err()); Ok(()) @@ -99,15 +101,16 @@ fn non_mintable_asset_can_be_minted_if_registered_with_zero_value() -> Result<() // Given let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); - let create_asset = - RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone()).mintable_once()); + let create_asset = Register::asset_definition( + AssetDefinition::quantity(asset_definition_id.clone()).mintable_once(), + ); let asset_id = AssetId::new(asset_definition_id.clone(), account_id.clone()); - let register_asset = RegisterExpr::new(Asset::new(asset_id.clone(), 0_u32)); - let mint = MintExpr::new(1_u32.to_value(), IdBox::AssetId(asset_id)); + let register_asset = Register::asset(Asset::new(asset_id.clone(), 0_u32)); + let mint = Mint::asset_quantity(1_u32, asset_id); // We can register the non-mintable token wih zero value and then mint it - let instructions: [InstructionExpr; 3] = + let instructions: [InstructionBox; 3] = [create_asset.into(), register_asset.into(), mint.into()]; test_client.submit_all(instructions)?; test_client.poll_request(client::asset::by_account_id(account_id), |result| { diff --git a/client/tests/integration/offline_peers.rs b/client/tests/integration/offline_peers.rs index 86838146000..193ff34afaf 100644 --- a/client/tests/integration/offline_peers.rs +++ b/client/tests/integration/offline_peers.rs @@ -21,7 +21,7 @@ fn genesis_block_is_committed_with_some_offline_peers() -> Result<()> { )); wait_for_genesis_committed(&network.clients(), 1); - client.submit_blocking( + client.submit_all_blocking( ParametersBuilder::new() .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? .into_set_parameters(), diff --git a/client/tests/integration/pagination.rs b/client/tests/integration/pagination.rs index 1ab7ab4c14d..6e0ed462ec2 100644 --- a/client/tests/integration/pagination.rs +++ b/client/tests/integration/pagination.rs @@ -46,11 +46,11 @@ fn fetch_size_should_work() -> Result<()> { } fn register_assets(client: &Client) -> Result<()> { - let register: Vec = ('a'..='z') + let register: Vec = ('a'..='z') .map(|c| c.to_string()) .map(|name| (name + "#wonderland").parse().expect("Valid")) .map(|asset_definition_id| { - RegisterExpr::new(AssetDefinition::quantity(asset_definition_id)).into() + Register::asset_definition(AssetDefinition::quantity(asset_definition_id)).into() }) .collect(); let _ = client.submit_all_blocking(register)?; diff --git a/client/tests/integration/permissions.rs b/client/tests/integration/permissions.rs index 11234a6b16a..fb829ed2ce3 100644 --- a/client/tests/integration/permissions.rs +++ b/client/tests/integration/permissions.rs @@ -18,7 +18,7 @@ fn genesis_transactions_are_validated() { let mut genesis = GenesisNetwork::test(true).expect("Expected genesis"); - let grant_invalid_token = GrantExpr::new( + let grant_invalid_token = Grant::permission_token( PermissionToken::new("InvalidToken".parse().unwrap(), &json!(null)), AccountId::from_str("alice@wonderland").unwrap(), ); @@ -78,7 +78,8 @@ fn permissions_disallow_asset_transfer() { let bob_id: AccountId = "bob@wonderland".parse().expect("Valid"); let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); let asset_definition_id: AssetDefinitionId = "xor#wonderland".parse().expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); let mouse_keypair = iroha_crypto::KeyPair::generate().expect("Failed to generate KeyPair."); let alice_start_assets = get_assets(&iroha_client, &alice_id); @@ -87,19 +88,19 @@ fn permissions_disallow_asset_transfer() { .expect("Failed to prepare state."); let quantity: u32 = 200; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new(asset_definition_id.clone(), bob_id.clone())), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), bob_id.clone()), ); iroha_client .submit_blocking(mint_asset) .expect("Failed to create asset."); //When - let transfer_asset = TransferExpr::new( - IdBox::AssetId(AssetId::new(asset_definition_id, bob_id)), - quantity.to_value(), - IdBox::AccountId(alice_id.clone()), + let transfer_asset = Transfer::asset_quantity( + AssetId::new(asset_definition_id, bob_id), + quantity, + alice_id.clone(), ); let transfer_tx = TransactionBuilder::new(mouse_id) .with_instructions([transfer_asset]) @@ -131,7 +132,8 @@ fn permissions_disallow_asset_burn() { let bob_id: AccountId = "bob@wonderland".parse().expect("Valid"); let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); let mouse_keypair = iroha_crypto::KeyPair::generate().expect("Failed to generate KeyPair."); let alice_start_assets = get_assets(&iroha_client, &alice_id); @@ -141,16 +143,14 @@ fn permissions_disallow_asset_burn() { .expect("Failed to prepare state."); let quantity: u32 = 200; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new(asset_definition_id.clone(), bob_id)), - ); + let mint_asset = + Mint::asset_quantity(quantity, AssetId::new(asset_definition_id.clone(), bob_id)); iroha_client .submit_blocking(mint_asset) .expect("Failed to create asset."); - let burn_asset = BurnExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new(asset_definition_id, mouse_id.clone())), + let burn_asset = Burn::asset_quantity( + quantity, + AssetId::new(asset_definition_id, mouse_id.clone()), ); let burn_tx = TransactionBuilder::new(mouse_id) .with_instructions([burn_asset]) @@ -184,7 +184,7 @@ fn account_can_query_only_its_own_domain() -> Result<()> { // Given let domain_id: DomainId = "wonderland".parse()?; let new_domain_id: DomainId = "wonderland2".parse()?; - let register_domain = RegisterExpr::new(Domain::new(new_domain_id.clone())); + let register_domain = Register::domain(Domain::new(new_domain_id.clone())); client.submit_blocking(register_domain)?; @@ -213,20 +213,20 @@ fn permissions_differ_not_only_by_names() { let new_shoes_definition = AssetDefinition::store(shoes_definition_id.clone()); client .submit_all_blocking([ - RegisterExpr::new(new_hat_definition), - RegisterExpr::new(new_shoes_definition), + Register::asset_definition(new_hat_definition), + Register::asset_definition(new_shoes_definition), ]) .expect("Failed to register new asset definitions"); // Registering mouse let new_mouse_account = Account::new(mouse_id.clone(), [mouse_keypair.public_key().clone()]); client - .submit_blocking(RegisterExpr::new(new_mouse_account)) + .submit_blocking(Register::account(new_mouse_account)) .expect("Failed to register mouse"); // Granting permission to Alice to modify metadata in Mouse's hats let mouse_hat_id = AssetId::new(hat_definition_id, mouse_id.clone()); - let allow_alice_to_set_key_value_in_hats = GrantExpr::new( + let allow_alice_to_set_key_value_in_hats = Grant::permission_token( PermissionToken::new( "CanSetKeyValueInUserAsset".parse().unwrap(), &json!({ "asset_id": mouse_hat_id }), @@ -244,7 +244,7 @@ fn permissions_differ_not_only_by_names() { // Checking that Alice can modify Mouse's hats ... client - .submit_blocking(SetKeyValueExpr::new( + .submit_blocking(SetKeyValue::asset( mouse_hat_id, Name::from_str("color").expect("Valid"), "red".to_owned(), @@ -253,7 +253,7 @@ fn permissions_differ_not_only_by_names() { // ... but not shoes let mouse_shoes_id = AssetId::new(shoes_definition_id, mouse_id.clone()); - let set_shoes_color = SetKeyValueExpr::new( + let set_shoes_color = SetKeyValue::asset( mouse_shoes_id.clone(), Name::from_str("color").expect("Valid"), "yellow".to_owned(), @@ -263,7 +263,7 @@ fn permissions_differ_not_only_by_names() { .expect_err("Expected Alice to fail to modify Mouse's shoes"); // Granting permission to Alice to modify metadata in Mouse's shoes - let allow_alice_to_set_key_value_in_shoes = GrantExpr::new( + let allow_alice_to_set_key_value_in_shoes = Grant::permission_token( PermissionToken::new( "CanSetKeyValueInUserAsset".parse().unwrap(), &json!({ "asset_id": mouse_shoes_id }), @@ -287,6 +287,7 @@ fn permissions_differ_not_only_by_names() { } #[test] +#[allow(deprecated)] fn stored_vs_granted_token_payload() -> Result<()> { let (_rt, _peer, iroha_client) = ::new().with_port(10_730).start_with_runtime(); wait_for_genesis_committed(&[iroha_client.clone()], 0); @@ -296,12 +297,13 @@ fn stored_vs_granted_token_payload() -> Result<()> { // Registering mouse and asset definition let asset_definition_id: AssetDefinitionId = "xor#wonderland".parse().expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::store(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::store(asset_definition_id.clone())); let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); let mouse_keypair = iroha_crypto::KeyPair::generate().expect("Failed to generate KeyPair."); let new_mouse_account = Account::new(mouse_id.clone(), [mouse_keypair.public_key().clone()]); - let instructions: [InstructionExpr; 2] = [ - RegisterExpr::new(new_mouse_account).into(), + let instructions: [InstructionBox; 2] = [ + Register::account(new_mouse_account).into(), create_asset.into(), ]; iroha_client @@ -310,7 +312,7 @@ fn stored_vs_granted_token_payload() -> Result<()> { // Allow alice to mint mouse asset and mint initial value let mouse_asset = AssetId::new(asset_definition_id, mouse_id.clone()); - let allow_alice_to_set_key_value_in_mouse_asset = GrantExpr::new( + let allow_alice_to_set_key_value_in_mouse_asset = Grant::permission_token( PermissionToken::from_str_unchecked( "CanSetKeyValueInUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form @@ -328,8 +330,7 @@ fn stored_vs_granted_token_payload() -> Result<()> { .expect("Failed to grant permission to alice."); // Check that alice can indeed mint mouse asset - let set_key_value = - SetKeyValueExpr::new(mouse_asset, Name::from_str("color")?, "red".to_owned()); + let set_key_value = SetKeyValue::asset(mouse_asset, Name::from_str("color")?, "red".to_owned()); iroha_client .submit_blocking(set_key_value) .expect("Failed to mint asset for mouse."); diff --git a/client/tests/integration/queries/account.rs b/client/tests/integration/queries/account.rs index d19a4498361..69d28c66e6f 100644 --- a/client/tests/integration/queries/account.rs +++ b/client/tests/integration/queries/account.rs @@ -15,7 +15,7 @@ fn find_accounts_with_asset() -> Result<()> { // Registering new asset definition let definition_id = AssetDefinitionId::from_str("test_coin#wonderland").expect("Valid"); let asset_definition = AssetDefinition::quantity(definition_id.clone()); - test_client.submit_blocking(RegisterExpr::new(asset_definition.clone()))?; + test_client.submit_blocking(Register::asset_definition(asset_definition.clone()))?; // Checking results before all let received_asset_definition = @@ -40,7 +40,7 @@ fn find_accounts_with_asset() -> Result<()> { .iter() .skip(1) // Alice has already been registered in genesis .cloned() - .map(|account_id| RegisterExpr::new(Account::new(account_id, []))) + .map(|account_id| Register::account(Account::new(account_id, []))) .collect::>(); test_client.submit_all_blocking(register_accounts)?; @@ -48,7 +48,7 @@ fn find_accounts_with_asset() -> Result<()> { .iter() .cloned() .map(|account_id| AssetId::new(definition_id.clone(), account_id)) - .map(|asset_id| MintExpr::new(1_u32, asset_id)) + .map(|asset_id| Mint::asset_quantity(1_u32, asset_id)) .collect::>(); test_client.submit_all_blocking(mint_asset)?; diff --git a/client/tests/integration/queries/asset.rs b/client/tests/integration/queries/asset.rs index 4748cd6d7c2..bb34d302158 100644 --- a/client/tests/integration/queries/asset.rs +++ b/client/tests/integration/queries/asset.rs @@ -1,12 +1,14 @@ use eyre::Result; use iroha_client::{ - client::ClientQueryError, + client::{Client, ClientQueryError}, data_model::{ + asset::AssetValue, prelude::*, query::{asset::FindTotalAssetQuantityByAssetDefinitionId, error::QueryExecutionFail}, }, }; use iroha_crypto::KeyPair; +use iroha_data_model::isi::Instruction; use iroha_primitives::fixed::Fixed; use test_network::*; @@ -19,7 +21,7 @@ fn find_asset_total_quantity() -> Result<()> { // Register new domain let domain_id: DomainId = "looking_glass".parse()?; let domain = Domain::new(domain_id); - test_client.submit_blocking(RegisterExpr::new(domain))?; + test_client.submit_blocking(Register::domain(domain))?; let accounts: [AccountId; 5] = [ "alice@wonderland".parse()?, @@ -40,121 +42,52 @@ fn find_asset_total_quantity() -> Result<()> { .skip(1) // Alice has already been registered in genesis .cloned() .zip(keys.iter().map(KeyPair::public_key).cloned()) - .map(|(account_id, public_key)| RegisterExpr::new(Account::new(account_id, [public_key]))) + .map(|(account_id, public_key)| Register::account(Account::new(account_id, [public_key]))) .collect::>(); test_client.submit_all_blocking(register_accounts)?; // Test for numeric assets value types - for ( - definition, - asset_value_type, - initial_value, - to_mint, - to_burn, - expected_total_asset_quantity, - ) in [ - ( - "quantity#wonderland", - AssetValueType::Quantity, - AssetValue::Quantity(1_u32), - 10_u32.to_value(), - 5_u32.to_value(), - NumericValue::U32(30_u32), - ), - ( - "big-quantity#wonderland", - AssetValueType::BigQuantity, - AssetValue::BigQuantity(1_u128), - 10_u128.to_value(), - 5_u128.to_value(), - NumericValue::U128(30_u128), - ), - ( - "fixed#wonderland", - AssetValueType::Fixed, - AssetValue::Fixed(Fixed::try_from(1.0)?), - 10.0_f64.try_to_value()?, - 5.0_f64.try_to_value()?, - NumericValue::Fixed(Fixed::try_from(30.0)?), - ), - ] { - // Registering new asset definition - let definition_id: AssetDefinitionId = - definition.parse().expect("Failed to parse `definition_id`"); - let asset_definition = AssetDefinition::new(definition_id.clone(), asset_value_type); - test_client.submit_blocking(RegisterExpr::new(asset_definition.clone()))?; - - let asset_ids = accounts - .iter() - .cloned() - .map(|account_id| AssetId::new(definition_id.clone(), account_id)) - .collect::>(); - - // Assert that initial total quantity before any burns and mints is zero - let initial_total_asset_quantity = test_client.request( - FindTotalAssetQuantityByAssetDefinitionId::new(definition_id.clone()), - )?; - assert!(initial_total_asset_quantity.is_zero_value()); - - let register_asset = asset_ids - .iter() - .cloned() - .map(|asset_id| Asset::new(asset_id, initial_value.clone())) - .map(RegisterExpr::new) - .collect::>(); - test_client.submit_all_blocking(register_asset)?; - - let mint_asset = asset_ids - .iter() - .cloned() - .map(|asset_id| MintExpr::new(to_mint.clone(), asset_id)); - test_client.submit_all_blocking(mint_asset)?; - - let burn_asset = asset_ids - .iter() - .cloned() - .map(|asset_id| BurnExpr::new(to_burn.clone(), asset_id)) - .collect::>(); - test_client.submit_all_blocking(burn_asset)?; - - // Assert that total asset quantity is equal to: `n_accounts * (initial_value + to_mint - to_burn)` - let total_asset_quantity = test_client.request( - FindTotalAssetQuantityByAssetDefinitionId::new(definition_id.clone()), - )?; - assert_eq!(expected_total_asset_quantity, total_asset_quantity); - - let unregister_asset = asset_ids - .iter() - .cloned() - .map(UnregisterExpr::new) - .collect::>(); - test_client.submit_all_blocking(unregister_asset)?; - - // Assert that total asset quantity is zero after unregistering asset from all accounts - let total_asset_quantity = test_client.request( - FindTotalAssetQuantityByAssetDefinitionId::new(definition_id.clone()), - )?; - assert!(total_asset_quantity.is_zero_value()); - - // Unregister asset definition - test_client.submit_blocking(UnregisterExpr::new(definition_id.clone()))?; - - // Assert that total asset quantity cleared with unregistering of asset definition - let result = test_client.request(FindTotalAssetQuantityByAssetDefinitionId::new( - definition_id.clone(), - )); - assert!(matches!( - result, - Err(ClientQueryError::Validation(ValidationFail::QueryFailed( - QueryExecutionFail::Find(_) - ))) - )); - } + test_total_quantity( + &test_client, + &accounts, + "quantity#wonderland", + AssetValueType::Quantity, + 1_u32, + 10_u32, + 5_u32, + NumericValue::U32(30_u32), + Mint::asset_quantity, + Burn::asset_quantity, + )?; + test_total_quantity( + &test_client, + &accounts, + "big-quantity#wonderland", + AssetValueType::BigQuantity, + 1_u128, + 10_u128, + 5_u128, + NumericValue::U128(30_u128), + Mint::asset_big_quantity, + Burn::asset_big_quantity, + )?; + test_total_quantity( + &test_client, + &accounts, + "fixed#wonderland", + AssetValueType::Fixed, + Fixed::try_from(1.0)?, + Fixed::try_from(10.0)?, + Fixed::try_from(5.0)?, + NumericValue::Fixed(Fixed::try_from(30.0)?), + Mint::asset_fixed, + Burn::asset_fixed, + )?; // Test for `Store` asset value type let definition_id: AssetDefinitionId = "store#wonderland".parse().expect("Valid"); let asset_definition = AssetDefinition::store(definition_id.clone()); - test_client.submit_blocking(RegisterExpr::new(asset_definition))?; + test_client.submit_blocking(Register::asset_definition(asset_definition))?; let asset_ids = accounts .iter() @@ -168,13 +101,13 @@ fn find_asset_total_quantity() -> Result<()> { )?; assert!(initial_total_asset_quantity.is_zero_value()); - let register_asset = asset_ids + let register_assets = asset_ids .iter() .cloned() .map(|asset_id| Asset::new(asset_id, Metadata::default())) - .map(RegisterExpr::new) + .map(Register::asset) .collect::>(); - test_client.submit_all_blocking(register_asset)?; + test_client.submit_all_blocking(register_assets)?; // Assert that total quantity is equal to number of registrations let result = test_client.request(FindTotalAssetQuantityByAssetDefinitionId::new( @@ -182,12 +115,106 @@ fn find_asset_total_quantity() -> Result<()> { ))?; assert_eq!(NumericValue::U32(5), result); - let unregister_asset = asset_ids + let unregister_assets = asset_ids + .iter() + .cloned() + .map(Unregister::asset) + .collect::>(); + test_client.submit_all_blocking(unregister_assets)?; + + // Assert that total asset quantity is zero after unregistering asset from all accounts + let total_asset_quantity = test_client.request( + FindTotalAssetQuantityByAssetDefinitionId::new(definition_id.clone()), + )?; + assert!(total_asset_quantity.is_zero_value()); + + // Unregister asset definition + test_client.submit_blocking(Unregister::asset_definition(definition_id.clone()))?; + + // Assert that total asset quantity cleared with unregistering of asset definition + let result = test_client.request(FindTotalAssetQuantityByAssetDefinitionId::new( + definition_id, + )); + assert!(matches!( + result, + Err(ClientQueryError::Validation(ValidationFail::QueryFailed( + QueryExecutionFail::Find(_) + ))) + )); + + Ok(()) +} + +#[allow(clippy::too_many_arguments)] +fn test_total_quantity( + test_client: &Client, + accounts: &[AccountId; 5], + definition: &str, + asset_value_type: AssetValueType, + initial_value: T, + to_mint: T, + to_burn: T, + expected_total_asset_quantity: NumericValue, + mint_ctr: impl Fn(T, AssetId) -> Mint, + burn_ctr: impl Fn(T, AssetId) -> Burn, +) -> Result<()> +where + T: Copy + Into, + Value: From, + Mint: Instruction, + Burn: Instruction, +{ + // Registering new asset definition + let definition_id: AssetDefinitionId = + definition.parse().expect("Failed to parse `definition_id`"); + let asset_definition = AssetDefinition::new(definition_id.clone(), asset_value_type); + test_client.submit_blocking(Register::asset_definition(asset_definition))?; + + let asset_ids = accounts + .iter() + .cloned() + .map(|account_id| AssetId::new(definition_id.clone(), account_id)) + .collect::>(); + + // Assert that initial total quantity before any burns and mints is zero + let initial_total_asset_quantity = test_client.request( + FindTotalAssetQuantityByAssetDefinitionId::new(definition_id.clone()), + )?; + assert!(initial_total_asset_quantity.is_zero_value()); + + let register_assets = asset_ids + .iter() + .cloned() + .map(|asset_id| Asset::new(asset_id, initial_value)) + .map(Register::asset) + .collect::>(); + test_client.submit_all_blocking(register_assets)?; + + let mint_assets = asset_ids + .iter() + .cloned() + .map(|asset_id| mint_ctr(to_mint, asset_id)); + test_client.submit_all_blocking(mint_assets)?; + + let burn_assets = asset_ids + .iter() + .cloned() + .map(|asset_id| burn_ctr(to_burn, asset_id)) + .collect::>(); + test_client.submit_all_blocking(burn_assets)?; + + // Assert that total asset quantity is equal to: `n_accounts * (initial_value + to_mint - to_burn)` + let total_asset_quantity = test_client.request( + FindTotalAssetQuantityByAssetDefinitionId::new(definition_id.clone()), + )?; + assert_eq!(expected_total_asset_quantity, total_asset_quantity); + + let unregister_assets = asset_ids .iter() .cloned() - .map(UnregisterExpr::new) + .map(Unregister::asset) .collect::>(); - test_client.submit_all_blocking(unregister_asset)?; + test_client.submit_all_blocking(unregister_assets)?; // Assert that total asset quantity is zero after unregistering asset from all accounts let total_asset_quantity = test_client.request( @@ -196,7 +223,7 @@ fn find_asset_total_quantity() -> Result<()> { assert!(total_asset_quantity.is_zero_value()); // Unregister asset definition - test_client.submit_blocking(UnregisterExpr::new(definition_id.clone()))?; + test_client.submit_blocking(Unregister::asset_definition(definition_id.clone()))?; // Assert that total asset quantity cleared with unregistering of asset definition let result = test_client.request(FindTotalAssetQuantityByAssetDefinitionId::new( diff --git a/client/tests/integration/queries/role.rs b/client/tests/integration/queries/role.rs index 5432dc2e547..9d18b523910 100644 --- a/client/tests/integration/queries/role.rs +++ b/client/tests/integration/queries/role.rs @@ -29,7 +29,7 @@ fn find_roles() -> Result<()> { let register_roles = role_ids .iter() .cloned() - .map(|role_id| RegisterExpr::new(Role::new(role_id))) + .map(|role_id| Register::role(Role::new(role_id))) .collect::>(); test_client.submit_all_blocking(register_roles)?; @@ -61,7 +61,7 @@ fn find_role_ids() -> Result<()> { let register_roles = role_ids .iter() .cloned() - .map(|role_id| RegisterExpr::new(Role::new(role_id))) + .map(|role_id| Register::role(Role::new(role_id))) .collect::>(); test_client.submit_all_blocking(register_roles)?; @@ -87,7 +87,7 @@ fn find_role_by_id() -> Result<()> { let new_role = Role::new(role_id.clone()); // Registering role - let register_role = RegisterExpr::new(new_role.clone()); + let register_role = Register::role(new_role.clone()); test_client.submit_blocking(register_role)?; let found_role = test_client.request(client::role::by_id(role_id))?; @@ -130,7 +130,7 @@ fn find_roles_by_account_id() -> Result<()> { .iter() .cloned() .map(|role_id| { - RegisterExpr::new(Role::new(role_id).add_permission(PermissionToken::new( + Register::role(Role::new(role_id).add_permission(PermissionToken::new( "CanSetKeyValueInUserAccount".parse().unwrap(), &json!({ "account_id": alice_id }), ))) @@ -142,7 +142,7 @@ fn find_roles_by_account_id() -> Result<()> { let grant_roles = role_ids .iter() .cloned() - .map(|role_id| GrantExpr::new(role_id, alice_id.clone())) + .map(|role_id| Grant::role(role_id, alice_id.clone())) .collect::>(); test_client.submit_all_blocking(grant_roles)?; diff --git a/client/tests/integration/restart_peer.rs b/client/tests/integration/restart_peer.rs index cfe153e3c9d..1699ae9763e 100644 --- a/client/tests/integration/restart_peer.rs +++ b/client/tests/integration/restart_peer.rs @@ -22,7 +22,8 @@ fn restarted_peer_should_have_the_same_asset_amount() -> Result<()> { let account_id = AccountId::from_str("alice@wonderland").unwrap(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").unwrap(); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); let quantity: u32 = 200; let iroha_client = client::Client::test(&peer.api_address); @@ -38,12 +39,9 @@ fn restarted_peer_should_have_the_same_asset_amount() -> Result<()> { wait_for_genesis_committed(&vec![iroha_client.clone()], 0); iroha_client.submit_blocking(create_asset)?; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); iroha_client.submit_blocking(mint_asset)?; diff --git a/client/tests/integration/roles.rs b/client/tests/integration/roles.rs index a89a939c69d..8523cfb39b6 100644 --- a/client/tests/integration/roles.rs +++ b/client/tests/integration/roles.rs @@ -14,7 +14,7 @@ fn register_empty_role() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let role_id = "root".parse().expect("Valid"); - let register_role = RegisterExpr::new(Role::new(role_id)); + let register_role = Register::role(Role::new(role_id)); test_client.submit(register_role)?; Ok(()) @@ -29,7 +29,7 @@ fn register_role_with_empty_token_params() -> Result<()> { let token = PermissionToken::new("token".parse()?, &json!(null)); let role = Role::new(role_id).add_permission(token); - test_client.submit(RegisterExpr::new(role))?; + test_client.submit(Register::role(role))?; Ok(()) } @@ -53,7 +53,7 @@ fn register_and_grant_role_for_metadata_access() -> Result<()> { // Registering Mouse let mouse_key_pair = iroha_crypto::KeyPair::generate()?; - let register_mouse = RegisterExpr::new(Account::new( + let register_mouse = Register::account(Account::new( mouse_id.clone(), [mouse_key_pair.public_key().clone()], )); @@ -70,18 +70,18 @@ fn register_and_grant_role_for_metadata_access() -> Result<()> { "CanRemoveKeyValueInUserAccount".parse()?, &json!({ "account_id": mouse_id }), )); - let register_role = RegisterExpr::new(role); + let register_role = Register::role(role); test_client.submit_blocking(register_role)?; // Mouse grants role to Alice - let grant_role = GrantExpr::new(role_id.clone(), alice_id.clone()); + let grant_role = Grant::role(role_id.clone(), alice_id.clone()); let grant_role_tx = TransactionBuilder::new(mouse_id.clone()) .with_instructions([grant_role]) .sign(mouse_key_pair)?; test_client.submit_transaction_blocking(&grant_role_tx)?; // Alice modifies Mouse's metadata - let set_key_value = SetKeyValueExpr::new( + let set_key_value = SetKeyValue::account( mouse_id, Name::from_str("key").expect("Valid"), Value::String("value".to_owned()), @@ -107,11 +107,11 @@ fn unregistered_role_removed_from_account() -> Result<()> { let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); // Registering Mouse - let register_mouse = RegisterExpr::new(Account::new(mouse_id.clone(), [])); + let register_mouse = Register::account(Account::new(mouse_id.clone(), [])); test_client.submit_blocking(register_mouse)?; // Register root role - let register_role = RegisterExpr::new(Role::new(role_id.clone()).add_permission( + let register_role = Register::role(Role::new(role_id.clone()).add_permission( PermissionToken::new( "CanSetKeyValueInUserAccount".parse()?, &json!({ "account_id": alice_id }), @@ -120,7 +120,7 @@ fn unregistered_role_removed_from_account() -> Result<()> { test_client.submit_blocking(register_role)?; // Grant root role to Mouse - let grant_role = GrantExpr::new(role_id.clone(), mouse_id.clone()); + let grant_role = Grant::role(role_id.clone(), mouse_id.clone()); test_client.submit_blocking(grant_role)?; // Check that Mouse has root role @@ -130,7 +130,7 @@ fn unregistered_role_removed_from_account() -> Result<()> { assert!(found_mouse_roles.contains(&role_id)); // Unregister root role - let unregister_role = UnregisterExpr::new(role_id.clone()); + let unregister_role = Unregister::role(role_id.clone()); test_client.submit_blocking(unregister_role)?; // Check that Mouse doesn't have the root role @@ -155,7 +155,7 @@ fn role_with_invalid_permissions_is_not_accepted() -> Result<()> { )); let err = test_client - .submit_blocking(RegisterExpr::new(role)) + .submit_blocking(Register::role(role)) .expect_err("Submitting role with invalid permission token should fail"); let rejection_reason = err diff --git a/client/tests/integration/set_parameter.rs b/client/tests/integration/set_parameter.rs index 1308c7ea141..08012429e01 100644 --- a/client/tests/integration/set_parameter.rs +++ b/client/tests/integration/set_parameter.rs @@ -14,7 +14,7 @@ fn can_change_parameter_value() -> Result<()> { let parameter = Parameter::from_str("?BlockTime=4000")?; let parameter_id = ParameterId::from_str("BlockTime")?; - let param_box = SetParameterExpr::new(parameter); + let param_box = SetParameter::new(parameter); let old_params = test_client .request(client::parameter::all())? @@ -46,13 +46,13 @@ fn parameter_propagated() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let too_long_domain_name: DomainId = "0".repeat(2_usize.pow(8)).parse()?; - let create_domain = RegisterExpr::new(Domain::new(too_long_domain_name)); + let create_domain = Register::domain(Domain::new(too_long_domain_name)); let _ = test_client .submit_blocking(create_domain.clone()) .expect_err("Should fail before ident length limits update"); let parameter = Parameter::from_str("?WSVIdentLengthLimits=1,256_LL")?; - let param_box = SetParameterExpr::new(parameter); + let param_box = SetParameter::new(parameter); test_client.submit_blocking(param_box)?; test_client diff --git a/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs b/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs index 5fa18856b48..bce2802adcb 100644 --- a/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs +++ b/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs @@ -43,8 +43,10 @@ fn main(_owner: AccountId, _event: Event) { let account_nft_id = AssetId::new(nft_id, account.id().clone()); let account_nft = Asset::new(account_nft_id, Metadata::new()); - RegisterExpr::new(nft_definition).execute().dbg_unwrap(); - RegisterExpr::new(account_nft).execute().dbg_unwrap(); + Register::asset_definition(nft_definition) + .execute() + .dbg_unwrap(); + Register::asset(account_nft).execute().dbg_unwrap(); } iroha_trigger::log::info!("Smart contract executed successfully"); diff --git a/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs index 1b3b6443ef8..8a950ee38cd 100644 --- a/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs @@ -6,23 +6,22 @@ #[cfg(not(test))] extern crate panic_halt; -use iroha_executor::{parse, prelude::*, smart_contract}; +use iroha_executor::{parse, prelude::*}; use lol_alloc::{FreeListAllocator, LockedAllocator}; #[global_allocator] static ALLOC: LockedAllocator = LockedAllocator::new(FreeListAllocator::new()); -#[derive(Constructor, ValidateEntrypoints, ExpressionEvaluator, Validate, Visit)] +#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] #[visit(custom(visit_instruction))] struct Executor { verdict: Result, block_height: u64, - host: smart_contract::Host, } -fn visit_instruction(executor: &mut Executor, authority: &AccountId, isi: &InstructionExpr) { +fn visit_instruction(executor: &mut Executor, authority: &AccountId, isi: &InstructionBox) { if parse!("admin@admin" as AccountId) == *authority { - pass!(executor); + execute!(executor, isi); } iroha_executor::default::visit_instruction(executor, authority, isi); diff --git a/client/tests/integration/smartcontracts/executor_with_custom_token/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_custom_token/src/lib.rs index f75d0e43fed..bd9322a7f87 100644 --- a/client/tests/integration/smartcontracts/executor_with_custom_token/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_custom_token/src/lib.rs @@ -20,7 +20,7 @@ use alloc::{borrow::ToOwned, string::String}; use anyhow::anyhow; use iroha_executor::{ - default::default_permission_token_schema, permission::Token as _, prelude::*, smart_contract, + default::default_permission_token_schema, permission::Token as _, prelude::*, }; use iroha_schema::IntoSchema; use lol_alloc::{FreeListAllocator, LockedAllocator}; @@ -54,12 +54,11 @@ mod token { pub struct CanControlDomainLives; } -#[derive(Constructor, ValidateEntrypoints, ExpressionEvaluator, Validate, Visit)] +#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] #[visit(custom(visit_register_domain, visit_unregister_domain))] struct Executor { verdict: Result, block_height: u64, - host: smart_contract::Host, } impl Executor { @@ -119,7 +118,7 @@ impl Executor { accounts .iter() .try_for_each(|(account, domain_id)| { - RevokeExpr::new( + Revoke::permission_token( PermissionToken::new( can_unregister_domain_definition_id.clone(), &json!({ "domain_id": domain_id }), @@ -138,7 +137,7 @@ impl Executor { ) })?; - GrantExpr::new( + Grant::permission_token( PermissionToken::new( can_control_domain_lives_definition_id.clone(), &json!(null), @@ -170,13 +169,12 @@ impl Executor { } } -// TODO (#4049): Fix unused `visit_register_domain()` -fn visit_register_domain(executor: &mut Executor, authority: &AccountId, _isi: Register) { +fn visit_register_domain(executor: &mut Executor, authority: &AccountId, isi: &Register) { if executor.block_height() == 0 { - pass!(executor) + execute!(executor, isi); } if token::CanControlDomainLives.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -188,13 +186,13 @@ fn visit_register_domain(executor: &mut Executor, authority: &AccountId, _isi: R fn visit_unregister_domain( executor: &mut Executor, authority: &AccountId, - _isi: Unregister, + isi: &Unregister, ) { if executor.block_height() == 0 { - pass!(executor); + execute!(executor, isi); } if token::CanControlDomainLives.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "You don't have permission to unregister domain"); diff --git a/client/tests/integration/smartcontracts/executor_with_migration_fail/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_migration_fail/src/lib.rs index 437e01b9bdd..e603758dd1d 100644 --- a/client/tests/integration/smartcontracts/executor_with_migration_fail/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_migration_fail/src/lib.rs @@ -9,17 +9,16 @@ extern crate panic_halt; use alloc::{borrow::ToOwned as _, format}; use anyhow::anyhow; -use iroha_executor::{parse, prelude::*, smart_contract}; +use iroha_executor::{parse, prelude::*}; use lol_alloc::{FreeListAllocator, LockedAllocator}; #[global_allocator] static ALLOC: LockedAllocator = LockedAllocator::new(FreeListAllocator::new()); -#[derive(Constructor, ValidateEntrypoints, ExpressionEvaluator, Validate, Visit)] +#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] struct Executor { verdict: Result, block_height: u64, - host: smart_contract::Host, } #[entrypoint] @@ -28,7 +27,7 @@ pub fn migrate(_block_height: u64) -> MigrationResult { // Registering a new domain (using ISI) let domain_id = parse!("failed_migration_test_domain" as DomainId); - RegisterExpr::new(Domain::new(domain_id)) + Register::domain(Domain::new(domain_id)) .execute() .map_err(|error| { format!( diff --git a/client/tests/integration/smartcontracts/mint_rose_trigger/src/lib.rs b/client/tests/integration/smartcontracts/mint_rose_trigger/src/lib.rs index 7dd2d5c7c0d..f794772bebd 100644 --- a/client/tests/integration/smartcontracts/mint_rose_trigger/src/lib.rs +++ b/client/tests/integration/smartcontracts/mint_rose_trigger/src/lib.rs @@ -20,7 +20,7 @@ fn main(owner: AccountId, _event: Event) { .dbg_expect("Failed to parse `rose#wonderland` asset definition id"); let rose_id = AssetId::new(rose_definition_id, owner); - MintExpr::new(1_u32, rose_id) + Mint::asset_quantity(1_u32, rose_id) .execute() .dbg_expect("Failed to mint rose"); } diff --git a/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs b/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs index c86e452e693..87137474596 100644 --- a/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs +++ b/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs @@ -26,12 +26,14 @@ fn main(owner: AccountId) { let (_batch, cursor) = asset_cursor.into_raw_parts(); - SetKeyValueExpr::new( + SetKeyValue::account( owner, parse!("cursor" as Name), - serde_json::to_value(cursor) - .dbg_expect("Failed to convert cursor to JSON") - .to_string(), + Value::String( + serde_json::to_value(cursor) + .dbg_expect("Failed to convert cursor to JSON") + .to_string(), + ), ) .execute() .dbg_expect("Failed to save cursor to the owner's metadata"); diff --git a/client/tests/integration/sorting.rs b/client/tests/integration/sorting.rs index 31b974d2b05..19f69f3b86e 100644 --- a/client/tests/integration/sorting.rs +++ b/client/tests/integration/sorting.rs @@ -14,6 +14,7 @@ use iroha_client::{ query::{Pagination, Sorting}, }, }; +use iroha_data_model::isi::InstructionBox; use test_network::*; #[test] @@ -46,8 +47,9 @@ fn correct_pagination_assets_after_creating_new_one() { assets.push(asset.clone()); - let create_asset_definition = RegisterExpr::new(asset_definition); - let create_asset = RegisterExpr::new(asset); + let create_asset_definition: InstructionBox = + Register::asset_definition(asset_definition).into(); + let create_asset = Register::asset(asset).into(); instructions.push(create_asset_definition); instructions.push(create_asset); @@ -94,8 +96,9 @@ fn correct_pagination_assets_after_creating_new_one() { AssetValue::Store(new_asset_metadata), ); - let create_asset_definition = RegisterExpr::new(new_asset_definition); - let create_asset = RegisterExpr::new(new_asset.clone()); + let create_asset_definition: InstructionBox = + Register::asset_definition(new_asset_definition).into(); + let create_asset = Register::asset(new_asset.clone()).into(); test_client .submit_all_blocking([create_asset_definition, create_asset]) @@ -153,7 +156,7 @@ fn correct_sorting_of_entities() { metadata_of_assets.push(asset_metadata); asset_definitions.push(asset_definition_id); - let create_asset_definition = RegisterExpr::new(asset_definition); + let create_asset_definition = Register::asset_definition(asset_definition); instructions.push(create_asset_definition); } @@ -203,7 +206,7 @@ fn correct_sorting_of_entities() { accounts.push(account_id); metadata_of_accounts.push(account_metadata); - let create_account = RegisterExpr::new(account); + let create_account = Register::account(account); instructions.push(create_account); } @@ -249,7 +252,7 @@ fn correct_sorting_of_entities() { domains.push(domain_id); metadata_of_domains.push(domain_metadata); - let create_account = RegisterExpr::new(domain); + let create_account = Register::domain(domain); instructions.push(create_account); } @@ -294,7 +297,7 @@ fn correct_sorting_of_entities() { domains.push(domain_id); metadata_of_domains.push(domain_metadata); - let create_account = RegisterExpr::new(domain); + let create_account = Register::domain(domain); instructions.push(create_account); } test_client @@ -356,7 +359,7 @@ fn sort_only_elements_which_have_sorting_key() -> Result<()> { account }; - let create_account = RegisterExpr::new(account); + let create_account = Register::account(account); instructions.push(create_account); } diff --git a/client/tests/integration/transfer_asset.rs b/client/tests/integration/transfer_asset.rs index b62ba7dc216..cbc23b190fa 100644 --- a/client/tests/integration/transfer_asset.rs +++ b/client/tests/integration/transfer_asset.rs @@ -3,17 +3,32 @@ use iroha_client::{ data_model::{prelude::*, Registered}, }; use iroha_crypto::KeyPair; +use iroha_data_model::isi::Instruction; use iroha_primitives::fixed::Fixed; use test_network::*; #[test] fn simulate_transfer_quantity() { - simulate_transfer(200_u32, &20_u32, AssetDefinition::quantity, 10_710) + simulate_transfer( + 200_u32, + &20_u32, + AssetDefinition::quantity, + Mint::asset_quantity, + Transfer::asset_quantity, + 10_710, + ) } #[test] fn simulate_transfer_big_quantity() { - simulate_transfer(200_u128, &20_u128, AssetDefinition::big_quantity, 10_785) + simulate_transfer( + 200_u128, + &20_u128, + AssetDefinition::big_quantity, + Mint::asset_big_quantity, + Transfer::asset_big_quantity, + 10_785, + ) } #[test] @@ -22,6 +37,8 @@ fn simulate_transfer_fixed() { Fixed::try_from(200_f64).expect("Valid"), &Fixed::try_from(20_f64).expect("Valid"), AssetDefinition::fixed, + Mint::asset_fixed, + Transfer::asset_fixed, 10_790, ) } @@ -34,22 +51,24 @@ fn simulate_insufficient_funds() { Fixed::try_from(20_f64).expect("Valid"), &Fixed::try_from(200_f64).expect("Valid"), AssetDefinition::fixed, + Mint::asset_fixed, + Transfer::asset_fixed, 10_800, ) } -// TODO add tests when the transfer uses the wrong AssetId. - -fn simulate_transfer< - T: Into + Clone, - D: FnOnce(AssetDefinitionId) -> ::With, ->( +fn simulate_transfer( starting_amount: T, amount_to_transfer: &T, - value_type: D, + asset_definition_ctr: impl FnOnce(AssetDefinitionId) -> ::With, + mint_ctr: impl FnOnce(T, AssetId) -> Mint, + transfer_ctr: impl FnOnce(AssetId, T, AccountId) -> Transfer, port_number: u16, ) where + T: std::fmt::Debug + Clone + Into, Value: From, + Mint: Instruction, + Transfer: Instruction, { let (_rt, _peer, iroha_client) = ::new() .with_port(port_number) @@ -61,15 +80,16 @@ fn simulate_transfer< let (bob_public_key, _) = KeyPair::generate() .expect("Failed to generate KeyPair") .into(); - let create_mouse = RegisterExpr::new(Account::new(mouse_id.clone(), [bob_public_key])); + let create_mouse = Register::account(Account::new(mouse_id.clone(), [bob_public_key])); let asset_definition_id: AssetDefinitionId = "camomile#wonderland".parse().expect("Valid"); - let create_asset = RegisterExpr::new(value_type(asset_definition_id.clone())); - let mint_asset = MintExpr::new( - starting_amount.to_value(), - IdBox::AssetId(AssetId::new(asset_definition_id.clone(), alice_id.clone())), + let create_asset = + Register::asset_definition(asset_definition_ctr(asset_definition_id.clone())); + let mint_asset = mint_ctr( + starting_amount, + AssetId::new(asset_definition_id.clone(), alice_id.clone()), ); - let instructions: [InstructionExpr; 3] = [ + let instructions: [InstructionBox; 3] = [ // create_alice.into(), We don't need to register Alice, because she is created in genesis create_mouse.into(), create_asset.into(), @@ -80,10 +100,10 @@ fn simulate_transfer< .expect("Failed to prepare state."); //When - let transfer_asset = TransferExpr::new( - IdBox::AssetId(AssetId::new(asset_definition_id.clone(), alice_id)), - amount_to_transfer.clone().to_value(), - IdBox::AccountId(mouse_id.clone()), + let transfer_asset = transfer_ctr( + AssetId::new(asset_definition_id.clone(), alice_id), + amount_to_transfer.clone(), + mouse_id.clone(), ); iroha_client .submit_till( diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index a2b03df24d7..41644169a73 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -9,6 +9,7 @@ use iroha_client::{ transaction::Executable, }, }; +use iroha_data_model::events::TriggeringFilterBox; use iroha_genesis::GenesisNetwork; use iroha_logger::info; use test_network::*; @@ -25,12 +26,12 @@ fn call_execute_trigger() -> Result<()> { let asset_id = AssetId::new(asset_definition_id, account_id); let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; - let instruction = MintExpr::new(1_u32, asset_id.clone()); + let instruction = Mint::asset_quantity(1_u32, asset_id.clone()); let register_trigger = build_register_trigger_isi(asset_id.clone(), vec![instruction.into()]); test_client.submit_blocking(register_trigger)?; let trigger_id = TriggerId::from_str(TRIGGER_NAME)?; - let call_trigger = ExecuteTriggerExpr::new(trigger_id); + let call_trigger = ExecuteTrigger::new(trigger_id); test_client.submit_blocking(call_trigger)?; let new_value = get_asset_value(&mut test_client, asset_id)?; @@ -48,12 +49,12 @@ fn execute_trigger_should_produce_event() -> Result<()> { let account_id: AccountId = "alice@wonderland".parse()?; let asset_id = AssetId::new(asset_definition_id, account_id.clone()); - let instruction = MintExpr::new(1_u32, asset_id.clone()); + let instruction = Mint::asset_quantity(1_u32, asset_id.clone()); let register_trigger = build_register_trigger_isi(asset_id, vec![instruction.into()]); test_client.submit_blocking(register_trigger)?; let trigger_id = TriggerId::from_str(TRIGGER_NAME)?; - let call_trigger = ExecuteTriggerExpr::new(trigger_id.clone()); + let call_trigger = ExecuteTrigger::new(trigger_id.clone()); let thread_client = test_client.clone(); let (sender, receiver) = mpsc::channel(); @@ -83,11 +84,11 @@ fn infinite_recursion_should_produce_one_call_per_block() -> Result<()> { let account_id = "alice@wonderland".parse()?; let asset_id = AssetId::new(asset_definition_id, account_id); let trigger_id = TriggerId::from_str(TRIGGER_NAME)?; - let call_trigger = ExecuteTriggerExpr::new(trigger_id); + let call_trigger = ExecuteTrigger::new(trigger_id); let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; let instructions = vec![ - MintExpr::new(1_u32, asset_id.clone()).into(), + Mint::asset_quantity(1_u32, asset_id.clone()).into(), call_trigger.clone().into(), ]; let register_trigger = build_register_trigger_isi(asset_id.clone(), instructions); @@ -113,8 +114,8 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { // Registering trigger that should fail on execution let bad_trigger_id = TriggerId::from_str("bad_trigger")?; // Invalid instruction - let bad_trigger_instructions = vec![MintExpr::new(1_u32, account_id.clone())]; - let register_bad_trigger = RegisterExpr::new(Trigger::new( + let bad_trigger_instructions = vec![Fail::new("Bad trigger".to_owned())]; + let register_bad_trigger = Register::trigger(Trigger::new( bad_trigger_id.clone(), Action::new( bad_trigger_instructions, @@ -130,8 +131,8 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { // Registering normal trigger let trigger_id = TriggerId::from_str(TRIGGER_NAME)?; - let trigger_instructions = vec![MintExpr::new(1_u32, asset_id.clone())]; - let register_trigger = RegisterExpr::new(Trigger::new( + let trigger_instructions = vec![Mint::asset_quantity(1_u32, asset_id.clone())]; + let register_trigger = Register::trigger(Trigger::new( trigger_id, Action::new( trigger_instructions, @@ -147,7 +148,7 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; // Executing bad trigger - test_client.submit_blocking(ExecuteTriggerExpr::new(bad_trigger_id))?; + test_client.submit_blocking(ExecuteTrigger::new(bad_trigger_id))?; // Checking results let new_asset_value = get_asset_value(&mut test_client, asset_id)?; @@ -165,8 +166,8 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let trigger_id = TriggerId::from_str("self_modifying_trigger")?; - let trigger_instructions = vec![MintExpr::new(1_u32, asset_id.clone())]; - let register_trigger = RegisterExpr::new(Trigger::new( + let trigger_instructions = vec![Mint::asset_quantity(1_u32, asset_id.clone())]; + let register_trigger = Register::trigger(Trigger::new( trigger_id.clone(), Action::new( trigger_instructions, @@ -184,7 +185,7 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; // Executing trigger first time - let execute_trigger = ExecuteTriggerExpr::new(trigger_id.clone()); + let execute_trigger = ExecuteTrigger::new(trigger_id.clone()); test_client.submit_blocking(execute_trigger.clone())?; // Executing trigger second time @@ -224,10 +225,10 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> { let trigger_id = TriggerId::from_str("self_modifying_trigger")?; let trigger_instructions = vec![ - MintExpr::new(1_u32, trigger_id.clone()), - MintExpr::new(1_u32, asset_id.clone()), + InstructionBox::from(Mint::trigger_repetitions(1_u32, trigger_id.clone())), + InstructionBox::from(Mint::asset_quantity(1_u32, asset_id.clone())), ]; - let register_trigger = RegisterExpr::new(Trigger::new( + let register_trigger = Register::trigger(Trigger::new( trigger_id.clone(), Action::new( trigger_instructions, @@ -245,7 +246,7 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> { let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; // Executing trigger first time - let execute_trigger = ExecuteTriggerExpr::new(trigger_id); + let execute_trigger = ExecuteTrigger::new(trigger_id); test_client.submit_blocking(execute_trigger.clone())?; // Executing trigger second time @@ -270,7 +271,7 @@ fn unregister_trigger() -> Result<()> { let trigger = Trigger::new( trigger_id.clone(), Action::new( - Vec::::new(), + Vec::::new(), Repeats::Indefinitely, account_id.clone(), TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( @@ -279,12 +280,12 @@ fn unregister_trigger() -> Result<()> { )), ), ); - let register_trigger = RegisterExpr::new(trigger.clone()); + let register_trigger = Register::trigger(trigger.clone()); test_client.submit_blocking(register_trigger)?; // Finding trigger let find_trigger = FindTriggerById { - id: trigger_id.clone().into(), + id: trigger_id.clone(), }; let found_trigger = test_client.request(find_trigger.clone())?; let found_action = found_trigger.action; @@ -303,7 +304,7 @@ fn unregister_trigger() -> Result<()> { assert_eq!(found_trigger, trigger); // Unregistering trigger - let unregister_trigger = UnregisterExpr::new(trigger_id); + let unregister_trigger = Unregister::trigger(trigger_id); test_client.submit_blocking(unregister_trigger)?; // Checking result @@ -362,7 +363,7 @@ fn trigger_in_genesis_using_base64() -> Result<()> { let tx_ref = &mut genesis.transactions[0].0; match &mut tx_ref.payload_mut().instructions { Executable::Instructions(instructions) => { - instructions.push(RegisterExpr::new(trigger).into()); + instructions.push(Register::trigger(trigger).into()); } Executable::Wasm(_) => panic!("Expected instructions"), } @@ -378,7 +379,7 @@ fn trigger_in_genesis_using_base64() -> Result<()> { let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; // Executing trigger - let call_trigger = ExecuteTriggerExpr::new(trigger_id); + let call_trigger = ExecuteTrigger::new(trigger_id); test_client.submit_blocking(call_trigger)?; // Checking result @@ -397,12 +398,11 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { let account_id = AccountId::from_str("alice@wonderland")?; let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let trigger_id_unregister = TriggerId::from_str("unregister_other_trigger")?; - let trigger_id_should_be_unregistered = TriggerId::from_str("should_be_unregistered_trigger")?; + let trigger_id_to_be_unregistered = TriggerId::from_str("should_be_unregistered_trigger")?; - let trigger_unregister_instructions = vec![UnregisterExpr::new( - trigger_id_should_be_unregistered.clone(), - )]; - let register_trigger = RegisterExpr::new(Trigger::new( + let trigger_unregister_instructions = + vec![Unregister::trigger(trigger_id_to_be_unregistered.clone())]; + let register_trigger = Register::trigger(Trigger::new( trigger_id_unregister.clone(), Action::new( trigger_unregister_instructions, @@ -416,15 +416,16 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { )); test_client.submit_blocking(register_trigger)?; - let trigger_should_be_unregistered_instructions = vec![MintExpr::new(1_u32, asset_id.clone())]; - let register_trigger = RegisterExpr::new(Trigger::new( - trigger_id_should_be_unregistered.clone(), + let trigger_should_be_unregistered_instructions = + vec![Mint::asset_quantity(1_u32, asset_id.clone())]; + let register_trigger = Register::trigger(Trigger::new( + trigger_id_to_be_unregistered.clone(), Action::new( trigger_should_be_unregistered_instructions, Repeats::from(1_u32), account_id.clone(), TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id_should_be_unregistered.clone(), + trigger_id_to_be_unregistered.clone(), account_id, )), ), @@ -435,9 +436,8 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; // Executing triggers - let execute_trigger_unregister = ExecuteTriggerExpr::new(trigger_id_unregister); - let execute_trigger_should_be_unregistered = - ExecuteTriggerExpr::new(trigger_id_should_be_unregistered); + let execute_trigger_unregister = ExecuteTrigger::new(trigger_id_unregister); + let execute_trigger_should_be_unregistered = ExecuteTrigger::new(trigger_id_to_be_unregistered); test_client.submit_all_blocking([ execute_trigger_unregister, execute_trigger_should_be_unregistered, @@ -461,8 +461,8 @@ fn trigger_burn_repetitions() -> Result<()> { let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let trigger_id = TriggerId::from_str("trigger")?; - let trigger_instructions = vec![MintExpr::new(1_u32, asset_id)]; - let register_trigger = RegisterExpr::new(Trigger::new( + let trigger_instructions = vec![Mint::asset_quantity(1_u32, asset_id)]; + let register_trigger = Register::trigger(Trigger::new( trigger_id.clone(), Action::new( trigger_instructions, @@ -476,10 +476,10 @@ fn trigger_burn_repetitions() -> Result<()> { )); test_client.submit_blocking(register_trigger)?; - test_client.submit_blocking(BurnExpr::new(1_u32, trigger_id.clone()))?; + test_client.submit_blocking(Burn::trigger_repetitions(1_u32, trigger_id.clone()))?; // Executing trigger - let execute_trigger = ExecuteTriggerExpr::new(trigger_id); + let execute_trigger = ExecuteTrigger::new(trigger_id); let _err = test_client .submit_blocking(execute_trigger) .expect_err("Should fail without repetitions"); @@ -494,11 +494,11 @@ fn get_asset_value(client: &mut Client, asset_id: AssetId) -> Result { fn build_register_trigger_isi( asset_id: AssetId, - trigger_instructions: Vec, -) -> RegisterExpr { + trigger_instructions: Vec, +) -> Register> { let trigger_id: TriggerId = TRIGGER_NAME.parse().expect("Valid"); - RegisterExpr::new(Trigger::new( + Register::trigger(Trigger::new( trigger_id.clone(), Action::new( trigger_instructions, diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index 46744151559..e7096f7b024 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -13,8 +13,8 @@ fn must_execute_both_triggers() -> Result<()> { let prev_value = get_asset_value(&test_client, asset_id.clone())?; - let instruction = MintExpr::new(1_u32, asset_id.clone()); - let register_trigger = RegisterExpr::new(Trigger::new( + let instruction = Mint::asset_quantity(1_u32, asset_id.clone()); + let register_trigger = Register::trigger(Trigger::new( "mint_rose_1".parse()?, Action::new( [instruction.clone()], @@ -27,7 +27,7 @@ fn must_execute_both_triggers() -> Result<()> { )); test_client.submit_blocking(register_trigger)?; - let register_trigger = RegisterExpr::new(Trigger::new( + let register_trigger = Register::trigger(Trigger::new( "mint_rose_2".parse()?, Action::new( [instruction], @@ -40,11 +40,11 @@ fn must_execute_both_triggers() -> Result<()> { )); test_client.submit_blocking(register_trigger)?; - test_client.submit_blocking(RegisterExpr::new(Account::new( + test_client.submit_blocking(Register::account(Account::new( "bunny@wonderland".parse()?, [], )))?; - test_client.submit_blocking(RegisterExpr::new(Domain::new("neverland".parse()?)))?; + test_client.submit_blocking(Register::domain(Domain::new("neverland".parse()?)))?; let new_value = get_asset_value(&test_client, asset_id)?; assert_eq!(new_value, prev_value + 2); @@ -57,18 +57,19 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu let (_rt, _peer, test_client) = ::new().with_port(10_655).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); - let create_neverland_domain = RegisterExpr::new(Domain::new("neverland".parse()?)); + let create_neverland_domain: InstructionBox = + Register::domain(Domain::new("neverland".parse()?)).into(); let account_id: AccountId = "sapporo@neverland".parse()?; - let create_sapporo_account = RegisterExpr::new(Account::new(account_id.clone(), [])); + let create_sapporo_account = Register::account(Account::new(account_id.clone(), [])).into(); let asset_definition_id: AssetDefinitionId = "sakura#neverland".parse()?; let create_sakura_asset_definition = - RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())).into(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let create_sakura_asset = - RegisterExpr::new(Asset::new(asset_id.clone(), AssetValue::Quantity(0))); + Register::asset(Asset::new(asset_id.clone(), AssetValue::Quantity(0))).into(); test_client.submit_all_blocking([ create_neverland_domain, @@ -79,10 +80,10 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu let prev_value = get_asset_value(&test_client, asset_id.clone())?; - let register_trigger = RegisterExpr::new(Trigger::new( + let register_trigger = Register::trigger(Trigger::new( "mint_sakura$neverland".parse()?, Action::new( - [MintExpr::new(1_u32, asset_id.clone())], + [Mint::asset_quantity(1_u32, asset_id.clone())], Repeats::Indefinitely, account_id, TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAccount(BySome( @@ -92,12 +93,12 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu )); test_client.submit_blocking(register_trigger)?; - test_client.submit_blocking(RegisterExpr::new(Account::new( + test_client.submit_blocking(Register::account(Account::new( "asahi@wonderland".parse()?, [], )))?; - test_client.submit_blocking(RegisterExpr::new(Account::new( + test_client.submit_blocking(Register::account(Account::new( "asahi@neverland".parse()?, [], )))?; diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index 8b438d47fb9..8269a244ad4 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -17,8 +17,8 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; - let instruction = MintExpr::new(1_u32, asset_id.clone()); - let register_trigger = RegisterExpr::new(Trigger::new( + let instruction = Mint::asset_quantity(1_u32, asset_id.clone()); + let register_trigger = Register::trigger(Trigger::new( "mint_rose".parse()?, Action::new( vec![instruction], @@ -35,7 +35,8 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { test_client.submit(register_trigger)?; let tea_definition_id = "tea#wonderland".parse()?; - let register_tea_definition = RegisterExpr::new(AssetDefinition::quantity(tea_definition_id)); + let register_tea_definition = + Register::asset_definition(AssetDefinition::quantity(tea_definition_id)); test_client.submit_blocking(register_tea_definition)?; let new_value = get_asset_value(&mut test_client, asset_id)?; diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index 2a150f336c4..9b9c76d3fe6 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -44,8 +44,8 @@ fn time_trigger_execution_count_error_should_be_less_than_15_percent() -> Result let schedule = TimeSchedule::starting_at(start_time).with_period(Duration::from_millis(PERIOD_MS)); - let instruction = MintExpr::new(1_u32, asset_id.clone()); - let register_trigger = RegisterExpr::new(Trigger::new( + let instruction = Mint::asset_quantity(1_u32, asset_id.clone()); + let register_trigger = Register::trigger(Trigger::new( "mint_rose".parse()?, Action::new( vec![instruction], @@ -98,8 +98,8 @@ fn change_asset_metadata_after_1_sec() -> Result<()> { let schedule = TimeSchedule::starting_at(start_time + Duration::from_millis(PERIOD_MS)); let instruction = - SetKeyValueExpr::new(asset_definition_id.clone(), key.clone(), 3_u32.to_value()); - let register_trigger = RegisterExpr::new(Trigger::new( + SetKeyValue::asset_definition(asset_definition_id.clone(), key.clone(), 3_u32.to_value()); + let register_trigger = Register::trigger(Trigger::new( "change_rose_metadata".parse().expect("Valid"), Action::new( vec![instruction], @@ -119,8 +119,8 @@ fn change_asset_metadata_after_1_sec() -> Result<()> { let value = test_client .request(FindAssetDefinitionKeyValueByIdAndKey { - id: asset_definition_id.into(), - key: key.into(), + id: asset_definition_id, + key, })? .into(); assert!(matches!(value, Value::Numeric(NumericValue::U32(3_u32)))); @@ -144,8 +144,8 @@ fn pre_commit_trigger_should_be_executed() -> Result<()> { // Start listening BEFORE submitting any transaction not to miss any block committed event let event_listener = get_block_committed_event_listener(&test_client)?; - let instruction = MintExpr::new(1_u32, asset_id.clone()); - let register_trigger = RegisterExpr::new(Trigger::new( + let instruction = Mint::asset_quantity(1_u32, asset_id.clone()); + let register_trigger = Register::trigger(Trigger::new( "mint_rose".parse()?, Action::new( vec![instruction], @@ -162,7 +162,7 @@ fn pre_commit_trigger_should_be_executed() -> Result<()> { prev_value = new_value; // ISI just to create a new block - let sample_isi = SetKeyValueExpr::new( + let sample_isi = SetKeyValue::account( account_id.clone(), "key".parse::()?, String::from("value"), @@ -196,7 +196,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { .iter() .skip(1) // Alice has already been registered in genesis .cloned() - .map(|account_id| RegisterExpr::new(Account::new(account_id, []))) + .map(|account_id| Register::account(Account::new(account_id, []))) .collect::>(); test_client.submit_all_blocking(register_accounts)?; @@ -220,7 +220,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { let start_time = current_time(); let schedule = TimeSchedule::starting_at(start_time).with_period(Duration::from_millis(TRIGGER_PERIOD_MS)); - let register_trigger = RegisterExpr::new(Trigger::new( + let register_trigger = Register::trigger(Trigger::new( "mint_nft_for_all".parse()?, Action::new( WasmSmartContract::from_compiled(wasm), @@ -295,7 +295,7 @@ fn submit_sample_isi_on_every_block_commit( for _ in block_committed_event_listener.take(times) { std::thread::sleep(timeout); // ISI just to create a new block - let sample_isi = SetKeyValueExpr::new( + let sample_isi = SetKeyValue::account( account_id.clone(), "key".parse::()?, String::from("value"), diff --git a/client/tests/integration/triggers/trigger_rollback.rs b/client/tests/integration/triggers/trigger_rollback.rs index 67861a9f7b2..182045a2c7e 100644 --- a/client/tests/integration/triggers/trigger_rollback.rs +++ b/client/tests/integration/triggers/trigger_rollback.rs @@ -14,9 +14,13 @@ fn failed_trigger_revert() -> Result<()> { let trigger_id = TriggerId::from_str("trigger")?; let account_id = AccountId::from_str("alice@wonderland")?; let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland")?; - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); - let instructions: [InstructionExpr; 2] = [create_asset.into(), Fail::new("Always fail").into()]; - let register_trigger = RegisterExpr::new(Trigger::new( + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); + let instructions: [InstructionBox; 2] = [ + create_asset.into(), + Fail::new("Always fail".to_owned()).into(), + ]; + let register_trigger = Register::trigger(Trigger::new( trigger_id.clone(), Action::new( instructions, @@ -30,7 +34,7 @@ fn failed_trigger_revert() -> Result<()> { )); let _ = client.submit_blocking(register_trigger); - let call_trigger = ExecuteTriggerExpr::new(trigger_id); + let call_trigger = ExecuteTrigger::new(trigger_id); client.submit_blocking(call_trigger)?; //Then diff --git a/client/tests/integration/tx_history.rs b/client/tests/integration/tx_history.rs index 15c2ef3c3e1..8cbf9a3f5cc 100644 --- a/client/tests/integration/tx_history.rs +++ b/client/tests/integration/tx_history.rs @@ -24,19 +24,20 @@ fn client_has_rejected_and_acepted_txs_should_return_tx_history() -> Result<()> // Given let account_id = AccountId::from_str("alice@wonderland")?; let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland")?; - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); client.submit_blocking(create_asset)?; //When let quantity: u32 = 200; let asset_id = AssetId::new(asset_definition_id, account_id.clone()); - let mint_existed_asset = MintExpr::new(quantity.to_value(), IdBox::AssetId(asset_id)); - let mint_not_existed_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( + let mint_existed_asset = Mint::asset_quantity(quantity, asset_id); + let mint_not_existed_asset = Mint::asset_quantity( + quantity, + AssetId::new( AssetDefinitionId::from_str("foo#wonderland")?, account_id.clone(), - )), + ), ); let transactions_count = 100; @@ -47,7 +48,7 @@ fn client_has_rejected_and_acepted_txs_should_return_tx_history() -> Result<()> } else { &mint_not_existed_asset }; - let instructions: Vec = vec![mint_asset.clone().into()]; + let instructions: Vec = vec![mint_asset.clone().into()]; let transaction = client.build_transaction(instructions, UnlimitedMetadata::new())?; client.submit_transaction(&transaction)?; } diff --git a/client/tests/integration/tx_rollback.rs b/client/tests/integration/tx_rollback.rs index a8b1b918dc9..0c04bbec3a8 100644 --- a/client/tests/integration/tx_rollback.rs +++ b/client/tests/integration/tx_rollback.rs @@ -16,16 +16,13 @@ fn client_sends_transaction_with_invalid_instruction_should_not_see_any_changes( let account_id = AccountId::from_str("alice@wonderland")?; let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland")?; let wrong_asset_definition_id = AssetDefinitionId::from_str("ksor#wonderland")?; - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id)); + let create_asset = Register::asset_definition(AssetDefinition::quantity(asset_definition_id)); let quantity: u32 = 200; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - wrong_asset_definition_id.clone(), - account_id.clone(), - )), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(wrong_asset_definition_id.clone(), account_id.clone()), ); - let instructions: [InstructionExpr; 2] = [create_asset.into(), mint_asset.into()]; + let instructions: [InstructionBox; 2] = [create_asset.into(), mint_asset.into()]; let _ = client.submit_all_blocking(instructions); //Then diff --git a/client/tests/integration/unregister_peer.rs b/client/tests/integration/unregister_peer.rs index 845f938de16..84a2e4fa5b3 100644 --- a/client/tests/integration/unregister_peer.rs +++ b/client/tests/integration/unregister_peer.rs @@ -34,7 +34,7 @@ fn unstable_network_stable_after_add_and_after_remove_peer() -> Result<()> { // Then the new peer should already have the mint result. check_assets(&peer_client, &account_id, &asset_definition_id, 100); // Also, when a peer is unregistered - let remove_peer = UnregisterExpr::new(IdBox::PeerId(peer.id.clone())); + let remove_peer = Unregister::peer(peer.id.clone()); genesis_client.submit(remove_peer)?; thread::sleep(pipeline_time * 2); // We can mint without error. @@ -82,12 +82,9 @@ fn mint( pipeline_time: std::time::Duration, quantity: u32, ) -> Result { - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); client.submit(mint_asset)?; thread::sleep(pipeline_time * 5); @@ -109,18 +106,21 @@ fn init() -> Result<( let parameters = ParametersBuilder::new() .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? .into_set_parameters(); - let create_domain = RegisterExpr::new(Domain::new("domain".parse()?)); + let create_domain = Register::domain(Domain::new("domain".parse()?)); let account_id: AccountId = "account@domain".parse()?; let (public_key, _) = KeyPair::generate()?.into(); - let create_account = RegisterExpr::new(Account::new(account_id.clone(), [public_key])); + let create_account = Register::account(Account::new(account_id.clone(), [public_key])); let asset_definition_id: AssetDefinitionId = "xor#domain".parse()?; - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); - let instructions: [InstructionExpr; 4] = [ - parameters.into(), - create_domain.into(), - create_account.into(), - create_asset.into(), - ]; + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); + let instructions = parameters.into_iter().chain( + [ + create_domain.into(), + create_account.into(), + create_asset.into(), + ] + .into_iter(), + ); client.submit_all_blocking(instructions)?; iroha_logger::info!("Init"); Ok(( diff --git a/client/tests/integration/unstable_network.rs b/client/tests/integration/unstable_network.rs index da962f4728d..d0cd9ce186b 100644 --- a/client/tests/integration/unstable_network.rs +++ b/client/tests/integration/unstable_network.rs @@ -77,7 +77,8 @@ fn unstable_network( let account_id: AccountId = "alice@wonderland".parse().expect("Valid"); let asset_definition_id: AssetDefinitionId = "camomile#wonderland".parse().expect("Valid"); - let register_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + let register_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); iroha_client .submit_blocking(register_asset) .expect("Failed to register asset"); @@ -99,12 +100,9 @@ fn unstable_network( } let quantity = 1; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new( - asset_definition_id.clone(), - account_id.clone(), - )), + let mint_asset = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id.clone(), account_id.clone()), ); iroha_client .submit(mint_asset) diff --git a/client/tests/integration/upgrade.rs b/client/tests/integration/upgrade.rs index 5c1de0736c4..cfa822046c2 100644 --- a/client/tests/integration/upgrade.rs +++ b/client/tests/integration/upgrade.rs @@ -17,19 +17,19 @@ fn executor_upgrade_should_work() -> Result<()> { // Register `admin` domain and account let admin_domain = Domain::new("admin".parse()?); - let register_admin_domain = RegisterExpr::new(admin_domain); + let register_admin_domain = Register::domain(admin_domain); client.submit_blocking(register_admin_domain)?; let admin_id: AccountId = "admin@admin".parse()?; let admin_keypair = KeyPair::generate()?; let admin_account = Account::new(admin_id.clone(), [admin_keypair.public_key().clone()]); - let register_admin_account = RegisterExpr::new(admin_account); + let register_admin_account = Register::account(admin_account); client.submit_blocking(register_admin_account)?; // Check that admin isn't allowed to transfer alice's rose by default let alice_rose: AssetId = "rose##alice@wonderland".parse()?; let admin_rose: AccountId = "admin@admin".parse()?; - let transfer_alice_rose = TransferExpr::new(alice_rose, NumericValue::U32(1), admin_rose); + let transfer_alice_rose = Transfer::asset_quantity(alice_rose, 1_u32, admin_rose); let transfer_rose_tx = TransactionBuilder::new(admin_id.clone()) .with_instructions([transfer_alice_rose.clone()]) .sign(admin_keypair.clone())?; @@ -152,7 +152,7 @@ fn upgrade_executor(client: &Client, executor: impl AsRef) -> Result<()> { info!("WASM size is {} bytes", wasm.len()); - let upgrade_executor = UpgradeExpr::new(Executor::new(WasmSmartContract::from_compiled(wasm))); + let upgrade_executor = Upgrade::new(Executor::new(WasmSmartContract::from_compiled(wasm))); client.submit_blocking(upgrade_executor)?; Ok(()) diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index c16c633fd56..8aca7cef98c 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -391,7 +391,7 @@ mod domain { id, metadata: Metadata(metadata), } = self; - let create_domain = RegisterExpr::new(Domain::new(id)); + let create_domain = iroha_client::data_model::isi::Register::domain(Domain::new(id)); submit([create_domain], metadata, context).wrap_err("Failed to create domain") } } @@ -449,7 +449,7 @@ mod domain { to, metadata: Metadata(metadata), } = self; - let transfer_domain = TransferExpr::new(from, id, to); + let transfer_domain = iroha_client::data_model::isi::Transfer::domain(from, id, to); submit([transfer_domain], metadata, context).wrap_err("Failed to transfer domain") } } @@ -512,7 +512,8 @@ mod account { key, metadata: Metadata(metadata), } = self; - let create_account = RegisterExpr::new(Account::new(id, [key])); + let create_account = + iroha_client::data_model::isi::Register::account(Account::new(id, [key])); submit([create_account], metadata, context).wrap_err("Failed to register account") } } @@ -558,12 +559,12 @@ mod account { impl RunArgs for SignatureCondition { fn run(self, context: &mut dyn RunContext) -> Result<()> { - let account = Account::new(context.configuration().account_id.clone(), []); + let account_id = context.configuration().account_id.clone(); let Self { condition: Signature(condition), metadata: Metadata(metadata), } = self; - let mint_box = MintExpr::new(account, EvaluatesTo::new_unchecked(condition)); + let mint_box = Mint::account_signature_check_condition(condition, account_id); submit([mint_box], metadata, context).wrap_err("Failed to set signature condition") } } @@ -634,7 +635,7 @@ mod account { permission, metadata: Metadata(metadata), } = self; - let grant = GrantExpr::new(permission.0, id); + let grant = iroha_client::data_model::isi::Grant::permission_token(permission.0, id); submit([grant], metadata, context) .wrap_err("Failed to grant the permission to the account") } @@ -727,7 +728,8 @@ mod asset { if unmintable { asset_definition = asset_definition.mintable_once(); } - let create_asset_definition = RegisterExpr::new(asset_definition); + let create_asset_definition = + iroha_client::data_model::isi::Register::asset_definition(asset_definition); submit([create_asset_definition], metadata, context) .wrap_err("Failed to register asset") } @@ -758,9 +760,9 @@ mod asset { quantity, metadata: Metadata(metadata), } = self; - let mint_asset = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new(asset, account)), + let mint_asset = iroha_client::data_model::isi::Mint::asset_quantity( + quantity, + AssetId::new(asset, account), ); submit([mint_asset], metadata, context) .wrap_err("Failed to mint asset of type `NumericValue::U32`") @@ -792,9 +794,9 @@ mod asset { quantity, metadata: Metadata(metadata), } = self; - let burn_asset = BurnExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new(asset, account)), + let burn_asset = iroha_client::data_model::isi::Burn::asset_quantity( + quantity, + AssetId::new(asset, account), ); submit([burn_asset], metadata, context) .wrap_err("Failed to burn asset of type `NumericValue::U32`") @@ -830,10 +832,10 @@ mod asset { quantity, metadata: Metadata(metadata), } = self; - let transfer_asset = TransferExpr::new( - IdBox::AssetId(AssetId::new(asset_id, from)), - quantity.to_value(), - IdBox::AccountId(to), + let transfer_asset = iroha_client::data_model::isi::Transfer::asset_quantity( + AssetId::new(asset_id, from), + quantity, + to, ); submit([transfer_asset], metadata, context).wrap_err("Failed to transfer asset") } @@ -934,7 +936,9 @@ mod peer { key, metadata: Metadata(metadata), } = self; - let register_peer = RegisterExpr::new(Peer::new(PeerId::new(&address, &key))); + let register_peer = iroha_client::data_model::isi::Register::peer(Peer::new( + PeerId::new(&address, &key), + )); submit([register_peer], metadata, context).wrap_err("Failed to register peer") } } @@ -960,7 +964,8 @@ mod peer { key, metadata: Metadata(metadata), } = self; - let unregister_peer = UnregisterExpr::new(IdBox::PeerId(PeerId::new(&address, &key))); + let unregister_peer = + iroha_client::data_model::isi::Unregister::peer(PeerId::new(&address, &key)); submit([unregister_peer], metadata, context).wrap_err("Failed to unregister peer") } } @@ -1017,7 +1022,7 @@ mod json { reader.read_to_end(&mut raw_content)?; let string_content = String::from_utf8(raw_content)?; - let instructions: Vec = json5::from_str(&string_content)?; + let instructions: Vec = json5::from_str(&string_content)?; submit(instructions, UnlimitedMetadata::new(), context) .wrap_err("Failed to submit parsed instructions") } diff --git a/configs/peer/executor.wasm b/configs/peer/executor.wasm index 2ef54f969b6..48c0f25b41c 100644 Binary files a/configs/peer/executor.wasm and b/configs/peer/executor.wasm differ diff --git a/configs/peer/genesis.json b/configs/peer/genesis.json index 2ca5d0365ed..a915d22f4f8 100644 --- a/configs/peer/genesis.json +++ b/configs/peer/genesis.json @@ -3,7 +3,7 @@ [ { "Register": { - "NewDomain": { + "Domain": { "id": "wonderland", "logo": null, "metadata": { @@ -16,7 +16,7 @@ }, { "Register": { - "NewAccount": { + "Account": { "id": "alice@wonderland", "signatories": [ "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" @@ -31,7 +31,7 @@ }, { "Register": { - "NewAccount": { + "Account": { "id": "bob@wonderland", "signatories": [ "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" @@ -46,7 +46,7 @@ }, { "Register": { - "NewAssetDefinition": { + "AssetDefinition": { "id": "rose#wonderland", "value_type": "Quantity", "mintable": "Infinitely", @@ -57,7 +57,7 @@ }, { "Register": { - "NewDomain": { + "Domain": { "id": "garden_of_live_flowers", "logo": null, "metadata": {} @@ -66,7 +66,7 @@ }, { "Register": { - "NewAccount": { + "Account": { "id": "carpenter@garden_of_live_flowers", "signatories": [ "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" @@ -77,7 +77,7 @@ }, { "Register": { - "NewAssetDefinition": { + "AssetDefinition": { "id": "cabbage#garden_of_live_flowers", "value_type": "Quantity", "mintable": "Infinitely", @@ -88,95 +88,71 @@ }, { "Mint": { - "object": "13_u32", - "destination_id": { - "AssetId": "rose##alice@wonderland" + "Asset": { + "Quantity": { + "object": 13, + "destination_id": "rose##alice@wonderland" + } } } }, { "Mint": { - "object": "44_u32", - "destination_id": { - "AssetId": "cabbage#garden_of_live_flowers#alice@wonderland" + "Asset": { + "Quantity": { + "object": 44, + "destination_id": "cabbage#garden_of_live_flowers#alice@wonderland" + } } } }, { "Grant": { - "object": { - "PermissionToken": { + "PermissionToken": { + "object": { "definition_id": "CanSetParameters", "payload": null - } - }, - "destination_id": { - "AccountId": "alice@wonderland" + }, + "destination_id": "alice@wonderland" } } }, { - "Sequence": [ - { - "NewParameter": { - "Parameter": "?MaxTransactionsInBlock=512" - } - }, - { - "NewParameter": { - "Parameter": "?BlockTime=2000" - } - }, - { - "NewParameter": { - "Parameter": "?CommitTimeLimit=4000" - } - }, - { - "NewParameter": { - "Parameter": "?TransactionLimits=4096,4194304_TL" - } - }, - { - "NewParameter": { - "Parameter": "?WSVAssetMetadataLimits=1048576,4096_ML" - } - }, - { - "NewParameter": { - "Parameter": "?WSVAssetDefinitionMetadataLimits=1048576,4096_ML" - } - }, - { - "NewParameter": { - "Parameter": "?WSVAccountMetadataLimits=1048576,4096_ML" - } - }, - { - "NewParameter": { - "Parameter": "?WSVDomainMetadataLimits=1048576,4096_ML" - } - }, - { - "NewParameter": { - "Parameter": "?WSVIdentLengthLimits=1,128_LL" - } - }, - { - "NewParameter": { - "Parameter": "?WASMFuelLimit=23000000" - } - }, - { - "NewParameter": { - "Parameter": "?WASMMaxMemory=524288000" - } - } - ] + "NewParameter": "?MaxTransactionsInBlock=512" + }, + { + "NewParameter": "?BlockTime=2000" + }, + { + "NewParameter": "?CommitTimeLimit=4000" + }, + { + "NewParameter": "?TransactionLimits=4096,4194304_TL" + }, + { + "NewParameter": "?WSVAssetMetadataLimits=1048576,4096_ML" + }, + { + "NewParameter": "?WSVAssetDefinitionMetadataLimits=1048576,4096_ML" + }, + { + "NewParameter": "?WSVAccountMetadataLimits=1048576,4096_ML" + }, + { + "NewParameter": "?WSVDomainMetadataLimits=1048576,4096_ML" + }, + { + "NewParameter": "?WSVIdentLengthLimits=1,128_LL" + }, + { + "NewParameter": "?WASMFuelLimit=23000000" + }, + { + "NewParameter": "?WASMMaxMemory=524288000" }, { "Register": { - "NewRole": { + "Role": { "id": "ALICE_METADATA_ACCESS", "permissions": [ { diff --git a/core/benches/blocks/common.rs b/core/benches/blocks/common.rs index f4f412eb633..7aef12edd2d 100644 --- a/core/benches/blocks/common.rs +++ b/core/benches/blocks/common.rs @@ -12,7 +12,7 @@ use iroha_data_model::{ account::Account, asset::{AssetDefinition, AssetDefinitionId}, domain::Domain, - isi::InstructionExpr, + isi::InstructionBox, prelude::*, transaction::TransactionLimits, }; @@ -22,7 +22,7 @@ use serde_json::json; /// Create block pub fn create_block( wsv: &mut WorldStateView, - instructions: Vec, + instructions: Vec, account_id: AccountId, key_pair: KeyPair, ) -> CommittedBlock { @@ -57,13 +57,13 @@ pub fn populate_wsv( accounts_per_domain: usize, assets_per_domain: usize, owner_id: &AccountId, -) -> Vec { - let mut instructions: Vec = Vec::new(); +) -> Vec { + let mut instructions: Vec = Vec::new(); for i in 0..domains { let domain_id = construct_domain_id(i); let domain = Domain::new(domain_id.clone()); - instructions.push(RegisterExpr::new(domain).into()); - let can_unregister_domain = GrantExpr::new( + instructions.push(Register::domain(domain).into()); + let can_unregister_domain = Grant::permission_token( PermissionToken::new( "CanUnregisterDomain".parse().unwrap(), &json!({ "domain_id": domain_id.clone() }), @@ -74,8 +74,8 @@ pub fn populate_wsv( for j in 0..accounts_per_domain { let account_id = construct_account_id(j, domain_id.clone()); let account = Account::new(account_id.clone(), []); - instructions.push(RegisterExpr::new(account).into()); - let can_unregister_account = GrantExpr::new( + instructions.push(Register::account(account).into()); + let can_unregister_account = Grant::permission_token( PermissionToken::new( "CanUnregisterAccount".parse().unwrap(), &json!({ "account_id": account_id.clone() }), @@ -90,8 +90,8 @@ pub fn populate_wsv( asset_definition_id.clone(), iroha_data_model::asset::AssetValueType::Quantity, ); - instructions.push(RegisterExpr::new(asset_definition).into()); - let can_unregister_asset_definition = GrantExpr::new( + instructions.push(Register::asset_definition(asset_definition).into()); + let can_unregister_asset_definition = Grant::permission_token( PermissionToken::new( "CanUnregisterAssetDefinition".parse().unwrap(), &json!({ "asset_definition_id": asset_definition_id }), @@ -109,23 +109,23 @@ pub fn delete_every_nth( accounts_per_domain: usize, assets_per_domain: usize, nth: usize, -) -> Vec { - let mut instructions: Vec = Vec::new(); +) -> Vec { + let mut instructions: Vec = Vec::new(); for i in 0..domains { let domain_id = construct_domain_id(i); if i % nth == 0 { - instructions.push(UnregisterExpr::new(domain_id.clone()).into()); + instructions.push(Unregister::domain(domain_id.clone()).into()); } else { for j in 0..accounts_per_domain { if j % nth == 0 { let account_id = construct_account_id(j, domain_id.clone()); - instructions.push(UnregisterExpr::new(account_id.clone()).into()); + instructions.push(Unregister::account(account_id.clone()).into()); } } for k in 0..assets_per_domain { if k % nth == 0 { let asset_definition_id = construct_asset_definition_id(k, domain_id.clone()); - instructions.push(UnregisterExpr::new(asset_definition_id).into()); + instructions.push(Unregister::asset_definition(asset_definition_id).into()); } } } @@ -138,19 +138,19 @@ pub fn restore_every_nth( accounts_per_domain: usize, assets_per_domain: usize, nth: usize, -) -> Vec { - let mut instructions: Vec = Vec::new(); +) -> Vec { + let mut instructions: Vec = Vec::new(); for i in 0..domains { let domain_id = construct_domain_id(i); if i % nth == 0 { let domain = Domain::new(domain_id.clone()); - instructions.push(RegisterExpr::new(domain).into()); + instructions.push(Register::domain(domain).into()); } for j in 0..accounts_per_domain { if j % nth == 0 || i % nth == 0 { let account_id = construct_account_id(j, domain_id.clone()); let account = Account::new(account_id.clone(), []); - instructions.push(RegisterExpr::new(account).into()); + instructions.push(Register::account(account).into()); } } for k in 0..assets_per_domain { @@ -160,7 +160,7 @@ pub fn restore_every_nth( asset_definition_id, iroha_data_model::asset::AssetValueType::Quantity, ); - instructions.push(RegisterExpr::new(asset_definition).into()); + instructions.push(Register::asset_definition(asset_definition).into()); } } } @@ -186,7 +186,7 @@ pub fn build_wsv(account_id: &AccountId, key_pair: &KeyPair) -> WorldStateView { let wasm = std::fs::read(&path_to_executor) .unwrap_or_else(|_| panic!("Failed to read file: {}", path_to_executor.display())); let executor = Executor::new(WasmSmartContract::from_compiled(wasm)); - UpgradeExpr::new(executor) + Upgrade::new(executor) .execute(account_id, &mut wsv) .expect("Failed to load executor"); } diff --git a/core/benches/blocks/validate_blocks.rs b/core/benches/blocks/validate_blocks.rs index 6a6d0bc585d..f39e7eb288e 100644 --- a/core/benches/blocks/validate_blocks.rs +++ b/core/benches/blocks/validate_blocks.rs @@ -1,6 +1,6 @@ use eyre::Result; use iroha_core::prelude::*; -use iroha_data_model::{isi::InstructionExpr, prelude::*}; +use iroha_data_model::{isi::InstructionBox, prelude::*}; #[path = "./common.rs"] mod common; @@ -10,7 +10,7 @@ use common::*; #[derive(Clone)] pub struct WsvValidateBlocks { wsv: WorldStateView, - instructions: Vec>, + instructions: Vec>, key_pair: KeyPair, account_id: AccountId, } diff --git a/core/benches/kura.rs b/core/benches/kura.rs index 279f8d97528..a47f731e31d 100644 --- a/core/benches/kura.rs +++ b/core/benches/kura.rs @@ -23,11 +23,7 @@ async fn measure_block_size_for_n_executors(n_executors: u32) { let bob_id = AccountId::from_str("bob@test").expect("tested"); let xor_id = AssetDefinitionId::from_str("xor#test").expect("tested"); let alice_xor_id = AssetId::new(xor_id, alice_id); - let transfer = TransferExpr::new( - IdBox::AssetId(alice_xor_id), - 10_u32.to_value(), - IdBox::AccountId(bob_id), - ); + let transfer = Transfer::asset_quantity(alice_xor_id, 10_u32, bob_id); let keypair = KeyPair::generate().expect("Failed to generate KeyPair."); let tx = TransactionBuilder::new(AccountId::from_str("alice@wonderland").expect("checked")) .with_instructions([transfer]) diff --git a/core/benches/validation.rs b/core/benches/validation.rs index 0a474ab3ea0..3a5bcaefe23 100644 --- a/core/benches/validation.rs +++ b/core/benches/validation.rs @@ -12,7 +12,7 @@ use iroha_core::{ tx::TransactionExecutor, wsv::World, }; -use iroha_data_model::{prelude::*, transaction::TransactionLimits}; +use iroha_data_model::{isi::InstructionBox, prelude::*, transaction::TransactionLimits}; use iroha_primitives::unique_vec::UniqueVec; const START_DOMAIN: &str = "start"; @@ -26,23 +26,25 @@ const TRANSACTION_LIMITS: TransactionLimits = TransactionLimits { fn build_test_transaction(keys: KeyPair) -> SignedTransaction { let domain_name = "domain"; let domain_id = DomainId::from_str(domain_name).expect("does not panic"); - let create_domain = RegisterExpr::new(Domain::new(domain_id)); + let create_domain: InstructionBox = Register::domain(Domain::new(domain_id)).into(); let account_name = "account"; let (public_key, _) = KeyPair::generate() .expect("Failed to generate KeyPair.") .into(); - let create_account = RegisterExpr::new(Account::new( + let create_account = Register::account(Account::new( AccountId::new( account_name.parse().expect("Valid"), domain_name.parse().expect("Valid"), ), [public_key], - )); + )) + .into(); let asset_definition_id = AssetDefinitionId::new( "xor".parse().expect("Valid"), domain_name.parse().expect("Valid"), ); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id)); + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id)).into(); let instructions = [create_domain, create_account, create_asset]; TransactionBuilder::new(AccountId::new( @@ -82,7 +84,7 @@ fn build_test_and_transient_wsv(keys: KeyPair) -> WorldStateView { .unwrap_or_else(|_| panic!("Failed to read file: {}", path_to_executor.display())); let executor = Executor::new(WasmSmartContract::from_compiled(wasm)); let authority = "genesis@genesis".parse().expect("Valid"); - UpgradeExpr::new(executor) + Upgrade::new(executor) .execute(&authority, &mut wsv) .expect("Failed to load executor"); } diff --git a/core/src/block.rs b/core/src/block.rs index 9322d16400d..21a7405ef42 100644 --- a/core/src/block.rs +++ b/core/src/block.rs @@ -735,7 +735,7 @@ mod tests { // Creating an instruction let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset_definition = - RegisterExpr::new(AssetDefinition::quantity(asset_definition_id)); + Register::asset_definition(AssetDefinition::quantity(asset_definition_id)); // Making two transactions that have the same instruction let transaction_limits = &wsv.transaction_executor().transaction_limits; @@ -778,7 +778,7 @@ mod tests { // Creating an instruction let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset_definition = - RegisterExpr::new(AssetDefinition::quantity(asset_definition_id.clone())); + Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); // Making two transactions that have the same instruction let transaction_limits = &wsv.transaction_executor().transaction_limits; @@ -791,14 +791,14 @@ mod tests { let quantity: u32 = 200; let fail_quantity: u32 = 20; - let fail_mint = MintExpr::new( - fail_quantity.to_value(), - IdBox::AssetId(AssetId::new(asset_definition_id.clone(), alice_id.clone())), + let fail_mint = Mint::asset_quantity( + fail_quantity, + AssetId::new(asset_definition_id.clone(), alice_id.clone()), ); - let succeed_mint = MintExpr::new( - quantity.to_value(), - IdBox::AssetId(AssetId::new(asset_definition_id, alice_id.clone())), + let succeed_mint = Mint::asset_quantity( + quantity, + AssetId::new(asset_definition_id, alice_id.clone()), ); let tx0 = TransactionBuilder::new(alice_id.clone()) @@ -848,14 +848,15 @@ mod tests { let transaction_limits = &wsv.transaction_executor().transaction_limits; let domain_id = DomainId::from_str("domain").expect("Valid"); - let create_domain = RegisterExpr::new(Domain::new(domain_id)); + let create_domain = Register::domain(Domain::new(domain_id)); let asset_definition_id = AssetDefinitionId::from_str("coin#domain").expect("Valid"); - let create_asset = RegisterExpr::new(AssetDefinition::quantity(asset_definition_id)); - let instructions_fail: [InstructionExpr; 2] = [ + let create_asset = + Register::asset_definition(AssetDefinition::quantity(asset_definition_id)); + let instructions_fail: [InstructionBox; 2] = [ create_domain.clone().into(), - Fail::new("Always fail").into(), + Fail::new("Always fail".to_owned()).into(), ]; - let instructions_accept: [InstructionExpr; 2] = [create_domain.into(), create_asset.into()]; + let instructions_accept: [InstructionBox; 2] = [create_domain.into(), create_asset.into()]; let tx_fail = TransactionBuilder::new(alice_id.clone()) .with_instructions(instructions_fail) .sign(alice_keys.clone()) diff --git a/core/src/executor.rs b/core/src/executor.rs index 971f7dd7867..62af571fe49 100644 --- a/core/src/executor.rs +++ b/core/src/executor.rs @@ -4,7 +4,7 @@ use derive_more::DebugCustom; use iroha_data_model::{ account::AccountId, executor as data_model_executor, - isi::InstructionExpr, + isi::InstructionBox, query::QueryBox, transaction::{Executable, SignedTransaction}, ValidationFail, @@ -181,7 +181,7 @@ impl Executor { &self, wsv: &mut WorldStateView, authority: &AccountId, - instruction: InstructionExpr, + instruction: InstructionBox, ) -> Result<(), ValidationFail> { trace!("Running instruction validation"); diff --git a/core/src/queue.rs b/core/src/queue.rs index e19e46f2ba5..2872ebc9365 100644 --- a/core/src/queue.rs +++ b/core/src/queue.rs @@ -512,7 +512,7 @@ mod tests { .build() .expect("Default queue config should always build") }); - let instructions: [InstructionExpr; 0] = []; + let instructions: [InstructionBox; 0] = []; let tx = TransactionBuilder::new("alice@wonderland".parse().expect("Valid")) .with_instructions(instructions); let tx_limits = TransactionLimits { diff --git a/core/src/smartcontracts/isi/account.rs b/core/src/smartcontracts/isi/account.rs index 2c1e67ca25c..eff4dbaebbc 100644 --- a/core/src/smartcontracts/isi/account.rs +++ b/core/src/smartcontracts/isi/account.rs @@ -478,10 +478,9 @@ pub mod isi { /// Account-related [`Query`] instructions. pub mod query { - use eyre::{Result, WrapErr}; + use eyre::Result; use iroha_data_model::{ account::Account, - evaluate::ExpressionEvaluator, permission::PermissionToken, query::{error::QueryExecutionFail as Error, MetadataValue}, }; @@ -494,13 +493,10 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let account_id = wsv - .evaluate(&self.id) - .wrap_err("Failed to evaluate account id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let account_id = &self.id; iroha_logger::trace!(%account_id, roles=?wsv.world.roles); - wsv.account(&account_id)?; - Ok(Box::new(wsv.account_roles(&account_id).cloned())) + wsv.account(account_id)?; + Ok(Box::new(wsv.account_roles(account_id).cloned())) } } @@ -510,13 +506,10 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let account_id = wsv - .evaluate(&self.id) - .wrap_err("Failed to evaluate account id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let account_id = &self.id; iroha_logger::trace!(%account_id, accounts=?wsv.world.domains); Ok(Box::new( - wsv.account_permission_tokens(&account_id)?.cloned(), + wsv.account_permission_tokens(account_id)?.cloned(), )) } } @@ -539,12 +532,9 @@ pub mod query { impl ValidQuery for FindAccountById { #[metrics(+"find_account_by_id")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to evaluate id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; iroha_logger::trace!(%id); - wsv.map_account(&id, Clone::clone).map_err(Into::into) + wsv.map_account(id, Clone::clone).map_err(Into::into) } } @@ -554,10 +544,7 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let name = wsv - .evaluate(&self.name) - .wrap_err("Failed to evaluate account name") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let name = self.name.clone(); iroha_logger::trace!(%name); Ok(Box::new( wsv.domains() @@ -581,30 +568,21 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let id = wsv - .evaluate(&self.domain_id) - .wrap_err("Failed to evaluate domain id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.domain_id; iroha_logger::trace!(%id); - Ok(Box::new(wsv.domain(&id)?.accounts.values().cloned())) + Ok(Box::new(wsv.domain(id)?.accounts.values().cloned())) } } impl ValidQuery for FindAccountKeyValueByIdAndKey { #[metrics(+"find_account_key_value_by_id_and_key")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to evaluate account id") - .map_err(|e| Error::Evaluate(e.to_string()))?; - let key = wsv - .evaluate(&self.key) - .wrap_err("Failed to evaluate key") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; + let key = &self.key; iroha_logger::trace!(%id, %key); - wsv.map_account(&id, |account| account.metadata.get(&key).map(Clone::clone))? - .ok_or_else(|| FindError::MetadataKey(key).into()) + wsv.map_account(id, |account| account.metadata.get(key).map(Clone::clone))? + .ok_or_else(|| FindError::MetadataKey(key.clone()).into()) .map(Into::into) } } @@ -615,10 +593,7 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let asset_definition_id = wsv - .evaluate(&self.asset_definition_id) - .wrap_err("Failed to evaluate asset id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let asset_definition_id = self.asset_definition_id.clone(); iroha_logger::trace!(%asset_definition_id); Ok(Box::new( diff --git a/core/src/smartcontracts/isi/asset.rs b/core/src/smartcontracts/isi/asset.rs index 6d5fd0ccda3..4aaf3e19168 100644 --- a/core/src/smartcontracts/isi/asset.rs +++ b/core/src/smartcontracts/isi/asset.rs @@ -416,7 +416,7 @@ pub mod isi { /// Asset-related query implementations. pub mod query { - use eyre::{Result, WrapErr as _}; + use eyre::Result; use iroha_data_model::{ asset::{Asset, AssetDefinition}, query::{ @@ -464,12 +464,9 @@ pub mod query { impl ValidQuery for FindAssetById { #[metrics(+"find_asset_by_id")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to get asset id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; iroha_logger::trace!(%id); - wsv.asset(&id).map_err(|asset_err| { + wsv.asset(id).map_err(|asset_err| { if let Err(definition_err) = wsv.asset_definition(&id.definition_id) { definition_err.into() } else { @@ -482,12 +479,9 @@ pub mod query { impl ValidQuery for FindAssetDefinitionById { #[metrics(+"find_asset_defintion_by_id")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to get asset definition id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; - let entry = wsv.asset_definition(&id).map_err(Error::from)?; + let entry = wsv.asset_definition(id).map_err(Error::from)?; Ok(entry) } @@ -499,10 +493,7 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let name = wsv - .evaluate(&self.name) - .wrap_err("Failed to get asset name") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let name = self.name.clone(); iroha_logger::trace!(%name); Ok(Box::new( wsv.domains() @@ -530,12 +521,9 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let id = wsv - .evaluate(&self.account_id) - .wrap_err("Failed to get account id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.account_id; iroha_logger::trace!(%id); - Ok(Box::new(wsv.account_assets(&id)?.cloned())) + Ok(Box::new(wsv.account_assets(id)?.cloned())) } } @@ -545,10 +533,7 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let id = wsv - .evaluate(&self.asset_definition_id) - .wrap_err("Failed to get asset definition id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = self.asset_definition_id.clone(); iroha_logger::trace!(%id); Ok(Box::new( wsv.domains() @@ -576,13 +561,10 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let id = wsv - .evaluate(&self.domain_id) - .wrap_err("Failed to get domain id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.domain_id; iroha_logger::trace!(%id); Ok(Box::new( - wsv.domain(&id)? + wsv.domain(id)? .accounts .values() .flat_map(|account| account.assets.values()) @@ -597,14 +579,8 @@ pub mod query { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, Error> { - let domain_id = wsv - .evaluate(&self.domain_id) - .wrap_err("Failed to get domain id") - .map_err(|e| Error::Evaluate(e.to_string()))?; - let asset_definition_id = wsv - .evaluate(&self.asset_definition_id) - .wrap_err("Failed to get asset definition id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let domain_id = self.domain_id.clone(); + let asset_definition_id = self.asset_definition_id.clone(); let domain = wsv.domain(&domain_id)?; let _definition = domain .asset_definitions @@ -632,13 +608,10 @@ pub mod query { impl ValidQuery for FindAssetQuantityById { #[metrics(+"find_asset_quantity_by_id")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to get asset id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; iroha_logger::trace!(%id); let value = wsv - .asset(&id) + .asset(id) .map_err(|asset_err| { if let Err(definition_err) = wsv.asset_definition(&id.definition_id) { Error::Find(definition_err) @@ -656,12 +629,9 @@ pub mod query { impl ValidQuery for FindTotalAssetQuantityByAssetDefinitionId { #[metrics(+"find_total_asset_quantity_by_asset_definition_id")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to get asset definition id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; iroha_logger::trace!(%id); - let asset_value = wsv.asset_total_amount(&id)?; + let asset_value = wsv.asset_total_amount(id)?; Ok(asset_value) } } @@ -669,15 +639,9 @@ pub mod query { impl ValidQuery for FindAssetKeyValueByIdAndKey { #[metrics(+"find_asset_key_value_by_id_and_key")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to get asset id") - .map_err(|e| Error::Evaluate(e.to_string()))?; - let key = wsv - .evaluate(&self.key) - .wrap_err("Failed to get key") - .map_err(|e| Error::Evaluate(e.to_string()))?; - let asset = wsv.asset(&id).map_err(|asset_err| { + let id = &self.id; + let key = &self.key; + let asset = wsv.asset(id).map_err(|asset_err| { if let Err(definition_err) = wsv.asset_definition(&id.definition_id) { Error::Find(definition_err) } else { @@ -691,8 +655,8 @@ pub mod query { .map_err(eyre::Error::from) .map_err(|e| Error::Conversion(e.to_string()))?; store - .get(&key) - .ok_or_else(|| Error::Find(FindError::MetadataKey(key))) + .get(key) + .ok_or_else(|| Error::Find(FindError::MetadataKey(key.clone()))) .cloned() .map(Into::into) } diff --git a/core/src/smartcontracts/isi/block.rs b/core/src/smartcontracts/isi/block.rs index 4f241372ef1..08f4af0fb6e 100644 --- a/core/src/smartcontracts/isi/block.rs +++ b/core/src/smartcontracts/isi/block.rs @@ -1,8 +1,7 @@ //! This module contains trait implementations related to block queries -use eyre::{Result, WrapErr}; +use eyre::Result; use iroha_data_model::{ block::{BlockHeader, SignedBlock}, - evaluate::ExpressionEvaluator, query::{ block::FindBlockHeaderByHash, error::{FindError, QueryExecutionFail}, @@ -43,10 +42,7 @@ impl ValidQuery for FindAllBlockHeaders { impl ValidQuery for FindBlockHeaderByHash { #[metrics(+"find_block_header")] fn execute(&self, wsv: &WorldStateView) -> Result { - let hash = wsv - .evaluate(&self.hash) - .wrap_err("Failed to evaluate hash") - .map_err(|e| QueryExecutionFail::Evaluate(e.to_string()))?; + let hash = self.hash; let block = wsv .all_blocks() diff --git a/core/src/smartcontracts/isi/domain.rs b/core/src/smartcontracts/isi/domain.rs index b7930106a04..81855321e7c 100644 --- a/core/src/smartcontracts/isi/domain.rs +++ b/core/src/smartcontracts/isi/domain.rs @@ -301,7 +301,7 @@ pub mod isi { /// Query module provides [`Query`] Domain related implementations. pub mod query { - use eyre::{Result, WrapErr}; + use eyre::Result; use iroha_data_model::{ domain::Domain, query::{error::QueryExecutionFail as Error, MetadataValue}, @@ -322,29 +322,20 @@ pub mod query { impl ValidQuery for FindDomainById { #[metrics(+"find_domain_by_id")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to get domain id") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; iroha_logger::trace!(%id); - Ok(wsv.domain(&id)?.clone()) + Ok(wsv.domain(id)?.clone()) } } impl ValidQuery for FindDomainKeyValueByIdAndKey { #[metrics(+"find_domain_key_value_by_id_and_key")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to get domain id") - .map_err(|e| Error::Evaluate(e.to_string()))?; - let key = wsv - .evaluate(&self.key) - .wrap_err("Failed to get key") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; + let key = &self.key; iroha_logger::trace!(%id, %key); - wsv.map_domain(&id, |domain| domain.metadata.get(&key).map(Clone::clone))? - .ok_or_else(|| FindError::MetadataKey(key).into()) + wsv.map_domain(id, |domain| domain.metadata.get(key).map(Clone::clone))? + .ok_or_else(|| FindError::MetadataKey(key.clone()).into()) .map(Into::into) } } @@ -352,20 +343,14 @@ pub mod query { impl ValidQuery for FindAssetDefinitionKeyValueByIdAndKey { #[metrics(+"find_asset_definition_key_value_by_id_and_key")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .wrap_err("Failed to get asset definition id") - .map_err(|e| Error::Evaluate(e.to_string()))?; - let key = wsv - .evaluate(&self.key) - .wrap_err("Failed to get key") - .map_err(|e| Error::Evaluate(e.to_string()))?; + let id = &self.id; + let key = &self.key; iroha_logger::trace!(%id, %key); Ok(wsv - .asset_definition(&id)? + .asset_definition(id)? .metadata - .get(&key) - .ok_or(FindError::MetadataKey(key)) + .get(key) + .ok_or(FindError::MetadataKey(key.clone())) .cloned() .map(Into::into)?) } diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index 7f80bbfade1..a0bf424f1ef 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -12,12 +12,10 @@ pub mod world; use eyre::Result; use iroha_data_model::{ - evaluate::ExpressionEvaluator, isi::{error::InstructionExecutionError as Error, *}, prelude::*, }; -use iroha_logger::prelude::{Span, *}; -use iroha_primitives::fixed::Fixed; +use iroha_logger::prelude::*; use super::Execute; use crate::{prelude::*, wsv::WorldStateView}; @@ -31,343 +29,167 @@ pub trait Registrable { fn build(self, authority: &AccountId) -> Self::Target; } -impl Execute for InstructionExpr { +impl Execute for InstructionBox { fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { iroha_logger::debug!(isi=%self, "Executing"); - macro_rules! match_all { - ($($isi:ident),+ $(,)?) => { - - match self { $( - InstructionExpr::$isi(isi) => isi.execute(authority, wsv), )+ - } - }; - } - - match_all! { - Register, - Unregister, - Mint, - Burn, - Transfer, - If, - Pair, - Sequence, - Fail, - SetKeyValue, - RemoveKeyValue, - Grant, - Revoke, - ExecuteTrigger, - SetParameter, - NewParameter, - Upgrade, - Log, + match self { + Self::Register(isi) => isi.execute(authority, wsv), + Self::Unregister(isi) => isi.execute(authority, wsv), + Self::Mint(isi) => isi.execute(authority, wsv), + Self::Burn(isi) => isi.execute(authority, wsv), + Self::Transfer(isi) => isi.execute(authority, wsv), + Self::Fail(isi) => isi.execute(authority, wsv), + Self::SetKeyValue(isi) => isi.execute(authority, wsv), + Self::RemoveKeyValue(isi) => isi.execute(authority, wsv), + Self::Grant(isi) => isi.execute(authority, wsv), + Self::Revoke(isi) => isi.execute(authority, wsv), + Self::ExecuteTrigger(isi) => isi.execute(authority, wsv), + Self::SetParameter(isi) => isi.execute(authority, wsv), + Self::NewParameter(isi) => isi.execute(authority, wsv), + Self::Upgrade(isi) => isi.execute(authority, wsv), + Self::Log(isi) => isi.execute(authority, wsv), } } } -impl Execute for RegisterExpr { +impl Execute for RegisterBox { #[iroha_logger::log(name = "register", skip_all, fields(id))] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let object_id = wsv.evaluate(&self.object)?; - Span::current().record("id", &object_id.to_string()); - match object_id { - RegistrableBox::Peer(object) => Register:: { object }.execute(authority, wsv), - RegistrableBox::Domain(object) => Register:: { object }.execute(authority, wsv), - RegistrableBox::Account(object) => { - Register:: { object }.execute(authority, wsv) - } - RegistrableBox::AssetDefinition(object) => { - Register:: { object }.execute(authority, wsv) - } - RegistrableBox::Asset(object) => Register:: { object }.execute(authority, wsv), - RegistrableBox::Trigger(object) => { - Register::> { object }.execute(authority, wsv) - } - RegistrableBox::Role(object) => Register:: { object }.execute(authority, wsv), + match self { + Self::Peer(isi) => isi.execute(authority, wsv), + Self::Domain(isi) => isi.execute(authority, wsv), + Self::Account(isi) => isi.execute(authority, wsv), + Self::AssetDefinition(isi) => isi.execute(authority, wsv), + Self::Asset(isi) => isi.execute(authority, wsv), + Self::Role(isi) => isi.execute(authority, wsv), + Self::Trigger(isi) => isi.execute(authority, wsv), } } } -impl Execute for UnregisterExpr { +impl Execute for UnregisterBox { #[iroha_logger::log(name = "unregister", skip_all, fields(id))] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let object_id = wsv.evaluate(&self.object_id)?; - Span::current().record("id", &object_id.to_string()); - match object_id { - IdBox::AccountId(object_id) => { - Unregister:: { object_id }.execute(authority, wsv) - } - IdBox::AssetId(object_id) => Unregister:: { object_id }.execute(authority, wsv), - IdBox::AssetDefinitionId(object_id) => { - Unregister:: { object_id }.execute(authority, wsv) - } - IdBox::DomainId(object_id) => { - Unregister:: { object_id }.execute(authority, wsv) - } - IdBox::PeerId(object_id) => Unregister:: { object_id }.execute(authority, wsv), - IdBox::RoleId(object_id) => Unregister:: { object_id }.execute(authority, wsv), - IdBox::TriggerId(object_id) => { - Unregister::> { object_id }.execute(authority, wsv) - } - IdBox::PermissionTokenId(_) | IdBox::ParameterId(_) => { - Err(Error::Evaluate(InstructionType::Unregister.into())) - } + match self { + Self::Peer(isi) => isi.execute(authority, wsv), + Self::Domain(isi) => isi.execute(authority, wsv), + Self::Account(isi) => isi.execute(authority, wsv), + Self::AssetDefinition(isi) => isi.execute(authority, wsv), + Self::Asset(isi) => isi.execute(authority, wsv), + Self::Role(isi) => isi.execute(authority, wsv), + Self::Trigger(isi) => isi.execute(authority, wsv), } } } -impl Execute for MintExpr { +impl Execute for MintBox { #[iroha_logger::log(name = "Mint", skip_all, fields(destination))] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let destination_id = wsv.evaluate(&self.destination_id)?; - let object = wsv.evaluate(&self.object)?; - Span::current().record("destination", &destination_id.to_string()); - iroha_logger::trace!(?object, %authority); - match (destination_id, object) { - (IdBox::AssetId(destination_id), Value::Numeric(NumericValue::U32(object))) => { - Mint:: { - object, - destination_id, - } - .execute(authority, wsv) - } - (IdBox::AssetId(destination_id), Value::Numeric(NumericValue::U128(object))) => { - Mint:: { - object, - destination_id, - } - .execute(authority, wsv) - } - (IdBox::AssetId(destination_id), Value::Numeric(NumericValue::Fixed(object))) => { - Mint:: { - object, - destination_id, - } - .execute(authority, wsv) - } - (IdBox::AccountId(destination_id), Value::PublicKey(object)) => { - Mint:: { - object, - destination_id, - } - .execute(authority, wsv) - } - (IdBox::AccountId(destination_id), Value::SignatureCheckCondition(object)) => { - Mint:: { - object, - destination_id, - } - .execute(authority, wsv) - } - (IdBox::TriggerId(destination_id), Value::Numeric(NumericValue::U32(object))) => { - Mint::> { - object, - destination_id, - } - .execute(authority, wsv) - } - _ => Err(Error::Evaluate(InstructionType::Mint.into())), + match self { + Self::Account(isi) => isi.execute(authority, wsv), + Self::Asset(isi) => isi.execute(authority, wsv), + Self::TriggerRepetitions(isi) => isi.execute(authority, wsv), } } } -impl Execute for BurnExpr { - #[iroha_logger::log(name = "burn", skip_all, fields(destination))] - fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let destination_id = wsv.evaluate(&self.destination_id)?; - let object = wsv.evaluate(&self.object)?; - Span::current().record("destination", &destination_id.to_string()); - iroha_logger::trace!(?object, %authority); - match (destination_id, object) { - (IdBox::AssetId(destination_id), Value::Numeric(NumericValue::U32(object))) => { - Burn:: { - object, - destination_id, - } - .execute(authority, wsv) - } - (IdBox::AssetId(destination_id), Value::Numeric(NumericValue::U128(object))) => Burn { - object, - destination_id, - } - .execute(authority, wsv), - (IdBox::AssetId(destination_id), Value::Numeric(NumericValue::Fixed(object))) => Burn { - object, - destination_id, - } - .execute(authority, wsv), - (IdBox::AccountId(destination_id), Value::PublicKey(object)) => Burn { - object, - destination_id, - } - .execute(authority, wsv), - (IdBox::TriggerId(destination_id), Value::Numeric(NumericValue::U32(object))) => { - Burn::> { - object, - destination_id, - } - .execute(authority, wsv) - } - // TODO: Not implemented yet. - // (IdBox::AccountId(account_id), Value::SignatureCheckCondition(condition)) => { - // Burn::{condition, account_id}.execute(authority, wsv) - // } - _ => Err(Error::Evaluate(InstructionType::Burn.into())), +impl Execute for AccountMintBox { + fn execute( + self, + authority: &AccountId, + wsv: &mut WorldStateView, + ) -> std::prelude::v1::Result<(), Error> { + match self { + Self::PublicKey(isi) => isi.execute(authority, wsv), + Self::SignatureCheckCondition(isi) => isi.execute(authority, wsv), } } } -impl Execute for TransferExpr { - #[iroha_logger::log(name = "transfer", skip_all, fields(from, to))] - fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let source_id = wsv.evaluate(&self.source_id)?; - let destination_id = wsv.evaluate(&self.destination_id)?; - let object = wsv.evaluate(&self.object)?; - iroha_logger::trace!(%object, %authority); - Span::current().record("from", source_id.to_string()); - Span::current().record("to", destination_id.to_string()); - - match (source_id, object, destination_id) { - ( - IdBox::AssetId(source_id), - Value::Numeric(value), - IdBox::AccountId(destination_id), - ) => match value { - NumericValue::U32(object) => Transfer { - source_id, - object, - destination_id, - } - .execute(authority, wsv), - NumericValue::U128(object) => Transfer { - source_id, - object, - destination_id, - } - .execute(authority, wsv), - NumericValue::Fixed(object) => Transfer { - source_id, - object, - destination_id, - } - .execute(authority, wsv), - _ => Err(Error::Evaluate(InstructionType::Transfer.into())), - }, - ( - IdBox::AccountId(source_id), - Value::Id(IdBox::AssetDefinitionId(object)), - IdBox::AccountId(destination_id), - ) => Transfer { - source_id, - object, - destination_id, - } - .execute(authority, wsv), - ( - IdBox::AccountId(source_id), - Value::Id(IdBox::DomainId(object)), - IdBox::AccountId(destination_id), - ) => Transfer { - source_id, - object, - destination_id, - } - .execute(authority, wsv), - _ => Err(Error::Evaluate(InstructionType::Transfer.into())), +impl Execute for AssetMintBox { + fn execute( + self, + authority: &AccountId, + wsv: &mut WorldStateView, + ) -> std::prelude::v1::Result<(), Error> { + match self { + Self::Quantity(isi) => isi.execute(authority, wsv), + Self::BigQuantity(isi) => isi.execute(authority, wsv), + Self::Fixed(isi) => isi.execute(authority, wsv), } } } -impl Execute for SetKeyValueExpr { +impl Execute for BurnBox { + #[iroha_logger::log(name = "burn", skip_all, fields(destination))] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let key = wsv.evaluate(&self.key)?; - let value = wsv.evaluate(&self.value)?; - iroha_logger::trace!(?key, ?value, %authority); - match wsv.evaluate(&self.object_id)? { - IdBox::AssetId(object_id) => SetKeyValue:: { - object_id, - key, - value, - } - .execute(authority, wsv), - IdBox::AssetDefinitionId(object_id) => SetKeyValue:: { - object_id, - key, - value, - } - .execute(authority, wsv), - IdBox::AccountId(object_id) => SetKeyValue:: { - object_id, - key, - value, - } - .execute(authority, wsv), - IdBox::DomainId(object_id) => SetKeyValue:: { - object_id, - key, - value, - } - .execute(authority, wsv), - _ => Err(Error::Evaluate(InstructionType::SetKeyValue.into())), + match self { + Self::AccountPublicKey(isi) => isi.execute(authority, wsv), + Self::Asset(isi) => isi.execute(authority, wsv), + Self::TriggerRepetitions(isi) => isi.execute(authority, wsv), } } } -impl Execute for RemoveKeyValueExpr { - fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let key = wsv.evaluate(&self.key)?; - iroha_logger::trace!(?key, %authority); - match wsv.evaluate(&self.object_id)? { - IdBox::AssetId(object_id) => { - RemoveKeyValue:: { object_id, key }.execute(authority, wsv) - } - IdBox::AssetDefinitionId(object_id) => { - RemoveKeyValue:: { object_id, key }.execute(authority, wsv) - } - IdBox::AccountId(object_id) => { - RemoveKeyValue:: { object_id, key }.execute(authority, wsv) - } - IdBox::DomainId(object_id) => { - RemoveKeyValue:: { object_id, key }.execute(authority, wsv) - } - _ => Err(Error::Evaluate(InstructionType::RemoveKeyValue.into())), +impl Execute for AssetBurnBox { + fn execute( + self, + authority: &AccountId, + wsv: &mut WorldStateView, + ) -> std::prelude::v1::Result<(), Error> { + match self { + Self::Quantity(isi) => isi.execute(authority, wsv), + Self::BigQuantity(isi) => isi.execute(authority, wsv), + Self::Fixed(isi) => isi.execute(authority, wsv), } } } -impl Execute for ConditionalExpr { +impl Execute for TransferBox { + #[iroha_logger::log(name = "transfer", skip_all, fields(from, to))] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - iroha_logger::trace!(?self); - if wsv.evaluate(&self.condition)? { - self.then.execute(authority, wsv)?; - } else if let Some(otherwise) = self.otherwise { - otherwise.execute(authority, wsv)?; + match self { + Self::Domain(isi) => isi.execute(authority, wsv), + Self::AssetDefinition(isi) => isi.execute(authority, wsv), + Self::Asset(isi) => isi.execute(authority, wsv), } - Ok(()) } } -impl Execute for PairExpr { - fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - iroha_logger::trace!(?self); +impl Execute for AssetTransferBox { + fn execute( + self, + authority: &AccountId, + wsv: &mut WorldStateView, + ) -> std::prelude::v1::Result<(), Error> { + match self { + Self::Quantity(isi) => isi.execute(authority, wsv), + Self::BigQuantity(isi) => isi.execute(authority, wsv), + Self::Fixed(isi) => isi.execute(authority, wsv), + } + } +} - self.left_instruction.execute(authority, wsv)?; - self.right_instruction.execute(authority, wsv)?; - Ok(()) +impl Execute for SetKeyValueBox { + fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { + match self { + Self::Domain(isi) => isi.execute(authority, wsv), + Self::Account(isi) => isi.execute(authority, wsv), + Self::AssetDefinition(isi) => isi.execute(authority, wsv), + Self::Asset(isi) => isi.execute(authority, wsv), + } } } -impl Execute for SequenceExpr { - #[iroha_logger::log(skip_all, name = "Sequence", fields(count))] +impl Execute for RemoveKeyValueBox { fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - Span::current().record("count", self.instructions.len()); - for instruction in self.instructions { - iroha_logger::trace!(%instruction); - instruction.execute(authority, wsv)?; + match self { + Self::Domain(isi) => isi.execute(authority, wsv), + Self::Account(isi) => isi.execute(authority, wsv), + Self::AssetDefinition(isi) => isi.execute(authority, wsv), + Self::Asset(isi) => isi.execute(authority, wsv), } - Ok(()) } } @@ -379,86 +201,26 @@ impl Execute for Fail { } } -impl Execute for GrantExpr { +impl Execute for GrantBox { #[iroha_logger::log(name = "grant", skip_all, fields(object))] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let destination_id = wsv.evaluate(&self.destination_id)?; - let object = wsv.evaluate(&self.object)?; - Span::current().record("object", &object.to_string()); - iroha_logger::trace!(%destination_id, %authority); - match object { - Value::PermissionToken(object) => Grant:: { - object, - destination_id, - } - .execute(authority, wsv), - Value::Id(IdBox::RoleId(object)) => Grant:: { - object, - destination_id, - } - .execute(authority, wsv), - _ => Err(Error::Evaluate(InstructionType::Grant.into())), + match self { + Self::PermissionToken(sub_isi) => sub_isi.execute(authority, wsv), + Self::Role(sub_isi) => sub_isi.execute(authority, wsv), } } } -impl Execute for RevokeExpr { +impl Execute for RevokeBox { #[iroha_logger::log(name = "revoke", skip_all, fields(object))] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let destination_id = wsv.evaluate(&self.destination_id)?; - let object = wsv.evaluate(&self.object)?; - Span::current().record("object", &object.to_string()); - iroha_logger::trace!(?destination_id, ?object, %authority); - match object { - Value::PermissionToken(object) => Revoke:: { - object, - destination_id, - } - .execute(authority, wsv), - Value::Id(IdBox::RoleId(object)) => Revoke:: { - object, - destination_id, - } - .execute(authority, wsv), - _ => Err(Error::Evaluate(InstructionType::Revoke.into())), + match self { + Self::PermissionToken(sub_isi) => sub_isi.execute(authority, wsv), + Self::Role(sub_isi) => sub_isi.execute(authority, wsv), } } } -impl Execute for SetParameterExpr { - fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let parameter = wsv.evaluate(&self.parameter)?; - SetParameter { parameter }.execute(authority, wsv) - } -} - -impl Execute for NewParameterExpr { - fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let parameter = wsv.evaluate(&self.parameter)?; - NewParameter { parameter }.execute(authority, wsv) - } -} - -impl Execute for UpgradeExpr { - fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let object = wsv.evaluate(&self.object)?; - match object { - UpgradableBox::Executor(object) => { - Upgrade:: { object }.execute(authority, wsv) - } - } - } -} - -impl Execute for LogExpr { - fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let level = wsv.evaluate(&self.level)?; - let msg = wsv.evaluate(&self.msg)?; - - Log { level, msg }.execute(authority, wsv) - } -} - pub mod prelude { //! Re-export important traits and types for glob import `(::*)` pub use super::*; @@ -483,11 +245,11 @@ mod tests { let account_id = AccountId::from_str("alice@wonderland")?; let (public_key, _) = KeyPair::generate()?.into(); let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland")?; - RegisterExpr::new(Domain::new(DomainId::from_str("wonderland")?)) + Register::domain(Domain::new(DomainId::from_str("wonderland")?)) .execute(&genesis_account_id, &mut wsv)?; - RegisterExpr::new(Account::new(account_id, [public_key])) + Register::account(Account::new(account_id, [public_key])) .execute(&genesis_account_id, &mut wsv)?; - RegisterExpr::new(AssetDefinition::store(asset_definition_id)) + Register::asset_definition(AssetDefinition::store(asset_definition_id)) .execute(&genesis_account_id, &mut wsv)?; Ok(wsv) } @@ -499,8 +261,8 @@ mod tests { let account_id = AccountId::from_str("alice@wonderland")?; let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland")?; let asset_id = AssetId::new(asset_definition_id, account_id.clone()); - SetKeyValueExpr::new( - IdBox::from(asset_id.clone()), + SetKeyValue::asset( + asset_id.clone(), Name::from_str("Bytes")?, vec![1_u32, 2_u32, 3_u32], ) @@ -526,8 +288,8 @@ mod tests { let kura = Kura::blank_kura_for_testing(); let mut wsv = wsv_with_test_domains(&kura)?; let account_id = AccountId::from_str("alice@wonderland")?; - SetKeyValueExpr::new( - IdBox::from(account_id.clone()), + SetKeyValue::account( + account_id.clone(), Name::from_str("Bytes")?, vec![1_u32, 2_u32, 3_u32], ) @@ -555,8 +317,8 @@ mod tests { let mut wsv = wsv_with_test_domains(&kura)?; let definition_id = AssetDefinitionId::from_str("rose#wonderland")?; let account_id = AccountId::from_str("alice@wonderland")?; - SetKeyValueExpr::new( - IdBox::from(definition_id.clone()), + SetKeyValue::asset_definition( + definition_id.clone(), Name::from_str("Bytes")?, vec![1_u32, 2_u32, 3_u32], ) @@ -583,8 +345,8 @@ mod tests { let mut wsv = wsv_with_test_domains(&kura)?; let domain_id = DomainId::from_str("wonderland")?; let account_id = AccountId::from_str("alice@wonderland")?; - SetKeyValueExpr::new( - IdBox::from(domain_id.clone()), + SetKeyValue::domain( + domain_id.clone(), Name::from_str("Bytes")?, vec![1_u32, 2_u32, 3_u32], ) @@ -613,7 +375,7 @@ mod tests { let trigger_id = TriggerId::from_str("test_trigger_id")?; assert!(matches!( - ExecuteTriggerExpr::new(trigger_id) + ExecuteTrigger::new(trigger_id) .execute(&account_id, &mut wsv) .expect_err("Error expected"), Error::Find(_) @@ -635,14 +397,14 @@ mod tests { .expect("Failed to generate KeyPair") .into(); let register_account = - RegisterExpr::new(Account::new(fake_account_id.clone(), [public_key])); + Register::account(Account::new(fake_account_id.clone(), [public_key])); register_account.execute(&account_id, &mut wsv)?; // register the trigger - let register_trigger = RegisterExpr::new(Trigger::new( + let register_trigger = Register::trigger(Trigger::new( trigger_id.clone(), Action::new( - Vec::::new(), + Vec::::new(), Repeats::Indefinitely, account_id.clone(), TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( @@ -655,11 +417,11 @@ mod tests { register_trigger.execute(&account_id, &mut wsv)?; // execute with the valid account - ExecuteTriggerExpr::new(trigger_id.clone()).execute(&account_id, &mut wsv)?; + ExecuteTrigger::new(trigger_id.clone()).execute(&account_id, &mut wsv)?; // execute with the fake account assert!(matches!( - ExecuteTriggerExpr::new(trigger_id) + ExecuteTrigger::new(trigger_id) .execute(&fake_account_id, &mut wsv) .expect_err("Error expected"), Error::InvariantViolation(_) diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index 19671e06587..d14ed740d0b 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -265,14 +265,14 @@ mod tests { wsv.config.transaction_limits = limits; let valid_tx = { - let instructions: [InstructionExpr; 0] = []; + let instructions: [InstructionBox; 0] = []; let tx = TransactionBuilder::new(ALICE_ID.clone()) .with_instructions(instructions) .sign(ALICE_KEYS.clone())?; AcceptedTransaction::accept(tx, &limits)? }; let invalid_tx = { - let isi = Fail::new("fail"); + let isi = Fail::new("fail".to_owned()); let tx = TransactionBuilder::new(ALICE_ID.clone()) .with_instructions([isi.clone(), isi]) .sign(ALICE_KEYS.clone())?; @@ -413,7 +413,7 @@ mod tests { let query_handle = LiveQueryStore::test().start(); let mut wsv = WorldStateView::new(world_with_test_domains(), kura.clone(), query_handle); - let instructions: [InstructionExpr; 0] = []; + let instructions: [InstructionBox; 0] = []; let tx = TransactionBuilder::new(ALICE_ID.clone()) .with_instructions(instructions) .sign(ALICE_KEYS.clone())?; @@ -432,9 +432,7 @@ mod tests { kura.store_block(vcb); let unapplied_tx = TransactionBuilder::new(ALICE_ID.clone()) - .with_instructions([UnregisterExpr::new( - "account@domain".parse::().unwrap(), - )]) + .with_instructions([Unregister::account("account@domain".parse().unwrap())]) .sign(ALICE_KEYS.clone())?; let wrong_hash = unapplied_tx.hash(); let not_found = FindTransactionByHash::new(wrong_hash).execute(&wsv); diff --git a/core/src/smartcontracts/isi/triggers/mod.rs b/core/src/smartcontracts/isi/triggers/mod.rs index 7c814b6fe47..2b8da8ed19f 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -1,9 +1,7 @@ //! This module contains implementations of smart-contract traits and //! instructions for triggers in Iroha. -use iroha_data_model::{ - evaluate::ExpressionEvaluator, isi::error::MathError, prelude::*, query::error::FindError, -}; +use iroha_data_model::{isi::error::MathError, prelude::*, query::error::FindError}; use iroha_telemetry::metrics; pub mod set; @@ -154,13 +152,13 @@ pub mod isi { } } - impl Execute for ExecuteTriggerExpr { + impl Execute for ExecuteTrigger { #[metrics(+"execute_trigger")] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let id = wsv.evaluate(&self.trigger_id)?; + let id = &self.trigger_id; wsv.triggers() - .inspect_by_id(&id, |action| -> Result<(), Error> { + .inspect_by_id(id, |action| -> Result<(), Error> { let allow_execute = if let TriggeringFilterBox::ExecuteTrigger(filter) = action.clone_and_box().filter { @@ -186,7 +184,7 @@ pub mod isi { .ok_or_else(|| Error::Find(Box::new(FindError::Trigger(id.clone())))) .and_then(core::convert::identity)?; - wsv.execute_trigger(id, authority); + wsv.execute_trigger(id.clone(), authority); Ok(()) } @@ -217,43 +215,37 @@ pub mod query { impl ValidQuery for FindTriggerById { #[metrics(+"find_trigger_by_id")] fn execute(&self, wsv: &WorldStateView) -> Result, Error> { - let id = wsv - .evaluate(&self.id) - .map_err(|e| Error::Evaluate(format!("Failed to evaluate trigger id. {e}")))?; + let id = &self.id; iroha_logger::trace!(%id); // Can't use just `LoadedActionTrait::clone_and_box` cause this will trigger lifetime mismatch #[allow(clippy::redundant_closure_for_method_calls)] let loaded_action = wsv .triggers() - .inspect_by_id(&id, |action| action.clone_and_box()) + .inspect_by_id(id, |action| action.clone_and_box()) .ok_or_else(|| Error::Find(FindError::Trigger(id.clone())))?; let action = wsv.triggers().get_original_action(loaded_action); // TODO: Should we redact the metadata if the account is not the authority/owner? - Ok(Trigger::new(id, action)) + Ok(Trigger::new(id.clone(), action)) } } impl ValidQuery for FindTriggerKeyValueByIdAndKey { #[metrics(+"find_trigger_key_value_by_id_and_key")] fn execute(&self, wsv: &WorldStateView) -> Result { - let id = wsv - .evaluate(&self.id) - .map_err(|e| Error::Evaluate(format!("Failed to evaluate trigger id. {e}")))?; - let key = wsv - .evaluate(&self.key) - .map_err(|e| Error::Evaluate(format!("Failed to evaluate key. {e}")))?; + let id = &self.id; + let key = &self.key; iroha_logger::trace!(%id, %key); wsv.triggers() - .inspect_by_id(&id, |action| { + .inspect_by_id(id, |action| { action .metadata() - .get(&key) + .get(key) .cloned() .ok_or_else(|| FindError::MetadataKey(key.clone()).into()) }) - .ok_or_else(|| Error::Find(FindError::Trigger(id)))? + .ok_or_else(|| Error::Find(FindError::Trigger(id.clone())))? .map(Into::into) } } @@ -265,13 +257,11 @@ pub mod query { wsv: &'wsv WorldStateView, ) -> eyre::Result> + 'wsv>, Error> { - let domain_id = wsv - .evaluate(&self.domain_id) - .map_err(|e| Error::Evaluate(format!("Failed to evaluate domain id. {e}")))?; + let domain_id = &self.domain_id; Ok(Box::new( wsv.triggers() - .inspect_by_domain_id(&domain_id, |trigger_id, action| { + .inspect_by_domain_id(domain_id, |trigger_id, action| { (trigger_id.clone(), action.clone_and_box()) }) .map(|(trigger_id, action)| { diff --git a/core/src/smartcontracts/isi/triggers/set.rs b/core/src/smartcontracts/isi/triggers/set.rs index b32e49190e1..57e32ae1406 100644 --- a/core/src/smartcontracts/isi/triggers/set.rs +++ b/core/src/smartcontracts/isi/triggers/set.rs @@ -862,7 +862,7 @@ pub enum LoadedExecutable { /// Loaded WASM Wasm(LoadedWasm), /// Vector of ISI - Instructions(Vec), + Instructions(Vec), } impl core::fmt::Debug for LoadedExecutable { diff --git a/core/src/smartcontracts/isi/tx.rs b/core/src/smartcontracts/isi/tx.rs index b33fa69f7f5..f103853a9d5 100644 --- a/core/src/smartcontracts/isi/tx.rs +++ b/core/src/smartcontracts/isi/tx.rs @@ -2,11 +2,10 @@ use std::sync::Arc; -use eyre::{Result, WrapErr}; +use eyre::Result; use iroha_crypto::HashOf; use iroha_data_model::{ block::SignedBlock, - evaluate::ExpressionEvaluator, prelude::*, query::{ error::{FindError, QueryExecutionFail}, @@ -66,7 +65,7 @@ impl ValidQuery for FindAllTransactions { .flat_map(BlockTransactionIter::new) .map(|tx| TransactionQueryOutput { block_hash: tx.block_hash(), - transaction: tx.value(), + transaction: Box::new(tx.value()), }), )) } @@ -78,10 +77,7 @@ impl ValidQuery for FindTransactionsByAccountId { &self, wsv: &'wsv WorldStateView, ) -> Result + 'wsv>, QueryExecutionFail> { - let account_id = wsv - .evaluate(&self.account_id) - .wrap_err("Failed to get account id") - .map_err(|e| QueryExecutionFail::Evaluate(e.to_string()))?; + let account_id = self.account_id.clone(); Ok(Box::new( wsv.all_blocks() @@ -89,7 +85,7 @@ impl ValidQuery for FindTransactionsByAccountId { .filter(move |tx| *tx.authority() == account_id) .map(|tx| TransactionQueryOutput { block_hash: tx.block_hash(), - transaction: tx.value(), + transaction: Box::new(tx.value()), }), )) } @@ -98,10 +94,7 @@ impl ValidQuery for FindTransactionsByAccountId { impl ValidQuery for FindTransactionByHash { #[metrics(+"find_transaction_by_hash")] fn execute(&self, wsv: &WorldStateView) -> Result { - let tx_hash = wsv - .evaluate(&self.hash) - .wrap_err("Failed to get hash") - .map_err(|e| QueryExecutionFail::Evaluate(e.to_string()))?; + let tx_hash = self.hash; iroha_logger::trace!(%tx_hash); if !wsv.has_transaction(tx_hash) { return Err(FindError::Transaction(tx_hash).into()); @@ -118,6 +111,7 @@ impl ValidQuery for FindTransactionByHash { .iter() .find(|transaction| transaction.value.hash() == tx_hash) .cloned() + .map(Box::new) .map(|transaction| TransactionQueryOutput { block_hash, transaction, diff --git a/core/src/smartcontracts/isi/world.rs b/core/src/smartcontracts/isi/world.rs index 64199fd9eb8..44ae2f2eb2e 100644 --- a/core/src/smartcontracts/isi/world.rs +++ b/core/src/smartcontracts/isi/world.rs @@ -214,10 +214,10 @@ pub mod isi { } } - impl Execute for Upgrade { + impl Execute for Upgrade { #[metrics(+"upgrade_executor")] fn execute(self, authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - let raw_executor = self.object; + let raw_executor = self.executor; // Cloning executor to avoid multiple mutable borrows of `wsv`. // Also it's a cheap operation. @@ -303,13 +303,11 @@ pub mod query { impl ValidQuery for FindRoleByRoleId { #[metrics(+"find_role_by_role_id")] fn execute(&self, wsv: &WorldStateView) -> Result { - let role_id = wsv - .evaluate(&self.id) - .map_err(|e| Error::Evaluate(e.to_string()))?; + let role_id = &self.id; iroha_logger::trace!(%role_id); - wsv.world.roles.get(&role_id).map_or_else( - || Err(Error::Find(FindError::Role(role_id))), + wsv.world.roles.get(role_id).map_or_else( + || Err(Error::Find(FindError::Role(role_id.clone()))), |role_ref| Ok(role_ref.clone()), ) } diff --git a/core/src/smartcontracts/mod.rs b/core/src/smartcontracts/mod.rs index 05d0195defd..35587c6580b 100644 --- a/core/src/smartcontracts/mod.rs +++ b/core/src/smartcontracts/mod.rs @@ -7,15 +7,12 @@ pub mod isi; pub mod wasm; -use std::collections::BTreeMap; - use iroha_data_model::{ - evaluate::ExpressionEvaluator, isi::error::InstructionExecutionError as Error, prelude::*, - query::error::QueryExecutionFail, + isi::error::InstructionExecutionError as Error, prelude::*, query::error::QueryExecutionFail, }; pub use isi::*; -use self::query::{Lazy, LazyValue}; +use self::query::Lazy; use crate::wsv::WorldStateView; /// Trait implementations should provide actions to apply changes on [`WorldStateView`]. @@ -44,50 +41,3 @@ where wsv: &'wsv WorldStateView, ) -> Result<::Lazy<'wsv>, QueryExecutionFail>; } - -impl ExpressionEvaluator for WorldStateView { - fn evaluate( - &self, - expression: &E, - ) -> Result { - expression.evaluate(&Context::new(self)) - } -} - -#[derive(Clone)] -pub(crate) struct Context<'wsv> { - values: BTreeMap, - wsv: &'wsv WorldStateView, -} - -impl<'a> Context<'a> { - /// Create new [`Self`] - pub fn new(wsv: &'a WorldStateView) -> Self { - Self { - values: BTreeMap::new(), - wsv, - } - } -} - -impl iroha_data_model::evaluate::Context for Context<'_> { - fn query(&self, query: &QueryBox) -> Result { - query - .execute(self.wsv) - .map(|value| match value { - LazyValue::Value(value) => value, - // NOTE: This will only be executed when evaluating an expression for an - // instruction, i.e. it will only be executed from the executor. - LazyValue::Iter(iter) => Value::Vec(iter.collect()), - }) - .map_err(Into::into) - } - - fn get(&self, name: &Name) -> Option<&Value> { - self.values.get(name) - } - - fn update(&mut self, other: impl IntoIterator) { - self.values.extend(other) - } -} diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index a7c0b8b757e..cde7fe6a624 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -13,7 +13,7 @@ use iroha_config::{ use iroha_data_model::{ account::AccountId, executor::{self, MigrationResult}, - isi::InstructionExpr, + isi::InstructionBox, permission::PermissionTokenSchema, prelude::*, query::{QueryBox, QueryId, QueryRequest, QueryWithParameters}, @@ -87,7 +87,7 @@ mod import { /// Execute `instruction` on host #[codec::wrap_trait_fn] fn execute_instruction( - instruction: InstructionExpr, + instruction: InstructionBox, state: &mut S, ) -> Result<(), ValidationFail>; } @@ -100,7 +100,7 @@ mod import { fn get_validate_transaction_payload(state: &S) -> Validate; #[codec::wrap_trait_fn] - fn get_validate_instruction_payload(state: &S) -> Validate; + fn get_validate_instruction_payload(state: &S) -> Validate; #[codec::wrap_trait_fn] fn get_validate_query_payload(state: &S) -> Validate; @@ -480,7 +480,7 @@ pub mod state { pub type ValidateQuery = Validate; /// State kind for executing `validate_instruction()` entrypoint of executor - pub type ValidateInstruction = Validate; + pub type ValidateInstruction = Validate; /// State kind for executing `migrate()` entrypoint of executor #[derive(Copy, Clone)] @@ -802,7 +802,7 @@ where impl<'wrld, S> Runtime, S>> { fn default_execute_instruction( - instruction: InstructionExpr, + instruction: InstructionBox, state: &mut state::CommonState, S>, ) -> Result<(), ValidationFail> { debug!(%instruction, "Executing"); @@ -912,7 +912,7 @@ impl<'wrld> import::traits::ExecuteOperations> #[codec::wrap] fn execute_instruction( - instruction: InstructionExpr, + instruction: InstructionBox, state: &mut state::SmartContract<'wrld>, ) -> Result<(), ValidationFail> { if let Some(limits_executor) = state.specific_state.limits_executor.as_mut() { @@ -984,7 +984,7 @@ impl<'wrld> import::traits::ExecuteOperations> #[codec::wrap] fn execute_instruction( - instruction: InstructionExpr, + instruction: InstructionBox, state: &mut state::Trigger<'wrld>, ) -> Result<(), ValidationFail> { Self::default_execute_instruction(instruction, state) @@ -1015,7 +1015,7 @@ where #[codec::wrap] fn execute_instruction( - instruction: InstructionExpr, + instruction: InstructionBox, state: &mut state::CommonState, S>, ) -> Result<(), ValidationFail> { debug!(%instruction, "Executing as executor"); @@ -1109,7 +1109,7 @@ impl<'wrld> import::traits::GetExecutorPayloads, - ) -> Validate { + ) -> Validate { panic!("Executor `validate_transaction()` entrypoint should not query payload for `validate_instruction()` entrypoint") } @@ -1141,7 +1141,7 @@ impl<'wrld> Runtime> { wsv: &'wrld mut WorldStateView, authority: &AccountId, module: &wasmtime::Module, - instruction: InstructionExpr, + instruction: InstructionBox, ) -> Result { let span = wasm_log_span!("Running `validate_instruction()`"); @@ -1184,7 +1184,7 @@ impl<'wrld> import::traits::GetExecutorPayloads, - ) -> Validate { + ) -> Validate { Validate { authority: state.authority.clone(), block_height: state.wsv.0.height(), @@ -1253,7 +1253,7 @@ impl<'wrld> import::traits::ExecuteOperations, ) -> Result<(), ValidationFail> { panic!("Executor `validate_query()` entrypoint should not execute instructions") @@ -1278,7 +1278,7 @@ impl<'wrld> import::traits::GetExecutorPayloads, - ) -> Validate { + ) -> Validate { panic!("Executor `validate_query()` entrypoint should not query payload for `validate_instruction()` entrypoint") } @@ -1377,7 +1377,7 @@ impl<'wrld> import::traits::GetExecutorPayloads> #[codec::wrap] fn get_validate_instruction_payload( _state: &state::executor::Migrate<'wrld>, - ) -> Validate { + ) -> Validate { panic!("Executor `migrate()` entrypoint should not query payload for `validate_instruction()` entrypoint") } @@ -1715,8 +1715,8 @@ mod tests { let isi_hex = { let new_authority = AccountId::from_str("mad_hatter@wonderland").expect("Valid"); - let register_isi = RegisterExpr::new(Account::new(new_authority, [])); - encode_hex(InstructionExpr::from(register_isi)) + let register_isi = Register::account(Account::new(new_authority, [])); + encode_hex(InstructionBox::from(register_isi)) }; let wat = format!( @@ -1801,8 +1801,8 @@ mod tests { let isi_hex = { let new_authority = AccountId::from_str("mad_hatter@wonderland").expect("Valid"); - let register_isi = RegisterExpr::new(Account::new(new_authority, [])); - encode_hex(InstructionExpr::from(register_isi)) + let register_isi = Register::account(Account::new(new_authority, [])); + encode_hex(InstructionBox::from(register_isi)) }; let wat = format!( @@ -1850,8 +1850,8 @@ mod tests { let isi_hex = { let new_authority = AccountId::from_str("mad_hatter@wonderland").expect("Valid"); - let register_isi = RegisterExpr::new(Account::new(new_authority, [])); - encode_hex(InstructionExpr::from(register_isi)) + let register_isi = Register::account(Account::new(new_authority, [])); + encode_hex(InstructionBox::from(register_isi)) }; let wat = format!( diff --git a/core/src/sumeragi/main_loop.rs b/core/src/sumeragi/main_loop.rs index 441c0946b2d..b24b263188a 100644 --- a/core/src/sumeragi/main_loop.rs +++ b/core/src/sumeragi/main_loop.rs @@ -1210,7 +1210,7 @@ mod tests { // Create "genesis" block // Creating an instruction - let fail_box: InstructionExpr = Fail::new("Dummy isi").into(); + let fail_box: InstructionBox = Fail::new("Dummy isi".to_owned()).into(); // Making two transactions that have the same instruction let tx = TransactionBuilder::new(alice_id.clone()) @@ -1231,10 +1231,10 @@ mod tests { kura.store_block(genesis); // Making two transactions that have the same instruction - let create_asset_definition1 = RegisterExpr::new(AssetDefinition::quantity( + let create_asset_definition1 = Register::asset_definition(AssetDefinition::quantity( "xor1#wonderland".parse().expect("Valid"), )); - let create_asset_definition2 = RegisterExpr::new(AssetDefinition::quantity( + let create_asset_definition2 = Register::asset_definition(AssetDefinition::quantity( "xor2#wonderland".parse().expect("Valid"), )); diff --git a/core/src/tx.rs b/core/src/tx.rs index 790d8942326..01ee688edcf 100644 --- a/core/src/tx.rs +++ b/core/src/tx.rs @@ -36,179 +36,6 @@ pub enum AcceptTransactionFail { UnexpectedGenesisAccountSignature, } -mod len { - use iroha_data_model::{expression::*, query::QueryBox, Value}; - - pub trait ExprLen { - fn len(&self) -> usize; - } - - impl> ExprLen for EvaluatesTo { - fn len(&self) -> usize { - self.expression.len() - } - } - - impl ExprLen for Expression { - fn len(&self) -> usize { - use Expression::*; - - match self { - Add(add) => add.len(), - Subtract(subtract) => subtract.len(), - Greater(greater) => greater.len(), - Less(less) => less.len(), - Equal(equal) => equal.len(), - Not(not) => not.len(), - And(and) => and.len(), - Or(or) => or.len(), - If(if_expression) => if_expression.len(), - Raw(raw) => raw.len(), - Query(query) => query.len(), - Contains(contains) => contains.len(), - ContainsAll(contains_all) => contains_all.len(), - ContainsAny(contains_any) => contains_any.len(), - Where(where_expression) => where_expression.len(), - ContextValue(context_value) => context_value.len(), - Multiply(multiply) => multiply.len(), - Divide(divide) => divide.len(), - Mod(modulus) => modulus.len(), - RaiseTo(raise_to) => raise_to.len(), - } - } - } - impl ExprLen for ContextValue { - fn len(&self) -> usize { - 1 - } - } - impl ExprLen for QueryBox { - fn len(&self) -> usize { - 1 - } - } - - impl ExprLen for Add { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for Subtract { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for Multiply { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for RaiseTo { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for Divide { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for Mod { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for Greater { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for Less { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for Equal { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for And { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - impl ExprLen for Or { - fn len(&self) -> usize { - self.left.len() + self.right.len() + 1 - } - } - - impl ExprLen for Not { - fn len(&self) -> usize { - self.expression.len() + 1 - } - } - - impl ExprLen for Contains { - fn len(&self) -> usize { - self.collection.len() + self.element.len() + 1 - } - } - impl ExprLen for ContainsAll { - fn len(&self) -> usize { - self.collection.len() + self.elements.len() + 1 - } - } - impl ExprLen for ContainsAny { - fn len(&self) -> usize { - self.collection.len() + self.elements.len() + 1 - } - } - - impl ExprLen for If { - fn len(&self) -> usize { - // TODO: This is wrong because we don't evaluate both branches - self.condition.len() + self.then.len() + self.otherwise.len() + 1 - } - } - impl ExprLen for Where { - fn len(&self) -> usize { - self.expression.len() + self.values.values().map(EvaluatesTo::len).sum::() + 1 - } - } -} - -fn instruction_size(isi: &InstructionExpr) -> usize { - use len::ExprLen as _; - use InstructionExpr::*; - - match isi { - Register(isi) => isi.object.len() + 1, - Unregister(isi) => isi.object_id.len() + 1, - Mint(isi) => isi.destination_id.len() + isi.object.len() + 1, - Burn(isi) => isi.destination_id.len() + isi.object.len() + 1, - Transfer(isi) => isi.destination_id.len() + isi.object.len() + isi.source_id.len() + 1, - If(isi) => { - let otherwise = isi.otherwise.as_ref().map_or(0, instruction_size); - isi.condition.len() + instruction_size(&isi.then) + otherwise + 1 - } - Pair(isi) => { - instruction_size(&isi.left_instruction) + instruction_size(&isi.right_instruction) + 1 - } - Sequence(isi) => isi.instructions.iter().map(instruction_size).sum::() + 1, - SetKeyValue(isi) => isi.object_id.len() + isi.key.len() + isi.value.len() + 1, - RemoveKeyValue(isi) => isi.object_id.len() + isi.key.len() + 1, - Grant(isi) => isi.object.len() + isi.destination_id.len() + 1, - Revoke(isi) => isi.object.len() + isi.destination_id.len() + 1, - SetParameter(isi) => isi.parameter.len() + 1, - NewParameter(isi) => isi.parameter.len() + 1, - Upgrade(isi) => isi.object.len() + 1, - Log(isi) => isi.msg.len() + isi.msg.len() + 1, - Fail(_) | ExecuteTrigger(_) => 1, - } -} - impl AcceptedTransaction { /// Accept genesis transaction. Transition from [`GenesisTransaction`] to [`AcceptedTransaction`]. pub fn accept_genesis(tx: GenesisTransaction) -> Self { @@ -230,14 +57,10 @@ impl AcceptedTransaction { match &transaction.payload().instructions { Executable::Instructions(instructions) => { - let instruction_count: u64 = instructions - .iter() - .map(instruction_size) - .sum::() - .try_into() - .expect("`usize` should always fit in `u64`"); - - if instruction_count > limits.max_instruction_number { + let instruction_count = instructions.len(); + if u64::try_from(instruction_count).expect("`usize` should always fit into `u64`") + > limits.max_instruction_number + { return Err(AcceptTransactionFail::TransactionLimit( TransactionLimitError { reason: format!( @@ -426,67 +249,3 @@ impl TransactionExecutor { }) } } - -#[cfg(test)] -mod tests { - use core::str::FromStr as _; - - use super::*; - - fn if_instruction( - c: impl Into, - then: InstructionExpr, - otherwise: Option, - ) -> InstructionExpr { - let condition: Expression = c.into(); - let condition = EvaluatesTo::new_unchecked(condition); - ConditionalExpr { - condition, - then, - otherwise, - } - .into() - } - - fn fail() -> InstructionExpr { - Fail { - message: String::default(), - } - .into() - } - - #[test] - fn len_empty_sequence() { - assert_eq!(instruction_size(&SequenceExpr::new(vec![]).into()), 1); - } - - #[test] - fn len_if_one_branch() { - let instructions = vec![if_instruction( - ContextValue { - value_name: Name::from_str("a").expect("Cannot fail."), - }, - fail(), - None, - )]; - - assert_eq!(instruction_size(&SequenceExpr::new(instructions).into()), 4); - } - - #[test] - fn len_sequence_if() { - let instructions = vec![ - fail(), - if_instruction( - ContextValue { - value_name: Name::from_str("b").expect("Cannot fail."), - }, - fail(), - Some(fail()), - ), - fail(), - ]; - - assert_eq!(instruction_size(&SequenceExpr::new(instructions).into()), 7); - } -} diff --git a/core/src/wsv.rs b/core/src/wsv.rs index 29274a3323e..01c4e8e8d30 100644 --- a/core/src/wsv.rs +++ b/core/src/wsv.rs @@ -602,7 +602,7 @@ impl WorldStateView { fn process_instructions( &mut self, - instructions: impl IntoIterator, + instructions: impl IntoIterator, authority: &AccountId, ) -> Result<()> { instructions.into_iter().try_for_each(|instruction| { diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index 96c4210fd08..b51e1726e47 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -118,7 +118,7 @@ impl TestGenesis for GenesisNetwork { upgrade_executor_permission, ] { first_transaction - .append_instruction(GrantExpr::new(permission, alice_id.clone()).into()); + .append_instruction(Grant::permission_token(permission, alice_id.clone()).into()); } if submit_genesis { @@ -211,7 +211,7 @@ impl Network { time::sleep(Configuration::pipeline_time() + Configuration::block_sync_gossip_time()).await; - let add_peer = RegisterExpr::new(DataModelPeer::new(peer.id.clone())); + let add_peer = Register::peer(DataModelPeer::new(peer.id.clone())); genesis_client .submit(add_peer) .expect("Failed to add new peer."); @@ -704,7 +704,7 @@ pub trait TestClient: Sized { /// If predicate is not satisfied, after maximum retries. fn submit_all_till( &self, - instructions: Vec, + instructions: Vec, request: R, f: impl Fn(::Target) -> bool, ) -> eyre::Result<()> @@ -836,7 +836,7 @@ impl TestClient for Client { fn submit_all_till( &self, - instructions: Vec, + instructions: Vec, request: R, f: impl Fn(::Target) -> bool, ) -> eyre::Result<()> diff --git a/data_model/src/evaluate.rs b/data_model/src/evaluate.rs deleted file mode 100644 index b566bf4e0b9..00000000000 --- a/data_model/src/evaluate.rs +++ /dev/null @@ -1,869 +0,0 @@ -//! Implementations for Expression evaluation for different expressions. - -#[cfg(not(feature = "std"))] -use alloc::{ - boxed::Box, - collections::BTreeMap, - format, - string::{String, ToString}, - vec::Vec, -}; -#[cfg(feature = "std")] -use std::collections::BTreeMap; - -use iroha_data_model_derive::model; -use iroha_macro::FromVariant; -use iroha_schema::IntoSchema; - -pub use self::model::*; -use crate::{ - expression::{prelude::*, Expression}, - isi::error::{BinaryOpIncompatibleNumericValueTypesError, MathError}, - prelude::*, -}; - -/// Expression evaluator -pub trait ExpressionEvaluator { - /// Evaluates expression against current state of the underlying system - /// - /// # Errors - /// - /// - if expression is malformed - fn evaluate(&self, expression: &E) -> Result; -} - -/// Context of expression evaluation, holding (name, value) pairs for resolving identifiers. -/// Context comes into play because of [`Where`] and [`Query`] expressions. -/// -/// # Example -/// -/// Say you have an expression such as: `SELECT name FROM table WHERE name = "alice"`. This -/// compound expression is made up of two basic expressions, namely `SELECT FROM` and `WHERE`. -/// To evaluate any expression you have to substitute concrete values for variable names. -/// In this case, `WHERE` should be evaluated first which would place `name = "alice"` -/// inside the context. This context will then be used to evaluate `SELECT FROM`. -/// Starting expression would then be evaluated to `SELECT "alice" FROM table` -pub trait Context: Clone { - /// Execute query against the current state of `Iroha` - /// - /// # Errors - /// - /// If query execution fails - fn query(&self, query: &QueryBox) -> Result; - - /// Return a reference to the [`Value`] corresponding to the [`Name`]. - fn get(&self, name: &Name) -> Option<&Value>; - - /// Update this context with given values. - fn update(&mut self, other: impl IntoIterator); -} - -/// Calculate the result of the expression without mutating the state. -#[allow(clippy::len_without_is_empty)] // NOTE: Evaluate cannot be empty -pub trait Evaluate { - /// The resulting type of the expression. - type Value; - - /// Calculate result. - /// - /// # Errors - /// Concrete to each implementer. - fn evaluate(&self, context: &C) -> Result; -} - -impl> Evaluate for EvaluatesTo -where - V::Error: ToString, -{ - type Value = V; - - fn evaluate(&self, context: &C) -> Result { - let expr = self.expression.evaluate(context)?; - - V::try_from(expr).map_err(|error| EvaluationError::Conversion(error.to_string())) - } -} - -impl Evaluate for Expression { - type Value = Value; - - fn evaluate(&self, context: &C) -> Result { - macro_rules! match_evals { - ($($non_value: ident),+ $(,)?) => { - match self { $( - $non_value(expr) => expr.evaluate(context).map(Into::into)?, )+ - Raw(value) => value.clone(), - } - }; - } - - use Expression::*; - let result = match_evals!( - // numeric - Add, - Subtract, - Greater, - Less, - Multiply, - Divide, - Mod, - RaiseTo, - // logical - Equal, - Not, - And, - Or, - Contains, - ContainsAll, - ContainsAny, - // value - If, - Where, - Query, - ContextValue, - ); - - Ok(result) - } -} - -impl Evaluate for ContextValue { - type Value = Value; - - fn evaluate(&self, context: &C) -> Result { - context - .get(&self.value_name) - .cloned() - .ok_or_else(|| EvaluationError::Find(self.value_name.to_string())) - } -} - -mod numeric { - use super::*; - - impl Evaluate for Add { - type Value = NumericValue; - - fn evaluate(&self, context: &C) -> Result { - use NumericValue::*; - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - - let result = match (left, right) { - (U32(left), U32(right)) => left - .checked_add(right) - .ok_or(MathError::Overflow) - .map(NumericValue::from)?, - (U128(left), U128(right)) => left - .checked_add(right) - .ok_or(MathError::Overflow) - .map(NumericValue::from)?, - (Fixed(left), Fixed(right)) => left - .checked_add(right) - .map(NumericValue::from) - .map_err(MathError::from)?, - (left, right) => Err(MathError::from( - BinaryOpIncompatibleNumericValueTypesError { left, right }, - ))?, - }; - - Ok(result) - } - } - - impl Evaluate for Subtract { - type Value = NumericValue; - - fn evaluate(&self, context: &C) -> Result { - use NumericValue::*; - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - - let result = match (left, right) { - (U32(left), U32(right)) => left - .checked_sub(right) - .ok_or(MathError::NotEnoughQuantity) - .map(NumericValue::from)?, - (U128(left), U128(right)) => left - .checked_sub(right) - .ok_or(MathError::NotEnoughQuantity) - .map(NumericValue::from)?, - (Fixed(left), Fixed(right)) => left - .checked_sub(right) - .map(NumericValue::from) - .map_err(MathError::from)?, - (left, right) => Err(MathError::from( - BinaryOpIncompatibleNumericValueTypesError { left, right }, - ))?, - }; - - Ok(result) - } - } - - impl Evaluate for Multiply { - type Value = NumericValue; - - fn evaluate(&self, context: &C) -> Result { - use NumericValue::*; - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - - let result = match (left, right) { - (U32(left), U32(right)) => left - .checked_mul(right) - .ok_or(MathError::Overflow) - .map(NumericValue::from)?, - (U128(left), U128(right)) => left - .checked_mul(right) - .ok_or(MathError::Overflow) - .map(NumericValue::from)?, - (Fixed(left), Fixed(right)) => left - .checked_mul(right) - .map(NumericValue::from) - .map_err(MathError::from)?, - (left, right) => Err(MathError::from( - BinaryOpIncompatibleNumericValueTypesError { left, right }, - ))?, - }; - - Ok(result) - } - } - - impl Evaluate for RaiseTo { - type Value = NumericValue; - - fn evaluate(&self, context: &C) -> Result { - use NumericValue::*; - let value = self.left.evaluate(context)?; - let exp = self.right.evaluate(context)?; - - let result = match (value, exp) { - (U32(value), U32(exp)) => value - .checked_pow(exp) - .ok_or(MathError::Overflow) - .map(NumericValue::from)?, - (U128(value), U32(exp)) => value - .checked_pow(exp) - .ok_or(MathError::Overflow) - .map(NumericValue::from)?, - // TODO (#2945): Extend `RaiseTo` to support `Fixed` - (left, right) => Err(MathError::from( - BinaryOpIncompatibleNumericValueTypesError { left, right }, - ))?, - }; - - Ok(result) - } - } - - impl Evaluate for Divide { - type Value = NumericValue; - - fn evaluate(&self, context: &C) -> Result { - use NumericValue::*; - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - - let result = match (left, right) { - (U32(left), U32(right)) => left - .checked_div(right) - .ok_or(MathError::DivideByZero) - .map(NumericValue::from)?, - (U128(left), U128(right)) => left - .checked_div(right) - .ok_or(MathError::DivideByZero) - .map(NumericValue::from)?, - (Fixed(left), Fixed(right)) => left - .checked_div(right) - .map(NumericValue::from) - .map_err(MathError::from)?, - (left, right) => Err(MathError::from( - BinaryOpIncompatibleNumericValueTypesError { left, right }, - ))?, - }; - - Ok(result) - } - } - - impl Evaluate for Mod { - type Value = NumericValue; - - fn evaluate(&self, context: &C) -> Result { - use NumericValue::*; - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - - let result = match (left, right) { - (U32(left), U32(right)) => left - .checked_rem(right) - .ok_or(MathError::DivideByZero) - .map(NumericValue::from)?, - (U128(left), U128(right)) => left - .checked_rem(right) - .ok_or(MathError::DivideByZero) - .map(NumericValue::from)?, - (left, right) => Err(MathError::from( - BinaryOpIncompatibleNumericValueTypesError { left, right }, - ))?, - }; - - Ok(result) - } - } -} - -mod logical { - use super::*; - - impl Evaluate for Greater { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - use NumericValue::*; - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - - let result = match (left, right) { - (U32(left), U32(right)) => left > right, - (U128(left), U128(right)) => left > right, - (Fixed(left), Fixed(right)) => left > right, - (left, right) => Err(MathError::from( - BinaryOpIncompatibleNumericValueTypesError { left, right }, - ))?, - }; - - Ok(result) - } - } - - impl Evaluate for Less { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - use NumericValue::*; - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - - let result = match (left, right) { - (U32(left), U32(right)) => left < right, - (U128(left), U128(right)) => left < right, - (Fixed(left), Fixed(right)) => left < right, - (left, right) => Err(MathError::from( - BinaryOpIncompatibleNumericValueTypesError { left, right }, - ))?, - }; - - Ok(result) - } - } - - impl Evaluate for Equal { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - Ok(left == right) - } - } - - impl Evaluate for And { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - Ok(left && right) - } - } - - impl Evaluate for Or { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - let left = self.left.evaluate(context)?; - let right = self.right.evaluate(context)?; - Ok(left || right) - } - } - - impl Evaluate for Not { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - let expression = self.expression.evaluate(context)?; - Ok(!expression) - } - } - - impl Evaluate for Contains { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - let collection = self.collection.evaluate(context)?; - let element = self.element.evaluate(context)?; - Ok(collection.contains(&element)) - } - } - - impl Evaluate for ContainsAll { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - let collection = self.collection.evaluate(context)?; - let elements = self.elements.evaluate(context)?; - Ok(elements.iter().all(|element| collection.contains(element))) - } - } - - impl Evaluate for ContainsAny { - type Value = bool; - - fn evaluate(&self, context: &C) -> Result { - let collection = self.collection.evaluate(context)?; - let elements = self.elements.evaluate(context)?; - Ok(elements.iter().any(|element| collection.contains(element))) - } - } -} - -impl Evaluate for If { - type Value = Value; - - fn evaluate(&self, context: &C) -> Result { - let condition = self.condition.evaluate(context)?; - if condition { - self.then.evaluate(context) - } else { - self.otherwise.evaluate(context) - } - } -} - -impl Evaluate for Where { - type Value = Value; - - fn evaluate(&self, context: &C) -> Result { - let additional_context: Result, EvaluationError> = self - .values - .clone() - .into_iter() - .map(|(value_name, expression)| { - expression - .evaluate(context) - .map(|expression_result| (value_name, expression_result)) - }) - .collect(); - - let mut combined_context = context.clone(); - combined_context.update(additional_context?); - self.expression.evaluate(&combined_context) - } -} - -impl Evaluate for QueryBox { - type Value = Value; - - fn evaluate(&self, context: &C) -> Result { - context - .query(self) - .map_err(|err| EvaluationError::Validation(Box::new(err))) - } -} - -#[model] -pub mod model { - #[cfg(not(feature = "std"))] - use alloc::boxed::Box; - - use parity_scale_codec::{Decode, Encode}; - use serde::{Deserialize, Serialize}; - - use super::*; - - /// Expression evaluation error - #[derive( - Debug, - displaydoc::Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - FromVariant, - Deserialize, - Serialize, - Decode, - Encode, - IntoSchema, - )] - #[cfg_attr(feature = "std", derive(thiserror::Error))] - // TODO: Only temporarily opaque because of problems with FFI - #[ffi_type(opaque)] - pub enum EvaluationError { - /// Failed due to math exception - Math(#[cfg_attr(feature = "std", source)] MathError), - /// Validation failed - Validation(#[cfg_attr(feature = "std", source)] Box), - /// `{0}`: Value not found in the context - Find( - #[skip_from] - #[skip_try_from] - String, - ), - /// Conversion evaluation error: {0} - Conversion( - #[skip_from] - #[skip_try_from] - String, - ), - } -} - -pub mod prelude { - //! Prelude: re-export of most commonly used traits, structs and macros in this crate. - - pub use super::Evaluate; -} - -#[cfg(test)] -mod tests { - use core::{fmt::Debug, str::FromStr as _}; - - use iroha_crypto::KeyPair; - use iroha_primitives::fixed::Fixed; - use parity_scale_codec::{DecodeAll, Encode}; - - use super::*; - use crate::val_vec; - - /// Context of expression evaluation - #[derive(Clone)] - #[repr(transparent)] - struct TestContext { - values: BTreeMap, - } - - impl TestContext { - fn new() -> Self { - Self { - values: BTreeMap::new(), - } - } - } - - impl super::Context for TestContext { - fn query(&self, _: &QueryBox) -> Result { - unimplemented!("This has to be tested on iroha_core") - } - - fn get(&self, name: &Name) -> Option<&Value> { - self.values.get(name) - } - - fn update(&mut self, other: impl IntoIterator) { - self.values.extend(other) - } - } - - /// Example taken from [whitepaper](https://github.com/hyperledger/iroha/blob/iroha2-dev/docs/source/iroha_2_whitepaper.md#261-multisignature-transactions) - #[test] - #[allow(clippy::too_many_lines)] - fn conditional_multisignature_quorum() -> Result<(), EvaluationError> { - let asset_quantity_high = 750_u32.to_value(); - let asset_quantity_low = 300_u32.to_value(); - let (public_key_teller_1, _) = KeyPair::generate().expect("Valid").into(); - let (public_key_teller_2, _) = KeyPair::generate().expect("Valid").into(); - let (manager_public_key, _) = KeyPair::generate().expect("Valid").into(); - let teller_signatory_set = vec![ - Value::PublicKey(public_key_teller_1.clone()), - Value::PublicKey(public_key_teller_2), - ]; - let one_teller_set = Value::Vec(vec![Value::PublicKey(public_key_teller_1)]); - let manager_signatory = Value::PublicKey(manager_public_key); - let manager_signatory_set = Value::Vec(vec![manager_signatory.clone()]); - let condition = If::new( - And::new( - Greater::new( - EvaluatesTo::new_unchecked(ContextValue::new( - Name::from_str("usd_quantity").expect("Can't fail."), - )), - 500_u32, - ), - Less::new( - EvaluatesTo::new_unchecked(ContextValue::new( - Name::from_str("usd_quantity").expect("Can't fail."), - )), - 1000_u32, - ), - ), - EvaluatesTo::new_evaluates_to_value(Or::new( - ContainsAll::new( - EvaluatesTo::new_unchecked(ContextValue::new( - Name::from_str("signatories").expect("Can't fail."), - )), - teller_signatory_set.clone(), - ), - Contains::new( - EvaluatesTo::new_unchecked(ContextValue::new( - Name::from_str("signatories").expect("Can't fail."), - )), - manager_signatory, - ), - )), - true, - ); - // Signed by all tellers - let expression = Where::new(EvaluatesTo::new_evaluates_to_value(condition.clone())) - .with_value( - //TODO: use query to get the actual quantity of an asset from WSV - // in that case this test should be moved to iroha_core - Name::from_str("usd_quantity").expect("Can't fail."), - asset_quantity_high.clone(), - ) - .with_value( - Name::from_str("signatories").expect("Can't fail."), - teller_signatory_set, - ); - assert_eq!(expression.evaluate(&TestContext::new())?, Value::Bool(true)); - // Signed by manager - let expression = Where::new(EvaluatesTo::new_evaluates_to_value(condition.clone())) - .with_value( - Name::from_str("usd_quantity").expect("Can't fail."), - asset_quantity_high.clone(), - ) - .with_value( - Name::from_str("signatories").expect("Can't fail."), - manager_signatory_set, - ); - assert_eq!(expression.evaluate(&TestContext::new())?, Value::Bool(true)); - // Signed by one teller - let expression = Where::new(EvaluatesTo::new_evaluates_to_value(condition.clone())) - .with_value( - Name::from_str("usd_quantity").expect("Can't fail."), - asset_quantity_high, - ) - .with_value( - Name::from_str("signatories").expect("Can't fail."), - one_teller_set.clone(), - ); - assert_eq!( - expression.evaluate(&TestContext::new())?, - Value::Bool(false) - ); - // Signed by one teller with less value - let expression = Where::new(EvaluatesTo::new_evaluates_to_value(condition)) - .with_value( - Name::from_str("usd_quantity").expect("Can't fail."), - asset_quantity_low, - ) - .with_value( - Name::from_str("signatories").expect("Can't fail."), - one_teller_set, - ); - assert_eq!(expression.evaluate(&TestContext::new())?, Value::Bool(true)); - Ok(()) - } - - #[test] - fn where_expression() -> Result<(), EvaluationError> { - assert_eq!( - Where::new(EvaluatesTo::new_unchecked(ContextValue::new( - Name::from_str("test_value").expect("Can't fail.") - ))) - .with_value( - Name::from_str("test_value").expect("Can't fail."), - EvaluatesTo::new_evaluates_to_value(Add::new(2_u32, 3_u32)) - ) - .evaluate(&TestContext::new())?, - 5_u32.to_value() - ); - Ok(()) - } - - #[test] - fn nested_where_expression() -> Result<(), EvaluationError> { - let expression = Where::new(EvaluatesTo::new_unchecked(ContextValue::new( - Name::from_str("a").expect("Can't fail."), - ))) - .with_value(Name::from_str("a").expect("Can't fail."), 2_u32); - let outer_expression = Where::new(EvaluatesTo::new_evaluates_to_value(Add::new( - EvaluatesTo::new_unchecked(expression), - EvaluatesTo::new_unchecked(ContextValue::new( - Name::from_str("b").expect("Can't fail."), - )), - ))) - .with_value(Name::from_str("b").expect("Can't fail."), 4_u32); - assert_eq!( - outer_expression.evaluate(&TestContext::new())?, - 6_u32.to_value() - ); - Ok(()) - } - - #[test] - fn if_condition_branches_correctly() -> Result<(), EvaluationError> { - assert_eq!( - If::new(true, 1_u32, 2_u32).evaluate(&TestContext::new())?, - 1_u32.to_value() - ); - assert_eq!( - If::new(false, 1_u32, 2_u32).evaluate(&TestContext::new())?, - 2_u32.to_value() - ); - Ok(()) - } - - #[test] - #[allow(clippy::unnecessary_wraps)] - fn incorrect_types_are_caught() -> Result<(), EvaluationError> { - fn assert_eval(inst: &I, err_msg: &str) - where - I: Evaluate + Debug, - I::Value: Debug, - { - let result: Result<_, _> = inst.evaluate(&TestContext::new()); - let _err = result.expect_err(err_msg); - } - - assert_eval( - &And::new( - EvaluatesTo::new_unchecked(1_u32), - EvaluatesTo::new_unchecked(Vec::::new()), - ), - "Should not be possible to apply logical and to int and vec.", - ); - assert_eval( - &Or::new( - EvaluatesTo::new_unchecked(1_u32), - EvaluatesTo::new_unchecked(Vec::::new()), - ), - "Should not be possible to apply logical or to int and vec.", - ); - assert_eval( - &Greater::new( - EvaluatesTo::new_unchecked(1_u32), - EvaluatesTo::new_unchecked(Vec::::new()), - ), - "Should not be possible to apply greater sign to int and vec.", - ); - assert_eval( - &Less::new( - EvaluatesTo::new_unchecked(1_u32), - EvaluatesTo::new_unchecked(Vec::::new()), - ), - "Should not be possible to apply greater sign to int and vec.", - ); - assert_eval( - &If::new(EvaluatesTo::new_unchecked(1_u32), 2_u32, 3_u32), - "If condition should be bool", - ); - assert_eval( - &Add::new(10_u32, 1_u128), - "Should not be possible to add `u32` and `u128`", - ); - assert_eval( - &Subtract::new(Fixed::try_from(10.2_f64).map_err(MathError::from)?, 1_u128), - "Should not be possible to subtract `Fixed` and `u128`", - ); - assert_eval( - &Multiply::new(0_u32, Fixed::try_from(1.0_f64).map_err(MathError::from)?), - "Should not be possible to multiply `u32` and `Fixed`", - ); - Ok(()) - } - - #[test] - fn operations_are_correctly_calculated() -> Result<(), EvaluationError> { - assert_eq!( - Add::new(1_u32, 2_u32).evaluate(&TestContext::new())?, - 3_u32.into() - ); - assert_eq!( - Add::new(1_u128, 2_u128).evaluate(&TestContext::new())?, - 3_u128.into(), - ); - assert_eq!( - Add::new( - Fixed::try_from(1.17_f64).map_err(MathError::from)?, - Fixed::try_from(2.13_f64).map_err(MathError::from)? - ) - .evaluate(&TestContext::new())?, - 3.30_f64.try_into().map_err(MathError::from)? - ); - assert_eq!( - Subtract::new(7_u32, 2_u32).evaluate(&TestContext::new())?, - 5_u32.into() - ); - assert_eq!( - Subtract::new(7_u128, 2_u128).evaluate(&TestContext::new())?, - 5_u128.into() - ); - assert_eq!( - Subtract::new( - Fixed::try_from(7.250_f64).map_err(MathError::from)?, - Fixed::try_from(2.125_f64).map_err(MathError::from)? - ) - .evaluate(&TestContext::new())?, - 5.125_f64.try_into().map_err(MathError::from)? - ); - assert!(!Greater::new(1_u32, 2_u32).evaluate(&TestContext::new())?); - assert!(Greater::new(2_u32, 1_u32).evaluate(&TestContext::new())?); - assert!(Less::new(1_u32, 2_u32).evaluate(&TestContext::new())?); - assert!(!Less::new(2_u32, 1_u32).evaluate(&TestContext::new())?); - assert!(!Equal::new(1_u32, 2_u32).evaluate(&TestContext::new())?); - assert!( - Equal::new(vec![1_u32, 3_u32, 5_u32], vec![1_u32, 3_u32, 5_u32]) - .evaluate(&TestContext::new())? - ); - assert!(Contains::new(val_vec![1_u32, 3_u32, 5_u32], 3_u32).evaluate(&TestContext::new())?); - assert!(!Contains::new(val_vec![1_u32, 3_u32, 5_u32], 7_u32).evaluate(&TestContext::new())?); - assert!( - ContainsAll::new(val_vec![1_u32, 3_u32, 5_u32], val_vec![1_u32, 5_u32]) - .evaluate(&TestContext::new())? - ); - assert!( - !ContainsAll::new(val_vec![1_u32, 3_u32, 5_u32], val_vec![1_u32, 5_u32, 7_u32]) - .evaluate(&TestContext::new())? - ); - Ok(()) - } - - #[test] - #[ignore = "Stack overflow"] - fn serde_serialization_works() { - let expression: Expression = Add::new(1_u32, Subtract::new(7_u32, 4_u32)).into(); - let serialized_expression = - serde_json::to_string(&expression).expect("Failed to serialize."); - let deserialized_expression: Expression = - serde_json::from_str(&serialized_expression).expect("Failed to de-serialize."); - assert_eq!( - expression - .evaluate(&TestContext::new()) - .expect("Failed to calculate."), - deserialized_expression - .evaluate(&TestContext::new()) - .expect("Failed to calculate.") - ) - } - - #[test] - fn scale_codec_serialization_works() { - let expression: Expression = Add::new(1_u32, Subtract::new(7_u32, 4_u32)).into(); - let serialized_expression: Vec = expression.encode(); - let deserialized_expression: Expression = - DecodeAll::decode_all(&mut serialized_expression.as_slice()) - .expect("Failed to decode."); - assert_eq!( - expression - .evaluate(&TestContext::new()) - .expect("Failed to calculate."), - deserialized_expression - .evaluate(&TestContext::new()) - .expect("Failed to calculate.") - ) - } -} diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 8bf07a8e49b..90f1caf2cf8 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -566,6 +566,7 @@ mod executor { #[derive( Debug, + Copy, Clone, PartialEq, Eq, @@ -586,6 +587,23 @@ mod executor { } /// Filter for [`ExecutorEvent`]. + #[derive( + Debug, + Copy, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + parity_scale_codec::Decode, + parity_scale_codec::Encode, + serde::Deserialize, + serde::Serialize, + iroha_schema::IntoSchema, + )] + #[non_exhaustive] + #[serde(untagged)] // Unaffected by #3330, as single unit variant + #[repr(transparent)] pub enum ExecutorFilter { Upgraded, } diff --git a/data_model/src/expression.rs b/data_model/src/expression.rs deleted file mode 100644 index b5e75ce26bc..00000000000 --- a/data_model/src/expression.rs +++ /dev/null @@ -1,703 +0,0 @@ -//! Expressions to use inside of ISIs. - -#![allow( - // Because of `codec(skip)` - clippy::default_trait_access, - // Because of length on instructions and expressions (can't be 0) - clippy::len_without_is_empty, - // Because of length on instructions and expressions (XXX: Should it be trait?) - clippy::unused_self -)] - -#[cfg(not(feature = "std"))] -use alloc::{boxed::Box, collections::btree_map, format, string::String, vec, vec::Vec}; -use core::marker::PhantomData; -#[cfg(feature = "std")] -use std::collections::btree_map; - -use derive_more::{Constructor, DebugCustom, Display}; -use getset::Getters; -use iroha_data_model_derive::{model, PartiallyTaggedDeserialize, PartiallyTaggedSerialize}; -use iroha_macro::FromVariant; -use iroha_schema::{IntoSchema, TypeId}; -use operation::*; -use parity_scale_codec::{Decode, Encode}; -use serde::{Deserialize, Serialize}; - -pub use self::model::*; -use super::{query::QueryBox, Name, Value}; -use crate::NumericValue; - -/// Generate expression structure and basic impls for it. -/// -/// # Syntax -/// -/// Basic syntax: -/// -/// ```ignore -/// gen_expr_and_impls! { -/// /// Comment -/// #[derive(Derives)] -/// pub Expr(param1: Type1, param2: Type2, param3: Type3, ...) -> OutputType -/// } -/// ``` -/// -/// The macro has three syntax forms to specify parameters: -/// - One unnamed parameter. In that case, the parameter name will be `expression`. -/// - Two unnamed parameters. -/// In that case, the parameter names will be `left` and `right` respectively. -/// - Any number of named parameters. -/// -/// The macro has two syntax forms to specify result: -/// - With the actual result type after the arrow (`->`). -/// In that case, `impl From<$i> for EvaluatesTo<$result_type>` will be generated. -/// - With `?` sign as a result type. -/// In that case `impl From<$i> for EvaluatesTo<$result_type>` **won't** be generated. -/// -/// See the example and further usage for more details. -/// -/// # Example -/// -/// ```ignore -/// gen_expr_and_impls! { -/// /// Evaluates to the sum of left and right expressions. -/// #[derive(Debug)] -/// pub Add(u32, u32) -> u32 -/// } -/// -/// // Will generate the following code: -/// -/// /// Evaluates to the sum of left and right expressions. -/// iroha_data_model_derive::model_single! { -/// #[derive(Debug)] -/// pub struct Add { -/// #[allow(missing_docs)] -/// pub left: EvaluatesTo, -/// #[allow(missing_docs)] -/// pub right: EvaluatesTo, -/// } -/// } -/// -/// impl Add { -/// /// Construct new [`Add`] expression -/// pub fn new(left: impl Into>, right: impl Into>) -> Self { -/// Self { -/// left: left.into(), -/// right: right.into(), -/// } -/// } -/// } -/// -/// impl From for EvaluatesTo { -/// fn from(expression: Add) -> Self { -/// EvaluatesTo::new_unchecked(expression) -/// } -/// } -/// ``` -macro_rules! gen_expr_and_impls { - // Case: one unnamed parameter - ($(#[$me:meta])* $v:vis $i:ident($first_type:ty $(,)?) -> $($result:tt)*) => { - gen_expr_and_impls!($(#[$me])* $v $i(expression: $first_type) -> $($result)*); - }; - // Case: two unnamed parameters - ($(#[$me:meta])* $v:vis $i:ident($first_type:ty, $second_type:ty $(,)?) -> $($result:tt)*) => { - gen_expr_and_impls!($(#[$me])* $v $i(left: $first_type, right: $second_type) -> $($result)*); - }; - // Case: any number of named parameters - ($(#[$me:meta])* $v:vis $i:ident($($param_name:ident: $param_type:ty),* $(,)?) -> $($result:tt)*) => { - gen_expr_and_impls!(impl_basic $(#[$me])* $v $i($($param_name: $param_type),*)); - gen_expr_and_impls!(impl_extra_convert $i $($result)*); - }; - // Internal usage: generate basic code for the expression - (impl_basic $(#[$me:meta])* $v:vis $i:ident($($param_name:ident: $param_type:ty),* $(,)?)) => { - iroha_data_model_derive::model_single! { - #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Getters, Decode, Encode, Deserialize, Serialize, IntoSchema)] - #[getset(get = "pub")] - $(#[$me])* - $v struct $i { $( - /// - #[allow(missing_docs)] - pub $param_name: EvaluatesTo<$param_type>, )* - } - } - - impl $i { - #[doc = concat!(" Construct new [`", stringify!($i), "`] expression")] - pub fn new( - $($param_name: impl Into>),* - ) -> Self { - Self { - $($param_name: $param_name.into()),* - } - } - } - }; - // Internal usage: do nothing for expressions with unknown result type - (impl_extra_convert $i:ident ?) => { - }; - // Internal usage: generate extra `From` impl for expressions with known result type - (impl_extra_convert $i:ident $result_type:ty) => { - impl From<$i> for EvaluatesTo<$result_type> { - fn from(expression: $i) -> Self { - EvaluatesTo::new_unchecked(expression) - } - } - }; -} - -#[model] -pub mod model { - use super::*; - - /// Struct for type checking and converting expression results. - #[derive( - DebugCustom, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - TypeId, - )] - // As this structure exists only for type checking - // it makes sense to display `expression` directly - #[display(fmt = "{expression}")] - #[debug(fmt = "{expression:?}")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `EvaluatesTo` has no trap representation in `Box` - #[ffi_type(unsafe {robust})] - pub struct EvaluatesTo { - /// Expression. - #[serde(flatten)] - pub expression: Box, - #[codec(skip)] - pub(super) _value_type: PhantomData, - } - - /// Represents all possible expressions. - #[derive( - DebugCustom, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - FromVariant, - Decode, - Encode, - PartiallyTaggedDeserialize, - PartiallyTaggedSerialize, - IntoSchema, - )] - #[ffi_type(opaque)] - pub enum Expression { - /// Add expression. - Add(Add), - /// Subtract expression. - Subtract(Subtract), - /// Multiply expression. - Multiply(Multiply), - /// Divide expression. - Divide(Divide), - /// Module expression. - Mod(Mod), - /// Raise to power expression. - RaiseTo(RaiseTo), - /// Greater expression. - Greater(Greater), - /// Less expression. - Less(Less), - /// Equal expression. - Equal(Equal), - /// Not expression. - Not(Not), - /// And expression. - And(And), - /// Or expression. - Or(Or), - /// If expression. - If(If), - /// Raw value. - #[serde_partially_tagged(untagged)] - #[debug(fmt = "{_0:?}")] - Raw(#[skip_from] Value), - /// Query to Iroha state. - Query(QueryBox), - /// Contains expression for vectors. - Contains(Contains), - /// Contains all expression for vectors. - ContainsAll(ContainsAll), - /// Contains any expression for vectors. - ContainsAny(ContainsAny), - /// Where expression to supply temporary values to local context. - Where(Where), - /// Get a temporary value by name - ContextValue(ContextValue), - } - - /// Get a temporary value by name. The values are brought into [`Context`] by [`Where`] expression. - // NOTE: Can't use `gen_expr_and_impls!` here because we need special type for `value_name` - #[derive( - Debug, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Getters, - Constructor, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[display(fmt = "CONTEXT `{value_name}`")] - #[getset(get = "pub")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `ContextValue` has no trap representation in `Name` - #[ffi_type(unsafe {robust})] - pub struct ContextValue { - /// Name bound to the value. - pub value_name: Name, - } - - gen_expr_and_impls! { - /// Evaluates to the multiplication of left and right expressions. - #[derive(Display)] - #[display(fmt = "{}*{}", // Keep without spaces - "self.left.parenthesise(Operation::Multiply)", - "self.right.parenthesise(Operation::Multiply)" - )] - #[ffi_type] - pub Multiply(NumericValue, NumericValue) -> NumericValue - } - - gen_expr_and_impls! { - /// Evaluates to the left expression divided by the right expression. - #[derive(Display)] - #[display(fmt = "{}/{}", // Keep without spaces - "self.left.parenthesise(Operation::Divide)", - "self.right.parenthesise(Operation::Divide)" - )] - #[ffi_type] - pub Divide(NumericValue, NumericValue) -> NumericValue - } - - gen_expr_and_impls! { - /// Evaluates to the left expression modulo the right expression. - #[derive(Display)] - #[display(fmt = "{} % {}", - "self.left.parenthesise(Operation::Mod)", - "self.right.parenthesise(Operation::Mod)" - )] - #[ffi_type] - pub Mod(NumericValue, NumericValue) -> NumericValue - } - - gen_expr_and_impls! { - /// Evaluates to the left expression in the power of right expression. - /// Currently does not support [`NumericValue::Fixed`]. - #[derive(Display)] - #[display(fmt = "{}**{}", - "self.left.parenthesise(Operation::RaiseTo)", - "self.right.parenthesise(Operation::RaiseTo)" - )] - #[ffi_type] - pub RaiseTo(NumericValue, NumericValue) -> NumericValue - } - - gen_expr_and_impls! { - /// Evaluates to the sum of left and right expressions. - #[derive(Display)] - #[display(fmt = "{}+{}", - "self.left.parenthesise(Operation::Add)", - "self.right.parenthesise(Operation::Add)" - )] - #[ffi_type] - pub Add(NumericValue, NumericValue) -> NumericValue - } - - gen_expr_and_impls! { - /// Evaluates to the left expression minus the right expression. - #[derive(Display)] - #[display(fmt = "{}-{}", - "self.left.parenthesise(Operation::Subtract)", - "self.right.parenthesise(Operation::Subtract)" - )] - #[ffi_type] - pub Subtract(NumericValue, NumericValue) -> NumericValue - } - - gen_expr_and_impls! { - /// Returns whether the `left` expression is greater than the `right`. - #[derive(Display)] - #[display(fmt = "{} > {}", - "self.left.parenthesise(Operation::Greater)", - "self.right.parenthesise(Operation::Greater)" - )] - #[ffi_type] - pub Greater(NumericValue, NumericValue) -> bool - } - - gen_expr_and_impls! { - /// Returns whether the `left` expression is less than the `right`. - #[derive(Display)] - #[display(fmt = "{} < {}", - "self.left.parenthesise(Operation::Less)", - "self.right.parenthesise(Operation::Less)" - )] - #[ffi_type] - pub Less(NumericValue, NumericValue) -> bool - } - - gen_expr_and_impls! { - /// Negates the result of the `expression`. - /// Works only for `Value::Bool`. - #[derive(Display)] - #[display(fmt = "!{}", "self.expression.parenthesise(Operation::Not)")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `Not` has no trap representation in `bool` - #[ffi_type(unsafe {robust})] - pub Not(bool) -> bool - } - - gen_expr_and_impls! { - /// Applies the logical `and` to two `Value::Bool` operands. - #[derive(Display)] - #[display(fmt = "{} && {}", - "self.left.parenthesise(Operation::And)", - "self.right.parenthesise(Operation::And)" - )] - #[ffi_type] - pub And(bool, bool) -> bool - } - - gen_expr_and_impls! { - /// Applies the logical `or` to two `Value::Bool` operands. - #[derive(Display)] - #[display(fmt = "{} || {}", - "self.left.parenthesise(Operation::Or)", - "self.right.parenthesise(Operation::Or)" - )] - #[ffi_type] - pub Or(bool, bool) -> bool - } - - gen_expr_and_impls! { - /// If expression. Based on the `condition`, returns the result of either `then` or `otherwise`. - #[derive(Display)] - #[display(fmt = "if {condition} {{ {then} }} else {{ {otherwise} }}")] - #[ffi_type] - pub If(condition: bool, then: Value, otherwise: Value) -> ? - } - - gen_expr_and_impls! { - /// `Contains` expression. - /// Returns `true` if `collection` contains an `element`, `false` otherwise. - #[derive(Display)] - #[display(fmt = "{}.contains({})", "collection.parenthesise(Operation::MethodCall)", "element")] - #[ffi_type] - pub Contains(collection: Vec, element: Value) -> bool - } - - gen_expr_and_impls! { - /// `ContainsAll` expression. - /// Returns `true` if `collection` contains all `elements`, `false` otherwise. - #[derive(Display)] - #[display(fmt = "{}.contains_all({})", "collection.parenthesise(Operation::MethodCall)", "elements")] - #[ffi_type] - pub ContainsAll(collection: Vec, elements: Vec) -> bool - } - - gen_expr_and_impls! { - /// `ContainsAny` expression. - /// Returns `true` if `collection` contains any element out of the `elements`, `false` otherwise. - #[derive(Display)] - #[display(fmt = "{}.contains_any({})", "collection.parenthesise(Operation::MethodCall)", "elements")] - #[ffi_type] - pub ContainsAny(collection: Vec, elements: Vec) -> bool - } - - gen_expr_and_impls! { - /// Returns `true` if `left` operand is equal to the `right` operand. - #[derive(Display)] - #[display(fmt = "{} == {}", - "self.left.parenthesise(Operation::Equal)", - "self.right.parenthesise(Operation::Equal)" - )] - #[ffi_type] - pub Equal(Value, Value) -> bool - } - - /// Adds a local context of `values` for the `expression`. - /// It is similar to **where** syntax in *Haskell* although evaluated eagerly. - // NOTE: Can't use `gen_expr_and_impls!` here because we need special type for `values` - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Getters, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[ffi_type] - pub struct Where { - /// Expression to be evaluated. - #[getset(get = "pub")] - pub expression: EvaluatesTo, - /// Context values for the context bonded to their `String` names. - pub values: btree_map::BTreeMap>, - } -} - -impl> From for Expression { - fn from(value: V) -> Self { - Self::Raw(value.into()) - } -} - -impl, E: Into + Into> From for EvaluatesTo { - fn from(expression: E) -> Self { - Self::new_unchecked(expression) - } -} - -impl EvaluatesTo { - /// Expression - #[inline] - // NOTE: getset would return &Box - pub fn expression(&self) -> &Expression { - &self.expression - } - - /// Construct new [`EvaluatesTo`] from [`Expression`] without type checking. - /// - /// # Warning - /// Prefer using [`Into`] conversions rather than this method, - /// because it does not check the value type at compile-time. - #[inline] - pub fn new_unchecked(expression: impl Into) -> Self { - Self { - expression: Box::new(expression.into()), - _value_type: PhantomData, - } - } - - fn operation(&self) -> Operation { - use Expression::*; - - match self.expression.as_ref() { - Add(_) => Operation::Add, - Subtract(_) => Operation::Subtract, - Multiply(_) => Operation::Multiply, - Divide(_) => Operation::Divide, - Mod(_) => Operation::Mod, - RaiseTo(_) => Operation::RaiseTo, - Greater(_) => Operation::Greater, - Less(_) => Operation::Less, - Equal(_) => Operation::Equal, - Not(_) => Operation::Not, - And(_) => Operation::And, - Or(_) => Operation::Or, - Contains(_) | ContainsAll(_) | ContainsAny(_) => Operation::MethodCall, - If(_) | Raw(_) | Query(_) | Where(_) | ContextValue(_) => Operation::Other, - } - } - - /// Wrap expression into parentheses depending on `operation` and get the resulting string. - fn parenthesise(&self, operation: Operation) -> String { - if self.operation().priority() < operation.priority() - && !matches!(self.expression.as_ref(), Expression::Raw(_)) - { - format!("({})", self.expression) - } else { - format!("{}", self.expression) - } - } -} - -impl EvaluatesTo { - /// Construct `EvaluatesTo` from any `expression` - /// because all of them evaluate to [`Value`]. - #[inline] - pub fn new_evaluates_to_value(expression: impl Into) -> Self { - Self::new_unchecked(expression) - } -} - -impl + IntoSchema> IntoSchema for EvaluatesTo { - fn type_name() -> String { - format!("EvaluatesTo<{}>", V::type_name()) - } - fn update_schema_map(map: &mut iroha_schema::MetaMap) { - const EXPRESSION: &str = "expression"; - - if !map.contains_key::() { - map.insert::(iroha_schema::Metadata::Struct( - iroha_schema::NamedFieldsMeta { - declarations: vec![iroha_schema::Declaration { - name: String::from(EXPRESSION), - ty: core::any::TypeId::of::(), - }], - }, - )); - - Expression::update_schema_map(map); - } - } -} - -impl core::fmt::Display for Where { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "`{} where: [", self.expression)?; - - let mut first = true; - for (key, value) in &self.values { - if !first { - write!(f, ", ")?; - } - first = false; - write!(f, "`{key}` : `{value}`")?; - } - - write!(f, "]") - } -} - -impl Where { - /// Construct [`Where`] expression - #[must_use] - pub fn new(expression: impl Into>) -> Self { - Self { - expression: expression.into(), - values: Default::default(), - } - } - - /// Get an iterator over the values of [`Where`] clause - #[inline] - pub fn values(&self) -> impl ExactSizeIterator)> { - self.values.iter() - } - - /// Binds `expression` result to a `value_name`, by which it will be reachable from the main expression. - #[must_use] - pub fn with_value>>( - mut self, - value_name: Name, - expression: E, - ) -> Self { - self.values.insert(value_name, expression.into()); - self - } -} - -mod operation { - //! Module containing operations and their priorities. - - /// Type of expression operation. - #[derive(Clone, Copy, PartialEq, Eq)] - pub enum Operation { - MethodCall, - RaiseTo, - Multiply, - Divide, - Mod, - Add, - Subtract, - Greater, - Less, - Equal, - Not, - And, - Or, - Other, - } - - /// Priority of operation. - /// - /// [`First`](Operation::First) is the highest priority - /// and [`Ninth`](Operation::Ninth) is the lowest. - #[derive(Debug, Clone, Copy, PartialEq, Eq)] - pub enum Priority { - First = 1, - Second = 2, - Third = 3, - Fourth = 4, - Fifth = 5, - Sixth = 6, - Seventh = 7, - Eighth = 8, - Ninth = 9, - } - - impl Operation { - /// Get the priority of the operation. - /// - /// Ordering is the same as in Python code. - /// See [`here`](https://docs.python.org/3/reference/expressions.html#operator-precedence) - /// for more details. - pub fn priority(self) -> Priority { - use Operation::*; - - match self { - MethodCall => Priority::First, - RaiseTo => Priority::Second, - Multiply | Divide | Mod => Priority::Third, - Add | Subtract => Priority::Fourth, - Greater | Less | Equal => Priority::Fifth, - Not => Priority::Sixth, - And => Priority::Seventh, - Or => Priority::Eighth, - Other => Priority::Ninth, - } - } - } - - impl PartialOrd for Priority { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } - } - - impl Ord for Priority { - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - use core::cmp::Ordering::*; - - let lhs = *self as u8; - let rhs = *other as u8; - - match lhs.cmp(&rhs) { - Less => Greater, - Equal => Equal, - Greater => Less, - } - } - } -} - -/// The prelude re-exports most commonly used traits, structs and macros from this crate. -pub mod prelude { - pub use super::{ - Add, And, Contains, ContainsAll, ContainsAny, ContextValue, Divide, Equal, EvaluatesTo, - Expression, Greater, If, Less, Mod, Multiply, Not, Or, RaiseTo, Subtract, Where, - }; -} diff --git a/data_model/src/isi.rs b/data_model/src/isi.rs index c0b2fd41da1..0dd3b178d9e 100644 --- a/data_model/src/isi.rs +++ b/data_model/src/isi.rs @@ -4,36 +4,25 @@ #[cfg(not(feature = "std"))] use alloc::{boxed::Box, format, string::String, vec::Vec}; -use core::fmt::Debug; +use core::fmt::{Debug, Display}; -use derive_more::{DebugCustom, Display}; +use derive_more::{Constructor, DebugCustom, Display}; use iroha_data_model_derive::model; -use iroha_macro::FromVariant; use iroha_schema::IntoSchema; use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; use strum::EnumDiscriminants; -pub use self::model::*; -use super::{expression::EvaluatesTo, prelude::*, IdBox, RegistrableBox, Value}; +pub use self::{model::*, transparent::*}; +use super::{prelude::*, Value}; use crate::{seal, Level, Registered}; -/// Marker trait designating instruction -pub trait Instruction: Into + seal::Sealed {} - -macro_rules! isi { - ($($meta:meta)* $item:item) => { - iroha_data_model_derive::model_single! { - #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, getset::Getters)] - #[derive(parity_scale_codec::Decode, parity_scale_codec::Encode)] - #[derive(serde::Deserialize, serde::Serialize)] - #[derive(iroha_schema::IntoSchema)] - #[getset(get = "pub")] - $($meta)* - $item - } - }; -} +/// Marker trait designating instruction. +/// +/// Instructions allows to change the state of `Iroha`. +/// All possible instructions are implementors of this trait, excluding +/// [`InstructionBox`] which is just a wrapper. +pub trait Instruction: Into + seal::Sealed {} #[model] pub mod model { @@ -42,6 +31,10 @@ pub mod model { use super::*; /// Sized structure for all possible Instructions. + /// + /// Note that [`InstructionBox`] is not a self-sufficient instruction, + /// but just a wrapper to pass instructions back and forth. + /// If you are a client SDK user then you likely don't need to use this type directly. #[derive( DebugCustom, Display, @@ -50,7 +43,6 @@ pub mod model { Eq, PartialOrd, Ord, - FromVariant, EnumDiscriminants, Decode, Encode, @@ -79,790 +71,1151 @@ pub mod model { )] #[ffi_type(opaque)] #[allow(missing_docs)] - pub enum InstructionExpr { - #[debug(fmt = "{_0:?}")] - Register(RegisterExpr), + pub enum InstructionBox { #[debug(fmt = "{_0:?}")] - Unregister(UnregisterExpr), + Register(RegisterBox), #[debug(fmt = "{_0:?}")] - Mint(MintExpr), + Unregister(UnregisterBox), #[debug(fmt = "{_0:?}")] - Burn(BurnExpr), + Mint(MintBox), #[debug(fmt = "{_0:?}")] - Transfer(TransferExpr), + Burn(BurnBox), #[debug(fmt = "{_0:?}")] - If(Box), + Transfer(TransferBox), #[debug(fmt = "{_0:?}")] - Pair(Box), + SetKeyValue(SetKeyValueBox), #[debug(fmt = "{_0:?}")] - Sequence(SequenceExpr), + RemoveKeyValue(RemoveKeyValueBox), #[debug(fmt = "{_0:?}")] - SetKeyValue(SetKeyValueExpr), + Grant(GrantBox), #[debug(fmt = "{_0:?}")] - RemoveKeyValue(RemoveKeyValueExpr), + Revoke(RevokeBox), #[debug(fmt = "{_0:?}")] - Grant(GrantExpr), + ExecuteTrigger(ExecuteTrigger), #[debug(fmt = "{_0:?}")] - Revoke(RevokeExpr), + SetParameter(SetParameter), #[debug(fmt = "{_0:?}")] - ExecuteTrigger(ExecuteTriggerExpr), + NewParameter(NewParameter), #[debug(fmt = "{_0:?}")] - SetParameter(SetParameterExpr), + Upgrade(Upgrade), #[debug(fmt = "{_0:?}")] - NewParameter(NewParameterExpr), - Upgrade(UpgradeExpr), - /// `Log` variant. - Log(LogExpr), + Log(Log), #[debug(fmt = "{_0:?}")] Fail(Fail), } - impl Instruction for InstructionExpr {} - - impl Instruction for SetKeyValueExpr {} - impl Instruction for RemoveKeyValueExpr {} - impl Instruction for RegisterExpr {} - impl Instruction for UnregisterExpr {} - impl Instruction for MintExpr {} - impl Instruction for BurnExpr {} - impl Instruction for TransferExpr {} - impl Instruction for GrantExpr {} - impl Instruction for RevokeExpr {} - impl Instruction for SetParameterExpr {} - impl Instruction for NewParameterExpr {} - impl Instruction for UpgradeExpr {} - impl Instruction for ExecuteTriggerExpr {} - impl Instruction for LogExpr {} + impl Instruction for InstructionBox {} + + impl Instruction for SetKeyValue {} + impl Instruction for SetKeyValue {} + impl Instruction for SetKeyValue {} + impl Instruction for SetKeyValue {} + + impl Instruction for RemoveKeyValue {} + impl Instruction for RemoveKeyValue {} + impl Instruction for RemoveKeyValue {} + impl Instruction for RemoveKeyValue {} + + impl Instruction for Register {} + impl Instruction for Register {} + impl Instruction for Register {} + impl Instruction for Register {} + impl Instruction for Register {} + impl Instruction for Register {} + impl Instruction for Register> {} + + impl Instruction for Unregister {} + impl Instruction for Unregister {} + impl Instruction for Unregister {} + impl Instruction for Unregister {} + impl Instruction for Unregister {} + impl Instruction for Unregister {} + impl Instruction for Unregister> {} + + impl Instruction for Mint {} + impl Instruction for Mint {} + impl Instruction for Mint {} + impl Instruction for Mint {} + impl Instruction for Mint {} + impl Instruction for Mint> {} + + impl Instruction for Burn {} + impl Instruction for Burn {} + impl Instruction for Burn {} + impl Instruction for Burn {} + impl Instruction for Burn> {} + + impl Instruction for Transfer {} + impl Instruction for Transfer {} + impl Instruction for Transfer {} + impl Instruction for Transfer {} + impl Instruction for Transfer {} + + impl Instruction for Grant {} + impl Instruction for Grant {} + + impl Instruction for Revoke {} + impl Instruction for Revoke {} + + impl Instruction for SetParameter {} + impl Instruction for NewParameter {} + impl Instruction for Upgrade {} + impl Instruction for ExecuteTrigger {} + impl Instruction for Log {} impl Instruction for Fail {} - - // Composite instructions - impl Instruction for ConditionalExpr {} - impl Instruction for SequenceExpr {} - impl Instruction for PairExpr {} } mod transparent { - // NOTE: instructions in this module don't have to be made opaque with `model!` - // because they are never shared between client and server(http)/host(wasm) - use super::*; - use crate::executor::Executor; - - /// Generic instruction to set key value at the object. - #[derive(Debug, Clone)] - pub struct SetKeyValue { - /// Where to set key value. - pub object_id: O::Id, - /// Key. - pub key: Name, - /// Value. - pub value: Value, - } - - /// Generic instruction to remove key value at the object. - #[derive(Debug, Clone)] - pub struct RemoveKeyValue { - /// From where to remove key value. - pub object_id: O::Id, - /// Key of the pair to remove. - pub key: Name, - } - - /// Generic instruction for a registration of an object to the identifiable destination. - #[derive(Debug, Clone)] - pub struct Register { - /// The object that should be registered, should be uniquely identifiable by its id. - pub object: O::With, + use crate::{account::NewAccount, domain::NewDomain}; + + macro_rules! isi { + ($($meta:meta)* $item:item) => { + iroha_data_model_derive::model_single! { + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] + #[derive(getset::Getters)] + #[derive(parity_scale_codec::Decode, parity_scale_codec::Encode)] + #[derive(serde::Deserialize, serde::Serialize)] + #[derive(iroha_schema::IntoSchema)] + #[getset(get = "pub")] + $($meta)* + $item + } + }; + } + + macro_rules! impl_display { + ( + $ty:ident $(< $($generic:tt),+ >)? + $(where + $( $lt:path $( : $clt:tt $(< $inner_generic:tt >)? $(+ $dlt:tt )* )? ),+ $(,)?)? + => $fmt:literal, $($args:ident),* $(,)? + ) => { + impl $(< $($generic),+ >)? ::core::fmt::Display for $ty $(< $($generic),+ >)? + $(where + $( $lt $( : $clt $(< $inner_generic >)? $(+ $dlt )* )? ),+)? + { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!( + f, + $fmt, + $(self.$args),* + ) + } + } + } } - /// Generic instruction for an unregistration of an object from the identifiable destination. - #[derive(Debug, Clone)] - pub struct Unregister { - /// [`Identifiable::Id`] of the object which should be unregistered. - pub object_id: O::Id, + macro_rules! impl_into_box { + ( + $($isi:ident $(< $($generic:ident $(< $nested_generic:ident >)?),+ >)?)|* + ==> $boxed:ident :: $variant:ident + ) => {$( + impl From<$isi $(< $($generic $(< $nested_generic >)?),+ >)? > for $boxed { + fn from(instruction: $isi $(< $($generic $(< $nested_generic >)?),+ >)?) -> Self { + Self::$variant(instruction) + } + } + )*}; + ( + $($isi:ident $(< $($generic:ident $(< $nested_generic:ident >)?),+ >)?)|* + => $middle:ident ==> $boxed:ident :: $variant:ident + ) => {$( + impl From<$isi $(< $($generic $(< $nested_generic >)?),+ >)? > for $boxed { + fn from(instruction: $isi $(< $($generic $(< $nested_generic >)?),+ >)?) -> Self { + Self::$variant($middle::from(instruction)) + } + } + )*}; + } + + isi! { + /// Generic instruction for setting a chain-wide config parameter. + #[derive(Constructor, Display)] + #[display(fmt = "SET `{parameter}`")] + #[serde(transparent)] + #[repr(transparent)] + pub struct SetParameter { + /// The configuration parameter being changed. + #[serde(flatten)] + pub parameter: Parameter, + } } - /// Generic instruction for a mint of an object to the identifiable destination. - #[derive(Debug, Clone)] - pub struct Mint, D: Identifiable> { - /// Object which should be minted. - pub object: O, - /// Destination object [`Identifiable::Id`]. - pub destination_id: D::Id, + impl_into_box!(SetParameter ==> InstructionBox::SetParameter); + + isi! { + /// Sized structure for all possible on-chain configuration parameters when they are first created. + /// Generic instruction for setting a chain-wide config parameter. + #[derive(Constructor, Display)] + #[display(fmt = "SET `{parameter}`")] + #[serde(transparent)] + #[repr(transparent)] + pub struct NewParameter { + /// Parameter to be changed. + #[serde(flatten)] + pub parameter: Parameter, + } } - /// Generic instruction for a burn of an object to the identifiable destination. - #[derive(Debug, Clone)] - pub struct Burn, D: Identifiable> { - /// Object which should be burned. - pub object: O, - /// Destination object [`Identifiable::Id`]. - pub destination_id: D::Id, + impl_into_box!(NewParameter ==> InstructionBox::NewParameter); + + isi! { + /// Generic instruction to set key value at the object. + #[schema(bounds = "O: Identifiable, O::Id: IntoSchema")] + pub struct SetKeyValue { + /// Where to set key value. + #[serde(flatten)] + pub object_id: O::Id, + /// Key. + pub key: Name, + /// Value. + pub value: Value, + } } - /// Generic instruction for a transfer of an object from the identifiable source to the identifiable destination. - #[derive(Debug, Clone)] - pub struct Transfer, D: Identifiable> { - /// Source object `Id`. - pub source_id: S::Id, - /// Object which should be transferred. - pub object: O, - /// Destination object `Id`. - pub destination_id: D::Id, + impl SetKeyValue { + /// Constructs a new [`SetKeyValue`] for a [`Domain`] with the given `key` and `value`. + pub fn domain(domain_id: DomainId, key: Name, value: impl Into) -> Self { + Self { + object_id: domain_id, + key, + value: value.into(), + } + } } - /// Generic instruction for granting permission to an entity. - #[derive(Debug, Clone)] - pub struct Grant> { - /// Object to grant. - pub object: O, - /// Entity to which to grant this token. - pub destination_id: AccountId, + impl SetKeyValue { + /// Constructs a new [`SetKeyValue`] for an [`Account`] with the given `key` and `value`. + pub fn account(account_id: AccountId, key: Name, value: impl Into) -> Self { + Self { + object_id: account_id, + key, + value: value.into(), + } + } } - /// Generic instruction for revoking permission from an entity. - #[derive(Debug, Clone)] - pub struct Revoke> { - /// Object to revoke. - pub object: O, - /// Entity which is being revoked this token from. - pub destination_id: AccountId, + impl SetKeyValue { + /// Constructs a new [`SetKeyValue`] for an [`AssetDefinition`] with the given `key` and `value`. + pub fn asset_definition( + asset_definition_id: AssetDefinitionId, + key: Name, + value: impl Into, + ) -> Self { + Self { + object_id: asset_definition_id, + key, + value: value.into(), + } + } } - /// Generic instruction for setting a chain-wide config parameter. - #[derive(Debug, Clone)] - pub struct SetParameter { - /// Parameter to be changed. - pub parameter: Parameter, + impl SetKeyValue { + /// Constructs a new [`SetKeyValue`] for an [`Asset`] with the given `key` and `value`. + pub fn asset(asset_id: AssetId, key: Name, value: impl Into) -> Self { + Self { + object_id: asset_id, + key, + value: value.into(), + } + } } - /// Generic instruction for setting a chain-wide config parameter. - #[derive(Debug, Clone)] - pub struct NewParameter { - /// Parameter to be changed. - pub parameter: Parameter, + impl_display! { + SetKeyValue + where + O: Identifiable, + O::Id: Display, + => + "SET `{}` = `{}` IN `{}`", + key, value, object_id, + } + + impl_into_box! { + SetKeyValue | + SetKeyValue | + SetKeyValue | + SetKeyValue => SetKeyValueBox ==> InstructionBox::SetKeyValue + } + + isi! { + /// Generic instruction to remove key value at the object. + #[schema(bounds = "O: Identifiable, O::Id: IntoSchema")] + pub struct RemoveKeyValue { + /// From where to remove key value. + #[serde(flatten)] + pub object_id: O::Id, + /// Key of the pair to remove. + pub key: Name, + } } - /// Generic instruction for upgrading runtime objects. - #[derive(Debug, Clone)] - pub struct Upgrade> { - /// Object to upgrade. - pub object: O, + impl RemoveKeyValue { + /// Constructs a new [`RemoveKeyValue`] for a [`Domain`] with the given `key`. + pub fn domain(domain_id: DomainId, key: Name) -> Self { + Self { + object_id: domain_id, + key, + } + } + } + + impl RemoveKeyValue { + /// Constructs a new [`RemoveKeyValue`] for an [`Account`] with the given `key`. + pub fn account(account_id: AccountId, key: Name) -> Self { + Self { + object_id: account_id, + key, + } + } + } + + impl RemoveKeyValue { + /// Constructs a new [`RemoveKeyValue`] for an [`AssetDefinition`] with the given `key`. + pub fn asset_definition(asset_definition_id: AssetDefinitionId, key: Name) -> Self { + Self { + object_id: asset_definition_id, + key, + } + } + } + + impl RemoveKeyValue { + /// Constructs a new [`RemoveKeyValue`] for an [`Asset`] with the given `key`. + pub fn asset(asset_id: AssetId, key: Name) -> Self { + Self { + object_id: asset_id, + key, + } + } + } + + impl_display! { + RemoveKeyValue + where + O: Identifiable, + O::Id: Display, + => + "REMOVE `{}` from `{}`", + key, object_id, + } + + impl_into_box! { + RemoveKeyValue | + RemoveKeyValue | + RemoveKeyValue | + RemoveKeyValue => RemoveKeyValueBox ==> InstructionBox::RemoveKeyValue + } + + isi! { + /// Generic instruction for a registration of an object to the identifiable destination. + #[schema(bounds = "O: Registered, O::With: IntoSchema")] + #[serde(transparent)] + pub struct Register { + /// The object that should be registered, should be uniquely identifiable by its id. + pub object: O::With, + } } - /// Generic instruction for executing specified trigger - #[derive(Debug, Clone)] - pub struct ExecuteTrigger { - /// Id of a trigger to execute - pub trigger_id: TriggerId, + impl Register { + /// Constructs a new [`Register`] for a [`Peer`]. + pub fn peer(new_peer: Peer) -> Self { + Self { object: new_peer } + } } - /// Generic instruction for logging messages - #[derive(Debug, Clone)] - pub struct Log { - /// Log level of the message - pub level: Level, - /// Message to be logged - pub msg: String, + impl Register { + /// Constructs a new [`Register`] for a [`Domain`]. + pub fn domain(new_domain: NewDomain) -> Self { + Self { object: new_domain } + } } - impl From> for SetKeyValueExpr { - fn from(source: SetKeyValue) -> Self { - Self::new(source.object_id.into(), source.key, source.value) + impl Register { + /// Constructs a new [`Register`] for an [`Account`]. + pub fn account(new_account: NewAccount) -> Self { + Self { + object: new_account, + } } } - impl From> for RemoveKeyValueExpr { - fn from(source: RemoveKeyValue) -> Self { - Self::new(source.object_id.into(), source.key) + impl Register { + /// Constructs a new [`Register`] for an [`AssetDefinition`]. + pub fn asset_definition(new_asset_definition: NewAssetDefinition) -> Self { + Self { + object: new_asset_definition, + } } } - impl From> for RegisterExpr { - fn from(source: Register) -> Self { - Self::new(source.object.into()) + impl Register { + /// Constructs a new [`Register`] for an [`Asset`]. + pub fn asset(new_asset: Asset) -> Self { + Self { object: new_asset } } } - impl From> for UnregisterExpr { - fn from(source: Unregister) -> Self { - Self::new(source.object_id.into()) + impl Register { + /// Constructs a new [`Register`] for a [`Role`]. + pub fn role(new_role: NewRole) -> Self { + Self { object: new_role } } } - impl, D: Identifiable> From> for MintExpr { - fn from(source: Mint) -> Self { - Self::new(source.object, source.destination_id.into()) + impl Register> { + /// Constructs a new [`Register`] for a [`Trigger`]. + pub fn trigger(new_trigger: Trigger) -> Self { + Self { + object: new_trigger, + } } } - impl, D: Identifiable> From> for BurnExpr { - fn from(source: Burn) -> Self { - Self::new(source.object, source.destination_id.into()) + impl_display! { + Register + where + O: Registered, + O::With: Display, + => + "REGISTER `{}`", + object, + } + + impl_into_box! { + Register | + Register | + Register | + Register | + Register | + Register | + Register > => RegisterBox ==> InstructionBox::Register + } + + isi! { + /// Generic instruction for an unregistration of an object from the identifiable destination. + #[schema(bounds = "O: Identifiable, O::Id: IntoSchema")] + pub struct Unregister { + /// [`Identifiable::Id`] of the object which should be unregistered. + pub object_id: O::Id, } } - impl, D: Identifiable> From> for TransferExpr { - fn from(source: Transfer) -> Self { - Self::new( - source.source_id.into(), - source.object, - source.destination_id.into(), - ) + impl_display! { + Unregister + where + O: Identifiable, + O::Id: Display, + => + "UNREGISTER `{}`", + object_id, + } + + impl_into_box! { + Unregister | + Unregister | + Unregister | + Unregister | + Unregister | + Unregister | + Unregister > => UnregisterBox ==> InstructionBox::Unregister + } + + impl Unregister { + /// Constructs a new [`Unregister`] for a [`Peer`]. + pub fn peer(peer_id: PeerId) -> Self { + Self { object_id: peer_id } } } - impl> From> for GrantExpr { - fn from(source: Grant) -> Self { - Self::new(source.object, source.destination_id) + impl Unregister { + /// Constructs a new [`Unregister`] for a [`Domain`]. + pub fn domain(domain_id: DomainId) -> Self { + Self { + object_id: domain_id, + } } } - impl> From> for RevokeExpr { - fn from(source: Revoke) -> Self { - Self::new(source.object, source.destination_id) + impl Unregister { + /// Constructs a new [`Unregister`] for an [`Account`]. + pub fn account(account_id: AccountId) -> Self { + Self { + object_id: account_id, + } } } - impl From for SetParameterExpr { - fn from(source: SetParameter) -> Self { - Self::new(source.parameter) + impl Unregister { + /// Constructs a new [`Unregister`] for an [`AssetDefinition`]. + pub fn asset_definition(asset_definition_id: AssetDefinitionId) -> Self { + Self { + object_id: asset_definition_id, + } } } - impl From for NewParameterExpr { - fn from(source: NewParameter) -> Self { - Self::new(source.parameter) + impl Unregister { + /// Constructs a new [`Unregister`] for an [`Asset`]. + pub fn asset(asset_id: AssetId) -> Self { + Self { + object_id: asset_id, + } } } - impl From> for UpgradeExpr { - fn from(source: Upgrade) -> Self { - Self::new(source.object) + impl Unregister { + /// Constructs a new [`Unregister`] for a [`Role`]. + pub fn role(role_id: RoleId) -> Self { + Self { object_id: role_id } } } - impl From for ExecuteTriggerExpr { - fn from(source: ExecuteTrigger) -> Self { - Self::new(source.trigger_id) + impl Unregister> { + /// Constructs a new [`Unregister`] for a [`Trigger`]. + pub fn trigger(trigger_id: TriggerId) -> Self { + Self { + object_id: trigger_id, + } } } - impl From for LogExpr { - fn from(source: Log) -> Self { - Self::new(source.level, source.msg) + isi! { + /// Generic instruction for a mint of an object to the identifiable destination. + #[schema(bounds = "O: Into + IntoSchema, D: Identifiable, D::Id: IntoSchema")] + pub struct Mint, D: Identifiable> { + /// Object which should be minted. + pub object: O, + /// Destination object [`Identifiable::Id`]. + pub destination_id: D::Id, } } -} -isi! { - /// Sized structure for all possible on-chain configuration parameters. - #[derive(Display)] - #[display(fmt = "SET `{parameter}`")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `SetParameterExpr` has no trap representation in `EvaluatesTo` - #[ffi_type(unsafe {robust})] - pub struct SetParameterExpr { - /// The configuration parameter being changed. - #[serde(flatten)] - pub parameter: EvaluatesTo, + impl Mint { + /// Constructs a new [`Mint`] for a [`PublicKey`] for [`Account`]. + pub fn account_public_key(public_key: PublicKey, account_id: AccountId) -> Self { + Self { + object: public_key, + destination_id: account_id, + } + } } -} -isi! { - /// Sized structure for all possible on-chain configuration parameters when they are first created. - #[derive(Display)] - #[display(fmt = "SET `{parameter}`")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `NewParameterExpr` has no trap representation in `EvaluatesTo` - #[ffi_type(unsafe {robust})] - pub struct NewParameterExpr { - /// The configuration parameter being created. - #[serde(flatten)] - pub parameter: EvaluatesTo, + impl Mint { + /// Constructs a new [`Mint`] for a [`SignatureCheckCondition`] for [`Account`]. + pub fn account_signature_check_condition( + signature_check_condition: SignatureCheckCondition, + account_id: AccountId, + ) -> Self { + Self { + object: signature_check_condition, + destination_id: account_id, + } + } } -} -isi! { - /// Sized structure for all possible key value set instructions. - #[derive(Display)] - #[display(fmt = "SET `{key}` = `{value}` IN `{object_id}`")] - #[ffi_type] - pub struct SetKeyValueExpr { - /// Where to set this key value. - #[serde(flatten)] - pub object_id: EvaluatesTo, - /// Key string. - pub key: EvaluatesTo, - /// Object to set as a value. - pub value: EvaluatesTo, + impl Mint { + /// Constructs a new [`Mint`] for an [`Asset`] of [`Quantity`] type. + pub fn asset_quantity(quantity: u32, asset_id: AssetId) -> Self { + Self { + object: quantity, + destination_id: asset_id, + } + } } -} -isi! { - /// Sized structure for all possible key value pair remove instructions. - #[derive(Display)] - #[display(fmt = "REMOVE `{key}` from `{object_id}`")] - #[ffi_type] - pub struct RemoveKeyValueExpr { - /// From where to remove this key value. - #[serde(flatten)] - pub object_id: EvaluatesTo, - /// Key string. - pub key: EvaluatesTo, + impl Mint { + /// Constructs a new [`Mint`] for an [`Asset`] of [`BigQuantity`] type. + pub fn asset_big_quantity(big_quantity: u128, asset_id: AssetId) -> Self { + Self { + object: big_quantity, + destination_id: asset_id, + } + } } -} -isi! { - /// Sized structure for all possible Registers. - #[derive(Display)] - #[display(fmt = "REGISTER `{object}`")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `RegisterExpr` has no trap representation in `EvaluatesTo` - #[ffi_type(unsafe {robust})] - pub struct RegisterExpr { - /// The object that should be registered, should be uniquely identifiable by its id. - pub object: EvaluatesTo, + impl Mint { + /// Constructs a new [`Mint`] for an [`Asset`] of [`Fixed`] type. + pub fn asset_fixed(fixed: Fixed, asset_id: AssetId) -> Self { + Self { + object: fixed, + destination_id: asset_id, + } + } } -} -isi! { - /// Sized structure for all possible Unregisters. - #[derive(Display)] - #[display(fmt = "UNREGISTER `{object_id}`")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `UnregisterExpr` has no trap representation in `EvaluatesTo` - #[ffi_type(unsafe {robust})] - pub struct UnregisterExpr { - /// The id of the object that should be unregistered. - pub object_id: EvaluatesTo, + impl Mint> { + /// Constructs a new [`Mint`] for repetition count of [`Trigger`]. + pub fn trigger_repetitions(repetitions: u32, trigger_id: TriggerId) -> Self { + Self { + object: repetitions, + destination_id: trigger_id, + } + } } -} -isi! { - /// Sized structure for all possible Mints. - #[derive(Display)] - #[display(fmt = "MINT `{object}` TO `{destination_id}`")] - #[ffi_type] - pub struct MintExpr { - /// Object to mint. - pub object: EvaluatesTo, - /// Entity to mint to. - pub destination_id: EvaluatesTo, + impl_display! { + Mint + where + O: Into + Display, + D: Identifiable, + D::Id: Display, + => + "MINT `{}` TO `{}`", + object, + destination_id, } -} -isi! { - /// Sized structure for all possible Burns. - #[derive(Display)] - #[display(fmt = "BURN `{object}` FROM `{destination_id}`")] - #[ffi_type] - pub struct BurnExpr { - /// Object to burn. - pub object: EvaluatesTo, - /// Entity to burn from. - pub destination_id: EvaluatesTo, + impl_into_box! { + Mint | + Mint => AccountMintBox ==> MintBox::Account } -} -isi! { - /// Sized structure for all possible Transfers. - #[derive(Display)] - #[display(fmt = "TRANSFER `{object}` FROM `{source_id}` TO `{destination_id}`")] - #[ffi_type] - pub struct TransferExpr { - /// Entity to transfer from. - pub source_id: EvaluatesTo, - /// Object to transfer. - pub object: EvaluatesTo, - /// Entity to transfer to. - pub destination_id: EvaluatesTo, + impl_into_box! { + Mint | + Mint | + Mint => AssetMintBox ==> MintBox::Asset } -} -isi! { - /// Composite instruction for a pair of instructions. - #[derive(Display)] - #[display(fmt = "(`{left_instruction}`, `{right_instruction}`)")] - #[ffi_type] - pub struct PairExpr { - /// Left instruction - pub left_instruction: InstructionExpr, - /// Right instruction - pub right_instruction: InstructionExpr, + impl_into_box! { + Mint | + Mint | + Mint | + Mint | + Mint | + Mint > => MintBox ==> InstructionBox::Mint } -} -isi! { - /// Composite instruction for a sequence of instructions. - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `SequenceExpr` has no trap representation in `Vec` - #[ffi_type(unsafe {robust})] - pub struct SequenceExpr { - /// Sequence of Iroha Special Instructions to execute. - pub instructions: Vec, + isi! { + /// Generic instruction for a burn of an object to the identifiable destination. + #[schema(bounds = "O: Into + IntoSchema, D: Identifiable, D::Id: IntoSchema")] + pub struct Burn, D: Identifiable> { + /// Object which should be burned. + pub object: O, + /// Destination object [`Identifiable::Id`]. + pub destination_id: D::Id, + } } -} -impl core::fmt::Display for SequenceExpr { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "SEQUENCE [")?; - let mut first = true; - for instruction in &self.instructions { - if !first { - write!(f, ", ")?; + impl Burn { + /// Constructs a new [`Burn`] for a [`PublicKey`] for [`Account`]. + pub fn account_public_key(public_key: PublicKey, account_id: AccountId) -> Self { + Self { + object: public_key, + destination_id: account_id, } - first = false; + } + } - write!(f, "`{instruction}`")?; + impl Burn { + /// Constructs a new [`Burn`] for an [`Asset`] of [`Quantity`] type. + pub fn asset_quantity(quantity: u32, asset_id: AssetId) -> Self { + Self { + object: quantity, + destination_id: asset_id, + } } - write!(f, "]") } -} -isi! { - /// Composite instruction for a conditional execution of other instructions. - #[ffi_type] - pub struct ConditionalExpr { - /// Condition to be checked. - pub condition: EvaluatesTo, - /// Instruction to be executed if condition pass. - pub then: InstructionExpr, - /// Optional instruction to be executed if condition fail. - pub otherwise: Option, + impl Burn { + /// Constructs a new [`Burn`] for an [`Asset`] of [`BigQuantity`] type. + pub fn asset_big_quantity(big_quantity: u128, asset_id: AssetId) -> Self { + Self { + object: big_quantity, + destination_id: asset_id, + } + } } -} -impl core::fmt::Display for ConditionalExpr { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "IF `{}` THEN `{}`", self.condition, self.then)?; - if let Some(otherwise) = &self.otherwise { - write!(f, " ELSE `{otherwise}`")?; + impl Burn { + /// Constructs a new [`Burn`] for an [`Asset`] of [`Fixed`] type. + pub fn asset_fixed(fixed: Fixed, asset_id: AssetId) -> Self { + Self { + object: fixed, + destination_id: asset_id, + } } + } - Ok(()) + impl Burn> { + /// Constructs a new [`Burn`] for repetition count of [`Trigger`]. + pub fn trigger_repetitions(repetitions: u32, trigger_id: TriggerId) -> Self { + Self { + object: repetitions, + destination_id: trigger_id, + } + } } -} -isi! { - /// Utilitary instruction to fail execution and submit an error `message`. - #[derive(Display)] - #[display(fmt = "FAIL `{message}`")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `Fail` has no trap representation in `String` - #[ffi_type(unsafe {robust})] - pub struct Fail { - /// Message to submit. - pub message: String, + impl_display! { + Burn + where + O: Into + Display, + D: Identifiable, + D::Id: Display, + => + "BURN `{}` FROM `{}`", + object, + destination_id, + } + + impl_into_box! { + Burn | + Burn | + Burn => AssetBurnBox ==> BurnBox::Asset + } + + impl_into_box! { + Burn | + Burn | + Burn | + Burn | + Burn > => BurnBox ==> InstructionBox::Burn + } + + isi! { + /// Generic instruction for a transfer of an object from the identifiable source to the identifiable destination. + #[schema(bounds = "S: Identifiable, S::Id: IntoSchema, \ + O: Into + IntoSchema, \ + D: Identifiable, D::Id: IntoSchema")] + pub struct Transfer, D: Identifiable> { + /// Source object `Id`. + pub source_id: S::Id, + /// Object which should be transferred. + pub object: O, + /// Destination object `Id`. + pub destination_id: D::Id, + } } -} -isi! { - /// Sized structure for all possible Grants. - #[derive(Display)] - #[display(fmt = "GRANT `{object}` TO `{destination_id}`")] - #[ffi_type] - pub struct GrantExpr { - /// Object to grant. - pub object: EvaluatesTo, - /// Account to which to grant this object. - pub destination_id: EvaluatesTo, + impl Transfer { + /// Constructs a new [`Transfer`] for a [`Domain`]. + pub fn domain(from: AccountId, domain_id: DomainId, to: AccountId) -> Self { + Self { + source_id: from, + object: domain_id, + destination_id: to, + } + } } -} -isi! { - /// Sized structure for all possible Grants. - #[derive(Display)] - #[display(fmt = "REVOKE `{object}` FROM `{destination_id}`")] - #[ffi_type] - pub struct RevokeExpr { - /// Object to revoke. - pub object: EvaluatesTo, - /// Account to which to revoke this object from. - pub destination_id: EvaluatesTo, + impl Transfer { + /// Constructs a new [`Transfer`] for an [`AssetDefinition`]. + pub fn asset_definition( + from: AccountId, + asset_definition_id: AssetDefinitionId, + to: AccountId, + ) -> Self { + Self { + source_id: from, + object: asset_definition_id, + destination_id: to, + } + } } -} -isi! { - /// Instruction to execute specified trigger - #[derive(Display)] - #[display(fmt = "EXECUTE `{trigger_id}`")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `ExecuteTriggerExpr` has no trap representation in `TriggerId` - #[ffi_type(unsafe {robust})] - pub struct ExecuteTriggerExpr { - /// Id of a trigger to execute - pub trigger_id: EvaluatesTo, + impl Transfer { + /// Constructs a new [`Transfer`] for an [`Asset`] of [`Quantity`] type. + pub fn asset_quantity(asset_id: AssetId, quantity: u32, to: AccountId) -> Self { + Self { + source_id: asset_id, + object: quantity, + destination_id: to, + } + } } -} -isi! { - /// Sized structure for all possible Upgrades. - #[derive(Display)] - #[display(fmt = "UPGRADE `{object}`")] - #[serde(transparent)] - #[repr(transparent)] - // SAFETY: `UpgradeExpr` has no trap representation in `EvaluatesTo` - #[ffi_type(unsafe {robust})] - pub struct UpgradeExpr { - /// The object to upgrade. - pub object: EvaluatesTo, + impl Transfer { + /// Constructs a new [`Transfer`] for an [`Asset`] of [`BigQuantity`] type. + pub fn asset_big_quantity(asset_id: AssetId, big_quantity: u128, to: AccountId) -> Self { + Self { + source_id: asset_id, + object: big_quantity, + destination_id: to, + } + } } -} -isi! { - /// Instruction to print logs - #[derive(Display)] - #[display(fmt = "LOG({level}): {msg}")] - #[ffi_type] - pub struct LogExpr { - /// Message log level - #[serde(flatten)] - pub level: EvaluatesTo, - /// Msg to be logged - pub msg: EvaluatesTo, + impl Transfer { + /// Constructs a new [`Transfer`] for an [`Asset`] of [`Fixed`] type. + pub fn asset_fixed(asset_id: AssetId, fixed: Fixed, to: AccountId) -> Self { + Self { + source_id: asset_id, + object: fixed, + destination_id: to, + } + } } -} -impl ExecuteTriggerExpr { - /// Construct [`ExecuteTriggerExpr`] - pub fn new(trigger_id: I) -> Self - where - I: Into>, - { - Self { - trigger_id: trigger_id.into(), + impl_display! { + Transfer + where + S: Identifiable, + S::Id: Display, + O: Into + Display, + D: Identifiable, + D::Id: Display, + => + "TRANSFER `{}` FROM `{}` TO `{}`", + object, + source_id, + destination_id, + } + + impl_into_box! { + Transfer | + Transfer | + Transfer => AssetTransferBox ==> TransferBox::Asset + } + + impl_into_box! { + Transfer | + Transfer | + Transfer | + Transfer | + Transfer => TransferBox ==> InstructionBox::Transfer + } + + isi! { + /// Utilitary instruction to fail execution and submit an error `message`. + #[derive(Constructor, Display)] + #[display(fmt = "FAIL `{message}`")] + #[serde(transparent)] + #[repr(transparent)] + pub struct Fail { + /// Message to submit. + pub message: String, } } -} -impl RevokeExpr { - /// Generic constructor. - pub fn new>, I: Into>>( - object: P, - destination_id: I, - ) -> Self { - Self { - destination_id: destination_id.into(), - object: object.into(), + impl_into_box!(Fail ==> InstructionBox::Fail); + + isi! { + /// Generic instruction for granting permission to an entity. + pub struct Grant> { + /// Object to grant. + pub object: O, + /// Entity to which to grant this token. + pub destination_id: AccountId, } } -} -impl GrantExpr { - /// Constructor. - pub fn new>, I: Into>>( - object: P, - destination_id: I, - ) -> Self { - Self { - destination_id: destination_id.into(), - object: object.into(), + impl Grant { + /// Constructs a new [`Grant`] for a [`PermissionToken`]. + pub fn permission_token(permission_token: PermissionToken, to: AccountId) -> Self { + Self { + object: permission_token, + destination_id: to, + } } } -} -impl SetKeyValueExpr { - /// Construct [`SetKeyValueExpr`]. - pub fn new< - I: Into>, - K: Into>, - V: Into>, - >( - object_id: I, - key: K, - value: V, - ) -> Self { - Self { - object_id: object_id.into(), - key: key.into(), - value: value.into(), + impl Grant { + /// Constructs a new [`Grant`] for a [`Role`]. + pub fn role(role_id: RoleId, to: AccountId) -> Self { + Self { + object: role_id, + destination_id: to, + } } } -} -impl RemoveKeyValueExpr { - /// Construct [`RemoveKeyValueExpr`]. - pub fn new>, K: Into>>( - object_id: I, - key: K, - ) -> Self { - Self { - object_id: object_id.into(), - key: key.into(), + impl_display! { + Grant + where + O: Into + Display, + => + "GRANT `{}` TO `{}`", + object, + destination_id, + } + + impl_into_box! { + Grant | + Grant => GrantBox ==> InstructionBox::Grant + } + + isi! { + /// Generic instruction for revoking permission from an entity. + pub struct Revoke> { + /// Object to revoke. + pub object: O, + /// Entity which is being revoked this token from. + pub destination_id: AccountId, } } -} -impl RegisterExpr { - /// Construct [`Register`]. - pub fn new>>(object: O) -> Self { - Self { - object: object.into(), + impl Revoke { + /// Constructs a new [`Revoke`] for a [`PermissionToken`]. + pub fn permission_token(permission_token: PermissionToken, from: AccountId) -> Self { + Self { + object: permission_token, + destination_id: from, + } } } -} -impl UnregisterExpr { - /// Construct [`Unregister`]. - pub fn new>>(object_id: O) -> Self { - Self { - object_id: object_id.into(), + impl Revoke { + /// Constructs a new [`Revoke`] for a [`Role`]. + pub fn role(role_id: RoleId, from: AccountId) -> Self { + Self { + object: role_id, + destination_id: from, + } } } -} -impl MintExpr { - /// Construct [`Mint`]. - pub fn new>, D: Into>>( - object: O, - destination_id: D, - ) -> Self { - Self { - object: object.into(), - destination_id: destination_id.into(), + impl_display! { + Revoke + where + O: Into + Display, + => + "REVOKE `{}` FROM `{}`", + object, + destination_id, + } + + impl_into_box! { + Revoke | + Revoke => RevokeBox ==> InstructionBox::Revoke + } + + isi! { + /// Instruction to execute specified trigger + #[derive(Constructor, Display)] + #[display(fmt = "EXECUTE `{trigger_id}`")] + #[serde(transparent)] + #[repr(transparent)] + pub struct ExecuteTrigger { + /// Id of a trigger to execute + pub trigger_id: TriggerId, } } -} -impl BurnExpr { - /// Construct [`Burn`]. - pub fn new>, D: Into>>( - object: O, - destination_id: D, - ) -> Self { - Self { - object: object.into(), - destination_id: destination_id.into(), + impl_into_box!(ExecuteTrigger ==> InstructionBox::ExecuteTrigger); + + isi! { + /// Generic instruction for upgrading runtime objects. + #[derive(Constructor, Display)] + #[display(fmt = "UPGRADE")] + #[serde(transparent)] + #[repr(transparent)] + pub struct Upgrade { + /// Object to upgrade. + pub executor: Executor, } } -} -impl TransferExpr { - /// Construct [`Transfer`]. - pub fn new< - S: Into>, - O: Into>, - D: Into>, - >( - source_id: S, - object: O, - destination_id: D, - ) -> Self { - Self { - source_id: source_id.into(), - object: object.into(), - destination_id: destination_id.into(), + impl_into_box!(Upgrade ==> InstructionBox::Upgrade); + + isi! { + /// Instruction to print logs + #[derive(Constructor, Display)] + #[display(fmt = "LOG({level}): {msg}")] + pub struct Log { + /// Message log level + #[serde(flatten)] + pub level: Level, + #[getset(skip)] // TODO: Fix this by addressing ffi issues + /// Msg to be logged + pub msg: String, } } + + impl_into_box!(Log ==> InstructionBox::Log); } -impl PairExpr { - /// Construct [`Pair`]. - pub fn new, RI: Into>( - left_instruction: LI, - right_instruction: RI, - ) -> Self { - PairExpr { - left_instruction: left_instruction.into(), - right_instruction: right_instruction.into(), - } +macro_rules! isi_box { + ($($meta:meta)* $item:item) => { + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Display, + parity_scale_codec::Decode, + parity_scale_codec::Encode, + serde::Deserialize, + serde::Serialize, + iroha_schema::IntoSchema, + derive_more::From, + )] + $($meta)* + $item + }; +} + +isi_box! { + /// Enum with all supported [`SetKeyValue`] instructions. + pub enum SetKeyValueBox { + /// Set key value for [`Domain`]. + Domain(SetKeyValue), + /// Set key value for [`Account`]. + Account(SetKeyValue), + /// Set key value for [`AssetDefinition`]. + AssetDefinition(SetKeyValue), + /// Set key value for [`Asset`]. + Asset(SetKeyValue), } } -impl SequenceExpr { - /// Construct [`SequenceExpr`]. - pub fn new(instructions: impl IntoIterator) -> Self { - Self { - instructions: instructions.into_iter().collect(), - } +isi_box! { + /// Enum with all supported [`RemoveKeyValue`] instructions. + pub enum RemoveKeyValueBox { + /// Remove key value from [`Domain`]. + Domain(RemoveKeyValue), + /// Remove key value from [`Account`]. + Account(RemoveKeyValue), + /// Remove key value from [`AssetDefinition`]. + AssetDefinition(RemoveKeyValue), + /// Remove key value from [`Asset`]. + Asset(RemoveKeyValue), } } -impl ConditionalExpr { - /// Construct [`If`]. - pub fn new>, T: Into>( - condition: C, - then: T, - ) -> Self { - Self { - condition: condition.into(), - then: then.into(), - otherwise: None, - } - } - /// [`If`] constructor with `Otherwise` instruction. - pub fn with_otherwise< - C: Into>, - T: Into, - O: Into, - >( - condition: C, - then: T, - otherwise: O, - ) -> Self { - Self { - condition: condition.into(), - then: then.into(), - otherwise: Some(otherwise.into()), - } +isi_box! { + /// Enum with all supported [`Register`] instructions. + pub enum RegisterBox { + /// Register [`Peer`]. + Peer(Register), + /// Register [`Domain`]. + Domain(Register), + /// Register [`Account`]. + Account(Register), + /// Register [`AssetDefinition`]. + AssetDefinition(Register), + /// Register [`Asset`]. + Asset(Register), + /// Register [`Role`]. + Role(Register), + /// Register [`Trigger`]. + Trigger(Register>) } } -impl Fail { - /// Construct [`Fail`]. - pub fn new(message: &str) -> Self { - Self { - message: String::from(message), - } +isi_box! { + /// Enum with all supported [`Unregister`] instructions. + pub enum UnregisterBox { + /// Unregister [`Peer`]. + Peer(Unregister), + /// Unregister [`Domain`]. + Domain(Unregister), + /// Unregister [`Account`]. + Account(Unregister), + /// Unregister [`AssetDefinition`]. + AssetDefinition(Unregister), + /// Unregister [`Asset`]. + Asset(Unregister), + /// Unregister [`Role`]. + Role(Unregister), + /// Unregister [`Trigger`]. + Trigger(Unregister>) } } -impl SetParameterExpr { - /// Construct [`SetParameterExpr`]. - pub fn new>>(parameter: P) -> Self { - Self { - parameter: parameter.into(), - } +isi_box! { + /// Enum with all supported [`Mint`] instructions. + pub enum MintBox { + /// Mint for [`Account`]. + Account(AccountMintBox), + /// Mint for [`Asset`]. + Asset(AssetMintBox), + /// Mint [`Trigger`] repetitions. + TriggerRepetitions(Mint>), } } -impl NewParameterExpr { - /// Construct [`NewParameterExpr`]. - pub fn new>>(parameter: P) -> Self { - Self { - parameter: parameter.into(), - } +isi_box! { + /// Enum with all supported [`Mint`] instructions related to [`Account`]. + pub enum AccountMintBox { + /// Mint [`PublicKey`]. + PublicKey(Mint), + /// Mint [`SignatureCheckCondition`]. + SignatureCheckCondition(Mint), } } -impl UpgradeExpr { - /// Construct [`UpgradeExpr`]. - pub fn new>>(object: O) -> Self { - Self { - object: object.into(), - } +isi_box! { + /// Enum with all supported [`Mint`] instructions related to [`Asset`]. + pub enum AssetMintBox { + /// Mint [`Asset`] of [`Quantity`] type. + Quantity(Mint), + /// Mint [`Asset`] of [`BigQuantity`] type. + BigQuantity(Mint), + /// Mint [`Asset`] of [`Fixed`] type. + Fixed(Mint), } } -impl LogExpr { - /// Construct [`LogExpr`] - pub fn new>, M: Into>>( - level: L, - msg: M, - ) -> Self { - Self { - level: level.into(), - msg: msg.into(), - } +isi_box! { + /// Enum with all supported [`Burn`] instructions. + pub enum BurnBox { + /// Burn [`PublicKey`] for [`Account`]. + AccountPublicKey(Burn), + /// Burn [`Asset`]. + Asset(AssetBurnBox), + /// Burn [`Trigger`] repetitions. + TriggerRepetitions(Burn>), + } +} + +isi_box! { + /// Enum with all supported [`Burn`] instructions related to [`Asset`]. + pub enum AssetBurnBox { + /// Burn [`Asset`] of [`Quantity`] type. + Quantity(Burn), + /// Burn [`Asset`] of [`BigQuantity`] type. + BigQuantity(Burn), + /// Burn [`Asset`] of [`Fixed`] type. + Fixed(Burn), + } +} + +isi_box! { + /// Enum with all supported [`Transfer`] instructions. + pub enum TransferBox { + /// Transfer [`Domain`] to another [`Account`]. + Domain(Transfer), + /// Transfer [`AssetDefinition`] to another [`Account`]. + AssetDefinition(Transfer), + /// Transfer [`Asset`] to another [`Account`]. + Asset(AssetTransferBox), + } +} + +isi_box! { + /// Enum with all supported [`Transfer`] instructions related to [`Asset`]. + pub enum AssetTransferBox { + /// Transfer [`Asset`] of [`Quantity`] type. + Quantity(Transfer), + /// Transfer [`Asset`] of [`BigQuantity`] type. + BigQuantity(Transfer), + /// Transfer [`Asset`] of [`Fixed`] type. + Fixed(Transfer), + } +} + +isi_box! { + /// Enum with all supported [`Grant`] instructions. + pub enum GrantBox { + /// Grant [`PermissionToken`] to [`Account`]. + PermissionToken(Grant), + /// Grant [`Role`] to [`Account`]. + Role(Grant), + } +} + +isi_box! { + /// Enum with all supported [`Revoke`] instructions. + pub enum RevokeBox { + /// Revoke [`PermissionToken`] from [`Account`]. + PermissionToken(Revoke), + /// Revoke [`Role`] from [`Account`]. + Role(Revoke), } } @@ -884,9 +1237,9 @@ pub mod error { use super::InstructionType; use crate::{ asset::AssetValueType, - evaluate, metadata, + metadata, query::error::{FindError, QueryExecutionFail}, - IdBox, NumericValue, Value, + IdBox, Value, }; #[model] @@ -975,8 +1328,6 @@ pub mod error { // TODO: Only temporarily opaque because of problems with FFI #[ffi_type(opaque)] pub enum InstructionEvaluationError { - /// Failed to evaluate expression - Expression(#[cfg_attr(feature = "std", source)] evaluate::EvaluationError), /// Unsupported parameter type for instruction of type `{0}` Unsupported(InstructionType), /// Failed to find parameter in a permission: {0} @@ -1074,38 +1425,10 @@ pub mod error { /// /// No actual function should ever return this if possible Unknown, - /// Encountered incompatible type of arguments - BinaryOpIncompatibleNumericValueTypes( - #[cfg_attr(feature = "std", source)] BinaryOpIncompatibleNumericValueTypesError, - ), /// Conversion failed: {0} FixedPointConversion(String), } - #[derive( - Debug, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Deserialize, - Serialize, - Decode, - Encode, - IntoSchema, - )] - #[display( - fmt = "Binary operation does not support provided combination of arguments ({left}, {right})" - )] - #[cfg_attr(feature = "std", derive(thiserror::Error))] - #[ffi_type] - pub struct BinaryOpIncompatibleNumericValueTypesError { - pub left: NumericValue, - pub right: NumericValue, - } - /// Mintability logic error #[derive( Debug, @@ -1160,9 +1483,10 @@ pub mod error { NameLength, } + /// Repetition of of `{instruction_type}` for id `{id}` #[derive( Debug, - Display, + displaydoc::Display, Clone, PartialEq, Eq, @@ -1174,11 +1498,12 @@ pub mod error { Encode, IntoSchema, )] - #[display(fmt = "Repetition of of `{instruction_type}` for id `{id}`")] #[cfg_attr(feature = "std", derive(thiserror::Error))] #[ffi_type] pub struct RepetitionError { + /// Instruction type pub instruction_type: InstructionType, + /// Id of the object being repeated pub id: IdBox, } } @@ -1188,11 +1513,6 @@ pub mod error { Self::Evaluate(InstructionEvaluationError::Type(err)) } } - impl From for InstructionExecutionError { - fn from(err: evaluate::EvaluationError) -> Self { - Self::Evaluate(InstructionEvaluationError::Expression(err)) - } - } impl From for MathError { fn from(err: FixedPointOperationError) -> Self { match err { @@ -1215,10 +1535,9 @@ pub mod error { /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{ - Burn, BurnExpr, ConditionalExpr, ExecuteTrigger, ExecuteTriggerExpr, Fail, Grant, - GrantExpr, InstructionExpr, Log, LogExpr, Mint, MintExpr, NewParameter, NewParameterExpr, - PairExpr, Register, RegisterExpr, RemoveKeyValue, RemoveKeyValueExpr, Revoke, RevokeExpr, - SequenceExpr, SetKeyValue, SetKeyValueExpr, SetParameter, SetParameterExpr, Transfer, - TransferExpr, Unregister, UnregisterExpr, Upgrade, UpgradeExpr, + AccountMintBox, AssetBurnBox, AssetMintBox, AssetTransferBox, Burn, BurnBox, + ExecuteTrigger, Fail, Grant, GrantBox, InstructionBox, Log, Mint, MintBox, NewParameter, + Register, RegisterBox, RemoveKeyValue, RemoveKeyValueBox, Revoke, RevokeBox, SetKeyValue, + SetKeyValueBox, SetParameter, Transfer, TransferBox, Unregister, UnregisterBox, Upgrade, }; } diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index ff1920331da..0852f58d05f 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -56,10 +56,8 @@ pub mod account; pub mod asset; pub mod block; pub mod domain; -pub mod evaluate; pub mod events; pub mod executor; -pub mod expression; pub mod ipfs; pub mod isi; pub mod metadata; @@ -77,39 +75,76 @@ pub mod trigger; pub mod visit; mod seal { - use crate::{isi::prelude::*, query::prelude::*}; + use crate::prelude::*; pub trait Sealed {} macro_rules! impl_sealed { - ($($ident:ident),+ $(,)?) => { $( - impl Sealed for $ident {} )+ + ($($ident:ident $(< $($generic:ident $(< $inner_generic:ident >)?),+ >)?),+ $(,)?) => { $( + impl Sealed for $ident $(< $($generic $(< $inner_generic >)?),+ >)? {} )+ }; } impl_sealed! { // Boxed instructions - InstructionExpr, - SetKeyValueExpr, - RemoveKeyValueExpr, - RegisterExpr, - UnregisterExpr, - MintExpr, - BurnExpr, - TransferExpr, - GrantExpr, - RevokeExpr, - SetParameterExpr, - NewParameterExpr, - UpgradeExpr, - ExecuteTriggerExpr, - LogExpr, - - // Composite instructions - SequenceExpr, - ConditionalExpr, - PairExpr, - + InstructionBox, + + SetKeyValue, + SetKeyValue, + SetKeyValue, + SetKeyValue, + + RemoveKeyValue, + RemoveKeyValue, + RemoveKeyValue, + RemoveKeyValue, + + Register, + Register, + Register, + Register, + Register, + Register, + Register >, + + Unregister, + Unregister, + Unregister, + Unregister, + Unregister, + Unregister, + Unregister >, + + Mint, + Mint, + Mint, + Mint, + Mint, + Mint >, + + Burn, + Burn, + Burn, + Burn, + Burn >, + + Transfer, + Transfer, + Transfer, + Transfer, + Transfer, + + Grant, + Grant, + + Revoke, + Revoke, + + SetParameter, + NewParameter, + Upgrade, + ExecuteTrigger, + Log, Fail, // Boxed queries @@ -227,6 +262,7 @@ pub mod parameter { pub use self::model::*; use super::*; + use crate::isi::InstructionBox; /// Set of parameter names currently used by iroha #[allow(missing_docs)] @@ -450,27 +486,21 @@ pub mod parameter { } /// Create sequence isi for setting parameters - pub fn into_set_parameters(self) -> isi::SequenceExpr { - isi::SequenceExpr { - instructions: self - .parameters - .into_iter() - .map(isi::SetParameterExpr::new) - .map(Into::into) - .collect(), - } + pub fn into_set_parameters(self) -> Vec { + self.parameters + .into_iter() + .map(isi::SetParameter::new) + .map(Into::into) + .collect() } /// Create sequence isi for creating parameters - pub fn into_create_parameters(self) -> isi::SequenceExpr { - isi::SequenceExpr { - instructions: self - .parameters - .into_iter() - .map(isi::NewParameterExpr::new) - .map(Into::into) - .collect(), - } + pub fn into_create_parameters(self) -> Vec { + self.parameters + .into_iter() + .map(isi::NewParameter::new) + .map(Into::into) + .collect() } } @@ -1828,12 +1858,12 @@ pub mod prelude { #[cfg(feature = "std")] pub use super::current_time; pub use super::{ - account::prelude::*, asset::prelude::*, domain::prelude::*, evaluate::prelude::*, - events::prelude::*, executor::prelude::*, expression::prelude::*, isi::prelude::*, - metadata::prelude::*, name::prelude::*, parameter::prelude::*, peer::prelude::*, - permission::prelude::*, query::prelude::*, role::prelude::*, transaction::prelude::*, - trigger::prelude::*, EnumTryAsError, HasMetadata, IdBox, Identifiable, IdentifiableBox, - LengthLimits, NumericValue, PredicateTrait, RegistrableBox, ToValue, TryAsMut, TryAsRef, - TryToValue, UpgradableBox, ValidationFail, Value, + account::prelude::*, asset::prelude::*, domain::prelude::*, events::prelude::*, + executor::prelude::*, isi::prelude::*, metadata::prelude::*, name::prelude::*, + parameter::prelude::*, peer::prelude::*, permission::prelude::*, query::prelude::*, + role::prelude::*, transaction::prelude::*, trigger::prelude::*, EnumTryAsError, + HasMetadata, IdBox, Identifiable, IdentifiableBox, LengthLimits, NumericValue, + PredicateTrait, RegistrableBox, ToValue, TryAsMut, TryAsRef, TryToValue, UpgradableBox, + ValidationFail, Value, }; } diff --git a/data_model/src/query/mod.rs b/data_model/src/query/mod.rs index d5df0b85016..6d96d52634f 100644 --- a/data_model/src/query/mod.rs +++ b/data_model/src/query/mod.rs @@ -88,6 +88,7 @@ macro_rules! queries { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(parity_scale_codec::Decode, parity_scale_codec::Encode)] #[derive(serde::Deserialize, serde::Serialize)] + #[derive(derive_more::Constructor)] #[derive(iroha_schema::IntoSchema)] $($meta)* $item )+ @@ -184,7 +185,7 @@ pub mod model { /// The hash of the block to which `tx` belongs to pub block_hash: HashOf, /// Transaction - pub transaction: TransactionValue, + pub transaction: Box, } /// Type returned from [`Metadata`] queries @@ -220,9 +221,13 @@ pub mod model { )] #[getset(get = "pub")] pub struct QueryWithParameters { + /// The actual query. pub query: Q, + /// Sorting of the query results. pub sorting: Sorting, + /// Pagination of the query results. pub pagination: Pagination, + /// Amount of results to fetch. pub fetch_size: FetchSize, } } @@ -323,7 +328,7 @@ pub mod role { #[ffi_type(unsafe {robust})] pub struct FindRoleByRoleId { /// `Id` of the [`Role`] to find - pub id: EvaluatesTo, + pub id: RoleId, } /// [`FindRolesByAccountId`] Iroha Query finds all [`Role`]s for a specified account. @@ -334,7 +339,7 @@ pub mod role { #[ffi_type(unsafe {robust})] pub struct FindRolesByAccountId { /// `Id` of an account to find. - pub id: EvaluatesTo, + pub id: AccountId, } } @@ -354,22 +359,6 @@ pub mod role { type Output = Role; } - impl FindRoleByRoleId { - /// Construct [`FindRoleByRoleId`]. - pub fn new(id: impl Into>) -> Self { - Self { id: id.into() } - } - } - - impl FindRolesByAccountId { - /// Construct [`FindRolesByAccountId`]. - pub fn new(account_id: impl Into>) -> Self { - Self { - id: account_id.into(), - } - } - } - /// The prelude re-exports most commonly used traits, structs and macros from this module. pub mod prelude { pub use super::{FindAllRoleIds, FindAllRoles, FindRoleByRoleId, FindRolesByAccountId}; @@ -405,7 +394,7 @@ pub mod permission { #[ffi_type(unsafe {robust})] pub struct FindPermissionTokensByAccountId { /// `Id` of an account to find. - pub id: EvaluatesTo, + pub id: AccountId, } } @@ -417,15 +406,6 @@ pub mod permission { type Output = Vec; } - impl FindPermissionTokensByAccountId { - /// Construct [`FindPermissionTokensByAccountId`]. - pub fn new(account_id: impl Into>) -> Self { - Self { - id: account_id.into(), - } - } - } - /// The prelude re-exports most commonly used traits, structs and macros from this module. pub mod prelude { pub use super::{FindPermissionTokenSchema, FindPermissionTokensByAccountId}; @@ -459,7 +439,7 @@ pub mod account { #[ffi_type(unsafe {robust})] pub struct FindAccountById { /// `Id` of an account to find. - pub id: EvaluatesTo, + pub id: AccountId, } /// [`FindAccountKeyValueByIdAndKey`] Iroha Query finds a [`Value`] @@ -469,9 +449,9 @@ pub mod account { #[ffi_type] pub struct FindAccountKeyValueByIdAndKey { /// `Id` of an account to find. - pub id: EvaluatesTo, + pub id: AccountId, /// Key of the specific key-value in the Account's metadata. - pub key: EvaluatesTo, + pub key: Name, } /// [`FindAccountsByName`] Iroha Query gets [`Account`]s name as input and @@ -483,7 +463,7 @@ pub mod account { #[ffi_type(unsafe {robust})] pub struct FindAccountsByName { /// `name` of accounts to find. - pub name: EvaluatesTo, + pub name: Name, } @@ -496,7 +476,7 @@ pub mod account { #[ffi_type(unsafe {robust})] pub struct FindAccountsByDomainId { /// `Id` of the domain under which accounts should be found. - pub domain_id: EvaluatesTo, + pub domain_id: DomainId, } /// [`FindAccountsWithAsset`] Iroha Query gets [`AssetDefinition`]s id as input and @@ -508,7 +488,7 @@ pub mod account { #[ffi_type(unsafe {robust})] pub struct FindAccountsWithAsset { /// `Id` of the definition of the asset which should be stored in founded accounts. - pub asset_definition_id: EvaluatesTo, + pub asset_definition_id: AssetDefinitionId, } } @@ -536,51 +516,6 @@ pub mod account { type Output = Vec; } - impl FindAccountById { - /// Construct [`FindAccountById`]. - pub fn new(id: impl Into>) -> Self { - Self { id: id.into() } - } - } - - impl FindAccountKeyValueByIdAndKey { - /// Construct [`FindAccountById`]. - pub fn new( - id: impl Into>, - key: impl Into>, - ) -> Self { - Self { - id: id.into(), - key: key.into(), - } - } - } - - impl FindAccountsByName { - /// Construct [`FindAccountsByName`]. - pub fn new(name: impl Into>) -> Self { - Self { name: name.into() } - } - } - - impl FindAccountsByDomainId { - /// Construct [`FindAccountsByDomainId`]. - pub fn new(domain_id: impl Into>) -> Self { - Self { - domain_id: domain_id.into(), - } - } - } - - impl FindAccountsWithAsset { - /// Construct [`FindAccountsWithAsset`]. - pub fn new(asset_definition_id: impl Into>) -> Self { - Self { - asset_definition_id: asset_definition_id.into(), - } - } - } - /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{ @@ -627,7 +562,7 @@ pub mod asset { #[ffi_type(unsafe {robust})] pub struct FindAssetById { /// `Id` of an [`Asset`] to find. - pub id: EvaluatesTo, + pub id: AssetId, } /// [`FindAssetDefinitionById`] Iroha Query finds an [`AssetDefinition`] by it's identification in Iroha [`Peer`]. @@ -638,7 +573,7 @@ pub mod asset { #[ffi_type(unsafe {robust})] pub struct FindAssetDefinitionById { /// `Id` of an [`AssetDefinition`] to find. - pub id: EvaluatesTo, + pub id: AssetDefinitionId, } /// [`FindAssetsByName`] Iroha Query gets [`Asset`]s name as input and @@ -650,7 +585,7 @@ pub mod asset { #[ffi_type(unsafe {robust})] pub struct FindAssetsByName { /// [`Name`] of [`Asset`]s to find. - pub name: EvaluatesTo, + pub name: Name, } /// [`FindAssetsByAccountId`] Iroha Query gets [`AccountId`] as input and find all [`Asset`]s @@ -662,7 +597,7 @@ pub mod asset { #[ffi_type(unsafe {robust})] pub struct FindAssetsByAccountId { /// [`AccountId`] under which assets should be found. - pub account_id: EvaluatesTo, + pub account_id: AccountId, } /// [`FindAssetsByAssetDefinitionId`] Iroha Query gets [`AssetDefinitionId`] as input and @@ -674,7 +609,7 @@ pub mod asset { #[ffi_type(unsafe {robust})] pub struct FindAssetsByAssetDefinitionId { /// [`AssetDefinitionId`] with type of [`Asset`]s should be found. - pub asset_definition_id: EvaluatesTo, + pub asset_definition_id: AssetDefinitionId, } /// [`FindAssetsByDomainId`] Iroha Query gets [`Domain`]s id as input and @@ -686,7 +621,7 @@ pub mod asset { #[ffi_type(unsafe {robust})] pub struct FindAssetsByDomainId { /// `Id` of the domain under which assets should be found. - pub domain_id: EvaluatesTo, + pub domain_id: DomainId, } /// [`FindAssetsByDomainIdAndAssetDefinitionId`] Iroha Query gets [`DomainId`] and @@ -697,9 +632,9 @@ pub mod asset { #[ffi_type] pub struct FindAssetsByDomainIdAndAssetDefinitionId { /// `Id` of the domain under which assets should be found. - pub domain_id: EvaluatesTo, + pub domain_id: DomainId, /// [`AssetDefinitionId`] assets of which type should be found. - pub asset_definition_id: EvaluatesTo, + pub asset_definition_id: AssetDefinitionId, } /// [`FindAssetQuantityById`] Iroha Query gets [`AssetId`] as input and finds [`Asset::quantity`] @@ -711,7 +646,7 @@ pub mod asset { #[ffi_type(unsafe {robust})] pub struct FindAssetQuantityById { /// `Id` of an [`Asset`] to find quantity of. - pub id: EvaluatesTo, + pub id: AssetId, } /// [`FindTotalAssetQuantityByAssetDefinitionId`] Iroha Query gets [`AssetDefinitionId`] as input and finds total [`Asset::quantity`] @@ -724,7 +659,7 @@ pub mod asset { #[ffi_type(unsafe {robust})] pub struct FindTotalAssetQuantityByAssetDefinitionId { /// `Id` of an [`Asset`] to find quantity of. - pub id: EvaluatesTo, + pub id: AssetDefinitionId, } /// [`FindAssetKeyValueByIdAndKey`] Iroha Query gets [`AssetId`] and key as input and finds [`Value`] @@ -734,9 +669,9 @@ pub mod asset { #[ffi_type] pub struct FindAssetKeyValueByIdAndKey { /// `Id` of an [`Asset`] acting as [`Store`](crate::asset::AssetValue::Store). - pub id: EvaluatesTo, + pub id: AssetId, /// The key of the key-value pair stored in the asset. - pub key: EvaluatesTo, + pub key: Name, } /// [`FindAssetDefinitionKeyValueByIdAndKey`] Iroha Query gets [`AssetDefinitionId`] and key as input and finds [`Value`] @@ -746,9 +681,9 @@ pub mod asset { #[ffi_type] pub struct FindAssetDefinitionKeyValueByIdAndKey { /// `Id` of an [`Asset`] acting as [`Store`](crate::asset::AssetValue::Store).. - pub id: EvaluatesTo, + pub id: AssetDefinitionId, /// The key of the key-value pair stored in the asset. - pub key: EvaluatesTo, + pub key: Name, } } @@ -804,104 +739,6 @@ pub mod asset { type Output = MetadataValue; } - impl FindAssetById { - /// Construct [`FindAssetById`]. - pub fn new(id: impl Into>) -> Self { - Self { id: id.into() } - } - } - - impl FindAssetDefinitionById { - /// Construct [`FindAssetDefinitionById`]. - pub fn new(id: impl Into>) -> Self { - Self { id: id.into() } - } - } - - impl FindAssetsByName { - /// Construct [`FindAssetsByName`]. - pub fn new(name: impl Into>) -> Self { - Self { name: name.into() } - } - } - - impl FindAssetsByAccountId { - /// Construct [`FindAssetsByAccountId`]. - pub fn new(account_id: impl Into>) -> Self { - Self { - account_id: account_id.into(), - } - } - } - - impl FindAssetsByAssetDefinitionId { - /// Construct [`FindAssetsByAssetDefinitionId`]. - pub fn new(asset_definition_id: impl Into>) -> Self { - Self { - asset_definition_id: asset_definition_id.into(), - } - } - } - - impl FindAssetsByDomainId { - /// Construct [`FindAssetsByDomainId`]. - pub fn new(domain_id: impl Into>) -> Self { - Self { - domain_id: domain_id.into(), - } - } - } - - impl FindAssetsByDomainIdAndAssetDefinitionId { - /// Construct [`FindAssetsByDomainIdAndAssetDefinitionId`]. - pub fn new( - domain_id: impl Into>, - asset_definition_id: impl Into>, - ) -> Self { - Self { - domain_id: domain_id.into(), - asset_definition_id: asset_definition_id.into(), - } - } - } - - impl FindAssetQuantityById { - /// Construct [`FindAssetQuantityById`]. - pub fn new(id: impl Into>) -> Self { - Self { id: id.into() } - } - } - - impl FindTotalAssetQuantityByAssetDefinitionId { - /// Construct [`FindTotalAssetQuantityByAssetDefinitionId`] - pub fn new(id: impl Into>) -> Self { - Self { id: id.into() } - } - } - - impl FindAssetKeyValueByIdAndKey { - /// Construct [`FindAssetKeyValueByIdAndKey`]. - pub fn new(id: impl Into>, key: impl Into>) -> Self { - Self { - id: id.into(), - key: key.into(), - } - } - } - - impl FindAssetDefinitionKeyValueByIdAndKey { - /// Construct [`FindAssetDefinitionKeyValueByIdAndKey`]. - pub fn new( - id: impl Into>, - key: impl Into>, - ) -> Self { - Self { - id: id.into(), - key: key.into(), - } - } - } - /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{ @@ -942,10 +779,9 @@ pub mod domain { #[ffi_type(unsafe {robust})] pub struct FindDomainById { /// `Id` of the domain to find. - pub id: EvaluatesTo, + pub id: DomainId, } - /// [`FindDomainKeyValueByIdAndKey`] Iroha Query finds a [`Value`] of the key-value metadata pair /// in the specified domain. #[derive(Display)] @@ -953,9 +789,9 @@ pub mod domain { #[ffi_type] pub struct FindDomainKeyValueByIdAndKey { /// `Id` of an domain to find. - pub id: EvaluatesTo, + pub id: DomainId, /// Key of the specific key-value in the domain's metadata. - pub key: EvaluatesTo, + pub key: Name, } } @@ -971,26 +807,6 @@ pub mod domain { type Output = MetadataValue; } - impl FindDomainById { - /// Construct [`FindDomainById`]. - pub fn new(id: impl Into>) -> Self { - Self { id: id.into() } - } - } - - impl FindDomainKeyValueByIdAndKey { - /// Construct [`FindDomainKeyValueByIdAndKey`]. - pub fn new( - id: impl Into>, - key: impl Into>, - ) -> Self { - Self { - id: id.into(), - key: key.into(), - } - } - } - /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{FindAllDomains, FindDomainById, FindDomainKeyValueByIdAndKey}; @@ -1015,7 +831,6 @@ pub mod peer { #[ffi_type] pub struct FindAllPeers; - /// [`FindAllParameters`] Iroha Query finds all [`Peer`]s parameters. #[derive(Copy, Display)] #[display(fmt = "Find all peers parameters")] @@ -1049,8 +864,7 @@ pub mod trigger { use crate::{ domain::prelude::*, events::TriggeringFilterBox, - expression::EvaluatesTo, - prelude::InstructionExpr, + prelude::InstructionBox, trigger::{Trigger, TriggerId}, Executable, Identifiable, Name, Value, }; @@ -1063,7 +877,6 @@ pub mod trigger { #[ffi_type] pub struct FindAllActiveTriggerIds; - /// Find Trigger given its ID. #[derive(Display)] #[display(fmt = "Find `{id}` trigger")] @@ -1072,7 +885,7 @@ pub mod trigger { #[ffi_type(unsafe {robust})] pub struct FindTriggerById { /// The Identification of the trigger to be found. - pub id: EvaluatesTo, + pub id: TriggerId, } @@ -1082,9 +895,9 @@ pub mod trigger { #[ffi_type] pub struct FindTriggerKeyValueByIdAndKey { /// The Identification of the trigger to be found. - pub id: EvaluatesTo, + pub id: TriggerId, /// The key inside the metadata dictionary to be returned. - pub key: EvaluatesTo, + pub key: Name, } @@ -1096,7 +909,7 @@ pub mod trigger { #[ffi_type(unsafe {robust})] pub struct FindTriggersByDomainId { /// [`DomainId`] specifies the domain in which to search for triggers. - pub domain_id: EvaluatesTo, + pub domain_id: DomainId, } } @@ -1116,35 +929,6 @@ pub mod trigger { type Output = Vec>; } - impl FindTriggerById { - /// Construct [`FindTriggerById`]. - pub fn new(id: impl Into>) -> Self { - Self { id: id.into() } - } - } - - impl FindTriggerKeyValueByIdAndKey { - /// Construct [`FindTriggerKeyValueByIdAndKey`]. - pub fn new( - id: impl Into>, - key: impl Into>, - ) -> Self { - Self { - id: id.into(), - key: key.into(), - } - } - } - - impl FindTriggersByDomainId { - /// Construct [`FindTriggersByDomainId`]. - pub fn new(domain_id: impl Into>) -> Self { - Self { - domain_id: domain_id.into(), - } - } - } - pub mod prelude { //! Prelude Re-exports most commonly used traits, structs and macros from this crate. pub use super::{ @@ -1166,10 +950,7 @@ pub mod transaction { use iroha_crypto::HashOf; use super::{Query, TransactionQueryOutput}; - use crate::{ - account::AccountId, expression::EvaluatesTo, prelude::Account, - transaction::SignedTransaction, - }; + use crate::{account::AccountId, prelude::Account, transaction::SignedTransaction}; queries! { /// [`FindAllTransactions`] Iroha Query lists all transactions included in a blockchain @@ -1187,19 +968,19 @@ pub mod transaction { #[ffi_type(unsafe {robust})] pub struct FindTransactionsByAccountId { /// Signer's [`AccountId`] under which transactions should be found. - pub account_id: EvaluatesTo, + pub account_id: AccountId, } /// [`FindTransactionByHash`] Iroha Query finds a transaction (if any) /// with corresponding hash value - #[derive(Display)] + #[derive(Copy, Display)] #[display(fmt = "Find transaction with `{hash}` hash")] #[repr(transparent)] // SAFETY: `FindTransactionByHash` has no trap representation in `EvaluatesTo>` #[ffi_type(unsafe {robust})] pub struct FindTransactionByHash { /// Transaction hash. - pub hash: EvaluatesTo>, + pub hash: HashOf, } } @@ -1215,22 +996,6 @@ pub mod transaction { type Output = TransactionQueryOutput; } - impl FindTransactionsByAccountId { - /// Construct [`FindTransactionsByAccountId`]. - pub fn new(account_id: impl Into>) -> Self { - Self { - account_id: account_id.into(), - } - } - } - - impl FindTransactionByHash { - /// Construct [`FindTransactionByHash`]. - pub fn new(hash: impl Into>>) -> Self { - Self { hash: hash.into() } - } - } - /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{FindAllTransactions, FindTransactionByHash, FindTransactionsByAccountId}; @@ -1249,10 +1014,7 @@ pub mod block { use iroha_crypto::HashOf; use super::Query; - use crate::{ - block::{BlockHeader, SignedBlock}, - prelude::EvaluatesTo, - }; + use crate::block::{BlockHeader, SignedBlock}; queries! { /// [`FindAllBlocks`] Iroha Query lists all blocks sorted by @@ -1270,14 +1032,14 @@ pub mod block { pub struct FindAllBlockHeaders; /// [`FindBlockHeaderByHash`] Iroha Query finds block header by block hash - #[derive(Display)] + #[derive(Copy, Display)] #[display(fmt = "Find block header with `{hash}` hash")] #[repr(transparent)] // SAFETY: `FindBlockHeaderByHash` has no trap representation in `EvaluatesTo>` #[ffi_type(unsafe {robust})] pub struct FindBlockHeaderByHash { /// Block hash. - pub hash: EvaluatesTo>, + pub hash: HashOf, } } @@ -1293,13 +1055,6 @@ pub mod block { type Output = BlockHeader; } - impl FindBlockHeaderByHash { - /// Construct [`FindBlockHeaderByHash`]. - pub fn new(hash: impl Into>>) -> Self { - Self { hash: hash.into() } - } - } - /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{FindAllBlockHeaders, FindAllBlocks, FindBlockHeaderByHash}; @@ -1538,12 +1293,6 @@ pub mod error { #[skip_try_from] String, ), - /// Query has a malformed expression: {0} - Evaluate( - #[skip_from] - #[skip_try_from] - String, - ), /// {0} #[cfg_attr(feature = "std", error(transparent))] Find(FindError), diff --git a/data_model/src/transaction.rs b/data_model/src/transaction.rs index a7742873c7a..9d288239636 100644 --- a/data_model/src/transaction.rs +++ b/data_model/src/transaction.rs @@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize}; pub use self::model::*; use crate::{ account::AccountId, - isi::{Instruction, InstructionExpr}, + isi::{Instruction, InstructionBox}, metadata::UnlimitedMetadata, name::Name, Value, @@ -51,7 +51,7 @@ pub mod model { pub enum Executable { /// Ordered set of instructions. #[debug(fmt = "{_0:?}")] - Instructions(Vec), + Instructions(Vec), /// WebAssembly smartcontract Wasm(WasmSmartContract), } @@ -533,7 +533,7 @@ pub mod error { pub struct InstructionExecutionFail { /// Instruction for which execution failed #[getset(get = "pub")] - pub instruction: InstructionExpr, + pub instruction: InstructionBox, /// Error which happened during execution pub reason: String, } @@ -611,15 +611,12 @@ pub mod error { impl Display for InstructionExecutionFail { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - use InstructionExpr::*; + use InstructionBox::*; let kind = match self.instruction { Burn(_) => "burn", Fail(_) => "fail", - If(_) => "if", Mint(_) => "mint", - Pair(_) => "pair", Register(_) => "register", - Sequence(_) => "sequence", Transfer(_) => "transfer", Unregister(_) => "un-register", SetKeyValue(_) => "set key-value pair", @@ -691,7 +688,7 @@ mod http { creation_time_ms, nonce: None, time_to_live_ms: None, - instructions: Vec::::new().into(), + instructions: Vec::::new().into(), metadata: UnlimitedMetadata::new(), }, } @@ -707,7 +704,7 @@ mod http { self.payload.instructions = instructions .into_iter() .map(Into::into) - .collect::>() + .collect::>() .into(); self } diff --git a/data_model/src/trigger.rs b/data_model/src/trigger.rs index 0127ce3bf77..4270d2d34ac 100644 --- a/data_model/src/trigger.rs +++ b/data_model/src/trigger.rs @@ -203,7 +203,7 @@ pub mod action { /// Enumeration of possible repetitions schemes. #[derive( - Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema, + Debug, Copy, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema, )] #[ffi_type] pub enum Repeats { diff --git a/data_model/src/visit.rs b/data_model/src/visit.rs index 62a33f328c8..9f82b19baae 100644 --- a/data_model/src/visit.rs +++ b/data_model/src/visit.rs @@ -6,7 +6,7 @@ use alloc::format; use iroha_crypto::PublicKey; -use crate::{evaluate::ExpressionEvaluator, isi::Log, prelude::*, NumericValue}; +use crate::{isi::Log, prelude::*}; macro_rules! delegate { ( $($visitor:ident $(<$param:ident $(: $bound:path)?>)?($operation:ty)),+ $(,)? ) => { $( @@ -16,54 +16,36 @@ macro_rules! delegate { }; } -macro_rules! evaluate_expr { - ($visitor:ident, $authority:ident, <$isi:ident as $isi_type:ty>::$field:ident()) => {{ - $visitor.visit_expression($authority, $isi.$field()); - - $visitor.evaluate($isi.$field()).expect(&format!( - "Failed to evaluate field '{}::{}'", - stringify!($isi_type), - stringify!($field), - )) - }}; -} - /// Trait to validate Iroha entities. /// Default implementation of non-leaf visitors runs `visit_` functions for leafs. /// Default implementation for leaf visitors is blank. /// /// This trait is based on the visitor pattern. -pub trait Visit: ExpressionEvaluator { +pub trait Visit { delegate! { - visit_unsupported(T), - // Visit SignedTransaction visit_transaction(&SignedTransaction), - visit_instruction(&InstructionExpr), - visit_expression(&EvaluatesTo), + visit_instruction(&InstructionBox), visit_wasm(&WasmSmartContract), visit_query(&QueryBox), - // Visit InstructionExpr - visit_burn(&BurnExpr), + // Visit InstructionBox + visit_burn(&BurnBox), visit_fail(&Fail), - visit_grant(&GrantExpr), - visit_if(&ConditionalExpr), - visit_mint(&MintExpr), - visit_pair(&PairExpr), - visit_register(&RegisterExpr), - visit_remove_key_value(&RemoveKeyValueExpr), - visit_revoke(&RevokeExpr), - visit_sequence(&SequenceExpr), - visit_set_key_value(&SetKeyValueExpr), - visit_transfer(&TransferExpr), - visit_unregister(&UnregisterExpr), - visit_upgrade(&UpgradeExpr), - - visit_execute_trigger(ExecuteTrigger), - visit_new_parameter(NewParameter), - visit_set_parameter(SetParameter), - visit_log(Log), + visit_grant(&GrantBox), + visit_mint(&MintBox), + visit_register(&RegisterBox), + visit_remove_key_value(&RemoveKeyValueBox), + visit_revoke(&RevokeBox), + visit_set_key_value(&SetKeyValueBox), + visit_transfer(&TransferBox), + visit_unregister(&UnregisterBox), + visit_upgrade(&Upgrade), + + visit_execute_trigger(&ExecuteTrigger), + visit_new_parameter(&NewParameter), + visit_set_parameter(&SetParameter), + visit_log(&Log), // Visit QueryBox visit_find_account_by_id(&FindAccountById), @@ -78,7 +60,7 @@ pub trait Visit: ExpressionEvaluator { visit_find_all_block_headers(&FindAllBlockHeaders), visit_find_all_blocks(&FindAllBlocks), visit_find_all_domains(&FindAllDomains), - visit_find_all_parammeters(&FindAllParameters), + visit_find_all_parameters(&FindAllParameters), visit_find_all_peers(&FindAllPeers), visit_find_permission_token_schema(&FindPermissionTokenSchema), visit_find_all_role_ids(&FindAllRoleIds), @@ -107,74 +89,69 @@ pub trait Visit: ExpressionEvaluator { visit_find_trigger_key_value_by_id_and_key(&FindTriggerKeyValueByIdAndKey), visit_find_triggers_by_domain_id(&FindTriggersByDomainId), - // Visit RegisterExpr - visit_register_peer(Register), - visit_register_domain(Register), - visit_register_account(Register), - visit_register_asset_definition(Register), - visit_register_asset(Register), - visit_register_role(Register), - visit_register_trigger(Register>), - - // Visit UnregisterExpr - visit_unregister_peer(Unregister), - visit_unregister_domain(Unregister), - visit_unregister_account(Unregister), - visit_unregister_asset_definition(Unregister), - visit_unregister_asset(Unregister), + // Visit RegisterBox + visit_register_peer(&Register), + visit_register_domain(&Register), + visit_register_account(&Register), + visit_register_asset_definition(&Register), + visit_register_asset(&Register), + visit_register_role(&Register), + visit_register_trigger(&Register>), + + // Visit UnregisterBox + visit_unregister_peer(&Unregister), + visit_unregister_domain(&Unregister), + visit_unregister_account(&Unregister), + visit_unregister_asset_definition(&Unregister), + visit_unregister_asset(&Unregister), // TODO: Need to allow role creator to unregister it somehow - visit_unregister_role(Unregister), - visit_unregister_trigger(Unregister>), - - // Visit MintExpr - visit_mint_asset(Mint), - visit_mint_account_public_key(Mint), - visit_mint_account_signature_check_condition(Mint), - visit_mint_trigger_repetitions(Mint>), - - // Visit BurnExpr - visit_burn_account_public_key(Burn), - visit_burn_asset(Burn), - visit_burn_trigger_repetitions(Burn>), - - // Visit TransferExpr - visit_transfer_asset_definition(Transfer), - visit_transfer_asset(Transfer), - visit_transfer_domain(Transfer), - - // Visit SetKeyValueExpr - visit_set_domain_key_value(SetKeyValue), - visit_set_account_key_value(SetKeyValue), - visit_set_asset_definition_key_value(SetKeyValue), - visit_set_asset_key_value(SetKeyValue), - - // Visit RemoveKeyValueExpr - visit_remove_domain_key_value(RemoveKeyValue), - visit_remove_account_key_value(RemoveKeyValue), - visit_remove_asset_definition_key_value(RemoveKeyValue), - visit_remove_asset_key_value(RemoveKeyValue), - - // Visit GrantExpr - visit_grant_account_permission(Grant), - visit_grant_account_role(Grant), - - // Visit RevokeExpr - visit_revoke_account_permission(Revoke), - visit_revoke_account_role(Revoke), - - // Visit UpgradeExpr - visit_upgrade_executor(Upgrade), + visit_unregister_role(&Unregister), + visit_unregister_trigger(&Unregister>), + + // Visit MintBox + visit_mint_asset_quantity(&Mint), + visit_mint_asset_big_quantity(&Mint), + visit_mint_asset_fixed(&Mint), + visit_mint_account_public_key(&Mint), + visit_mint_account_signature_check_condition(&Mint), + visit_mint_trigger_repetitions(&Mint>), + + // Visit BurnBox + visit_burn_account_public_key(&Burn), + visit_burn_asset_quantity(&Burn), + visit_burn_asset_big_quantity(&Burn), + visit_burn_asset_fixed(&Burn), + visit_burn_trigger_repetitions(&Burn>), + + // Visit TransferBox + visit_transfer_asset_definition(&Transfer), + visit_transfer_asset_quantity(&Transfer), + visit_transfer_asset_big_quantity(&Transfer), + visit_transfer_asset_fixed(&Transfer), + visit_transfer_domain(&Transfer), + + // Visit SetKeyValueBox + visit_set_domain_key_value(&SetKeyValue), + visit_set_account_key_value(&SetKeyValue), + visit_set_asset_definition_key_value(&SetKeyValue), + visit_set_asset_key_value(&SetKeyValue), + + // Visit RemoveKeyValueBox + visit_remove_domain_key_value(&RemoveKeyValue), + visit_remove_account_key_value(&RemoveKeyValue), + visit_remove_asset_definition_key_value(&RemoveKeyValue), + visit_remove_asset_key_value(&RemoveKeyValue), + + // Visit GrantBox + visit_grant_account_permission(&Grant), + visit_grant_account_role(&Grant), + + // Visit RevokeBox + visit_revoke_account_permission(&Revoke), + visit_revoke_account_role(&Revoke), } } -/// Called when visiting any unsupported syntax tree node -fn visit_unsupported( - _visitor: &mut V, - _authority: &AccountId, - _isi: T, -) { -} - pub fn visit_transaction( visitor: &mut V, authority: &AccountId, @@ -213,7 +190,7 @@ pub fn visit_query(visitor: &mut V, authority: &AccountId, qu visit_find_all_block_headers(FindAllBlockHeaders), visit_find_all_blocks(FindAllBlocks), visit_find_all_domains(FindAllDomains), - visit_find_all_parammeters(FindAllParameters), + visit_find_all_parameters(FindAllParameters), visit_find_all_peers(FindAllPeers), visit_find_permission_token_schema(FindPermissionTokenSchema), visit_find_all_role_ids(FindAllRoleIds), @@ -251,7 +228,7 @@ pub fn visit_wasm( ) { } -/// Default validation for [`InstructionExpr`]. +/// Default validation for [`InstructionBox`]. /// /// # Warning /// @@ -259,430 +236,167 @@ pub fn visit_wasm( pub fn visit_instruction( visitor: &mut V, authority: &AccountId, - isi: &InstructionExpr, -) { - macro_rules! isi_visitors { - ( $($visitor:ident($isi:ident)),+ $(,)? ) => { - match isi { - InstructionExpr::NewParameter(isi) => { - let parameter = evaluate_expr!(visitor, authority, ::parameter()); - visitor.visit_new_parameter(authority, NewParameter{parameter}); - } - InstructionExpr::SetParameter(isi) => { - let parameter = evaluate_expr!(visitor, authority, ::parameter()); - visitor.visit_set_parameter(authority, SetParameter{parameter}); - } - InstructionExpr::ExecuteTrigger(isi) => { - let trigger_id = evaluate_expr!(visitor, authority, ::trigger_id()); - visitor.visit_execute_trigger(authority, ExecuteTrigger{trigger_id}); - } - InstructionExpr::Log(isi) => { - let msg = evaluate_expr!(visitor, authority, ::msg()); - let level = evaluate_expr!(visitor, authority, ::level()); - visitor.visit_log(authority, Log { msg, level }); - } $( - InstructionExpr::$isi(isi) => { - visitor.$visitor(authority, isi); - } )+ - } - }; - } - - isi_visitors! { - visit_burn(Burn), - visit_fail(Fail), - visit_grant(Grant), - visit_mint(Mint), - visit_register(Register), - visit_remove_key_value(RemoveKeyValue), - visit_revoke(Revoke), - visit_set_key_value(SetKeyValue), - visit_transfer(Transfer), - visit_unregister(Unregister), - visit_upgrade(Upgrade), - visit_sequence(Sequence), - visit_pair(Pair), - visit_if(If), - } -} - -pub fn visit_expression( - visitor: &mut V, - authority: &AccountId, - expression: &EvaluatesTo, + isi: &InstructionBox, ) { - macro_rules! visit_binary_math_expression { - ($e:ident) => {{ - visitor.visit_expression(authority, $e.left()); - visitor.visit_expression(authority, $e.right()) - }}; - } - - macro_rules! visit_binary_bool_expression { - ($e:ident) => {{ - visitor.visit_expression(authority, $e.left()); - visitor.visit_expression(authority, $e.right()) - }}; - } - - match expression.expression() { - Expression::Add(expr) => visit_binary_math_expression!(expr), - Expression::Subtract(expr) => visit_binary_math_expression!(expr), - Expression::Multiply(expr) => visit_binary_math_expression!(expr), - Expression::Divide(expr) => visit_binary_math_expression!(expr), - Expression::Mod(expr) => visit_binary_math_expression!(expr), - Expression::RaiseTo(expr) => visit_binary_math_expression!(expr), - Expression::Greater(expr) => visit_binary_math_expression!(expr), - Expression::Less(expr) => visit_binary_math_expression!(expr), - Expression::Equal(expr) => visit_binary_bool_expression!(expr), - Expression::Not(expr) => visitor.visit_expression(authority, expr.expression()), - Expression::And(expr) => visit_binary_bool_expression!(expr), - Expression::Or(expr) => visit_binary_bool_expression!(expr), - Expression::If(expr) => { - visitor.visit_expression(authority, expr.condition()); - visitor.visit_expression(authority, expr.then()); - visitor.visit_expression(authority, expr.otherwise()); + match isi { + InstructionBox::NewParameter(variant_value) => { + visitor.visit_new_parameter(authority, variant_value) } - Expression::Contains(expr) => { - visitor.visit_expression(authority, expr.collection()); - visitor.visit_expression(authority, expr.element()); + InstructionBox::SetParameter(variant_value) => { + visitor.visit_set_parameter(authority, variant_value) } - Expression::ContainsAll(expr) => { - visitor.visit_expression(authority, expr.collection()); - visitor.visit_expression(authority, expr.elements()); + InstructionBox::ExecuteTrigger(variant_value) => { + visitor.visit_execute_trigger(authority, variant_value) } - Expression::ContainsAny(expr) => { - visitor.visit_expression(authority, expr.collection()); - visitor.visit_expression(authority, expr.elements()); + InstructionBox::Log(variant_value) => visitor.visit_log(authority, variant_value), + InstructionBox::Burn(variant_value) => visitor.visit_burn(authority, variant_value), + InstructionBox::Fail(variant_value) => visitor.visit_fail(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::RemoveKeyValue(variant_value) => { + visitor.visit_remove_key_value(authority, variant_value) } - Expression::Where(expr) => visitor.visit_expression(authority, expr.expression()), - Expression::Query(query) => visitor.visit_query(authority, query), - Expression::ContextValue(_) | Expression::Raw(_) => {} + 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) + } + InstructionBox::Upgrade(variant_value) => visitor.visit_upgrade(authority, variant_value), } } pub fn visit_register( visitor: &mut V, authority: &AccountId, - isi: &RegisterExpr, + isi: &RegisterBox, ) { - macro_rules! match_all { - ( $( $visitor:ident($object:ident) ),+ $(,)? ) => { - let object = evaluate_expr!(visitor, authority, ::object()); - - match object { $( - RegistrableBox::$object(object) => visitor.$visitor(authority, Register{object}), )+ - } - }; - } - - match_all! { - visit_register_peer(Peer), - visit_register_domain(Domain), - visit_register_account(Account), - visit_register_asset_definition(AssetDefinition), - visit_register_asset(Asset), - visit_register_role(Role), - visit_register_trigger(Trigger), + 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), } } pub fn visit_unregister( visitor: &mut V, authority: &AccountId, - isi: &UnregisterExpr, + isi: &UnregisterBox, ) { - macro_rules! match_all { - ( $( $visitor:ident($id:ident) ),+ $(,)? ) => { - let object_id = evaluate_expr!(visitor, authority, ::object_id()); - match object_id { $( - IdBox::$id(object_id) => visitor.$visitor(authority, Unregister{object_id}), )+ - _ => visitor.visit_unsupported(authority, isi), - } - }; - } - - match_all! { - visit_unregister_peer(PeerId), - visit_unregister_domain(DomainId), - visit_unregister_account(AccountId), - visit_unregister_asset_definition(AssetDefinitionId), - visit_unregister_asset(AssetId), - visit_unregister_role(RoleId), - visit_unregister_trigger(TriggerId), + 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), } } -pub fn visit_mint(visitor: &mut V, authority: &AccountId, isi: &MintExpr) { - let destination_id = evaluate_expr!(visitor, authority, ::destination_id()); - let object = evaluate_expr!(visitor, authority, ::object()); - - match (destination_id, object) { - (IdBox::AssetId(destination_id), Value::Numeric(object)) => visitor.visit_mint_asset( - authority, - Mint { - object, - destination_id, - }, - ), - (IdBox::AccountId(destination_id), Value::PublicKey(object)) => visitor - .visit_mint_account_public_key( - authority, - Mint { - object, - destination_id, - }, - ), - (IdBox::AccountId(destination_id), Value::SignatureCheckCondition(object)) => visitor - .visit_mint_account_signature_check_condition( - authority, - Mint { - object, - destination_id, - }, - ), - (IdBox::TriggerId(destination_id), Value::Numeric(NumericValue::U32(object))) => visitor - .visit_mint_trigger_repetitions( - authority, - Mint { - object, - destination_id, - }, - ), - _ => visitor.visit_unsupported(authority, isi), +pub fn visit_mint(visitor: &mut V, authority: &AccountId, isi: &MintBox) { + match isi { + MintBox::Account(mint_account) => match mint_account { + AccountMintBox::PublicKey(obj) => visitor.visit_mint_account_public_key(authority, obj), + AccountMintBox::SignatureCheckCondition(obj) => { + visitor.visit_mint_account_signature_check_condition(authority, obj) + } + }, + MintBox::Asset(mint_asset) => match mint_asset { + AssetMintBox::Quantity(obj) => visitor.visit_mint_asset_quantity(authority, obj), + AssetMintBox::BigQuantity(obj) => visitor.visit_mint_asset_big_quantity(authority, obj), + AssetMintBox::Fixed(obj) => visitor.visit_mint_asset_fixed(authority, obj), + }, + MintBox::TriggerRepetitions(obj) => visitor.visit_mint_trigger_repetitions(authority, obj), } } -pub fn visit_burn(visitor: &mut V, authority: &AccountId, isi: &BurnExpr) { - let destination_id = evaluate_expr!(visitor, authority, ::destination_id()); - let object = evaluate_expr!(visitor, authority, ::object()); - - match (destination_id, object) { - (IdBox::AssetId(destination_id), Value::Numeric(object)) => visitor.visit_burn_asset( - authority, - Burn { - object, - destination_id, - }, - ), - (IdBox::AccountId(destination_id), Value::PublicKey(object)) => visitor - .visit_burn_account_public_key( - authority, - Burn { - object, - destination_id, - }, - ), - (IdBox::TriggerId(destination_id), Value::Numeric(NumericValue::U32(object))) => visitor - .visit_burn_trigger_repetitions( - authority, - Burn { - object, - destination_id, - }, - ), - _ => visitor.visit_unsupported(authority, isi), +pub fn visit_burn(visitor: &mut V, authority: &AccountId, isi: &BurnBox) { + match isi { + BurnBox::AccountPublicKey(obj) => visitor.visit_burn_account_public_key(authority, obj), + BurnBox::Asset(burn_asset) => match burn_asset { + AssetBurnBox::Quantity(obj) => visitor.visit_burn_asset_quantity(authority, obj), + AssetBurnBox::BigQuantity(obj) => visitor.visit_burn_asset_big_quantity(authority, obj), + AssetBurnBox::Fixed(obj) => visitor.visit_burn_asset_fixed(authority, obj), + }, + BurnBox::TriggerRepetitions(obj) => visitor.visit_burn_trigger_repetitions(authority, obj), } } pub fn visit_transfer( visitor: &mut V, authority: &AccountId, - isi: &TransferExpr, + isi: &TransferBox, ) { - let object = evaluate_expr!(visitor, authority, ::object()); - let source_id = evaluate_expr!(visitor, authority, ::source_id()); - let destination_id = evaluate_expr!(visitor, authority, ::destination_id()); - - match (source_id, object, destination_id) { - (IdBox::AssetId(source_id), Value::Numeric(object), IdBox::AccountId(destination_id)) => { - visitor.visit_transfer_asset( - authority, - Transfer { - source_id, - object, - destination_id, - }, - ); + match isi { + TransferBox::Domain(obj) => visitor.visit_transfer_domain(authority, obj), + TransferBox::AssetDefinition(obj) => { + visitor.visit_transfer_asset_definition(authority, obj) } - ( - IdBox::AccountId(source_id), - Value::Id(IdBox::AssetDefinitionId(object)), - IdBox::AccountId(destination_id), - ) => visitor.visit_transfer_asset_definition( - authority, - Transfer { - source_id, - object, - destination_id, - }, - ), - ( - IdBox::AccountId(source_id), - Value::Id(IdBox::DomainId(object)), - IdBox::AccountId(destination_id), - ) => visitor.visit_transfer_domain( - authority, - Transfer { - source_id, - object, - destination_id, - }, - ), - _ => visitor.visit_unsupported(authority, isi), + TransferBox::Asset(transfer_asset) => match transfer_asset { + AssetTransferBox::Quantity(obj) => { + visitor.visit_transfer_asset_quantity(authority, obj) + } + AssetTransferBox::BigQuantity(obj) => { + visitor.visit_transfer_asset_big_quantity(authority, obj) + } + AssetTransferBox::Fixed(obj) => visitor.visit_transfer_asset_fixed(authority, obj), + }, } } pub fn visit_set_key_value( visitor: &mut V, authority: &AccountId, - isi: &SetKeyValueExpr, + isi: &SetKeyValueBox, ) { - let object_id = evaluate_expr!(visitor, authority, ::object_id()); - let key = evaluate_expr!(visitor, authority, ::key()); - let value = evaluate_expr!(visitor, authority, ::value()); - - match object_id { - IdBox::AssetId(object_id) => visitor.visit_set_asset_key_value( - authority, - SetKeyValue { - object_id, - key, - value, - }, - ), - IdBox::AssetDefinitionId(object_id) => visitor.visit_set_asset_definition_key_value( - authority, - SetKeyValue { - object_id, - key, - value, - }, - ), - IdBox::AccountId(object_id) => visitor.visit_set_account_key_value( - authority, - SetKeyValue { - object_id, - key, - value, - }, - ), - IdBox::DomainId(object_id) => visitor.visit_set_domain_key_value( - authority, - SetKeyValue { - object_id, - key, - value, - }, - ), - _ => visitor.visit_unsupported(authority, isi), + 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), } } pub fn visit_remove_key_value( visitor: &mut V, authority: &AccountId, - isi: &RemoveKeyValueExpr, + isi: &RemoveKeyValueBox, ) { - let object_id = evaluate_expr!(visitor, authority, ::object_id()); - let key = evaluate_expr!(visitor, authority, ::key()); - - match object_id { - IdBox::AssetId(object_id) => { - visitor.visit_remove_asset_key_value(authority, RemoveKeyValue { object_id, key }); - } - IdBox::AssetDefinitionId(object_id) => visitor - .visit_remove_asset_definition_key_value(authority, RemoveKeyValue { object_id, key }), - IdBox::AccountId(object_id) => { - visitor.visit_remove_account_key_value(authority, RemoveKeyValue { object_id, key }); - } - IdBox::DomainId(object_id) => { - visitor.visit_remove_domain_key_value(authority, RemoveKeyValue { object_id, key }); - } - _ => visitor.visit_unsupported(authority, isi), - } -} - -pub fn visit_grant(visitor: &mut V, authority: &AccountId, isi: &GrantExpr) { - let destination_id = evaluate_expr!(visitor, authority, ::destination_id()); - let object = evaluate_expr!(visitor, authority, ::object()); - - match object { - Value::PermissionToken(object) => visitor.visit_grant_account_permission( - authority, - Grant { - object, - destination_id, - }, - ), - Value::Id(IdBox::RoleId(object)) => visitor.visit_grant_account_role( - authority, - Grant { - object, - destination_id, - }, - ), - _ => visitor.visit_unsupported(authority, isi), - } -} - -pub fn visit_revoke(visitor: &mut V, authority: &AccountId, isi: &RevokeExpr) { - let destination_id = evaluate_expr!(visitor, authority, ::destination_id()); - let object = evaluate_expr!(visitor, authority, ::object()); - - match object { - Value::PermissionToken(object) => visitor.visit_revoke_account_permission( - authority, - Revoke { - object, - destination_id, - }, - ), - Value::Id(IdBox::RoleId(object)) => visitor.visit_revoke_account_role( - authority, - Revoke { - object, - destination_id, - }, - ), - _ => visitor.visit_unsupported(authority, isi), - } -} - -pub fn visit_upgrade(visitor: &mut V, authority: &AccountId, isi: &UpgradeExpr) { - let object = evaluate_expr!(visitor, authority, ::object()); - - match object { - UpgradableBox::Executor(object) => { - visitor.visit_upgrade_executor(authority, Upgrade { object }); + 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::AssetDefinition(obj) => { + visitor.visit_remove_asset_definition_key_value(authority, obj) } + RemoveKeyValueBox::Asset(obj) => visitor.visit_remove_asset_key_value(authority, obj), } } -pub fn visit_if(visitor: &mut V, authority: &AccountId, isi: &ConditionalExpr) { - let condition = evaluate_expr!(visitor, authority, ::condition()); - - // TODO: Should visit both by default or not? It will affect Executor behavior - // because only one branch needs to be executed. IMO both should be validated - if condition { - visitor.visit_instruction(authority, isi.then()); - } else if let Some(otherwise) = isi.otherwise() { - visitor.visit_instruction(authority, otherwise); +pub fn visit_grant(visitor: &mut V, authority: &AccountId, isi: &GrantBox) { + match isi { + GrantBox::PermissionToken(obj) => visitor.visit_grant_account_permission(authority, obj), + GrantBox::Role(obj) => visitor.visit_grant_account_role(authority, obj), } } -pub fn visit_pair(visitor: &mut V, authority: &AccountId, isi: &PairExpr) { - visitor.visit_instruction(authority, isi.left_instruction()); - visitor.visit_instruction(authority, isi.right_instruction()); -} - -pub fn visit_sequence( - visitor: &mut V, - authority: &AccountId, - isi: &SequenceExpr, -) { - for instruction in isi.instructions() { - visitor.visit_instruction(authority, instruction); +pub fn visit_revoke(visitor: &mut V, authority: &AccountId, isi: &RevokeBox) { + match isi { + RevokeBox::PermissionToken(obj) => visitor.visit_revoke_account_permission(authority, obj), + RevokeBox::Role(obj) => visitor.visit_revoke_account_role(authority, obj), } } @@ -696,48 +410,54 @@ macro_rules! leaf_visitors { leaf_visitors! { // Instruction visitors - visit_register_account(Register), - visit_unregister_account(Unregister), - visit_mint_account_public_key(Mint), - visit_burn_account_public_key(Burn), - visit_mint_account_signature_check_condition(Mint), - visit_set_account_key_value(SetKeyValue), - visit_remove_account_key_value(RemoveKeyValue), - visit_register_asset(Register), - visit_unregister_asset(Unregister), - visit_mint_asset(Mint), - visit_burn_asset(Burn), - visit_transfer_asset(Transfer), - visit_set_asset_key_value(SetKeyValue), - visit_remove_asset_key_value(RemoveKeyValue), - visit_register_asset_definition(Register), - visit_unregister_asset_definition(Unregister), - visit_transfer_asset_definition(Transfer), - visit_set_asset_definition_key_value(SetKeyValue), - visit_remove_asset_definition_key_value(RemoveKeyValue), - visit_register_domain(Register), - visit_unregister_domain(Unregister), - visit_transfer_domain(Transfer), - visit_set_domain_key_value(SetKeyValue), - visit_remove_domain_key_value(RemoveKeyValue), - visit_register_peer(Register), - visit_unregister_peer(Unregister), - visit_grant_account_permission(Grant), - visit_revoke_account_permission(Revoke), - visit_register_role(Register), - visit_unregister_role(Unregister), - visit_grant_account_role(Grant), - visit_revoke_account_role(Revoke), - visit_register_trigger(Register>), - visit_unregister_trigger(Unregister>), - visit_mint_trigger_repetitions(Mint>), - visit_burn_trigger_repetitions(Burn>), - visit_upgrade_executor(Upgrade), - visit_new_parameter(NewParameter), - visit_set_parameter(SetParameter), - visit_execute_trigger(ExecuteTrigger), + visit_register_account(&Register), + visit_unregister_account(&Unregister), + visit_mint_account_public_key(&Mint), + visit_burn_account_public_key(&Burn), + visit_mint_account_signature_check_condition(&Mint), + visit_set_account_key_value(&SetKeyValue), + visit_remove_account_key_value(&RemoveKeyValue), + visit_register_asset(&Register), + visit_unregister_asset(&Unregister), + visit_mint_asset_quantity(&Mint), + visit_burn_asset_quantity(&Burn), + visit_mint_asset_big_quantity(&Mint), + visit_burn_asset_big_quantity(&Burn), + visit_mint_asset_fixed(&Mint), + visit_burn_asset_fixed(&Burn), + visit_transfer_asset_quantity(&Transfer), + visit_transfer_asset_big_quantity(&Transfer), + visit_transfer_asset_fixed(&Transfer), + visit_set_asset_key_value(&SetKeyValue), + visit_remove_asset_key_value(&RemoveKeyValue), + visit_register_asset_definition(&Register), + visit_unregister_asset_definition(&Unregister), + visit_transfer_asset_definition(&Transfer), + visit_set_asset_definition_key_value(&SetKeyValue), + visit_remove_asset_definition_key_value(&RemoveKeyValue), + visit_register_domain(&Register), + visit_unregister_domain(&Unregister), + visit_transfer_domain(&Transfer), + visit_set_domain_key_value(&SetKeyValue), + visit_remove_domain_key_value(&RemoveKeyValue), + visit_register_peer(&Register), + visit_unregister_peer(&Unregister), + visit_grant_account_permission(&Grant), + visit_revoke_account_permission(&Revoke), + visit_register_role(&Register), + visit_unregister_role(&Unregister), + visit_grant_account_role(&Grant), + visit_revoke_account_role(&Revoke), + visit_register_trigger(&Register>), + visit_unregister_trigger(&Unregister>), + visit_mint_trigger_repetitions(&Mint>), + visit_burn_trigger_repetitions(&Burn>), + visit_upgrade(&Upgrade), + visit_new_parameter(&NewParameter), + visit_set_parameter(&SetParameter), + visit_execute_trigger(&ExecuteTrigger), visit_fail(&Fail), - visit_log(Log), + visit_log(&Log), // Query visitors visit_find_account_by_id(&FindAccountById), @@ -752,7 +472,7 @@ leaf_visitors! { visit_find_all_block_headers(&FindAllBlockHeaders), visit_find_all_blocks(&FindAllBlocks), visit_find_all_domains(&FindAllDomains), - visit_find_all_parammeters(&FindAllParameters), + visit_find_all_parameters(&FindAllParameters), visit_find_all_peers(&FindAllPeers), visit_find_permission_token_schema(&FindPermissionTokenSchema), visit_find_all_role_ids(&FindAllRoleIds), diff --git a/data_model/tests/data_model.rs b/data_model/tests/data_model.rs index 09cf1d602ff..c795f7590a4 100644 --- a/data_model/tests/data_model.rs +++ b/data_model/tests/data_model.rs @@ -1,65 +1,14 @@ -use std::str::FromStr as _; - use iroha_data_model::{prelude::*, ParseError}; #[test] fn transfer_isi_should_be_valid() { - let _instruction = TransferExpr::new( - IdBox::AssetId("btc##seller@crypto".parse().expect("Valid")), + let _instruction = Transfer::asset_quantity( + "btc##seller@crypto".parse().expect("Valid"), 12_u32, - IdBox::AccountId("buyer@crypto".parse().expect("Valid")), + "buyer@crypto".parse().expect("Valid"), ); } -#[test] -fn find_quantity_and_check_it_greater_than_value_isi_should_be_valid() { - let asset_id: AssetId = "rose##alice@wonderland".parse().expect("Valid"); - let find_asset = QueryBox::from(FindAssetQuantityById::new(asset_id)); - - let _instruction = ConditionalExpr::new( - Not::new(Greater::new(EvaluatesTo::new_unchecked(find_asset), 10_u32)), - Fail::new("rate is less or equal to value"), - ); -} - -struct FindRateAndCheckItGreaterThanValue { - from_currency: String, - to_currency: String, - value: u32, -} - -impl FindRateAndCheckItGreaterThanValue { - pub fn new(from_currency: &str, to_currency: &str, value: u32) -> Self { - Self { - from_currency: from_currency.to_string(), - to_currency: to_currency.to_string(), - value, - } - } - - pub fn into_isi(self) -> ConditionalExpr { - ConditionalExpr::new( - Not::new(Greater::new( - EvaluatesTo::new_unchecked(QueryBox::from(FindAssetQuantityById::new( - AssetId::new( - format!("{}2{}_rate#exchange", self.from_currency, self.to_currency) - .parse() - .expect("Valid"), - AccountId::from_str("dex@exchange").expect("Valid"), - ), - ))), - self.value, - )), - Fail::new("rate is less or equal to value"), - ) - } -} - -#[test] -fn find_rate_and_check_it_greater_than_value_predefined_isi_should_be_valid() { - let _instruction = FindRateAndCheckItGreaterThanValue::new("btc", "eth", 10).into_isi(); -} - #[test] fn account_id_parsing() -> Result<(), ParseError> { // `AccountId` should have format `name@domain_name` diff --git a/data_model/tests/ui.rs b/data_model/tests/ui.rs deleted file mode 100644 index 48e1f1bbea3..00000000000 --- a/data_model/tests/ui.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![cfg(not(coverage))] -use trybuild::TestCases; - -#[test] -fn ui() { - TestCases::new().compile_fail("tests/ui_fail/*.rs"); -} diff --git a/data_model/tests/ui_fail/evaluates_to.rs b/data_model/tests/ui_fail/evaluates_to.rs deleted file mode 100644 index 6694b013653..00000000000 --- a/data_model/tests/ui_fail/evaluates_to.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! This test ensures that [`EvaluatesTo`] provides compile-time strong typing - -use iroha_data_model::prelude::*; - -fn get_assets_by_account_id(_account_id: impl Into>) -> Vec { - Vec::new() -} - -fn main() { - let asset_definition_id: AssetDefinitionId = "rose#wonderland".parse().unwrap(); - get_assets_by_account_id(asset_definition_id); -} diff --git a/data_model/tests/ui_fail/evaluates_to.stderr b/data_model/tests/ui_fail/evaluates_to.stderr deleted file mode 100644 index ff7da36be16..00000000000 --- a/data_model/tests/ui_fail/evaluates_to.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0277]: the trait bound `iroha_data_model::account::AccountId: From` is not satisfied - --> tests/ui_fail/evaluates_to.rs:11:30 - | -11 | get_assets_by_account_id(asset_definition_id); - | ------------------------ ^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `iroha_data_model::account::AccountId` - | | - | required by a bound introduced by this call - | - = note: required for `iroha_data_model::asset::AssetDefinitionId` to implement `Into` - = note: required for `iroha_data_model::expression::EvaluatesTo` to implement `From` - = note: 1 redundant requirement hidden - = note: required for `iroha_data_model::asset::AssetDefinitionId` to implement `Into>` -note: required by a bound in `get_assets_by_account_id` - --> tests/ui_fail/evaluates_to.rs:5:47 - | -5 | fn get_assets_by_account_id(_account_id: impl Into>) -> Vec { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `get_assets_by_account_id` diff --git a/default_executor/src/lib.rs b/default_executor/src/lib.rs index 4834bcc9228..6214fdaf03b 100644 --- a/default_executor/src/lib.rs +++ b/default_executor/src/lib.rs @@ -8,7 +8,7 @@ extern crate panic_halt; use alloc::borrow::ToOwned as _; -use iroha_executor::{default::default_permission_token_schema, prelude::*, smart_contract}; +use iroha_executor::{default::default_permission_token_schema, prelude::*}; use lol_alloc::{FreeListAllocator, LockedAllocator}; #[global_allocator] @@ -19,11 +19,10 @@ static ALLOC: LockedAllocator = LockedAllocator::new(FreeList /// # Warning /// /// The defaults are not guaranteed to be stable. -#[derive(Clone, Constructor, Debug, ValidateEntrypoints, ExpressionEvaluator, Validate, Visit)] +#[derive(Debug, Clone, Constructor, Visit, Validate, ValidateEntrypoints)] pub struct Executor { verdict: Result, block_height: u64, - host: smart_contract::Host, } impl Executor { diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 756d22082be..a4640d1122e 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -155,6 +155,20 @@ } ] }, + "AccountMintBox": { + "Enum": [ + { + "tag": "PublicKey", + "discriminant": 0, + "type": "Mint" + }, + { + "tag": "SignatureCheckCondition", + "discriminant": 1, + "type": "Mint" + } + ] + }, "AccountPermissionChanged": { "Struct": [ { @@ -203,18 +217,6 @@ } ] }, - "Add": { - "Struct": [ - { - "name": "left", - "type": "EvaluatesTo" - }, - { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, "Algorithm": { "Enum": [ { @@ -235,18 +237,6 @@ } ] }, - "And": { - "Struct": [ - { - "name": "left", - "type": "EvaluatesTo" - }, - { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, "Array, 8>": { "Array": { "type": "Interval", @@ -289,6 +279,25 @@ } ] }, + "AssetBurnBox": { + "Enum": [ + { + "tag": "Quantity", + "discriminant": 0, + "type": "Burn" + }, + { + "tag": "BigQuantity", + "discriminant": 1, + "type": "Burn" + }, + { + "tag": "Fixed", + "discriminant": 2, + "type": "Burn" + } + ] + }, "AssetChanged": { "Struct": [ { @@ -534,6 +543,44 @@ } ] }, + "AssetMintBox": { + "Enum": [ + { + "tag": "Quantity", + "discriminant": 0, + "type": "Mint" + }, + { + "tag": "BigQuantity", + "discriminant": 1, + "type": "Mint" + }, + { + "tag": "Fixed", + "discriminant": 2, + "type": "Mint" + } + ] + }, + "AssetTransferBox": { + "Enum": [ + { + "tag": "Quantity", + "discriminant": 0, + "type": "Transfer" + }, + { + "tag": "BigQuantity", + "discriminant": 1, + "type": "Transfer" + }, + { + "tag": "Fixed", + "discriminant": 2, + "type": "Transfer" + } + ] + }, "AssetValue": { "Enum": [ { @@ -632,18 +679,6 @@ } ] }, - "BinaryOpIncompatibleNumericValueTypesError": { - "Struct": [ - { - "name": "left", - "type": "NumericValue" - }, - { - "name": "right", - "type": "NumericValue" - } - ] - }, "BlockHeader": { "Struct": [ { @@ -702,31 +737,82 @@ ] }, "BlockSubscriptionRequest": "NonZero", - "BurnExpr": { + "Burn": { + "Struct": [ + { + "name": "object", + "type": "Fixed" + }, + { + "name": "destination_id", + "type": "AssetId" + } + ] + }, + "Burn": { + "Struct": [ + { + "name": "object", + "type": "PublicKey" + }, + { + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "Burn": { + "Struct": [ + { + "name": "object", + "type": "u128" + }, + { + "name": "destination_id", + "type": "AssetId" + } + ] + }, + "Burn": { "Struct": [ { "name": "object", - "type": "EvaluatesTo" + "type": "u32" }, { "name": "destination_id", - "type": "EvaluatesTo" + "type": "AssetId" } ] }, - "ConditionalExpr": { + "Burn>": { "Struct": [ { - "name": "condition", - "type": "EvaluatesTo" + "name": "object", + "type": "u32" + }, + { + "name": "destination_id", + "type": "TriggerId" + } + ] + }, + "BurnBox": { + "Enum": [ + { + "tag": "AccountPublicKey", + "discriminant": 0, + "type": "Burn" }, { - "name": "then", - "type": "InstructionExpr" + "tag": "Asset", + "discriminant": 1, + "type": "AssetBurnBox" }, { - "name": "otherwise", - "type": "Option" + "tag": "TriggerRepetitions", + "discriminant": 2, + "type": "Burn>" } ] }, @@ -778,50 +864,6 @@ } ] }, - "Contains": { - "Struct": [ - { - "name": "collection", - "type": "EvaluatesTo>" - }, - { - "name": "element", - "type": "EvaluatesTo" - } - ] - }, - "ContainsAll": { - "Struct": [ - { - "name": "collection", - "type": "EvaluatesTo>" - }, - { - "name": "elements", - "type": "EvaluatesTo>" - } - ] - }, - "ContainsAny": { - "Struct": [ - { - "name": "collection", - "type": "EvaluatesTo>" - }, - { - "name": "elements", - "type": "EvaluatesTo>" - } - ] - }, - "ContextValue": { - "Struct": [ - { - "name": "value_name", - "type": "Name" - } - ] - }, "DataEntityFilter": { "Enum": [ { @@ -915,18 +957,6 @@ } ] }, - "Divide": { - "Struct": [ - { - "name": "left", - "type": "EvaluatesTo" - }, - { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, "Domain": { "Struct": [ { @@ -1070,423 +1100,131 @@ "u32" ] }, - "Equal": { - "Struct": [ + "Event": { + "Enum": [ { - "name": "left", - "type": "EvaluatesTo" + "tag": "Pipeline", + "discriminant": 0, + "type": "PipelineEvent" }, { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, - "EvaluatesTo": { - "Struct": [ + "tag": "Data", + "discriminant": 1, + "type": "DataEvent" + }, { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo": { - "Struct": [ + "tag": "Time", + "discriminant": 2, + "type": "TimeEvent" + }, { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo": { - "Struct": [ + "tag": "ExecuteTrigger", + "discriminant": 3, + "type": "ExecuteTriggerEvent" + }, { - "name": "expression", - "type": "Expression" + "tag": "Notification", + "discriminant": 4, + "type": "NotificationEvent" } ] }, - "EvaluatesTo": { - "Struct": [ + "EventMessage": "Event", + "EventSubscriptionRequest": "FilterBox", + "Executable": { + "Enum": [ + { + "tag": "Instructions", + "discriminant": 0, + "type": "Vec" + }, { - "name": "expression", - "type": "Expression" + "tag": "Wasm", + "discriminant": 1, + "type": "WasmSmartContract" } ] }, - "EvaluatesTo>": { + "ExecuteTrigger": { "Struct": [ { - "name": "expression", - "type": "Expression" + "name": "trigger_id", + "type": "TriggerId" } ] }, - "EvaluatesTo>": { + "ExecuteTriggerEvent": { "Struct": [ { - "name": "expression", - "type": "Expression" + "name": "trigger_id", + "type": "TriggerId" + }, + { + "name": "authority", + "type": "AccountId" } ] }, - "EvaluatesTo": { + "ExecuteTriggerEventFilter": { "Struct": [ { - "name": "expression", - "type": "Expression" + "name": "trigger_id", + "type": "TriggerId" + }, + { + "name": "authority", + "type": "AccountId" } ] }, - "EvaluatesTo": { - "Struct": [ + "ExecutionTime": { + "Enum": [ + { + "tag": "PreCommit", + "discriminant": 0 + }, { - "name": "expression", - "type": "Expression" + "tag": "Schedule", + "discriminant": 1, + "type": "Schedule" } ] }, - "EvaluatesTo": { + "Executor": { "Struct": [ { - "name": "expression", - "type": "Expression" + "name": "wasm", + "type": "WasmSmartContract" } ] }, - "EvaluatesTo": { - "Struct": [ + "ExecutorEvent": { + "Enum": [ { - "name": "expression", - "type": "Expression" + "tag": "Upgraded", + "discriminant": 0 } ] }, - "EvaluatesTo": { - "Struct": [ + "ExecutorMode": { + "Enum": [ + { + "tag": "Path", + "discriminant": 0, + "type": "String" + }, { - "name": "expression", - "type": "Expression" + "tag": "Inline", + "discriminant": 1, + "type": "Executor" } ] }, - "EvaluatesTo": { + "Fail": { "Struct": [ { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo": { - "Struct": [ - { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo": { - "Struct": [ - { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo": { - "Struct": [ - { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo": { - "Struct": [ - { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo": { - "Struct": [ - { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo>": { - "Struct": [ - { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluatesTo": { - "Struct": [ - { - "name": "expression", - "type": "Expression" - } - ] - }, - "EvaluationError": { - "Enum": [ - { - "tag": "Math", - "discriminant": 0, - "type": "MathError" - }, - { - "tag": "Validation", - "discriminant": 1, - "type": "ValidationFail" - }, - { - "tag": "Find", - "discriminant": 2, - "type": "String" - }, - { - "tag": "Conversion", - "discriminant": 3, - "type": "String" - } - ] - }, - "Event": { - "Enum": [ - { - "tag": "Pipeline", - "discriminant": 0, - "type": "PipelineEvent" - }, - { - "tag": "Data", - "discriminant": 1, - "type": "DataEvent" - }, - { - "tag": "Time", - "discriminant": 2, - "type": "TimeEvent" - }, - { - "tag": "ExecuteTrigger", - "discriminant": 3, - "type": "ExecuteTriggerEvent" - }, - { - "tag": "Notification", - "discriminant": 4, - "type": "NotificationEvent" - } - ] - }, - "EventMessage": "Event", - "EventSubscriptionRequest": "FilterBox", - "Executable": { - "Enum": [ - { - "tag": "Instructions", - "discriminant": 0, - "type": "Vec" - }, - { - "tag": "Wasm", - "discriminant": 1, - "type": "WasmSmartContract" - } - ] - }, - "ExecuteTriggerEvent": { - "Struct": [ - { - "name": "trigger_id", - "type": "TriggerId" - }, - { - "name": "authority", - "type": "AccountId" - } - ] - }, - "ExecuteTriggerEventFilter": { - "Struct": [ - { - "name": "trigger_id", - "type": "TriggerId" - }, - { - "name": "authority", - "type": "AccountId" - } - ] - }, - "ExecuteTriggerExpr": { - "Struct": [ - { - "name": "trigger_id", - "type": "EvaluatesTo" - } - ] - }, - "ExecutionTime": { - "Enum": [ - { - "tag": "PreCommit", - "discriminant": 0 - }, - { - "tag": "Schedule", - "discriminant": 1, - "type": "Schedule" - } - ] - }, - "Executor": { - "Struct": [ - { - "name": "wasm", - "type": "WasmSmartContract" - } - ] - }, - "ExecutorEvent": { - "Enum": [ - { - "tag": "Upgraded", - "discriminant": 0 - } - ] - }, - "ExecutorMode": { - "Enum": [ - { - "tag": "Path", - "discriminant": 0, - "type": "String" - }, - { - "tag": "Inline", - "discriminant": 1, - "type": "Executor" - } - ] - }, - "Expression": { - "Enum": [ - { - "tag": "Add", - "discriminant": 0, - "type": "Add" - }, - { - "tag": "Subtract", - "discriminant": 1, - "type": "Subtract" - }, - { - "tag": "Multiply", - "discriminant": 2, - "type": "Multiply" - }, - { - "tag": "Divide", - "discriminant": 3, - "type": "Divide" - }, - { - "tag": "Mod", - "discriminant": 4, - "type": "Mod" - }, - { - "tag": "RaiseTo", - "discriminant": 5, - "type": "RaiseTo" - }, - { - "tag": "Greater", - "discriminant": 6, - "type": "Greater" - }, - { - "tag": "Less", - "discriminant": 7, - "type": "Less" - }, - { - "tag": "Equal", - "discriminant": 8, - "type": "Equal" - }, - { - "tag": "Not", - "discriminant": 9, - "type": "Not" - }, - { - "tag": "And", - "discriminant": 10, - "type": "And" - }, - { - "tag": "Or", - "discriminant": 11, - "type": "Or" - }, - { - "tag": "If", - "discriminant": 12, - "type": "If" - }, - { - "tag": "Raw", - "discriminant": 13, - "type": "Value" - }, - { - "tag": "Query", - "discriminant": 14, - "type": "QueryBox" - }, - { - "tag": "Contains", - "discriminant": 15, - "type": "Contains" - }, - { - "tag": "ContainsAll", - "discriminant": 16, - "type": "ContainsAll" - }, - { - "tag": "ContainsAny", - "discriminant": 17, - "type": "ContainsAny" - }, - { - "tag": "Where", - "discriminant": 18, - "type": "Where" - }, - { - "tag": "ContextValue", - "discriminant": 19, - "type": "ContextValue" - } - ] - }, - "Fail": { - "Struct": [ - { - "name": "message", - "type": "String" + "name": "message", + "type": "String" } ] }, @@ -1809,7 +1547,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AccountId" } ] }, @@ -1817,11 +1555,11 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AccountId" }, { "name": "key", - "type": "EvaluatesTo" + "type": "Name" } ] }, @@ -1829,7 +1567,7 @@ "Struct": [ { "name": "domain_id", - "type": "EvaluatesTo" + "type": "DomainId" } ] }, @@ -1837,7 +1575,7 @@ "Struct": [ { "name": "name", - "type": "EvaluatesTo" + "type": "Name" } ] }, @@ -1845,7 +1583,7 @@ "Struct": [ { "name": "asset_definition_id", - "type": "EvaluatesTo" + "type": "AssetDefinitionId" } ] }, @@ -1865,7 +1603,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AssetId" } ] }, @@ -1873,7 +1611,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AssetDefinitionId" } ] }, @@ -1881,11 +1619,11 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AssetDefinitionId" }, { "name": "key", - "type": "EvaluatesTo" + "type": "Name" } ] }, @@ -1893,11 +1631,11 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AssetId" }, { "name": "key", - "type": "EvaluatesTo" + "type": "Name" } ] }, @@ -1905,7 +1643,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AssetId" } ] }, @@ -1913,7 +1651,7 @@ "Struct": [ { "name": "account_id", - "type": "EvaluatesTo" + "type": "AccountId" } ] }, @@ -1921,7 +1659,7 @@ "Struct": [ { "name": "asset_definition_id", - "type": "EvaluatesTo" + "type": "AssetDefinitionId" } ] }, @@ -1929,7 +1667,7 @@ "Struct": [ { "name": "domain_id", - "type": "EvaluatesTo" + "type": "DomainId" } ] }, @@ -1937,11 +1675,11 @@ "Struct": [ { "name": "domain_id", - "type": "EvaluatesTo" + "type": "DomainId" }, { "name": "asset_definition_id", - "type": "EvaluatesTo" + "type": "AssetDefinitionId" } ] }, @@ -1949,7 +1687,7 @@ "Struct": [ { "name": "name", - "type": "EvaluatesTo" + "type": "Name" } ] }, @@ -1957,7 +1695,7 @@ "Struct": [ { "name": "hash", - "type": "EvaluatesTo>" + "type": "HashOf" } ] }, @@ -1965,7 +1703,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "DomainId" } ] }, @@ -1973,11 +1711,11 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "DomainId" }, { "name": "key", - "type": "EvaluatesTo" + "type": "Name" } ] }, @@ -2055,7 +1793,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AccountId" } ] }, @@ -2063,7 +1801,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "RoleId" } ] }, @@ -2071,7 +1809,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AccountId" } ] }, @@ -2079,7 +1817,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "AssetDefinitionId" } ] }, @@ -2087,7 +1825,7 @@ "Struct": [ { "name": "hash", - "type": "EvaluatesTo>" + "type": "HashOf" } ] }, @@ -2095,7 +1833,7 @@ "Struct": [ { "name": "account_id", - "type": "EvaluatesTo" + "type": "AccountId" } ] }, @@ -2103,7 +1841,7 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "TriggerId" } ] }, @@ -2111,11 +1849,11 @@ "Struct": [ { "name": "id", - "type": "EvaluatesTo" + "type": "TriggerId" }, { "name": "key", - "type": "EvaluatesTo" + "type": "Name" } ] }, @@ -2123,7 +1861,7 @@ "Struct": [ { "name": "domain_id", - "type": "EvaluatesTo" + "type": "DomainId" } ] }, @@ -2170,27 +1908,41 @@ } ] }, - "GrantExpr": { + "Grant": { "Struct": [ { "name": "object", - "type": "EvaluatesTo" + "type": "PermissionToken" }, { "name": "destination_id", - "type": "EvaluatesTo" + "type": "AccountId" } ] }, - "Greater": { + "Grant": { "Struct": [ { - "name": "left", - "type": "EvaluatesTo" + "name": "object", + "type": "RoleId" }, { - "name": "right", - "type": "EvaluatesTo" + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "GrantBox": { + "Enum": [ + { + "tag": "PermissionToken", + "discriminant": 0, + "type": "Grant" + }, + { + "tag": "Role", + "discriminant": 1, + "type": "Grant" } ] }, @@ -2291,76 +2043,134 @@ { "tag": "Domain", "discriminant": 5, - "type": "Domain" + "type": "Domain" + }, + { + "tag": "Account", + "discriminant": 6, + "type": "Account" + }, + { + "tag": "AssetDefinition", + "discriminant": 7, + "type": "AssetDefinition" + }, + { + "tag": "Asset", + "discriminant": 8, + "type": "Asset" + }, + { + "tag": "Trigger", + "discriminant": 9, + "type": "Trigger" + }, + { + "tag": "Role", + "discriminant": 10, + "type": "Role" + }, + { + "tag": "Parameter", + "discriminant": 11, + "type": "Parameter" + } + ] + }, + "InstructionBox": { + "Enum": [ + { + "tag": "Register", + "discriminant": 0, + "type": "RegisterBox" + }, + { + "tag": "Unregister", + "discriminant": 1, + "type": "UnregisterBox" + }, + { + "tag": "Mint", + "discriminant": 2, + "type": "MintBox" + }, + { + "tag": "Burn", + "discriminant": 3, + "type": "BurnBox" + }, + { + "tag": "Transfer", + "discriminant": 4, + "type": "TransferBox" + }, + { + "tag": "SetKeyValue", + "discriminant": 5, + "type": "SetKeyValueBox" }, { - "tag": "Account", + "tag": "RemoveKeyValue", "discriminant": 6, - "type": "Account" + "type": "RemoveKeyValueBox" }, { - "tag": "AssetDefinition", + "tag": "Grant", "discriminant": 7, - "type": "AssetDefinition" + "type": "GrantBox" }, { - "tag": "Asset", + "tag": "Revoke", "discriminant": 8, - "type": "Asset" + "type": "RevokeBox" }, { - "tag": "Trigger", + "tag": "ExecuteTrigger", "discriminant": 9, - "type": "Trigger" + "type": "ExecuteTrigger" }, { - "tag": "Role", + "tag": "SetParameter", "discriminant": 10, - "type": "Role" + "type": "SetParameter" }, { - "tag": "Parameter", + "tag": "NewParameter", "discriminant": 11, - "type": "Parameter" - } - ] - }, - "If": { - "Struct": [ + "type": "NewParameter" + }, { - "name": "condition", - "type": "EvaluatesTo" + "tag": "Upgrade", + "discriminant": 12, + "type": "Upgrade" }, { - "name": "then", - "type": "EvaluatesTo" + "tag": "Log", + "discriminant": 13, + "type": "Log" }, { - "name": "otherwise", - "type": "EvaluatesTo" + "tag": "Fail", + "discriminant": 14, + "type": "Fail" } ] }, "InstructionEvaluationError": { "Enum": [ - { - "tag": "Expression", - "discriminant": 0, - "type": "EvaluationError" - }, { "tag": "Unsupported", - "discriminant": 1, + "discriminant": 0, "type": "InstructionType" }, { "tag": "PermissionParameter", - "discriminant": 2, + "discriminant": 1, "type": "String" }, { "tag": "Type", - "discriminant": 3, + "discriminant": 2, "type": "TypeError" } ] @@ -2428,7 +2238,7 @@ "Struct": [ { "name": "instruction", - "type": "InstructionExpr" + "type": "InstructionBox" }, { "name": "reason", @@ -2436,100 +2246,6 @@ } ] }, - "InstructionExpr": { - "Enum": [ - { - "tag": "Register", - "discriminant": 0, - "type": "RegisterExpr" - }, - { - "tag": "Unregister", - "discriminant": 1, - "type": "UnregisterExpr" - }, - { - "tag": "Mint", - "discriminant": 2, - "type": "MintExpr" - }, - { - "tag": "Burn", - "discriminant": 3, - "type": "BurnExpr" - }, - { - "tag": "Transfer", - "discriminant": 4, - "type": "TransferExpr" - }, - { - "tag": "If", - "discriminant": 5, - "type": "ConditionalExpr" - }, - { - "tag": "Pair", - "discriminant": 6, - "type": "PairExpr" - }, - { - "tag": "Sequence", - "discriminant": 7, - "type": "SequenceExpr" - }, - { - "tag": "SetKeyValue", - "discriminant": 8, - "type": "SetKeyValueExpr" - }, - { - "tag": "RemoveKeyValue", - "discriminant": 9, - "type": "RemoveKeyValueExpr" - }, - { - "tag": "Grant", - "discriminant": 10, - "type": "GrantExpr" - }, - { - "tag": "Revoke", - "discriminant": 11, - "type": "RevokeExpr" - }, - { - "tag": "ExecuteTrigger", - "discriminant": 12, - "type": "ExecuteTriggerExpr" - }, - { - "tag": "SetParameter", - "discriminant": 13, - "type": "SetParameterExpr" - }, - { - "tag": "NewParameter", - "discriminant": 14, - "type": "NewParameterExpr" - }, - { - "tag": "Upgrade", - "discriminant": 15, - "type": "UpgradeExpr" - }, - { - "tag": "Log", - "discriminant": 16, - "type": "LogExpr" - }, - { - "tag": "Fail", - "discriminant": 17, - "type": "Fail" - } - ] - }, "InstructionType": { "Enum": [ { @@ -2552,57 +2268,45 @@ "tag": "Transfer", "discriminant": 4 }, - { - "tag": "If", - "discriminant": 5 - }, - { - "tag": "Pair", - "discriminant": 6 - }, - { - "tag": "Sequence", - "discriminant": 7 - }, { "tag": "SetKeyValue", - "discriminant": 8 + "discriminant": 5 }, { "tag": "RemoveKeyValue", - "discriminant": 9 + "discriminant": 6 }, { "tag": "Grant", - "discriminant": 10 + "discriminant": 7 }, { "tag": "Revoke", - "discriminant": 11 + "discriminant": 8 }, { "tag": "ExecuteTrigger", - "discriminant": 12 + "discriminant": 9 }, { "tag": "SetParameter", - "discriminant": 13 + "discriminant": 10 }, { "tag": "NewParameter", - "discriminant": 14 + "discriminant": 11 }, { "tag": "Upgrade", - "discriminant": 15 + "discriminant": 12 }, { "tag": "Log", - "discriminant": 16 + "discriminant": 13 }, { "tag": "Fail", - "discriminant": 17 + "discriminant": 14 } ] }, @@ -2660,18 +2364,6 @@ } ] }, - "Less": { - "Struct": [ - { - "name": "left", - "type": "EvaluatesTo" - }, - { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, "Level": { "Enum": [ { @@ -2708,15 +2400,15 @@ } ] }, - "LogExpr": { + "Log": { "Struct": [ { "name": "level", - "type": "EvaluatesTo" + "type": "Level" }, { "name": "msg", - "type": "EvaluatesTo" + "type": "String" } ] }, @@ -2746,14 +2438,9 @@ "tag": "Unknown", "discriminant": 5 }, - { - "tag": "BinaryOpIncompatibleNumericValueTypes", - "discriminant": 6, - "type": "BinaryOpIncompatibleNumericValueTypesError" - }, { "tag": "FixedPointConversion", - "discriminant": 7, + "discriminant": 6, "type": "String" } ] @@ -2801,75 +2488,154 @@ } ] }, - "MetadataChanged": { + "MetadataChanged": { + "Struct": [ + { + "name": "target_id", + "type": "AssetId" + }, + { + "name": "key", + "type": "Name" + }, + { + "name": "value", + "type": "Value" + } + ] + }, + "MetadataChanged": { + "Struct": [ + { + "name": "target_id", + "type": "DomainId" + }, + { + "name": "key", + "type": "Name" + }, + { + "name": "value", + "type": "Value" + } + ] + }, + "MetadataError": { + "Enum": [ + { + "tag": "EntryTooBig", + "discriminant": 0, + "type": "SizeError" + }, + { + "tag": "OverallSize", + "discriminant": 1, + "type": "SizeError" + }, + { + "tag": "EmptyPath", + "discriminant": 2 + }, + { + "tag": "MissingSegment", + "discriminant": 3, + "type": "Name" + }, + { + "tag": "InvalidSegment", + "discriminant": 4, + "type": "Name" + } + ] + }, + "Mint": { + "Struct": [ + { + "name": "object", + "type": "Fixed" + }, + { + "name": "destination_id", + "type": "AssetId" + } + ] + }, + "Mint": { + "Struct": [ + { + "name": "object", + "type": "PublicKey" + }, + { + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "Mint": { + "Struct": [ + { + "name": "object", + "type": "SignatureCheckCondition" + }, + { + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "Mint": { + "Struct": [ + { + "name": "object", + "type": "u128" + }, + { + "name": "destination_id", + "type": "AssetId" + } + ] + }, + "Mint": { "Struct": [ { - "name": "target_id", - "type": "AssetId" - }, - { - "name": "key", - "type": "Name" + "name": "object", + "type": "u32" }, { - "name": "value", - "type": "Value" + "name": "destination_id", + "type": "AssetId" } ] }, - "MetadataChanged": { + "Mint>": { "Struct": [ { - "name": "target_id", - "type": "DomainId" - }, - { - "name": "key", - "type": "Name" + "name": "object", + "type": "u32" }, { - "name": "value", - "type": "Value" + "name": "destination_id", + "type": "TriggerId" } ] }, - "MetadataError": { + "MintBox": { "Enum": [ { - "tag": "EntryTooBig", + "tag": "Account", "discriminant": 0, - "type": "SizeError" + "type": "AccountMintBox" }, { - "tag": "OverallSize", + "tag": "Asset", "discriminant": 1, - "type": "SizeError" - }, - { - "tag": "EmptyPath", - "discriminant": 2 - }, - { - "tag": "MissingSegment", - "discriminant": 3, - "type": "Name" - }, - { - "tag": "InvalidSegment", - "discriminant": 4, - "type": "Name" - } - ] - }, - "MintExpr": { - "Struct": [ - { - "name": "object", - "type": "EvaluatesTo" + "type": "AssetMintBox" }, { - "name": "destination_id", - "type": "EvaluatesTo" + "tag": "TriggerRepetitions", + "discriminant": 2, + "type": "Mint>" } ] }, @@ -2937,30 +2703,6 @@ } ] }, - "Mod": { - "Struct": [ - { - "name": "left", - "type": "EvaluatesTo" - }, - { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, - "Multiply": { - "Struct": [ - { - "name": "left", - "type": "EvaluatesTo" - }, - { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, "Name": "String", "NewAccount": { "Struct": [ @@ -3018,11 +2760,11 @@ } ] }, - "NewParameterExpr": { + "NewParameter": { "Struct": [ { "name": "parameter", - "type": "EvaluatesTo" + "type": "Parameter" } ] }, @@ -3037,14 +2779,6 @@ "NonTrivial>": "Vec>", "NonZero": "u32", "NonZero": "u64", - "Not": { - "Struct": [ - { - "name": "expression", - "type": "EvaluatesTo" - } - ] - }, "NotificationEvent": { "Enum": [ { @@ -3106,9 +2840,6 @@ "Option>": { "Option": "HashOf" }, - "Option": { - "Option": "InstructionExpr" - }, "Option": { "Option": "IpfsPath" }, @@ -3139,18 +2870,6 @@ "Option": { "Option": "TriggerId" }, - "Or": { - "Struct": [ - { - "name": "left", - "type": "EvaluatesTo" - }, - { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, "OriginFilter": "AccountId", "OriginFilter": "AssetDefinitionId", "OriginFilter": "AssetId", @@ -3158,18 +2877,6 @@ "OriginFilter": "PeerId", "OriginFilter": "RoleId", "OriginFilter": "TriggerId", - "PairExpr": { - "Struct": [ - { - "name": "left_instruction", - "type": "InstructionExpr" - }, - { - "name": "right_instruction", - "type": "InstructionExpr" - } - ] - }, "Parameter": { "Struct": [ { @@ -3610,28 +3317,23 @@ "discriminant": 0, "type": "String" }, - { - "tag": "Evaluate", - "discriminant": 1, - "type": "String" - }, { "tag": "Find", - "discriminant": 2, + "discriminant": 1, "type": "FindError" }, { "tag": "Conversion", - "discriminant": 3, + "discriminant": 2, "type": "String" }, { "tag": "UnknownCursor", - "discriminant": 4 + "discriminant": 3 }, { "tag": "FetchSizeTooBig", - "discriminant": 5 + "discriminant": 4 } ] }, @@ -3651,35 +3353,110 @@ } ] }, - "RaiseTo": { + "RawGenesisBlock": { "Struct": [ { - "name": "left", - "type": "EvaluatesTo" + "name": "transactions", + "type": "Vec>" }, { - "name": "right", - "type": "EvaluatesTo" + "name": "executor", + "type": "ExecutorMode" } ] }, - "RawGenesisBlock": { + "Register": { "Struct": [ { - "name": "transactions", - "type": "Vec>" - }, + "name": "object", + "type": "NewAccount" + } + ] + }, + "Register": { + "Struct": [ { - "name": "executor", - "type": "ExecutorMode" + "name": "object", + "type": "Asset" + } + ] + }, + "Register": { + "Struct": [ + { + "name": "object", + "type": "NewAssetDefinition" } ] }, - "RegisterExpr": { + "Register": { "Struct": [ { "name": "object", - "type": "EvaluatesTo" + "type": "NewDomain" + } + ] + }, + "Register": { + "Struct": [ + { + "name": "object", + "type": "Peer" + } + ] + }, + "Register": { + "Struct": [ + { + "name": "object", + "type": "NewRole" + } + ] + }, + "Register>": { + "Struct": [ + { + "name": "object", + "type": "Trigger" + } + ] + }, + "RegisterBox": { + "Enum": [ + { + "tag": "Peer", + "discriminant": 0, + "type": "Register" + }, + { + "tag": "Domain", + "discriminant": 1, + "type": "Register" + }, + { + "tag": "Account", + "discriminant": 2, + "type": "Register" + }, + { + "tag": "AssetDefinition", + "discriminant": 3, + "type": "Register" + }, + { + "tag": "Asset", + "discriminant": 4, + "type": "Register" + }, + { + "tag": "Role", + "discriminant": 5, + "type": "Register" + }, + { + "tag": "Trigger", + "discriminant": 6, + "type": "Register>" } ] }, @@ -3722,15 +3499,75 @@ } ] }, - "RemoveKeyValueExpr": { + "RemoveKeyValue": { + "Struct": [ + { + "name": "object_id", + "type": "AccountId" + }, + { + "name": "key", + "type": "Name" + } + ] + }, + "RemoveKeyValue": { "Struct": [ { "name": "object_id", - "type": "EvaluatesTo" + "type": "AssetId" + }, + { + "name": "key", + "type": "Name" + } + ] + }, + "RemoveKeyValue": { + "Struct": [ + { + "name": "object_id", + "type": "AssetDefinitionId" + }, + { + "name": "key", + "type": "Name" + } + ] + }, + "RemoveKeyValue": { + "Struct": [ + { + "name": "object_id", + "type": "DomainId" }, { "name": "key", - "type": "EvaluatesTo" + "type": "Name" + } + ] + }, + "RemoveKeyValueBox": { + "Enum": [ + { + "tag": "Domain", + "discriminant": 0, + "type": "RemoveKeyValue" + }, + { + "tag": "Account", + "discriminant": 1, + "type": "RemoveKeyValue" + }, + { + "tag": "AssetDefinition", + "discriminant": 2, + "type": "RemoveKeyValue" + }, + { + "tag": "Asset", + "discriminant": 3, + "type": "RemoveKeyValue" } ] }, @@ -3747,27 +3584,53 @@ } ] }, - "RepetitionError": { + "RepetitionError": { + "Struct": [ + { + "name": "instruction_type", + "type": "InstructionType" + }, + { + "name": "id", + "type": "IdBox" + } + ] + }, + "Revoke": { + "Struct": [ + { + "name": "object", + "type": "PermissionToken" + }, + { + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "Revoke": { "Struct": [ { - "name": "instruction_type", - "type": "InstructionType" + "name": "object", + "type": "RoleId" }, { - "name": "id", - "type": "IdBox" + "name": "destination_id", + "type": "AccountId" } ] }, - "RevokeExpr": { - "Struct": [ + "RevokeBox": { + "Enum": [ { - "name": "object", - "type": "EvaluatesTo" + "tag": "PermissionToken", + "discriminant": 0, + "type": "Revoke" }, { - "name": "destination_id", - "type": "EvaluatesTo" + "tag": "Role", + "discriminant": 1, + "type": "Revoke" } ] }, @@ -3905,35 +3768,99 @@ } ] }, - "SequenceExpr": { + "SetKeyValue": { "Struct": [ { - "name": "instructions", - "type": "Vec" + "name": "object_id", + "type": "AccountId" + }, + { + "name": "key", + "type": "Name" + }, + { + "name": "value", + "type": "Value" + } + ] + }, + "SetKeyValue": { + "Struct": [ + { + "name": "object_id", + "type": "AssetId" + }, + { + "name": "key", + "type": "Name" + }, + { + "name": "value", + "type": "Value" + } + ] + }, + "SetKeyValue": { + "Struct": [ + { + "name": "object_id", + "type": "AssetDefinitionId" + }, + { + "name": "key", + "type": "Name" + }, + { + "name": "value", + "type": "Value" } ] }, - "SetKeyValueExpr": { + "SetKeyValue": { "Struct": [ { "name": "object_id", - "type": "EvaluatesTo" + "type": "DomainId" }, { "name": "key", - "type": "EvaluatesTo" + "type": "Name" }, { "name": "value", - "type": "EvaluatesTo" + "type": "Value" + } + ] + }, + "SetKeyValueBox": { + "Enum": [ + { + "tag": "Domain", + "discriminant": 0, + "type": "SetKeyValue" + }, + { + "tag": "Account", + "discriminant": 1, + "type": "SetKeyValue" + }, + { + "tag": "AssetDefinition", + "discriminant": 2, + "type": "SetKeyValue" + }, + { + "tag": "Asset", + "discriminant": 3, + "type": "SetKeyValue" } ] }, - "SetParameterExpr": { + "SetParameter": { "Struct": [ { "name": "parameter", - "type": "EvaluatesTo" + "type": "Parameter" } ] }, @@ -4136,12 +4063,6 @@ "value": "Asset" } }, - "SortedMap>": { - "Map": { - "key": "Name", - "value": "EvaluatesTo" - } - }, "SortedMap": { "Map": { "key": "Name", @@ -4186,18 +4107,6 @@ ] }, "StringWithJson": "String", - "Subtract": { - "Struct": [ - { - "name": "left", - "type": "EvaluatesTo" - }, - { - "name": "right", - "type": "EvaluatesTo" - } - ] - }, "TimeEvent": { "Struct": [ { @@ -4328,19 +4237,102 @@ } ] }, - "TransferExpr": { + "Transfer": { + "Struct": [ + { + "name": "source_id", + "type": "AccountId" + }, + { + "name": "object", + "type": "AssetDefinitionId" + }, + { + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "Transfer": { + "Struct": [ + { + "name": "source_id", + "type": "AccountId" + }, + { + "name": "object", + "type": "DomainId" + }, + { + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "Transfer": { + "Struct": [ + { + "name": "source_id", + "type": "AssetId" + }, + { + "name": "object", + "type": "Fixed" + }, + { + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "Transfer": { + "Struct": [ + { + "name": "source_id", + "type": "AssetId" + }, + { + "name": "object", + "type": "u128" + }, + { + "name": "destination_id", + "type": "AccountId" + } + ] + }, + "Transfer": { "Struct": [ { "name": "source_id", - "type": "EvaluatesTo" + "type": "AssetId" }, { "name": "object", - "type": "EvaluatesTo" + "type": "u32" }, { "name": "destination_id", - "type": "EvaluatesTo" + "type": "AccountId" + } + ] + }, + "TransferBox": { + "Enum": [ + { + "tag": "Domain", + "discriminant": 0, + "type": "Transfer" + }, + { + "tag": "AssetDefinition", + "discriminant": 1, + "type": "Transfer" + }, + { + "tag": "Asset", + "discriminant": 2, + "type": "AssetTransferBox" } ] }, @@ -4529,11 +4521,98 @@ ] }, "UniqueVec": "Vec", - "UnregisterExpr": { + "Unregister": { + "Struct": [ + { + "name": "object_id", + "type": "AccountId" + } + ] + }, + "Unregister": { + "Struct": [ + { + "name": "object_id", + "type": "AssetId" + } + ] + }, + "Unregister": { + "Struct": [ + { + "name": "object_id", + "type": "AssetDefinitionId" + } + ] + }, + "Unregister": { + "Struct": [ + { + "name": "object_id", + "type": "DomainId" + } + ] + }, + "Unregister": { + "Struct": [ + { + "name": "object_id", + "type": "PeerId" + } + ] + }, + "Unregister": { + "Struct": [ + { + "name": "object_id", + "type": "RoleId" + } + ] + }, + "Unregister>": { "Struct": [ { "name": "object_id", - "type": "EvaluatesTo" + "type": "TriggerId" + } + ] + }, + "UnregisterBox": { + "Enum": [ + { + "tag": "Peer", + "discriminant": 0, + "type": "Unregister" + }, + { + "tag": "Domain", + "discriminant": 1, + "type": "Unregister" + }, + { + "tag": "Account", + "discriminant": 2, + "type": "Unregister" + }, + { + "tag": "AssetDefinition", + "discriminant": 3, + "type": "Unregister" + }, + { + "tag": "Asset", + "discriminant": 4, + "type": "Unregister" + }, + { + "tag": "Role", + "discriminant": 5, + "type": "Unregister" + }, + { + "tag": "Trigger", + "discriminant": 6, + "type": "Unregister>" } ] }, @@ -4546,11 +4625,11 @@ } ] }, - "UpgradeExpr": { + "Upgrade": { "Struct": [ { - "name": "object", - "type": "EvaluatesTo" + "name": "executor", + "type": "Executor" } ] }, @@ -4761,8 +4840,8 @@ "Vec>": { "Vec": "GenericPredicateBox" }, - "Vec": { - "Vec": "InstructionExpr" + "Vec": { + "Vec": "InstructionBox" }, "Vec": { "Vec": "Name" @@ -4782,8 +4861,8 @@ "Vec": { "Vec": "Value" }, - "Vec>": { - "Vec": "Vec" + "Vec>": { + "Vec": "Vec" }, "Vec": { "Vec": "u8" @@ -4797,18 +4876,6 @@ ] }, "WasmSmartContract": "Vec", - "Where": { - "Struct": [ - { - "name": "expression", - "type": "EvaluatesTo" - }, - { - "name": "values", - "type": "SortedMap>" - } - ] - }, "bool": "bool", "i64": { "Int": "FixedWidth" diff --git a/dsl/Cargo.toml b/dsl/Cargo.toml deleted file mode 100755 index 7cdbd40ee01..00000000000 --- a/dsl/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "iroha_dsl" - -edition.workspace = true -version.workspace = true -authors.workspace = true - -license.workspace = true - -[lints] -workspace = true - -[lib] -proc-macro = true - -[dependencies] -quote = "1.0" -proc-macro2 = "1.0" -litrs = "0.4.0" - -[dev-dependencies] -iroha_data_model = { workspace = true } -iroha_crypto = { workspace = true } -iroha_config = { workspace = true } -iroha_client = { workspace = true } -serde_json = "1.0" - - diff --git a/dsl/src/lib.rs b/dsl/src/lib.rs deleted file mode 100755 index c1378c24b1d..00000000000 --- a/dsl/src/lib.rs +++ /dev/null @@ -1,208 +0,0 @@ -// TODO: add docs -#![allow(missing_docs)] - -use std::{convert::TryFrom, iter::Peekable, str::FromStr}; - -use litrs::Literal; -use proc_macro2::{ - token_stream::IntoIter, - TokenStream, TokenTree, - TokenTree::{Ident, Punct}, -}; -use quote::quote; - -#[derive(PartialEq)] -enum ExprType { - Nil, - Int, - Bool, -} - -// within the compiler, these generate tokens for -// Value -struct ParsedExpr { - t: ExprType, - tokens: TokenStream, -} - -struct Operator(i32, ExprType, &'static str); - -fn parse_literal(it: &mut Peekable) -> ParsedExpr { - let token = it - .next() - .expect("failed to parse literal, hit end of string"); - - match token { - Punct(ref x) => { - if x.as_char() == '(' { - let v = parse_expr(it); - - it.next() - .expect("expected closing paren, hit end of string"); - return v; - } - } - - // boolean literals - Ident(ref x) => match x.to_string().as_str() { - "true" => { - return ParsedExpr { - t: ExprType::Bool, - tokens: quote! { true }, - } - } - "false" => { - return ParsedExpr { - t: ExprType::Bool, - tokens: quote! { false }, - } - } - - // unary not - "not" => { - let v = parse_literal(it).tokens; - return ParsedExpr { - t: ExprType::Bool, - tokens: quote! { Not::new(#v) }, - }; - } - _ => panic!("error: unknown identifier"), - }, - - // kinda ugly but we fallthrough basically - _ => {} - } - - // integer literals - if let Ok(Literal::Integer(i)) = Literal::try_from(token) { - let v = i.value::().expect("i don't think this integer fits?"); - return ParsedExpr { - t: ExprType::Int, - tokens: quote! { #v }, - }; - } - - ParsedExpr { - t: ExprType::Nil, - tokens: TokenStream::new(), - } -} - -fn precedence(it: &mut Peekable) -> Option { - match it.peek() { - Some(Punct(x)) => match x.as_char() { - // arithmatic - '+' => Some(Operator(4, ExprType::Int, "Add")), - '-' => Some(Operator(4, ExprType::Int, "Subtract")), - '*' => Some(Operator(3, ExprType::Int, "Multiply")), - - // compares - '=' => Some(Operator(2, ExprType::Int, "Equal")), - '>' => Some(Operator(2, ExprType::Int, "Greater")), - '<' => Some(Operator(2, ExprType::Int, "Less")), - _ => None, - }, - Some(Ident(ref x)) => match x.to_string().as_str() { - "and" => Some(Operator(1, ExprType::Bool, "And")), - "or" => Some(Operator(1, ExprType::Bool, "Or")), - _ => None, - }, - _ => None, - } -} - -/// precedence walking -fn parse_binop(it: &mut Peekable, min_prec: i32) -> ParsedExpr { - let mut lhs = parse_literal(it); - while let Some(prec) = precedence(it) { - it.next(); - if prec.0 < min_prec { - break; - } - - let op = proc_macro2::TokenStream::from_str(prec.2).unwrap(); - let rhs = parse_literal(it); - - assert!( - lhs.t == prec.1 && rhs.t == prec.1, - "cannot perform binary operator on these!" - ); - - let lhs_tokens = lhs.tokens; - let rhs_tokens = rhs.tokens; - lhs = ParsedExpr { - t: prec.1, - tokens: quote! { #op::new(#lhs_tokens, #rhs_tokens) }, - }; - } - - lhs -} - -fn is_ident(a: &TokenTree, b: &'static str) -> bool { - if let Ident(ref x) = a { - return x.to_string().as_str() == b; - } - - false -} - -fn parse_expr(it: &mut Peekable) -> ParsedExpr { - if is_ident(it.peek().expect("hit end of string"), "if") { - it.next(); - - let cond_tokens = parse_binop(it, 0).tokens; - assert!( - is_ident(&it.next().expect("hit end of string"), "then"), - "expected 'then'" - ); - - let true_case = parse_binop(it, 0); - assert!( - is_ident(&it.next().expect("hit end of string"), "else"), - "expected 'else'" - ); - - let false_case = parse_binop(it, 0); - assert!( - true_case.t == false_case.t, - "both types in a conditional must match" - ); - - let true_tokens = true_case.tokens; - let false_tokens = false_case.tokens; - return ParsedExpr { - t: ExprType::Int, - tokens: quote! { If::new(#cond_tokens, #true_tokens, #false_tokens) }, - }; - } - - // normal expression - parse_binop(it, 0) -} - -/// Convert arithmetic expression into bare expression in the iroha data model. -/// -/// Basic arithmetic and boolean expressions are supported, namely: `> < = + - * and or if not` -/// -/// # Examples -/// -/// ``` -/// extern crate iroha_dsl; -/// extern crate iroha_data_model; -/// use iroha_dsl::expr; -/// use iroha_data_model::{prelude::*, ParseError}; -/// -/// fn main() { -/// assert_eq!(expr!(54654*5 + 1), Add::new(Multiply::new(54654_u64, 5_u64), 1_u64)); -/// println!("{}", expr!(not true and false)); -/// println!("{}", expr!(if 4 = 4 then 64 else 32)); -/// } -/// ``` -#[proc_macro] -pub fn expr(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = proc_macro2::TokenStream::from(input); - let mut it = input.into_iter().peekable(); - - proc_macro::TokenStream::from(parse_expr(&mut it).tokens) -} diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index dcdd52f0d9a..4590f55b1c7 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -415,6 +415,7 @@ pub struct Extern { /// ``` pub trait WrapperTypeOf { /// Correct return type of `T` in a function generated via [`ffi_import`] + // TODO: Is associated type necessary if we already have a generic? type Type; } diff --git a/genesis/src/lib.rs b/genesis/src/lib.rs index 0428a2240ac..84cd9964e49 100644 --- a/genesis/src/lib.rs +++ b/genesis/src/lib.rs @@ -61,7 +61,7 @@ impl GenesisNetwork { // First instruction should be Executor upgrade. // This makes possible to grant permissions to users in genesis. let transactions_iter = std::iter::once(GenesisTransactionBuilder { - isi: vec![UpgradeExpr::new(Executor::try_from(raw_block.executor)?).into()], + isi: vec![Upgrade::new(Executor::try_from(raw_block.executor)?).into()], }) .chain(raw_block.transactions); @@ -190,7 +190,7 @@ impl ExecutorPath { #[repr(transparent)] pub struct GenesisTransactionBuilder { /// Instructions - isi: Vec, + isi: Vec, } impl GenesisTransactionBuilder { @@ -208,7 +208,7 @@ impl GenesisTransactionBuilder { } /// Add new instruction to the transaction. - pub fn append_instruction(&mut self, instruction: InstructionExpr) { + pub fn append_instruction(&mut self, instruction: InstructionBox) { self.isi.push(instruction); } } @@ -287,7 +287,7 @@ impl RawGenesisBlockBuilder { let new_domain = Domain::new(domain_id.clone()).with_metadata(metadata); self.transaction .isi - .push(RegisterExpr::new(new_domain).into()); + .push(Register::domain(new_domain).into()); RawGenesisDomainBuilder { transaction: self.transaction, domain_id, @@ -322,7 +322,7 @@ impl RawGenesisDomainBuilder { let account_id = AccountId::new(account_name, self.domain_id.clone()); self.transaction .isi - .push(RegisterExpr::new(Account::new(account_id, [])).into()); + .push(Register::account(Account::new(account_id, [])).into()); self } @@ -340,7 +340,7 @@ impl RawGenesisDomainBuilder { ) -> Self { let account_id = AccountId::new(account_name, self.domain_id.clone()); let register = - RegisterExpr::new(Account::new(account_id, [public_key]).with_metadata(metadata)); + Register::account(Account::new(account_id, [public_key]).with_metadata(metadata)); self.transaction.isi.push(register.into()); self } @@ -356,7 +356,7 @@ impl RawGenesisDomainBuilder { }; self.transaction .isi - .push(RegisterExpr::new(asset_definition).into()); + .push(Register::asset_definition(asset_definition).into()); self } } @@ -418,11 +418,11 @@ mod tests { let domain_id: DomainId = "wonderland".parse().unwrap(); assert_eq!( finished_genesis_block.transactions[0].isi[0], - RegisterExpr::new(Domain::new(domain_id.clone())).into() + Register::domain(Domain::new(domain_id.clone())).into() ); assert_eq!( finished_genesis_block.transactions[0].isi[1], - RegisterExpr::new(Account::new( + Register::account(Account::new( AccountId::new("alice".parse().unwrap(), domain_id.clone()), [] )) @@ -430,7 +430,7 @@ mod tests { ); assert_eq!( finished_genesis_block.transactions[0].isi[2], - RegisterExpr::new(Account::new( + Register::account(Account::new( AccountId::new("bob".parse().unwrap(), domain_id), [] )) @@ -441,11 +441,11 @@ mod tests { let domain_id: DomainId = "tulgey_wood".parse().unwrap(); assert_eq!( finished_genesis_block.transactions[0].isi[3], - RegisterExpr::new(Domain::new(domain_id.clone())).into() + Register::domain(Domain::new(domain_id.clone())).into() ); assert_eq!( finished_genesis_block.transactions[0].isi[4], - RegisterExpr::new(Account::new( + Register::account(Account::new( AccountId::new("Cheshire_Cat".parse().unwrap(), domain_id), [] )) @@ -456,11 +456,11 @@ mod tests { let domain_id: DomainId = "meadow".parse().unwrap(); assert_eq!( finished_genesis_block.transactions[0].isi[5], - RegisterExpr::new(Domain::new(domain_id.clone())).into() + Register::domain(Domain::new(domain_id.clone())).into() ); assert_eq!( finished_genesis_block.transactions[0].isi[6], - RegisterExpr::new(Account::new( + Register::account(Account::new( AccountId::new("Mad_Hatter".parse().unwrap(), domain_id), [public_key.parse().unwrap()], )) @@ -468,7 +468,7 @@ mod tests { ); assert_eq!( finished_genesis_block.transactions[0].isi[7], - RegisterExpr::new(AssetDefinition::big_quantity( + Register::asset_definition(AssetDefinition::big_quantity( "hats#meadow".parse().unwrap() )) .into() diff --git a/p2p/src/peer.rs b/p2p/src/peer.rs index e08a93f6aca..182b72e9e7d 100644 --- a/p2p/src/peer.rs +++ b/p2p/src/peer.rs @@ -409,6 +409,7 @@ mod state { } impl ConnectedTo { + #[allow(clippy::similar_names)] pub(super) async fn send_client_hello( Self { peer_addr, @@ -452,6 +453,7 @@ mod state { } impl ConnectedFrom { + #[allow(clippy::similar_names)] pub(super) async fn read_client_hello( Self { peer_addr, diff --git a/schema/derive/src/lib.rs b/schema/derive/src/lib.rs index 233a901e5cb..3f801b67459 100644 --- a/schema/derive/src/lib.rs +++ b/schema/derive/src/lib.rs @@ -65,6 +65,7 @@ impl FromMeta for Transparent { #[darling(attributes(schema))] struct SchemaAttributes { transparent: Transparent, + bounds: Option, } // NOTE: this will fail on unknown attributes.. This is not ideal @@ -184,12 +185,16 @@ pub fn schema_derive(input: TokenStream) -> Result { let impl_type_id = impl_type_id(&mut syn2::parse2(original_input).unwrap()); let impl_schema = match &input.schema_attrs.transparent { - Transparent::NotTransparent => impl_into_schema(&input), + Transparent::NotTransparent => impl_into_schema(&input, input.schema_attrs.bounds.as_ref()), Transparent::Transparent(transparent_type) => { let transparent_type = transparent_type .clone() .unwrap_or_else(|| infer_transparent_type(&input.data, &mut emitter)); - Ok(impl_transparent_into_schema(&input, &transparent_type)) + impl_transparent_into_schema( + &input, + &transparent_type, + input.schema_attrs.bounds.as_ref(), + ) } }; let impl_schema = match impl_schema { @@ -211,11 +216,16 @@ pub fn schema_derive(input: TokenStream) -> Result { fn impl_transparent_into_schema( input: &IntoSchemaInput, transparent_type: &syn2::Type, -) -> TokenStream { + bounds: Option<&String>, +) -> Result { let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let name = &input.ident; + let where_clause: Option = match bounds { + Some(bounds) => Some(syn2::parse_str(&format!("where {bounds}"))?), + None => where_clause.cloned(), + }; - quote! { + Ok(quote! { impl #impl_generics iroha_schema::IntoSchema for #name #ty_generics #where_clause { fn update_schema_map(map: &mut iroha_schema::MetaMap) { if !map.contains_key::() { @@ -233,14 +243,18 @@ fn impl_transparent_into_schema( <#transparent_type as iroha_schema::IntoSchema>::type_name() } } - } + }) } -fn impl_into_schema(input: &IntoSchemaInput) -> Result { +fn impl_into_schema(input: &IntoSchemaInput, bounds: Option<&String>) -> Result { let name = &input.ident; let type_name_body = trait_body(name, &input.generics, false); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let metadata = metadata(&input.data)?; + let where_clause: Option = match bounds { + Some(bounds) => Some(syn2::parse_str(&format!("where {bounds}"))?), + None => where_clause.cloned(), + }; Ok(quote! { impl #impl_generics iroha_schema::IntoSchema for #name #ty_generics #where_clause { diff --git a/schema/derive/tests/ui_pass/derive_into_schema.rs b/schema/derive/tests/ui_pass/derive_into_schema.rs index 576fb77f5ce..f75295a3f82 100644 --- a/schema/derive/tests/ui_pass/derive_into_schema.rs +++ b/schema/derive/tests/ui_pass/derive_into_schema.rs @@ -42,4 +42,14 @@ pub enum Enum { FortyTwo, } +pub trait Trait { + type Assoc; +} + +#[derive(IntoSchema)] +#[schema(bounds = "T: Trait, T::Assoc: IntoSchema")] +pub struct WithComplexGeneric { + _value: T::Assoc, +} + pub fn main() {} diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index ddac0fad272..ef3c1cab1f8 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -66,13 +66,13 @@ types!( AccountEventFilter, AccountFilter, AccountId, + AccountMintBox, AccountPermissionChanged, AccountRoleChanged, Action, - Add, Algorithm, - And, Asset, + AssetBurnBox, AssetChanged, AssetDefinition, AssetDefinitionEvent, @@ -85,6 +85,8 @@ types!( AssetEventFilter, AssetFilter, AssetId, + AssetMintBox, + AssetTransferBox, AssetValue, AssetValueType, AtIndex, @@ -92,7 +94,6 @@ types!( BTreeMap, BTreeMap, BTreeMap, - BTreeMap>, BTreeMap, BTreeSet, BTreeSet, @@ -106,53 +107,31 @@ types!( BlockSubscriptionRequest, Box, Box>, - Box, Box, Box, - BurnExpr, - ConditionalExpr, + BurnBox, ConfigurationEvent, ConstString, Container, - Contains, - ContainsAll, - ContainsAny, - ContextValue, DataEntityFilter, DataEvent, DataEventFilter, - Divide, Domain, DomainEvent, DomainEventFilter, DomainFilter, DomainId, Duration, - Equal, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo, - EvaluatesTo>, - EvaluatesTo, Event, EventMessage, EventSubscriptionRequest, Executable, - ExecuteTriggerExpr, + ExecuteTrigger, ExecuteTriggerEvent, ExecuteTriggerEventFilter, ExecutionTime, - Expression, + Executor, + ExecutorEvent, Fail, FilterBox, FilterOpt, @@ -220,16 +199,14 @@ types!( FixNum, Fixed, ForwardCursor, - GrantExpr, - Greater, + GrantBox, Hash, HashOf>, HashOf, HashOf, IdBox, IdentifiableBox, - If, - InstructionExpr, + InstructionBox, InstructionExecutionFail, Interval, Interval, @@ -239,7 +216,6 @@ types!( Ipv6Addr, Ipv6Predicate, LengthLimits, - Less, MerkleTree, Metadata, MetadataChanged, @@ -247,19 +223,16 @@ types!( MetadataChanged, MetadataChanged, MetadataLimits, - MintExpr, + MintBox, Mintable, - Mod, - Multiply, Name, NewAccount, NewAssetDefinition, NewDomain, - NewParameterExpr, + NewParameter, NewRole, NonTrivial, NonZeroU64, - Not, NotificationEventFilter, NumericValue, Option, @@ -267,7 +240,6 @@ types!( Option, Option>>, Option>, - Option, Option, Option, Option, @@ -275,7 +247,6 @@ types!( Option, Option, Option, - Or, OriginFilter, OriginFilter, OriginFilter, @@ -283,7 +254,6 @@ types!( OriginFilter, OriginFilter, OriginFilter, - PairExpr, Parameter, ParameterId, Peer, @@ -306,12 +276,11 @@ types!( QueryBox, QueryExecutionFail, QueryPayload, - RaiseTo, - RegisterExpr, + RegisterBox, RegistrableBox, - RemoveKeyValueExpr, + RemoveKeyValueBox, Repeats, - RevokeExpr, + RevokeBox, Role, RoleEvent, RoleEventFilter, @@ -321,9 +290,8 @@ types!( SemiInterval, SemiInterval, SemiRange, - SequenceExpr, - SetKeyValueExpr, - SetParameterExpr, + SetKeyValueBox, + SetParameter, Signature, SignatureCheckCondition, SignatureOf, @@ -339,7 +307,6 @@ types!( SignedTransactionV1, String, StringPredicate, - Subtract, TimeEvent, TimeEventFilter, TimeInterval, @@ -350,7 +317,7 @@ types!( TransactionQueryOutput, TransactionRejectionReason, TransactionValue, - TransferExpr, + TransferBox, Trigger, TriggerCompletedEventFilter, TriggerCompletedOutcomeType, @@ -360,16 +327,14 @@ types!( TriggerId, TriggerNumberOfExecutionsChanged, TriggeringFilterBox, - UnregisterExpr, + UnregisterBox, UpgradableBox, ValidationFail, - Executor, - ExecutorEvent, Value, ValueOfKey, ValuePredicate, Vec, - Vec, + Vec, Vec, Vec, Vec, @@ -377,7 +342,6 @@ types!( Vec, WasmExecutionFail, WasmSmartContract, - Where, [Interval; 8], [Interval; 4], [u16; 8], @@ -465,40 +429,18 @@ mod tests { let mut missing_schemas = HashMap::<&str, _>::new(); for type_name in type_names { - if let (Some(mut start), Some(end)) = (type_name.find('<'), type_name.rfind('>')) { - start += 1; - - let mut angle_bracket_diff = 0_u8; - for (i, c) in type_name[start..end].chars().enumerate() { - if c == '<' { - angle_bracket_diff += 1_u8; - } - if c == '>' { - angle_bracket_diff -= 1_u8; - } - - if c == ',' && angle_bracket_diff == 0_u8 { - let generic = type_name[start..(start + i)].trim(); + let (Some(start), Some(end)) = (type_name.find('<'), type_name.rfind('>')) else { + continue; + }; - start += i + 1; - if !is_const_generic(generic) { - continue; - } + assert!(start < end, "Invalid type name: {type_name}"); - if !type_names.contains(generic) { - missing_schemas - .entry(type_name) - .or_insert_with(Vec::new) - .push(generic); - } - } + for generic in type_name.split(", ") { + if !is_const_generic(generic) { + continue; } - let generic = type_name[start..end].trim(); - if !generic.is_empty() - && !is_const_generic(generic) - && !type_names.contains(generic) - { + if !type_names.contains(generic) { missing_schemas .entry(type_name) .or_insert_with(Vec::new) diff --git a/smart_contract/executor/derive/src/default.rs b/smart_contract/executor/derive/src/default.rs index 6045bd40b82..fa12601e750 100644 --- a/smart_contract/executor/derive/src/default.rs +++ b/smart_contract/executor/derive/src/default.rs @@ -54,7 +54,7 @@ pub fn impl_derive_entrypoints(emitter: &mut Emitter, input: &syn2::DeriveInput) #[::iroha_executor::prelude::entrypoint] pub fn validate_instruction( authority: ::iroha_executor::prelude::AccountId, - instruction: ::iroha_executor::prelude::InstructionExpr, + instruction: ::iroha_executor::prelude::InstructionBox, block_height: u64, #(#custom_args),* ) -> ::iroha_executor::prelude::Result { @@ -107,54 +107,63 @@ pub fn impl_derive_entrypoints(emitter: &mut Emitter, input: &syn2::DeriveInput) } } +#[allow(clippy::too_many_lines)] pub fn impl_derive_visit(emitter: &mut Emitter, input: &syn2::DeriveInput) -> TokenStream2 { let Some(input) = emitter.handle(ExecutorDeriveInput::from_derive_input(input)) else { return quote!(); }; let ExecutorDeriveInput { ident, custom, .. } = &input; let default_visit_sigs: Vec = [ - "fn visit_unsupported(operation: T)", "fn visit_transaction(operation: &SignedTransaction)", - "fn visit_instruction(operation: &InstructionExpr)", - "fn visit_expression(operation: &EvaluatesTo)", - "fn visit_sequence(operation: &SequenceExpr)", - "fn visit_if(operation: &ConditionalExpr)", - "fn visit_pair(operation: &PairExpr)", - "fn visit_unregister_peer(operation: Unregister)", - "fn visit_unregister_domain(operation: Unregister)", - "fn visit_transfer_domain(operation: Transfer)", - "fn visit_set_domain_key_value(operation: SetKeyValue)", - "fn visit_remove_domain_key_value(operation: RemoveKeyValue)", - "fn visit_unregister_account(operation: Unregister)", - "fn visit_mint_account_public_key(operation: Mint)", - "fn visit_burn_account_public_key(operation: Burn)", - "fn visit_mint_account_signature_check_condition(operation: Mint)", - "fn visit_set_account_key_value(operation: SetKeyValue)", - "fn visit_remove_account_key_value(operation: RemoveKeyValue)", - "fn visit_register_asset(operation: Register)", - "fn visit_unregister_asset(operation: Unregister)", - "fn visit_mint_asset(operation: Mint)", - "fn visit_burn_asset(operation: Burn)", - "fn visit_transfer_asset(operation: Transfer)", - "fn visit_set_asset_key_value(operation: SetKeyValue)", - "fn visit_remove_asset_key_value(operation: RemoveKeyValue)", - "fn visit_unregister_asset_definition(operation: Unregister)", - "fn visit_transfer_asset_definition(operation: Transfer)", - "fn visit_set_asset_definition_key_value(operation: SetKeyValue)", - "fn visit_remove_asset_definition_key_value(operation: RemoveKeyValue)", - "fn visit_grant_account_permission(operation: Grant)", - "fn visit_revoke_account_permission(operation: Revoke)", - "fn visit_register_role(operation: Register)", - "fn visit_unregister_role(operation: Unregister)", - "fn visit_grant_account_role(operation: Grant)", - "fn visit_revoke_account_role(operation: Revoke)", - "fn visit_unregister_trigger(operation: Unregister>)", - "fn visit_mint_trigger_repetitions(operation: Mint>)", - "fn visit_burn_trigger_repetitions(operation: Burn>)", - "fn visit_execute_trigger(operation: ExecuteTrigger)", - "fn visit_set_parameter(operation: SetParameter)", - "fn visit_new_parameter(operation: NewParameter)", - "fn visit_upgrade_executor(operation: Upgrade)", + "fn visit_instruction(operation: &InstructionBox)", + "fn visit_register_peer(operation: &Register)", + "fn visit_unregister_peer(operation: &Unregister)", + "fn visit_register_domain(operation: &Register)", + "fn visit_unregister_domain(operation: &Unregister)", + "fn visit_transfer_domain(operation: &Transfer)", + "fn visit_set_domain_key_value(operation: &SetKeyValue)", + "fn visit_remove_domain_key_value(operation: &RemoveKeyValue)", + "fn visit_register_account(operation: &Register)", + "fn visit_unregister_account(operation: &Unregister)", + "fn visit_mint_account_public_key(operation: &Mint)", + "fn visit_burn_account_public_key(operation: &Burn)", + "fn visit_mint_account_signature_check_condition(operation: &Mint)", + "fn visit_set_account_key_value(operation: &SetKeyValue)", + "fn visit_remove_account_key_value(operation: &RemoveKeyValue)", + "fn visit_register_asset(operation: &Register)", + "fn visit_unregister_asset(operation: &Unregister)", + "fn visit_mint_asset_quantity(operation: &Mint)", + "fn visit_burn_asset_quantity(operation: &Burn)", + "fn visit_mint_asset_big_quantity(operation: &Mint)", + "fn visit_burn_asset_big_quantity(operation: &Burn)", + "fn visit_mint_asset_fixed(operation: &Mint)", + "fn visit_burn_asset_fixed(operation: &Burn)", + "fn visit_transfer_asset_quantity(operation: &Transfer)", + "fn visit_transfer_asset_big_quantity(operation: &Transfer)", + "fn visit_transfer_asset_fixed(operation: &Transfer)", + "fn visit_set_asset_key_value(operation: &SetKeyValue)", + "fn visit_remove_asset_key_value(operation: &RemoveKeyValue)", + "fn visit_register_asset_definition(operation: &Register)", + "fn visit_unregister_asset_definition(operation: &Unregister)", + "fn visit_transfer_asset_definition(operation: &Transfer)", + "fn visit_set_asset_definition_key_value(operation: &SetKeyValue)", + "fn visit_remove_asset_definition_key_value(operation: &RemoveKeyValue)", + "fn visit_grant_account_permission(operation: &Grant)", + "fn visit_revoke_account_permission(operation: &Revoke)", + "fn visit_register_role(operation: &Register)", + "fn visit_unregister_role(operation: &Unregister)", + "fn visit_grant_account_role(operation: &Grant)", + "fn visit_revoke_account_role(operation: &Revoke)", + "fn visit_register_trigger(operation: &Register>)", + "fn visit_unregister_trigger(operation: &Unregister>)", + "fn visit_mint_trigger_repetitions(operation: &Mint>)", + "fn visit_burn_trigger_repetitions(operation: &Burn>)", + "fn visit_execute_trigger(operation: &ExecuteTrigger)", + "fn visit_set_parameter(operation: &SetParameter)", + "fn visit_new_parameter(operation: &NewParameter)", + "fn visit_upgrade(operation: &Upgrade)", + "fn visit_log(operation: &Log)", + "fn visit_fail(operation: &Fail)", ] .into_iter() .map(|item| { @@ -228,29 +237,6 @@ pub fn impl_derive_validate(emitter: &mut Emitter, input: &syn2::DeriveInput) -> } } -pub fn impl_derive_expression_evaluator( - emitter: &mut Emitter, - input: &syn2::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::data_model::evaluate::ExpressionEvaluator for #ident { - fn evaluate( - &self, - expression: &E, - ) -> ::core::result::Result - { - self.host.evaluate(expression) - } - } - - } -} - pub fn impl_derive_constructor(emitter: &mut Emitter, input: &syn2::DeriveInput) -> TokenStream2 { let Some(input) = emitter.handle(ExecutorDeriveInput::from_derive_input(input)) else { return quote!(); @@ -268,7 +254,6 @@ pub fn impl_derive_constructor(emitter: &mut Emitter, input: &syn2::DeriveInput) Self { verdict: Ok(()), block_height, - host: ::iroha_executor::smart_contract::Host, #(#custom_idents),* } } @@ -278,7 +263,8 @@ pub fn impl_derive_constructor(emitter: &mut Emitter, input: &syn2::DeriveInput) } fn check_required_fields(ast: &ExecutorData, emitter: &mut Emitter) { - let required_fields: syn2::FieldsNamed = parse_quote!({ verdict: ::iroha_executor::prelude::Result, block_height: u64, host: ::iroha_executor::smart_contract::Host }); + let required_fields: syn2::FieldsNamed = + parse_quote!({ verdict: ::iroha_executor::prelude::Result, block_height: u64 }); let struct_fields = ast .as_ref() .take_struct() @@ -328,7 +314,7 @@ fn check_type_equivalence(full_ty: &syn2::Type, given_ty: &syn2::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", "host"] + let required_idents: Vec = ["verdict", "block_height"] .iter() .map(|s| Ident::new(s, Span::call_site())) .collect(); diff --git a/smart_contract/executor/derive/src/lib.rs b/smart_contract/executor/derive/src/lib.rs index 228357ca7ef..71d682c974c 100644 --- a/smart_contract/executor/derive/src/lib.rs +++ b/smart_contract/executor/derive/src/lib.rs @@ -233,9 +233,7 @@ pub fn derive_ref_into_domain_owner(input: TokenStream) -> Result { } /// Implements the `iroha_executor::Validate` trait for the given `Executor` struct. As -/// this trait has a `iroha_executor::prelude::Visit`, and the latter has an -/// `iroha_executor::data_model::evaluate::ExpressionEvaluator` -/// bound, at least these two should be implemented as well. +/// 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`, `block_height`: `u64` and @@ -271,7 +269,7 @@ pub fn derive_validate(input: TokenStream) -> TokenStream { /// ```ignore /// use iroha_executor::{smart_contract, prelude::*}; /// -/// #[derive(Constructor, Entrypoints, ExpressionEvaluator, Validate, Visit)] +/// #[derive(Constructor, Entrypoints, Validate, Visit)] /// #[visit(custom(visit_query)] /// pub struct Executor { /// verdict: Result, @@ -318,7 +316,7 @@ pub fn derive_visit(input: TokenStream) -> TokenStream { /// ```ignore /// use iroha_executor::{smart_contract, prelude::*}; /// -/// #[derive(Constructor, Entrypoints, ExpressionEvaluator, Validate, Visit)] +/// #[derive(Constructor, Entrypoints, Validate, Visit)] /// #[entrypoints(custom(validate_query))] /// pub struct Executor { /// verdict: Result, @@ -341,27 +339,6 @@ pub fn derive_entrypoints(input: TokenStream) -> TokenStream { emitter.finish_token_stream_with(result) } -/// Implements `iroha_executor::data_model::evaluate::ExpressionEvaluator` trait -/// for the given `Executor` struct. -/// -/// Emits a compile error if the struct didn't have all the expected fields with corresponding -/// types, i.e. `verdict`: `iroha_executor::prelude::Result`, `block_height`: `u64` and -/// `host`: `iroha_executor::smart_contract::Host`, though technically only `host` is needed. -/// The types can be unqualified, but not aliased. -#[manyhow] -#[proc_macro_derive(ExpressionEvaluator)] -pub fn derive_expression_evaluator(input: TokenStream) -> TokenStream { - let mut emitter = Emitter::new(); - - let Some(input) = emitter.handle(syn2::parse2(input)) else { - return emitter.finish_token_stream(); - }; - - let result = default::impl_derive_expression_evaluator(&mut emitter, &input); - - emitter.finish_token_stream_with(result) -} - /// 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, diff --git a/smart_contract/executor/src/default.rs b/smart_contract/executor/src/default.rs index 771439e9742..5b70d96a884 100644 --- a/smart_contract/executor/src/default.rs +++ b/smart_contract/executor/src/default.rs @@ -7,48 +7,42 @@ use alloc::format; pub use account::{ visit_burn_account_public_key, visit_mint_account_public_key, - visit_mint_account_signature_check_condition, visit_remove_account_key_value, - visit_set_account_key_value, visit_unregister_account, + visit_mint_account_signature_check_condition, visit_register_account, + visit_remove_account_key_value, visit_set_account_key_value, visit_unregister_account, }; pub use asset::{ - visit_burn_asset, visit_mint_asset, visit_register_asset, visit_remove_asset_key_value, - visit_set_asset_key_value, visit_transfer_asset, visit_unregister_asset, + visit_burn_asset_big_quantity, visit_burn_asset_fixed, visit_burn_asset_quantity, + visit_mint_asset_big_quantity, visit_mint_asset_fixed, visit_mint_asset_quantity, + visit_register_asset, visit_remove_asset_key_value, visit_set_asset_key_value, + visit_transfer_asset_big_quantity, visit_transfer_asset_fixed, visit_transfer_asset_quantity, + visit_unregister_asset, }; pub use asset_definition::{ - visit_remove_asset_definition_key_value, visit_set_asset_definition_key_value, - visit_transfer_asset_definition, visit_unregister_asset_definition, + visit_register_asset_definition, visit_remove_asset_definition_key_value, + visit_set_asset_definition_key_value, visit_transfer_asset_definition, + visit_unregister_asset_definition, }; pub use domain::{ - visit_remove_domain_key_value, visit_set_domain_key_value, visit_transfer_domain, - visit_unregister_domain, + visit_register_domain, visit_remove_domain_key_value, visit_set_domain_key_value, + visit_transfer_domain, visit_unregister_domain, }; -pub use executor::visit_upgrade_executor; -use iroha_smart_contract::debug::DebugExpectExt as _; +pub use executor::visit_upgrade; +pub use fail::visit_fail; +use iroha_smart_contract::data_model::isi::InstructionBox; +pub use log::visit_log; pub use parameter::{visit_new_parameter, visit_set_parameter}; -pub use peer::visit_unregister_peer; +pub use peer::{visit_register_peer, visit_unregister_peer}; pub use permission_token::{visit_grant_account_permission, visit_revoke_account_permission}; pub use role::{ visit_grant_account_role, visit_register_role, visit_revoke_account_role, visit_unregister_role, }; pub use trigger::{ visit_burn_trigger_repetitions, visit_execute_trigger, visit_mint_trigger_repetitions, - visit_unregister_trigger, + visit_register_trigger, visit_unregister_trigger, }; use crate::{permission, permission::Token as _, prelude::*}; -macro_rules! evaluate_expr { - ($visitor:ident, $authority:ident, <$isi:ident as $isi_type:ty>::$field:ident()) => {{ - $visitor.visit_expression($authority, $isi.$field()); - - $visitor.evaluate($isi.$field()).dbg_expect(&alloc::format!( - "Failed to evaluate field '{}::{}'", - stringify!($isi_type), - stringify!($field), - )) - }}; -} - pub fn default_permission_token_schema() -> PermissionTokenSchema { let mut schema = iroha_executor::PermissionTokenSchema::default(); @@ -86,7 +80,7 @@ pub fn visit_transaction( } } -/// Default validation for [`InstructionExpr`]. +/// Default validation for [`InstructionBox`]. /// /// # Warning /// @@ -94,198 +88,53 @@ pub fn visit_transaction( pub fn visit_instruction( executor: &mut V, authority: &AccountId, - isi: &InstructionExpr, + isi: &InstructionBox, ) { - macro_rules! isi_executors { - ( - single {$( - $executor:ident($isi:ident) - ),+ $(,)?} - composite {$( - $composite_executor:ident($composite_isi:ident) - ),+ $(,)?} - ) => { - match isi { - InstructionExpr::NewParameter(isi) => { - let parameter = evaluate_expr!(executor, authority, ::parameter()); - executor.visit_new_parameter(authority, NewParameter{parameter}); - - if executor.verdict().is_ok() { - isi_executors!(@execute isi); - } - } - InstructionExpr::SetParameter(isi) => { - let parameter = evaluate_expr!(executor, authority, ::parameter()); - executor.visit_set_parameter(authority, SetParameter{parameter}); - - if executor.verdict().is_ok() { - isi_executors!(@execute isi); - } - } - InstructionExpr::ExecuteTrigger(isi) => { - let trigger_id = evaluate_expr!(executor, authority, ::trigger_id()); - executor.visit_execute_trigger(authority, ExecuteTrigger{trigger_id}); - - if executor.verdict().is_ok() { - isi_executors!(@execute isi); - } - } - InstructionExpr::Log(isi) => { - let msg = evaluate_expr!(executor, authority, ::msg()); - let level = evaluate_expr!(executor, authority, ::level()); - executor.visit_log(authority, Log{level, msg}); - - if executor.verdict().is_ok() { - isi_executors!(@execute isi); - } - } $( - InstructionExpr::$isi(isi) => { - executor.$executor(authority, isi); - - if executor.verdict().is_ok() { - isi_executors!(@execute isi); - } - } )+ $( - // NOTE: `visit_and_execute_instructions` is reentrant, so don't execute composite instructions - InstructionExpr::$composite_isi(isi) => executor.$composite_executor(authority, isi), )+ - } - }; - (@execute $isi:ident) => { - // TODO: Execution should be infallible after successful validation - if let Err(err) = isi.execute() { - executor.deny(err); - } + match isi { + InstructionBox::NewParameter(isi) => { + executor.visit_new_parameter(authority, isi); } - } - - isi_executors! { - single { - visit_burn(Burn), - visit_fail(Fail), - visit_grant(Grant), - visit_mint(Mint), - visit_register(Register), - visit_remove_key_value(RemoveKeyValue), - visit_revoke(Revoke), - visit_set_key_value(SetKeyValue), - visit_transfer(Transfer), - visit_unregister(Unregister), - visit_upgrade(Upgrade), - } - - composite { - visit_sequence(Sequence), - visit_pair(Pair), - visit_if(If), + InstructionBox::SetParameter(isi) => { + executor.visit_set_parameter(authority, isi); } - } -} - -pub fn visit_unsupported( - executor: &mut V, - _authority: &AccountId, - isi: T, -) { - deny!(executor, "{isi:?}: Unsupported operation"); -} - -pub fn visit_expression( - executor: &mut V, - authority: &AccountId, - expression: &EvaluatesTo, -) { - macro_rules! visit_binary_expression { - ($e:ident) => {{ - executor.visit_expression(authority, $e.left()); - - if executor.verdict().is_ok() { - executor.visit_expression(authority, $e.right()); - } - }}; - } - - match expression.expression() { - Expression::Add(expr) => visit_binary_expression!(expr), - Expression::Subtract(expr) => visit_binary_expression!(expr), - Expression::Multiply(expr) => visit_binary_expression!(expr), - Expression::Divide(expr) => visit_binary_expression!(expr), - Expression::Mod(expr) => visit_binary_expression!(expr), - Expression::RaiseTo(expr) => visit_binary_expression!(expr), - Expression::Greater(expr) => visit_binary_expression!(expr), - Expression::Less(expr) => visit_binary_expression!(expr), - Expression::Equal(expr) => visit_binary_expression!(expr), - Expression::Not(expr) => executor.visit_expression(authority, expr.expression()), - Expression::And(expr) => visit_binary_expression!(expr), - Expression::Or(expr) => visit_binary_expression!(expr), - Expression::If(expr) => { - executor.visit_expression(authority, expr.condition()); - - if executor.verdict().is_ok() { - executor.visit_expression(authority, expr.then()); - } - - if executor.verdict().is_ok() { - executor.visit_expression(authority, expr.otherwise()); - } + InstructionBox::Log(isi) => { + executor.visit_log(authority, isi); } - Expression::Contains(expr) => { - executor.visit_expression(authority, expr.collection()); - - if executor.verdict().is_ok() { - executor.visit_expression(authority, expr.element()); - } + InstructionBox::ExecuteTrigger(isi) => { + executor.visit_execute_trigger(authority, isi); } - Expression::ContainsAll(expr) => { - executor.visit_expression(authority, expr.collection()); - - if executor.verdict().is_ok() { - executor.visit_expression(authority, expr.elements()); - } + InstructionBox::Burn(isi) => { + executor.visit_burn(authority, isi); } - Expression::ContainsAny(expr) => { - executor.visit_expression(authority, expr.collection()); - - if executor.verdict().is_ok() { - executor.visit_expression(authority, expr.elements()); - } + InstructionBox::Fail(isi) => { + executor.visit_fail(authority, isi); } - Expression::Where(expr) => executor.visit_expression(authority, expr.expression()), - Expression::Query(query) => executor.visit_query(authority, query), - Expression::ContextValue(_) | Expression::Raw(_) => (), - } -} - -pub fn visit_if( - executor: &mut V, - authority: &AccountId, - isi: &ConditionalExpr, -) { - let condition = evaluate_expr!(executor, authority, ::condition()); - - // TODO: Do we have to make sure both branches are syntactically valid? - if condition { - executor.visit_instruction(authority, isi.then()); - } else if let Some(otherwise) = isi.otherwise() { - executor.visit_instruction(authority, otherwise); - } -} - -pub fn visit_pair(executor: &mut V, authority: &AccountId, isi: &PairExpr) { - executor.visit_instruction(authority, isi.left_instruction()); - - if executor.verdict().is_ok() { - executor.visit_instruction(authority, isi.right_instruction()) - } -} - -pub fn visit_sequence( - executor: &mut V, - authority: &AccountId, - sequence: &SequenceExpr, -) { - for isi in sequence.instructions() { - if executor.verdict().is_ok() { - executor.visit_instruction(authority, isi); + InstructionBox::Grant(isi) => { + executor.visit_grant(authority, isi); + } + InstructionBox::Mint(isi) => { + executor.visit_mint(authority, isi); + } + InstructionBox::Register(isi) => { + executor.visit_register(authority, isi); + } + InstructionBox::RemoveKeyValue(isi) => { + executor.visit_remove_key_value(authority, isi); + } + InstructionBox::Revoke(isi) => { + executor.visit_revoke(authority, isi); + } + InstructionBox::SetKeyValue(isi) => { + executor.visit_set_key_value(authority, isi); + } + InstructionBox::Transfer(isi) => { + executor.visit_transfer(authority, isi); + } + InstructionBox::Unregister(isi) => { + executor.visit_unregister(authority, isi); + } + InstructionBox::Upgrade(isi) => { + executor.visit_upgrade(authority, isi); } } } @@ -293,17 +142,25 @@ pub fn visit_sequence( pub mod peer { use super::*; + pub fn visit_register_peer( + executor: &mut V, + _authority: &AccountId, + isi: &Register, + ) { + execute!(executor, isi) + } + #[allow(clippy::needless_pass_by_value)] pub fn visit_unregister_peer( executor: &mut V, authority: &AccountId, - _isi: Unregister, + isi: &Unregister, ) { if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } if tokens::peer::CanUnregisterAnyPeer.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't unregister peer"); @@ -315,24 +172,34 @@ pub mod domain { use super::*; + pub fn visit_register_domain( + executor: &mut V, + _authority: &AccountId, + isi: &Register, + ) { + execute!(executor, isi) + } + pub fn visit_unregister_domain( executor: &mut V, authority: &AccountId, - isi: Unregister, + isi: &Unregister, ) { - let domain_id = isi.object_id; + let domain_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_domain_owner(&domain_id, authority) { + match is_domain_owner(domain_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_unregister_domain_token = tokens::domain::CanUnregisterDomain { domain_id }; + let can_unregister_domain_token = tokens::domain::CanUnregisterDomain { + domain_id: domain_id.clone(), + }; if can_unregister_domain_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't unregister domain"); @@ -341,16 +208,16 @@ pub mod domain { pub fn visit_transfer_domain( executor: &mut V, authority: &AccountId, - isi: Transfer, + isi: &Transfer, ) { - let destination_id = isi.object; + let destination_id = isi.object(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_domain_owner(&destination_id, authority) { + match is_domain_owner(destination_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } @@ -360,22 +227,23 @@ pub mod domain { pub fn visit_set_domain_key_value( executor: &mut V, authority: &AccountId, - isi: SetKeyValue, + isi: &SetKeyValue, ) { - let domain_id = isi.object_id; + let domain_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_domain_owner(&domain_id, authority) { + match is_domain_owner(domain_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_set_key_value_in_domain_token = - tokens::domain::CanSetKeyValueInDomain { domain_id }; + let can_set_key_value_in_domain_token = tokens::domain::CanSetKeyValueInDomain { + domain_id: domain_id.clone(), + }; if can_set_key_value_in_domain_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't set key value in domain metadata"); @@ -384,22 +252,23 @@ pub mod domain { pub fn visit_remove_domain_key_value( executor: &mut V, authority: &AccountId, - isi: RemoveKeyValue, + isi: &RemoveKeyValue, ) { - let domain_id = isi.object_id; + let domain_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_domain_owner(&domain_id, authority) { + match is_domain_owner(domain_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_remove_key_value_in_domain_token = - tokens::domain::CanRemoveKeyValueInDomain { domain_id }; + let can_remove_key_value_in_domain_token = tokens::domain::CanRemoveKeyValueInDomain { + domain_id: domain_id.clone(), + }; if can_remove_key_value_in_domain_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't remove key value in domain metadata"); @@ -411,24 +280,34 @@ pub mod account { use super::*; + pub fn visit_register_account( + executor: &mut V, + _authority: &AccountId, + isi: &Register, + ) { + execute!(executor, isi) + } + pub fn visit_unregister_account( executor: &mut V, authority: &AccountId, - isi: Unregister, + isi: &Unregister, ) { - let account_id = isi.object_id; + let account_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_account_owner(&account_id, authority) { + match is_account_owner(account_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_unregister_user_account = tokens::account::CanUnregisterAccount { account_id }; + let can_unregister_user_account = tokens::account::CanUnregisterAccount { + account_id: account_id.clone(), + }; if can_unregister_user_account.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't unregister another account"); @@ -437,21 +316,23 @@ pub mod account { pub fn visit_mint_account_public_key( executor: &mut V, authority: &AccountId, - isi: Mint, + isi: &Mint, ) { - let account_id = isi.destination_id; + let account_id = isi.destination_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_account_owner(&account_id, authority) { + match is_account_owner(account_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_mint_user_public_keys = tokens::account::CanMintUserPublicKeys { account_id }; + let can_mint_user_public_keys = tokens::account::CanMintUserPublicKeys { + account_id: account_id.clone(), + }; if can_mint_user_public_keys.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't mint public keys of another account"); @@ -460,21 +341,23 @@ pub mod account { pub fn visit_burn_account_public_key( executor: &mut V, authority: &AccountId, - isi: Burn, + isi: &Burn, ) { - let account_id = isi.destination_id; + let account_id = isi.destination_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_account_owner(&account_id, authority) { + match is_account_owner(account_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_burn_user_public_keys = tokens::account::CanBurnUserPublicKeys { account_id }; + let can_burn_user_public_keys = tokens::account::CanBurnUserPublicKeys { + account_id: account_id.clone(), + }; if can_burn_user_public_keys.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't burn public keys of another account"); @@ -483,22 +366,24 @@ pub mod account { pub fn visit_mint_account_signature_check_condition( executor: &mut V, authority: &AccountId, - isi: Mint, + isi: &Mint, ) { - let account_id = isi.destination_id; + let account_id = isi.destination_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_account_owner(&account_id, authority) { + match is_account_owner(account_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_mint_user_signature_check_conditions_token = - tokens::account::CanMintUserSignatureCheckConditions { account_id }; + tokens::account::CanMintUserSignatureCheckConditions { + account_id: account_id.clone(), + }; if can_mint_user_signature_check_conditions_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -510,22 +395,24 @@ pub mod account { pub fn visit_set_account_key_value( executor: &mut V, authority: &AccountId, - isi: SetKeyValue, + isi: &SetKeyValue, ) { - let account_id = isi.object_id; + let account_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_account_owner(&account_id, authority) { + match is_account_owner(account_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_set_key_value_in_user_account_token = - tokens::account::CanSetKeyValueInUserAccount { account_id }; + tokens::account::CanSetKeyValueInUserAccount { + account_id: account_id.clone(), + }; if can_set_key_value_in_user_account_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -537,22 +424,24 @@ pub mod account { pub fn visit_remove_account_key_value( executor: &mut V, authority: &AccountId, - isi: RemoveKeyValue, + isi: &RemoveKeyValue, ) { - let account_id = isi.object_id; + let account_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_account_owner(&account_id, authority) { + match is_account_owner(account_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_remove_key_value_in_user_account_token = - tokens::account::CanRemoveKeyValueInUserAccount { account_id }; + tokens::account::CanRemoveKeyValueInUserAccount { + account_id: account_id.clone(), + }; if can_remove_key_value_in_user_account_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -567,27 +456,35 @@ pub mod asset_definition { use super::*; + pub fn visit_register_asset_definition( + executor: &mut V, + _authority: &AccountId, + isi: &Register, + ) { + execute!(executor, isi); + } + pub fn visit_unregister_asset_definition( executor: &mut V, authority: &AccountId, - isi: Unregister, + isi: &Unregister, ) { - let asset_definition_id = isi.object_id; + let asset_definition_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_asset_definition_owner(&asset_definition_id, authority) { + match is_asset_definition_owner(asset_definition_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_unregister_asset_definition_token = tokens::asset_definition::CanUnregisterAssetDefinition { - asset_definition_id, + asset_definition_id: asset_definition_id.clone(), }; if can_unregister_asset_definition_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -599,22 +496,22 @@ pub mod asset_definition { pub fn visit_transfer_asset_definition( executor: &mut V, authority: &AccountId, - isi: Transfer, + isi: &Transfer, ) { - let source_id = isi.source_id; - let destination_id = isi.object; + let source_id = isi.source_id(); + let destination_id = isi.object(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_account_owner(&source_id, authority) { + match is_account_owner(source_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - match is_asset_definition_owner(&destination_id, authority) { + match is_asset_definition_owner(destination_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } @@ -627,24 +524,24 @@ pub mod asset_definition { pub fn visit_set_asset_definition_key_value( executor: &mut V, authority: &AccountId, - isi: SetKeyValue, + isi: &SetKeyValue, ) { - let asset_definition_id = isi.object_id; + let asset_definition_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_asset_definition_owner(&asset_definition_id, authority) { + match is_asset_definition_owner(asset_definition_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_set_key_value_in_asset_definition_token = tokens::asset_definition::CanSetKeyValueInAssetDefinition { - asset_definition_id, + asset_definition_id: asset_definition_id.clone(), }; if can_set_key_value_in_asset_definition_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -656,24 +553,24 @@ pub mod asset_definition { pub fn visit_remove_asset_definition_key_value( executor: &mut V, authority: &AccountId, - isi: RemoveKeyValue, + isi: &RemoveKeyValue, ) { - let asset_definition_id = isi.object_id; + let asset_definition_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_asset_definition_owner(&asset_definition_id, authority) { + match is_asset_definition_owner(asset_definition_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_remove_key_value_in_asset_definition_token = tokens::asset_definition::CanRemoveKeyValueInAssetDefinition { - asset_definition_id, + asset_definition_id: asset_definition_id.clone(), }; if can_remove_key_value_in_asset_definition_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -684,6 +581,8 @@ pub mod asset_definition { } pub mod asset { + use iroha_smart_contract::data_model::isi::Instruction; + use iroha_smart_contract_utils::Encode; use permission::{asset::is_asset_owner, asset_definition::is_asset_definition_owner}; use super::*; @@ -691,16 +590,16 @@ pub mod asset { pub fn visit_register_asset( executor: &mut V, authority: &AccountId, - isi: Register, + isi: &Register, ) { - let asset = isi.object; + let asset = isi.object(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } match is_asset_definition_owner(asset.id().definition_id(), authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_register_assets_with_definition_token = @@ -708,7 +607,7 @@ pub mod asset { asset_definition_id: asset.id().definition_id().clone(), }; if can_register_assets_with_definition_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -720,21 +619,21 @@ pub mod asset { pub fn visit_unregister_asset( executor: &mut V, authority: &AccountId, - isi: Unregister, + isi: &Unregister, ) { - let asset_id = isi.object_id; + let asset_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_asset_owner(&asset_id, authority) { + match is_asset_owner(asset_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } match is_asset_definition_owner(asset_id.definition_id(), authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_unregister_assets_with_definition_token = @@ -742,36 +641,38 @@ pub mod asset { asset_definition_id: asset_id.definition_id().clone(), }; if can_unregister_assets_with_definition_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } - let can_unregister_user_asset_token = tokens::asset::CanUnregisterUserAsset { asset_id }; + let can_unregister_user_asset_token = tokens::asset::CanUnregisterUserAsset { + asset_id: asset_id.clone(), + }; if can_unregister_user_asset_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't unregister asset from another account"); } - pub fn visit_mint_asset( - executor: &mut V, - authority: &AccountId, - isi: Mint, - ) { - let asset_id = isi.destination_id; - + fn validate_mint_asset(executor: &mut V, authority: &AccountId, isi: &Mint) + where + V: Validate + ?Sized, + Q: Into, + Mint: Instruction + Encode + Clone, + { + let asset_id = isi.destination_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } match is_asset_definition_owner(asset_id.definition_id(), authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_mint_assets_with_definition_token = tokens::asset::CanMintAssetsWithDefinition { asset_definition_id: asset_id.definition_id().clone(), }; if can_mint_assets_with_definition_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -780,58 +681,111 @@ pub mod asset { ); } - pub fn visit_burn_asset( + pub fn visit_mint_asset_quantity( executor: &mut V, authority: &AccountId, - isi: Burn, + isi: &Mint, ) { - let asset_id = isi.destination_id; + validate_mint_asset(executor, authority, isi); + } + pub fn visit_mint_asset_big_quantity( + executor: &mut V, + authority: &AccountId, + isi: &Mint, + ) { + validate_mint_asset(executor, authority, isi); + } + + pub fn visit_mint_asset_fixed( + executor: &mut V, + authority: &AccountId, + isi: &Mint, + ) { + validate_mint_asset(executor, authority, isi); + } + + fn validate_burn_asset(executor: &mut V, authority: &AccountId, isi: &Burn) + where + V: Validate + ?Sized, + Q: Into, + Burn: Instruction + Encode + Clone, + { + let asset_id = isi.destination_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_asset_owner(&asset_id, authority) { + match is_asset_owner(asset_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } match is_asset_definition_owner(asset_id.definition_id(), authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_burn_assets_with_definition_token = tokens::asset::CanBurnAssetsWithDefinition { asset_definition_id: asset_id.definition_id().clone(), }; if can_burn_assets_with_definition_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } - let can_burn_user_asset_token = tokens::asset::CanBurnUserAsset { asset_id }; + let can_burn_user_asset_token = tokens::asset::CanBurnUserAsset { + asset_id: asset_id.clone(), + }; if can_burn_user_asset_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't burn assets from another account"); } - pub fn visit_transfer_asset( + pub fn visit_burn_asset_quantity( + executor: &mut V, + authority: &AccountId, + isi: &Burn, + ) { + validate_burn_asset(executor, authority, isi); + } + + pub fn visit_burn_asset_big_quantity( + executor: &mut V, + authority: &AccountId, + isi: &Burn, + ) { + validate_burn_asset(executor, authority, isi); + } + + pub fn visit_burn_asset_fixed( executor: &mut V, authority: &AccountId, - isi: Transfer, + isi: &Burn, ) { - let asset_id = isi.source_id; + validate_burn_asset(executor, authority, isi); + } + fn validate_transfer_asset( + executor: &mut V, + authority: &AccountId, + isi: &Transfer, + ) where + V: Validate + ?Sized, + Q: Into, + Transfer: Instruction + Encode + Clone, + { + let asset_id = isi.source_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_asset_owner(&asset_id, authority) { + match is_asset_owner(asset_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } match is_asset_definition_owner(asset_id.definition_id(), authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_transfer_assets_with_definition_token = @@ -839,36 +793,63 @@ pub mod asset { asset_definition_id: asset_id.definition_id().clone(), }; if can_transfer_assets_with_definition_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } - let can_transfer_user_asset_token = tokens::asset::CanTransferUserAsset { asset_id }; + let can_transfer_user_asset_token = tokens::asset::CanTransferUserAsset { + asset_id: asset_id.clone(), + }; if can_transfer_user_asset_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't transfer assets of another account"); } + pub fn visit_transfer_asset_quantity( + executor: &mut V, + authority: &AccountId, + isi: &Transfer, + ) { + validate_transfer_asset(executor, authority, isi); + } + + pub fn visit_transfer_asset_big_quantity( + executor: &mut V, + authority: &AccountId, + isi: &Transfer, + ) { + validate_transfer_asset(executor, authority, isi); + } + + pub fn visit_transfer_asset_fixed( + executor: &mut V, + authority: &AccountId, + isi: &Transfer, + ) { + validate_transfer_asset(executor, authority, isi); + } + pub fn visit_set_asset_key_value( executor: &mut V, authority: &AccountId, - isi: SetKeyValue, + isi: &SetKeyValue, ) { - let asset_id = isi.object_id; + let asset_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_asset_owner(&asset_id, authority) { + match is_asset_owner(asset_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_set_key_value_in_user_asset_token = - tokens::asset::CanSetKeyValueInUserAsset { asset_id }; + let can_set_key_value_in_user_asset_token = tokens::asset::CanSetKeyValueInUserAsset { + asset_id: asset_id.clone(), + }; if can_set_key_value_in_user_asset_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -880,22 +861,24 @@ pub mod asset { pub fn visit_remove_asset_key_value( executor: &mut V, authority: &AccountId, - isi: RemoveKeyValue, + isi: &RemoveKeyValue, ) { - let asset_id = isi.object_id; + let asset_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_asset_owner(&asset_id, authority) { + match is_asset_owner(asset_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } let can_remove_key_value_in_user_asset_token = - tokens::asset::CanRemoveKeyValueInUserAsset { asset_id }; + tokens::asset::CanRemoveKeyValueInUserAsset { + asset_id: asset_id.clone(), + }; if can_remove_key_value_in_user_asset_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -912,13 +895,13 @@ pub mod parameter { pub fn visit_new_parameter( executor: &mut V, authority: &AccountId, - _isi: NewParameter, + isi: &NewParameter, ) { if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } if tokens::parameter::CanCreateParameters.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -931,13 +914,13 @@ pub mod parameter { pub fn visit_set_parameter( executor: &mut V, authority: &AccountId, - _isi: SetParameter, + isi: &SetParameter, ) { if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } if tokens::parameter::CanSetParameters.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -952,9 +935,9 @@ pub mod role { macro_rules! impl_validate { ($executor:ident, $isi:ident, $authority:ident, $method:ident) => { - let role_id = $isi.object; + let role_id = $isi.object(); - let find_role_query_res = match FindRoleByRoleId::new(role_id).execute() { + let find_role_query_res = match FindRoleByRoleId::new(role_id.clone()).execute() { Ok(res) => res.into_raw_parts().0, Err(error) => { deny!($executor, error); @@ -986,6 +969,7 @@ pub mod role { } assert!(unknown_tokens.is_empty(), "Role contains unknown permission tokens: {unknown_tokens:?}"); + execute!($executor, $isi) }; } @@ -993,9 +977,9 @@ pub mod role { pub fn visit_register_role( executor: &mut V, _authority: &AccountId, - isi: Register, + isi: &Register, ) { - let role = isi.object.inner(); + let role = isi.object().inner(); let mut unknown_tokens = Vec::new(); for token in role.permissions() { @@ -1021,20 +1005,20 @@ pub mod role { ); } - pass!(executor); + execute!(executor, isi); } #[allow(clippy::needless_pass_by_value)] pub fn visit_unregister_role( executor: &mut V, authority: &AccountId, - _isi: Unregister, + isi: &Unregister, ) { if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } if tokens::role::CanUnregisterAnyRole.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't unregister role"); @@ -1043,7 +1027,7 @@ pub mod role { pub fn visit_grant_account_role( executor: &mut V, authority: &AccountId, - isi: Grant, + isi: &Grant, ) { impl_validate!(executor, isi, authority, validate_grant); } @@ -1051,7 +1035,7 @@ pub mod role { pub fn visit_revoke_account_role( executor: &mut V, authority: &AccountId, - isi: Revoke, + isi: &Revoke, ) { impl_validate!(executor, isi, authority, validate_revoke); } @@ -1062,25 +1046,34 @@ pub mod trigger { use super::*; + pub fn visit_register_trigger( + executor: &mut V, + _authority: &AccountId, + isi: &Register>, + ) { + execute!(executor, isi) + } + pub fn visit_unregister_trigger( executor: &mut V, authority: &AccountId, - isi: Unregister>, + isi: &Unregister>, ) { - let trigger_id = isi.object_id; + let trigger_id = isi.object_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_trigger_owner(&trigger_id, authority) { + match is_trigger_owner(trigger_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_unregister_user_trigger_token = - tokens::trigger::CanUnregisterUserTrigger { trigger_id }; + let can_unregister_user_trigger_token = tokens::trigger::CanUnregisterUserTrigger { + trigger_id: trigger_id.clone(), + }; if can_unregister_user_trigger_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -1092,21 +1085,23 @@ pub mod trigger { pub fn visit_mint_trigger_repetitions( executor: &mut V, authority: &AccountId, - isi: Mint>, + isi: &Mint>, ) { - let trigger_id = isi.destination_id; + let trigger_id = isi.destination_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_trigger_owner(&trigger_id, authority) { + match is_trigger_owner(trigger_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_mint_user_trigger_token = tokens::trigger::CanMintUserTrigger { trigger_id }; + let can_mint_user_trigger_token = tokens::trigger::CanMintUserTrigger { + trigger_id: trigger_id.clone(), + }; if can_mint_user_trigger_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -1118,21 +1113,23 @@ pub mod trigger { pub fn visit_burn_trigger_repetitions( executor: &mut V, authority: &AccountId, - isi: Burn>, + isi: &Burn>, ) { - let trigger_id = isi.destination_id; + let trigger_id = isi.destination_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_trigger_owner(&trigger_id, authority) { + match is_trigger_owner(trigger_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_mint_user_trigger_token = tokens::trigger::CanBurnUserTrigger { trigger_id }; + let can_mint_user_trigger_token = tokens::trigger::CanBurnUserTrigger { + trigger_id: trigger_id.clone(), + }; if can_mint_user_trigger_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!( @@ -1144,21 +1141,23 @@ pub mod trigger { pub fn visit_execute_trigger( executor: &mut V, authority: &AccountId, - isi: ExecuteTrigger, + isi: &ExecuteTrigger, ) { - let trigger_id = isi.trigger_id; + let trigger_id = isi.trigger_id(); if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } - match is_trigger_owner(&trigger_id, authority) { + match is_trigger_owner(trigger_id, authority) { Err(err) => deny!(executor, err), - Ok(true) => pass!(executor), + Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_execute_trigger_token = tokens::trigger::CanExecuteUserTrigger { trigger_id }; + let can_execute_trigger_token = tokens::trigger::CanExecuteUserTrigger { + trigger_id: trigger_id.clone(), + }; if can_execute_trigger_token.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't execute trigger owned by another account"); @@ -1169,13 +1168,14 @@ pub mod permission_token { use super::*; macro_rules! impl_validate { - ($executor:ident, $authority:ident, $self:ident, $method:ident) => { - let token = $self.object; + ($executor:ident, $authority:ident, $isi:ident, $method:ident) => { + // TODO: https://github.com/hyperledger/iroha/issues/4082 + let token = $isi.object().clone(); macro_rules! visit_internal { ($token:ident) => { if is_genesis($executor) { - pass!($executor); + execute!($executor, $isi); } if let Err(error) = permission::ValidateGrantRevoke::$method( &$token, @@ -1185,7 +1185,7 @@ pub mod permission_token { deny!($executor, error); } - pass!($executor); + execute!($executor, $isi); }; } @@ -1201,7 +1201,7 @@ pub mod permission_token { pub fn visit_grant_account_permission( executor: &mut V, authority: &AccountId, - isi: Grant, + isi: &Grant, ) { impl_validate!(executor, authority, isi, validate_grant); } @@ -1209,7 +1209,7 @@ pub mod permission_token { pub fn visit_revoke_account_permission( executor: &mut V, authority: &AccountId, - isi: Revoke, + isi: &Revoke, ) { impl_validate!(executor, authority, isi, validate_revoke); } @@ -1219,22 +1219,38 @@ pub mod executor { use super::*; #[allow(clippy::needless_pass_by_value)] - pub fn visit_upgrade_executor( + pub fn visit_upgrade( executor: &mut V, authority: &AccountId, - _isi: Upgrade, + isi: &Upgrade, ) { if is_genesis(executor) { - pass!(executor); + execute!(executor, isi); } if tokens::executor::CanUpgradeExecutor.is_owned_by(authority) { - pass!(executor); + execute!(executor, isi); } deny!(executor, "Can't upgrade executor"); } } +pub mod log { + use super::*; + + pub fn visit_log(executor: &mut V, _authority: &AccountId, isi: &Log) { + execute!(executor, isi) + } +} + +pub mod fail { + use super::*; + + pub fn visit_fail(executor: &mut V, _authority: &AccountId, isi: &Fail) { + execute!(executor, isi) + } +} + fn is_genesis(executor: &V) -> bool { executor.block_height() == 0 } diff --git a/smart_contract/executor/src/lib.rs b/smart_contract/executor/src/lib.rs index 8b9a7403a52..ef953f78f14 100644 --- a/smart_contract/executor/src/lib.rs +++ b/smart_contract/executor/src/lib.rs @@ -49,7 +49,7 @@ pub fn get_validate_transaction_payload() -> payloads::Validate payloads::Validate { +pub fn get_validate_instruction_payload() -> 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()) } } @@ -131,20 +131,23 @@ mod host { } } -/// Shortcut for `return Ok(())`. +/// Execute instruction if verdict is [`Ok`], deny if execution failed and return. +/// +/// Convention is that you have no checks left if you decided to execute instruction. #[macro_export] -macro_rules! pass { - ($executor:ident) => {{ - #[cfg(debug_assertions)] - if let Err(_error) = $executor.verdict() { - unreachable!("Executor already denied"); +macro_rules! execute { + ($executor:ident, $isi:ident) => {{ + if $executor.verdict().is_ok() { + if let Err(err) = $isi.execute() { + $executor.deny(err); + } } return; }}; } -/// Shortcut for `return Err(ValidationFail)`. +/// Shortcut for setting verdict to [`Err`] and return. /// /// Supports [`format!`](alloc::fmt::format) syntax as well as any expression returning [`String`](alloc::string::String). #[macro_export] @@ -219,10 +222,9 @@ pub mod prelude { pub use alloc::vec::Vec; pub use iroha_executor_derive::{ - entrypoint, Constructor, ExpressionEvaluator, Token, Validate, ValidateEntrypoints, - ValidateGrantRevoke, Visit, + entrypoint, Constructor, Token, Validate, ValidateEntrypoints, ValidateGrantRevoke, Visit, }; - pub use iroha_smart_contract::{prelude::*, Context}; + pub use iroha_smart_contract::prelude::*; pub use super::{ data_model::{ @@ -230,6 +232,6 @@ pub mod prelude { visit::Visit, ValidationFail, }, - deny, pass, PermissionTokenSchema, Validate, + deny, execute, PermissionTokenSchema, Validate, }; } diff --git a/smart_contract/src/lib.rs b/smart_contract/src/lib.rs index 45232f9cdfb..2bdd93706db 100644 --- a/smart_contract/src/lib.rs +++ b/smart_contract/src/lib.rs @@ -4,14 +4,14 @@ extern crate alloc; -use alloc::{boxed::Box, collections::BTreeMap, vec::Vec}; +use alloc::{boxed::Box, vec::Vec}; #[cfg(not(test))] use data_model::smart_contract::payloads; use data_model::{ isi::Instruction, prelude::*, - query::{cursor::ForwardCursor, sorting::Sorting, Pagination, Query, QueryBox}, + query::{cursor::ForwardCursor, sorting::Sorting, Pagination, Query}, smart_contract::SmartContractQueryRequest, BatchedResponse, }; @@ -88,7 +88,7 @@ impl ExecuteOnHost for I { use tests::_iroha_smart_contract_execute_instruction_mock as host_execute_instruction; // TODO: Redundant conversion into `InstructionExpr` - let isi_box: InstructionExpr = self.clone().into(); + let isi_box: InstructionBox = self.clone().into(); // Safety: `host_execute_instruction` doesn't take ownership of it's pointer parameter unsafe { decode_with_length_prefix_from_raw(encode_and_execute( @@ -374,52 +374,6 @@ pub enum QueryOutputCursorError { #[derive(Debug, Clone, Copy)] pub struct Host; -impl iroha_data_model::evaluate::ExpressionEvaluator for Host { - fn evaluate( - &self, - expression: &E, - ) -> Result { - expression.evaluate(&Context::new()) - } -} - -/// Context of expression evaluation -#[derive(Clone, Default)] -#[repr(transparent)] -pub struct Context { - values: BTreeMap, -} - -impl Context { - /// Create new [`Self`] - pub fn new() -> Self { - Self { - values: BTreeMap::new(), - } - } -} - -impl iroha_data_model::evaluate::Context for Context { - fn query(&self, query: &QueryBox) -> Result { - let value_cursor = query.clone().execute()?; - match value_cursor.collect() { - Ok(value) => Ok(value), - Err(QueryOutputCursorError::Validation(err)) => Err(err), - Err(QueryOutputCursorError::Conversion(err)) => { - panic!("Conversion error during collecting query result: {err:?}") - } - } - } - - fn get(&self, name: &Name) -> Option<&Value> { - self.values.get(name) - } - - fn update(&mut self, other: impl IntoIterator) { - self.values.extend(other) - } -} - /// Get payload for smart contract `main()` entrypoint. #[cfg(not(test))] pub fn get_smart_contract_payload() -> payloads::SmartContract { @@ -481,11 +435,10 @@ mod tests { cursor: ForwardCursor::new(None, None), }); const ISI_RESULT: Result<(), ValidationFail> = Ok(()); - const EXPRESSION_RESULT: NumericValue = NumericValue::U32(5_u32); - fn get_test_instruction() -> InstructionExpr { + fn get_test_instruction() -> InstructionBox { let new_account_id = "mad_hatter@wonderland".parse().expect("Valid"); - let register_isi = RegisterExpr::new(Account::new(new_account_id, [])); + let register_isi = Register::account(Account::new(new_account_id, [])); register_isi.into() } @@ -495,17 +448,13 @@ mod tests { FindAssetQuantityById::new(asset_id).into() } - fn get_test_expression() -> EvaluatesTo { - Add::new(2_u32, 3_u32).into() - } - #[no_mangle] pub unsafe extern "C" fn _iroha_smart_contract_execute_instruction_mock( ptr: *const u8, len: usize, ) -> *const u8 { let bytes = slice::from_raw_parts(ptr, len); - let instruction = InstructionExpr::decode_all(&mut &*bytes); + let instruction = InstructionBox::decode_all(&mut &*bytes); assert_eq!(get_test_instruction(), instruction.unwrap()); ManuallyDrop::new(encode_with_length_prefix(&ISI_RESULT)).as_ptr() @@ -538,12 +487,4 @@ mod tests { fn execute_query() { assert_eq!(get_test_query().execute(), QUERY_RESULT); } - - #[webassembly_test] - fn evaluate_expression() { - assert_eq!( - get_test_expression().evaluate(&Context::new()), - Ok(EXPRESSION_RESULT) - ); - } } diff --git a/smart_contract/utils/src/lib.rs b/smart_contract/utils/src/lib.rs index ec9f70a242e..5e0919b095a 100644 --- a/smart_contract/utils/src/lib.rs +++ b/smart_contract/utils/src/lib.rs @@ -7,7 +7,7 @@ extern crate alloc; use alloc::{boxed::Box, format, vec::Vec}; use core::ops::RangeFrom; -use parity_scale_codec::{DecodeAll, Encode}; +pub use parity_scale_codec::{DecodeAll, Encode}; pub mod debug; pub mod log; diff --git a/tools/kagami/src/genesis.rs b/tools/kagami/src/genesis.rs index 48caeb74337..6036e4723ab 100644 --- a/tools/kagami/src/genesis.rs +++ b/tools/kagami/src/genesis.rs @@ -4,11 +4,9 @@ use clap::{ArgGroup, Parser, Subcommand}; use iroha_config::{sumeragi::default::*, wasm::default::*, wsv::default::*}; use iroha_data_model::{ asset::AssetValueType, - isi::{MintExpr, RegisterExpr}, metadata::Limits, parameter::{default::*, ParametersBuilder}, prelude::AssetId, - IdBox, }; use iroha_genesis::{ExecutorMode, ExecutorPath, RawGenesisBlock, RawGenesisBlockBuilder}; use serde_json::json; @@ -146,22 +144,19 @@ pub fn generate_default(executor: ExecutorMode) -> color_eyre::Result color_eyre::Result::new( - vec![MintExpr::new(1_u32, rose_id)], + vec![Mint::asset_quantity(1_u32, rose_id)], Repeats::Indefinitely, account_id, FilterBox::Data(DataEventFilter::BySome(DataEntityFilter::ByAccount(