diff --git a/client/benches/tps/utils.rs b/client/benches/tps/utils.rs index 0c376b9347f..7ad85776692 100644 --- a/client/benches/tps/utils.rs +++ b/client/benches/tps/utils.rs @@ -6,10 +6,10 @@ use iroha::{ crypto::KeyPair, data_model::{ events::pipeline::{BlockEventFilter, BlockStatus}, + param::BlockParameter, prelude::*, }, }; -use iroha_data_model::param::BlockLimits; use nonzero_ext::nonzero; use serde::Deserialize; use test_network::*; @@ -22,7 +22,7 @@ pub struct Config { pub peers: u32, /// Interval in microseconds between transactions to reduce load pub interval_us_per_tx: u64, - pub block_limits: BlockLimits, + pub block_limits: BlockParameter, pub blocks: u32, pub sample_size: u32, pub genesis_max_retries: u32, @@ -51,7 +51,7 @@ impl Config { let clients = network.clients(); wait_for_genesis_committed_with_max_retries(&clients, 0, self.genesis_max_retries); - client.submit_blocking(SetParameter::new(Parameter::BlockLimits(self.block_limits)))?; + client.submit_blocking(SetParameter::new(Parameter::Block(self.block_limits)))?; let unit_names = (UnitName::MIN..).take(self.peers as usize); let units = clients diff --git a/client/src/config/user.rs b/client/src/config/user.rs index 000ab2a2dd8..71bf826d4d3 100644 --- a/client/src/config/user.rs +++ b/client/src/config/user.rs @@ -6,11 +6,13 @@ use iroha_config_base::{ util::{DurationMs, Emitter, EmitterResultExt}, ReadConfig, WithOrigin, }; -use iroha_crypto::{KeyPair, PrivateKey, PublicKey}; -use iroha_data_model::prelude::{AccountId, ChainId, DomainId}; use url::Url; -use crate::config::BasicAuth; +use crate::{ + config::BasicAuth, + crypto::{KeyPair, PrivateKey, PublicKey}, + data_model::prelude::{AccountId, ChainId, DomainId}, +}; /// Root of the user configuration #[derive(Clone, Debug, ReadConfig)] diff --git a/client/tests/integration/add_domain.rs b/client/tests/integration/add_domain.rs deleted file mode 100644 index edb3f4810c1..00000000000 --- a/client/tests/integration/add_domain.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::thread; - -use eyre::Result; -use iroha::{client, data_model::prelude::*}; -use iroha_config::parameters::actual::Root as Config; -use test_network::*; - -#[test] -#[ignore = "should be implemented with custom parameters"] -fn client_add_domain_with_name_length_more_than_limit_should_not_commit_transaction() -> Result<()> -{ - let (_rt, _peer, test_client) = ::new().with_port(10_500).start_with_runtime(); - wait_for_genesis_committed(&vec![test_client.clone()], 0); - let pipeline_time = Config::pipeline_time(); - - // Given - - let normal_domain_id: DomainId = "sora".parse()?; - 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 = Register::domain(Domain::new(too_long_domain_name.clone())); - test_client.submit(create_domain)?; - - thread::sleep(pipeline_time * 2); - - assert!(test_client - .request(client::domain::by_id(normal_domain_id)) - .is_ok()); - assert!(test_client - .request(client::domain::by_id(too_long_domain_name)) - .is_err()); - - Ok(()) -} diff --git a/client/tests/integration/asset_propagation.rs b/client/tests/integration/asset_propagation.rs index 54f4df0034f..df38e50fbca 100644 --- a/client/tests/integration/asset_propagation.rs +++ b/client/tests/integration/asset_propagation.rs @@ -1,12 +1,12 @@ -use std::{num::NonZeroU64, str::FromStr as _, thread}; +use std::{str::FromStr as _, thread}; use eyre::Result; use iroha::{ client::{self, QueryResult}, - data_model::prelude::*, + data_model::{param::BlockParameter, prelude::*}, }; use iroha_config::parameters::actual::Root as Config; -use iroha_data_model::param::BlockLimits; +use nonzero_ext::nonzero; use test_network::*; use test_samples::gen_account_in; @@ -20,9 +20,9 @@ fn client_add_asset_quantity_to_existing_asset_should_increase_asset_amount_on_a wait_for_genesis_committed(&network.clients(), 0); let pipeline_time = Config::pipeline_time(); - client.submit_blocking(SetParameter::new(Parameter::BlockLimits(BlockLimits { - max_transactions: NonZeroU64::new(1).unwrap(), - })))?; + client.submit_blocking(SetParameter::new(Parameter::Block( + BlockParameter::MaxTransactions(nonzero!(1_u64)), + )))?; let create_domain: InstructionBox = Register::domain(Domain::new(DomainId::from_str("domain")?)).into(); diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index 5c3db17605f..e1c8d12b987 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -161,9 +161,9 @@ fn transaction_execution_should_produce_events( iroha_logger::info!("Event: {:?}", event); assert!(matches!(event, DataEvent::Domain(_))); if let DataEvent::Domain(domain_event) = event { - assert!(matches!(domain_event, DomainEvent::Create(_))); + assert!(matches!(domain_event, DomainEvent::Created(_))); - if let DomainEvent::Create(created_domain) = domain_event { + if let DomainEvent::Created(created_domain) = domain_event { let domain_id = DomainId::new(i.to_string().parse().expect("Valid")); assert_eq!(domain_id, *created_domain.id()); } @@ -226,9 +226,9 @@ fn produce_multiple_events() -> Result<()> { let event: DataEvent = event_receiver.recv()??.try_into()?; assert!(matches!(event, DataEvent::Role(_))); if let DataEvent::Role(role_event) = event { - assert!(matches!(role_event, RoleEvent::Create(_))); + assert!(matches!(role_event, RoleEvent::Created(_))); - if let RoleEvent::Create(created_role) = role_event { + if let RoleEvent::Created(created_role) = role_event { assert_eq!(created_role.id(), role.id()); assert!(created_role .permissions() @@ -237,43 +237,43 @@ fn produce_multiple_events() -> Result<()> { } let expected_domain_events: Vec = [ - DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdd( + DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( AccountPermissionChanged { account: bob_id.clone(), permission: token_1.id.clone(), }, ))), - DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdd( + DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( AccountPermissionChanged { account: bob_id.clone(), permission: token_2.id.clone(), }, ))), - DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleGrant( + DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleGranted( AccountRoleChanged { account: bob_id.clone(), role: role_id.clone(), }, ))), - DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemove( + DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( AccountPermissionChanged { account: bob_id.clone(), permission: token_1.id, }, ))), - DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemove( + DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( AccountPermissionChanged { account: bob_id.clone(), permission: token_2.id, }, ))), - DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleRevoke( + DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleRevoked( AccountRoleChanged { account: bob_id, role: role_id.clone(), }, ))), - DataEvent::Role(RoleEvent::Delete(role_id)), + DataEvent::Role(RoleEvent::Deleted(role_id)), ] .into_iter() .map(Into::into) diff --git a/client/tests/integration/events/pipeline.rs b/client/tests/integration/events/pipeline.rs index d3c87533f0b..cc89ddf8476 100644 --- a/client/tests/integration/events/pipeline.rs +++ b/client/tests/integration/events/pipeline.rs @@ -1,7 +1,4 @@ -use std::{ - num::NonZeroU64, - thread::{self, JoinHandle}, -}; +use std::thread::{self, JoinHandle}; use eyre::Result; use iroha::{ @@ -11,13 +8,14 @@ use iroha::{ BlockEvent, BlockEventFilter, BlockStatus, TransactionEventFilter, TransactionStatus, }, isi::error::InstructionExecutionError, + param::BlockParameter, prelude::*, transaction::error::TransactionRejectionReason, ValidationFail, }, }; use iroha_config::parameters::actual::Root as Config; -use iroha_data_model::param::BlockLimits; +use nonzero_ext::nonzero; use test_network::*; // Needed to re-enable ignored tests. @@ -56,9 +54,9 @@ fn test_with_instruction_and_status_and_port( wait_for_genesis_committed(&clients, 0); let pipeline_time = Config::pipeline_time(); - client.submit_blocking(SetParameter::new(Parameter::BlockLimits(BlockLimits { - max_transactions: NonZeroU64::new(1).unwrap(), - })))?; + client.submit_blocking(SetParameter::new(Parameter::Block( + BlockParameter::MaxTransactions(nonzero!(1_u64)), + )))?; // Given let submitter = client; diff --git a/client/tests/integration/extra_functional/multiple_blocks_created.rs b/client/tests/integration/extra_functional/multiple_blocks_created.rs index 7646e457f54..484723300ee 100644 --- a/client/tests/integration/extra_functional/multiple_blocks_created.rs +++ b/client/tests/integration/extra_functional/multiple_blocks_created.rs @@ -1,12 +1,12 @@ -use std::{num::NonZeroU64, thread}; +use std::thread; use eyre::Result; use iroha::{ client::{self, Client, QueryResult}, - data_model::prelude::*, + data_model::{param::BlockParameter, prelude::*}, }; use iroha_config::parameters::actual::Root as Config; -use iroha_data_model::param::BlockLimits; +use nonzero_ext::nonzero; use test_network::*; use test_samples::gen_account_in; @@ -20,9 +20,9 @@ fn long_multiple_blocks_created() -> Result<()> { wait_for_genesis_committed(&network.clients(), 0); let pipeline_time = Config::pipeline_time(); - client.submit_blocking(SetParameter::new(Parameter::BlockLimits(BlockLimits { - max_transactions: NonZeroU64::new(1).unwrap(), - })))?; + client.submit_blocking(SetParameter::new(Parameter::Block( + BlockParameter::MaxTransactions(nonzero!(1_u64)), + )))?; let create_domain: InstructionBox = Register::domain(Domain::new("domain".parse()?)).into(); let (account_id, _account_keypair) = gen_account_in("domain"); diff --git a/client/tests/integration/extra_functional/normal.rs b/client/tests/integration/extra_functional/normal.rs index 6c94ea2a02f..ea474a54d71 100644 --- a/client/tests/integration/extra_functional/normal.rs +++ b/client/tests/integration/extra_functional/normal.rs @@ -1,8 +1,9 @@ -use std::num::NonZeroU64; - -use iroha::client::{self, Client}; +use iroha::{ + client::{self, Client}, + data_model::{asset::AssetDefinitionId, param::BlockParameter, prelude::*}, +}; use iroha_config::parameters::actual::Root as Config; -use iroha_data_model::{asset::AssetDefinitionId, param::BlockLimits, prelude::*}; +use nonzero_ext::nonzero; use test_network::*; use tokio::runtime::Runtime; @@ -20,9 +21,9 @@ fn tranasctions_should_be_applied() { }); wait_for_genesis_committed(&network.clients(), 0); iroha - .submit_blocking(SetParameter::new(Parameter::BlockLimits(BlockLimits { - max_transactions: NonZeroU64::new(1).unwrap(), - }))) + .submit_blocking(SetParameter::new(Parameter::Block( + BlockParameter::MaxTransactions(nonzero!(1_u64)), + ))) .unwrap(); let domain_id = "and".parse::().unwrap(); diff --git a/client/tests/integration/extra_functional/unregister_peer.rs b/client/tests/integration/extra_functional/unregister_peer.rs index 0b3719a849d..07f6f6e7c3c 100644 --- a/client/tests/integration/extra_functional/unregister_peer.rs +++ b/client/tests/integration/extra_functional/unregister_peer.rs @@ -1,12 +1,12 @@ -use std::{num::NonZeroU64, thread}; +use std::thread; use eyre::Result; use iroha::{ client::{self, QueryResult}, - data_model::prelude::*, + data_model::{param::BlockParameter, prelude::*}, }; use iroha_config::parameters::actual::Root as Config; -use iroha_data_model::param::BlockLimits; +use nonzero_ext::nonzero; use test_network::*; use test_samples::gen_account_in; @@ -116,9 +116,9 @@ fn init() -> Result<( let pipeline_time = Config::pipeline_time(); iroha_logger::info!("Started"); - let set_max_txns_in_block = SetParameter::new(Parameter::BlockLimits(BlockLimits { - max_transactions: NonZeroU64::new(1).unwrap(), - })); + let set_max_txns_in_block = SetParameter::new(Parameter::Block( + BlockParameter::MaxTransactions(nonzero!(1_u64)), + )); let create_domain = Register::domain(Domain::new("domain".parse()?)); let (account_id, _account_keypair) = gen_account_in("domain"); diff --git a/client/tests/integration/mod.rs b/client/tests/integration/mod.rs index 37299969665..13b8bd2528c 100644 --- a/client/tests/integration/mod.rs +++ b/client/tests/integration/mod.rs @@ -1,4 +1,3 @@ -mod add_domain; mod asset; mod asset_propagation; mod domain_owner_permissions; diff --git a/client/tests/integration/set_parameter.rs b/client/tests/integration/set_parameter.rs index 20615c4d3c6..a863966fa76 100644 --- a/client/tests/integration/set_parameter.rs +++ b/client/tests/integration/set_parameter.rs @@ -3,9 +3,11 @@ use std::time::Duration; use eyre::Result; use iroha::{ client, - data_model::{param::Parameter, prelude::*}, + data_model::{ + param::{Parameter, Parameters, SumeragiParameter, SumeragiParameters}, + prelude::*, + }, }; -use iroha_data_model::param::Parameters; use test_network::*; #[test] @@ -14,15 +16,21 @@ fn can_change_parameter_value() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let old_params: Parameters = test_client.request(client::parameter::all())?; - assert_eq!(old_params.block_time, Parameters::default().block_time); + assert_eq!( + old_params.sumeragi().block_time(), + SumeragiParameters::default().block_time() + ); - let block_time = Duration::from_millis(40_000); - let parameter = Parameter::BlockTime(block_time); + let block_time = 40_000; + let parameter = Parameter::Sumeragi(SumeragiParameter::BlockTimeMs(block_time)); let set_param_isi = SetParameter::new(parameter); test_client.submit_blocking(set_param_isi)?; - let new_params = test_client.request(client::parameter::all())?; - assert_eq!(new_params.block_time, block_time); + let sumeragi_params = test_client.request(client::parameter::all())?.sumeragi; + assert_eq!( + sumeragi_params.block_time(), + Duration::from_millis(block_time) + ); Ok(()) } diff --git a/client/tests/integration/smartcontracts/Cargo.toml b/client/tests/integration/smartcontracts/Cargo.toml index 5004748a0c0..e6fb9bcaf40 100644 --- a/client/tests/integration/smartcontracts/Cargo.toml +++ b/client/tests/integration/smartcontracts/Cargo.toml @@ -13,6 +13,7 @@ members = [ "mint_rose_trigger", "executor_with_admin", "executor_with_custom_permission", + "executor_with_custom_parameter", "executor_remove_permission", "executor_with_migration_fail", "executor_custom_instructions_simple", diff --git a/client/tests/integration/smartcontracts/executor_custom_instructions_complex/src/lib.rs b/client/tests/integration/smartcontracts/executor_custom_instructions_complex/src/lib.rs index 13cf48b8fab..d8db869f703 100644 --- a/client/tests/integration/smartcontracts/executor_custom_instructions_complex/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_custom_instructions_complex/src/lib.rs @@ -77,7 +77,7 @@ impl executor_custom_data_model::complex::Context for Context { } #[entrypoint] -pub fn migrate(_block_height: u64) -> MigrationResult { +fn migrate(_block_height: u64) -> MigrationResult { DataModelBuilder::with_default_permissions() .with_custom_instruction::() .build_and_set(); diff --git a/client/tests/integration/smartcontracts/executor_custom_instructions_simple/src/lib.rs b/client/tests/integration/smartcontracts/executor_custom_instructions_simple/src/lib.rs index a10b0ea9fc6..0ae6a293b03 100644 --- a/client/tests/integration/smartcontracts/executor_custom_instructions_simple/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_custom_instructions_simple/src/lib.rs @@ -55,7 +55,7 @@ fn execute_mint_asset_for_all_accounts(isi: MintAssetForAllAccounts) -> Result<( } #[entrypoint] -pub fn migrate(_block_height: u64) -> MigrationResult { +fn migrate(_block_height: u64) -> MigrationResult { DataModelBuilder::with_default_permissions() .with_custom_instruction::() .build_and_set(); diff --git a/client/tests/integration/smartcontracts/executor_remove_permission/src/lib.rs b/client/tests/integration/smartcontracts/executor_remove_permission/src/lib.rs index a88a34fd123..83583d2cec0 100644 --- a/client/tests/integration/smartcontracts/executor_remove_permission/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_remove_permission/src/lib.rs @@ -23,7 +23,7 @@ struct Executor { } #[entrypoint] -pub fn migrate(_block_height: u64) -> MigrationResult { +fn migrate(_block_height: u64) -> MigrationResult { // Note that actually migration will reset token schema to default (minus `CanUnregisterDomain`) // So any added custom permission tokens will be also removed DataModelBuilder::with_default_permissions() 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 f34d4f2eb57..0f6b152a16b 100644 --- a/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs @@ -32,6 +32,6 @@ fn visit_instruction(executor: &mut Executor, authority: &AccountId, isi: &Instr } #[entrypoint] -pub fn migrate(_block_height: u64) -> MigrationResult { +fn migrate(_block_height: u64) -> MigrationResult { Ok(()) } diff --git a/client/tests/integration/smartcontracts/executor_with_custom_parameter/Cargo.toml b/client/tests/integration/smartcontracts/executor_with_custom_parameter/Cargo.toml new file mode 100644 index 00000000000..9287d2caff4 --- /dev/null +++ b/client/tests/integration/smartcontracts/executor_with_custom_parameter/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "executor_with_custom_parameter" + +edition.workspace = true +version.workspace = true +authors.workspace = true + +license.workspace = true + +[lib] +crate-type = ['cdylib'] + +[dependencies] +iroha_executor.workspace = true +iroha_schema.workspace = true + +parity-scale-codec.workspace = true +anyhow.workspace = true +serde_json.workspace = true +serde.workspace = true + +panic-halt.workspace = true +lol_alloc.workspace = true +getrandom.workspace = true diff --git a/client/tests/integration/smartcontracts/executor_with_custom_parameter/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_custom_parameter/src/lib.rs new file mode 100644 index 00000000000..4e646c2b341 --- /dev/null +++ b/client/tests/integration/smartcontracts/executor_with_custom_parameter/src/lib.rs @@ -0,0 +1,68 @@ +//! Runtime Executor which allows domains whose id satisfies the length limit +#![no_std] + +extern crate alloc; +#[cfg(not(test))] +extern crate panic_halt; + +use iroha_executor::{prelude::*, DataModelBuilder}; +use lol_alloc::{FreeListAllocator, LockedAllocator}; + +#[global_allocator] +static ALLOC: LockedAllocator = LockedAllocator::new(FreeListAllocator::new()); + +getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); + +use alloc::format; + +mod parameter { + //! Module with custom parameters + use alloc::string::String; + + use iroha_schema::IntoSchema; + use parity_scale_codec::{Decode, Encode}; + use serde::{Deserialize, Serialize}; + + use super::*; + + /// Parameter that controls domain limits + #[derive(PartialEq, Eq, Parameter, Decode, Encode, Serialize, Deserialize, IntoSchema)] + pub struct DomainLimits { + /// Length of domain id in bytes + pub id_len: u32, + } +} + +#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +#[visit(custom(visit_register_domain))] +struct Executor { + verdict: Result, + block_height: u64, +} + +fn visit_register_domain(executor: &mut Executor, _authority: &AccountId, isi: &Register) { + let parameters = FindAllParameters.execute().unwrap().into_inner(); + + let domain_limits_json = parameters + .custom() + .get(¶meter::DomainLimits::id()) + .unwrap(); + + let domain_limits: parameter::DomainLimits = serde_json::from_str(domain_limits_json.as_ref()) + .expect("INTERNAL BUG: Failed to deserialize json as `DomainLimits`"); + + if isi.object().id().name().as_ref().len() < domain_limits.id_len as usize { + deny!(executor, "Domain id exceeds the limit"); + } + + execute!(executor, isi); +} + +#[entrypoint] +fn migrate(_block_height: u64) -> MigrationResult { + DataModelBuilder::with_default_permissions() + .add_parameter::() + .build_and_set(); + + Ok(()) +} 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 0aaa7907707..98d517d084c 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 @@ -24,7 +24,7 @@ struct Executor { } #[entrypoint] -pub fn migrate(_block_height: u64) -> MigrationResult { +fn migrate(_block_height: u64) -> MigrationResult { // Performing side-effects to check in the test that it won't be applied after failure // Registering a new domain (using ISI) diff --git a/client/tests/integration/sorting.rs b/client/tests/integration/sorting.rs index 7f5fec19ec8..490a371ebef 100644 --- a/client/tests/integration/sorting.rs +++ b/client/tests/integration/sorting.rs @@ -52,9 +52,7 @@ fn correct_pagination_assets_after_creating_new_one() { AssetDefinitionId::from_str(&format!("xor{i}#wonderland")).expect("Valid"); let asset_definition = AssetDefinition::store(asset_definition_id.clone()); let mut asset_metadata = Metadata::default(); - asset_metadata - .insert(sort_by_metadata_key.clone(), i as u32) - .expect("Valid"); + asset_metadata.insert(sort_by_metadata_key.clone(), i as u32); let asset = Asset::new( AssetId::new(asset_definition_id, account_id.clone()), AssetValue::Store(asset_metadata), @@ -143,9 +141,7 @@ fn correct_sorting_of_entities() { let asset_definition_id = AssetDefinitionId::from_str(&format!("xor_{i}#wonderland")).expect("Valid"); let mut asset_metadata = Metadata::default(); - asset_metadata - .insert(sort_by_metadata_key.clone(), n - i - 1) - .expect("Valid"); + asset_metadata.insert(sort_by_metadata_key.clone(), n - i - 1); let asset_definition = AssetDefinition::numeric(asset_definition_id.clone()) .with_metadata(asset_metadata.clone()); @@ -200,9 +196,7 @@ fn correct_sorting_of_entities() { for i in 0..n { let account_id = AccountId::new(domain_id.clone(), public_keys[i as usize].clone()); let mut account_metadata = Metadata::default(); - account_metadata - .insert(sort_by_metadata_key.clone(), n - i - 1) - .expect("Valid"); + account_metadata.insert(sort_by_metadata_key.clone(), n - i - 1); let account = Account::new(account_id.clone()).with_metadata(account_metadata.clone()); accounts.push(account_id); @@ -244,9 +238,7 @@ fn correct_sorting_of_entities() { for i in 0..n { let domain_id = DomainId::from_str(&format!("neverland{i}")).expect("Valid"); let mut domain_metadata = Metadata::default(); - domain_metadata - .insert(sort_by_metadata_key.clone(), n - i - 1) - .expect("Valid"); + domain_metadata.insert(sort_by_metadata_key.clone(), n - i - 1); let domain = Domain::new(domain_id.clone()).with_metadata(domain_metadata.clone()); domains.push(domain_id); @@ -287,9 +279,7 @@ fn correct_sorting_of_entities() { for (idx, val) in input { let domain_id = DomainId::from_str(&format!("neverland_{idx}")).expect("Valid"); let mut domain_metadata = Metadata::default(); - domain_metadata - .insert(sort_by_metadata_key.clone(), val) - .expect("Valid"); + domain_metadata.insert(sort_by_metadata_key.clone(), val); let domain = Domain::new(domain_id.clone()).with_metadata(domain_metadata.clone()); domains.push(domain_id); @@ -357,9 +347,7 @@ fn sort_only_elements_which_have_sorting_key() -> Result<()> { account } else { let mut account_metadata = Metadata::default(); - account_metadata - .insert(sort_by_metadata_key.clone(), n - i - 1) - .expect("Valid"); + account_metadata.insert(sort_by_metadata_key.clone(), n - i - 1); let account = Account::new(account_id.clone()).with_metadata(account_metadata); accounts_a.push(account_id); account diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index bfbc48fd188..06ce5a2400e 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -32,7 +32,7 @@ fn must_execute_both_triggers() -> Result<()> { [instruction.clone()], Repeats::Indefinitely, account_id.clone(), - AccountEventFilter::new().for_events(AccountEventSet::Create), + AccountEventFilter::new().for_events(AccountEventSet::Created), ), )); test_client.submit_blocking(register_trigger)?; @@ -43,7 +43,7 @@ fn must_execute_both_triggers() -> Result<()> { [instruction], Repeats::Indefinitely, account_id, - DomainEventFilter::new().for_events(DomainEventSet::Create), + DomainEventFilter::new().for_events(DomainEventSet::Created), ), )); test_client.submit_blocking(register_trigger)?; diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index 190d507ff5d..0221d770139 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -23,7 +23,7 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { vec![instruction], Repeats::Indefinitely, account_id, - AssetDefinitionEventFilter::new().for_events(AssetDefinitionEventSet::Create), + AssetDefinitionEventFilter::new().for_events(AssetDefinitionEventSet::Created), ), )); test_client.submit(register_trigger)?; diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index 075a0f1bd7b..a7a3b4d70c5 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -6,6 +6,7 @@ use iroha::{ data_model::{ asset::AssetId, events::pipeline::{BlockEventFilter, BlockStatus}, + param::SumeragiParameters, prelude::*, transaction::WasmSmartContract, Level, @@ -17,13 +18,13 @@ use test_samples::{gen_account_in, ALICE_ID}; /// Default estimation of consensus duration. pub fn default_consensus_estimation() -> Duration { - let default_parameters = iroha_data_model::param::Parameters::default(); + let default_parameters = SumeragiParameters::default(); default_parameters - .block_time + .block_time() .checked_add( default_parameters - .commit_time + .commit_time() .checked_div(2) .map_or_else(|| unreachable!(), |x| x), ) diff --git a/client/tests/integration/upgrade.rs b/client/tests/integration/upgrade.rs index 9dac5fb46ef..7a66019aab6 100644 --- a/client/tests/integration/upgrade.rs +++ b/client/tests/integration/upgrade.rs @@ -6,6 +6,7 @@ use iroha::{ client::{self, Client, QueryResult}, data_model::prelude::*, }; +use iroha_data_model::param::{CustomParameter, Parameter}; use iroha_logger::info; use serde_json::json; use test_network::*; @@ -338,7 +339,7 @@ fn migration_should_cause_upgrade_event() { .await .unwrap(); while let Some(event) = stream.try_next().await.unwrap() { - if let EventBox::Data(DataEvent::Executor(ExecutorEvent::Upgrade(ExecutorUpgrade { + if let EventBox::Data(DataEvent::Executor(ExecutorEvent::Upgraded(ExecutorUpgrade { new_data_model, }))) = event { @@ -364,6 +365,35 @@ fn migration_should_cause_upgrade_event() { assert!(!data_model.permissions.is_empty()); } +#[test] +fn define_custom_parameter() -> Result<()> { + let (_rt, _peer, client) = ::new().with_port(10_996).start_with_runtime(); + wait_for_genesis_committed(&vec![client.clone()], 0); + + let long_domain_name = "0".repeat(2_usize.pow(10)).parse::()?; + let create_domain = Register::domain(Domain::new(long_domain_name)); + client.submit_blocking(create_domain)?; + + upgrade_executor( + &client, + "tests/integration/smartcontracts/executor_with_custom_parameter", + ) + .unwrap(); + + let too_long_domain_name = "1".repeat(2_usize.pow(10)).parse::()?; + let create_domain = Register::domain(Domain::new(too_long_domain_name)); + let _err = client.submit_blocking(create_domain.clone()).unwrap_err(); + + let parameter = Parameter::Custom(CustomParameter::new( + "DomainLimits".parse()?, + json!({ "id_len": 2_usize.pow(5) }), + )); + let set_param_isi: InstructionBox = SetParameter::new(parameter).into(); + client.submit_all_blocking([set_param_isi, create_domain.into()])?; + + Ok(()) +} + fn upgrade_executor(client: &Client, executor: impl AsRef) -> Result<()> { info!("Building executor"); diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index 77897205ba0..e5874248ba9 100644 Binary files a/configs/swarm/executor.wasm and b/configs/swarm/executor.wasm differ diff --git a/core/benches/blocks/common.rs b/core/benches/blocks/common.rs index 12400463122..30625d0dfa0 100644 --- a/core/benches/blocks/common.rs +++ b/core/benches/blocks/common.rs @@ -13,7 +13,7 @@ use iroha_data_model::{ asset::{AssetDefinition, AssetDefinitionId}, domain::Domain, isi::InstructionBox, - param::TransactionLimits, + param::TransactionParameters, prelude::*, ChainId, JsonString, }; @@ -32,7 +32,7 @@ pub fn create_block( let transaction = TransactionBuilder::new(chain_id.clone(), account_id) .with_instructions(instructions) .sign(private_key); - let limits = state.transaction_executor().transaction_limits; + let limits = state.transaction_executor().limits; let (peer_public_key, _) = KeyPair::random().into_parts(); let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), peer_public_key); @@ -186,12 +186,10 @@ pub fn build_state(rt: &tokio::runtime::Handle, account_id: &AccountId) -> State { let mut state_block = state.block(); - state_block.world.parameters.transaction_limits = TransactionLimits::new( - NonZeroU64::new(u64::MAX).unwrap(), - NonZeroU64::new(u64::MAX).unwrap(), - ); - state_block.world.parameters.executor_limits.fuel = NonZeroU64::new(u64::MAX).unwrap(); - state_block.world.parameters.executor_limits.memory = NonZeroU64::new(u64::MAX).unwrap(); + state_block.world.parameters.transaction = + TransactionParameters::new(NonZeroU64::MAX, NonZeroU64::MAX); + state_block.world.parameters.executor.fuel = NonZeroU64::MAX; + state_block.world.parameters.executor.memory = NonZeroU64::MAX; let mut state_transaction = state_block.transaction(); let path_to_executor = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) diff --git a/core/benches/kura.rs b/core/benches/kura.rs index 32904aec6d7..9b5e148a201 100644 --- a/core/benches/kura.rs +++ b/core/benches/kura.rs @@ -14,7 +14,7 @@ use iroha_core::{ sumeragi::network_topology::Topology, }; use iroha_crypto::KeyPair; -use iroha_data_model::{param::TransactionLimits, prelude::*}; +use iroha_data_model::{param::TransactionParameters, prelude::*}; use nonzero_ext::nonzero; use test_samples::gen_account_in; use tokio::{fs, runtime::Runtime}; @@ -30,7 +30,7 @@ async fn measure_block_size_for_n_executors(n_executors: u32) { let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([transfer]) .sign(alice_keypair.private_key()); - let txn_limits = TransactionLimits { + let txn_limits = TransactionParameters { max_instructions: nonzero!(4096_u64), smart_contract_size: nonzero!(1_u64), }; diff --git a/core/benches/validation.rs b/core/benches/validation.rs index c2420d1329d..9c391352d4d 100644 --- a/core/benches/validation.rs +++ b/core/benches/validation.rs @@ -11,7 +11,7 @@ use iroha_core::{ tx::TransactionExecutor, }; use iroha_data_model::{ - account::AccountId, isi::InstructionBox, param::TransactionLimits, prelude::*, + account::AccountId, isi::InstructionBox, param::TransactionParameters, prelude::*, transaction::TransactionBuilder, }; use iroha_primitives::unique_vec::UniqueVec; @@ -24,8 +24,8 @@ static STARTER_KEYPAIR: Lazy = Lazy::new(KeyPair::random); static STARTER_ID: Lazy = Lazy::new(|| AccountId::new(STARTER_DOMAIN.clone(), STARTER_KEYPAIR.public_key().clone())); -const TRANSACTION_LIMITS: TransactionLimits = - TransactionLimits::new(nonzero!(5096_u64), nonzero!(1_u64)); +const TRANSACTION_LIMITS: TransactionParameters = + TransactionParameters::new(nonzero!(4096_u64), nonzero!(1_u64)); fn build_test_transaction(chain_id: ChainId) -> TransactionBuilder { let domain_id: DomainId = "domain".parse().unwrap(); @@ -46,9 +46,9 @@ fn build_test_and_transient_state() -> State { let state = State::new( { let (account_id, _account_keypair) = gen_account_in(&*STARTER_DOMAIN); - let mut domain = Domain::new(STARTER_DOMAIN.clone()).build(&account_id); + let domain = Domain::new(STARTER_DOMAIN.clone()).build(&account_id); let account = Account::new(account_id.clone()).build(&account_id); - World::with([domain], UniqueVec::new()) + World::with([domain], [account], UniqueVec::new()) }, kura, query_handle, diff --git a/core/src/block.rs b/core/src/block.rs index a8023289a6a..87a756d46e5 100644 --- a/core/src/block.rs +++ b/core/src/block.rs @@ -243,7 +243,7 @@ mod pending { state.latest_block_hash(), view_change_index, &transactions, - state.consensus_estimation(), + state.world.parameters().sumeragi.consensus_estimation(), ), transactions, commit_topology: self.0.commit_topology.into_iter().collect(), @@ -535,7 +535,7 @@ mod valid { AcceptedTransaction::accept( value, expected_chain_id, - transaction_executor.transaction_limits, + transaction_executor.limits, ) }?; @@ -1029,7 +1029,7 @@ mod tests { Register::asset_definition(AssetDefinition::numeric(asset_definition_id)); // Making two transactions that have the same instruction - let transaction_limits = state_block.transaction_executor().transaction_limits; + let transaction_limits = state_block.transaction_executor().limits; let tx = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions([create_asset_definition]) .sign(alice_keypair.private_key()); @@ -1085,7 +1085,7 @@ mod tests { Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); // Making two transactions that have the same instruction - let transaction_limits = state_block.transaction_executor().transaction_limits; + let transaction_limits = state_block.transaction_executor().limits; let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([create_asset_definition]) .sign(alice_keypair.private_key()); @@ -1152,7 +1152,7 @@ mod tests { let query_handle = LiveQueryStore::test().start(); let state = State::new(world, kura, query_handle); let mut state_block = state.block(); - let transaction_limits = state_block.transaction_executor().transaction_limits; + let transaction_limits = state_block.transaction_executor().limits; let domain_id = DomainId::from_str("domain").expect("Valid"); let create_domain = Register::domain(Domain::new(domain_id)); diff --git a/core/src/executor.rs b/core/src/executor.rs index 178a3935731..167c634a3f6 100644 --- a/core/src/executor.rs +++ b/core/src/executor.rs @@ -158,7 +158,7 @@ impl Executor { let runtime = wasm::RuntimeBuilder::::new() .with_engine(state_transaction.engine.clone()) // Cloning engine is cheap, see [`wasmtime::Engine`] docs - .with_config(state_transaction.world.parameters().executor_limits) + .with_config(state_transaction.world.parameters().executor) .build()?; runtime.execute_executor_validate_transaction( @@ -194,7 +194,7 @@ impl Executor { let runtime = wasm::RuntimeBuilder::::new() .with_engine(state_transaction.engine.clone()) // Cloning engine is cheap, see [`wasmtime::Engine`] docs - .with_config(state_transaction.world.parameters().executor_limits) + .with_config(state_transaction.world.parameters().executor) .build()?; runtime.execute_executor_validate_instruction( @@ -228,7 +228,7 @@ impl Executor { let runtime = wasm::RuntimeBuilder::>::new() .with_engine(state_ro.engine().clone()) // Cloning engine is cheap, see [`wasmtime::Engine`] docs - .with_config(state_ro.world().parameters().executor_limits) + .with_config(state_ro.world().parameters().executor) .build()?; runtime.execute_executor_validate_query( @@ -263,7 +263,7 @@ impl Executor { let runtime = wasm::RuntimeBuilder::::new() .with_engine(state_transaction.engine.clone()) // Cloning engine is cheap, see [`wasmtime::Engine`] docs - .with_config(state_transaction.world().parameters().executor_limits) + .with_config(state_transaction.world().parameters().executor) .build()?; runtime diff --git a/core/src/gossiper.rs b/core/src/gossiper.rs index 9b6ca31881e..4a08606108e 100644 --- a/core/src/gossiper.rs +++ b/core/src/gossiper.rs @@ -110,7 +110,7 @@ impl TransactionGossiper { let state_view = self.state.view(); for tx in txs { - let transaction_limits = state_view.world().parameters().transaction_limits; + let transaction_limits = state_view.world().parameters().transaction; match AcceptedTransaction::accept(tx, &self.chain_id, transaction_limits) { Ok(tx) => match self.queue.push(tx, &state_view) { diff --git a/core/src/queue.rs b/core/src/queue.rs index 30218035305..a31de537054 100644 --- a/core/src/queue.rs +++ b/core/src/queue.rs @@ -377,7 +377,7 @@ impl Queue { pub mod tests { use std::{str::FromStr, sync::Arc, thread, time::Duration}; - use iroha_data_model::{param::TransactionLimits, prelude::*}; + use iroha_data_model::{param::TransactionParameters, prelude::*}; use nonzero_ext::nonzero; use rand::Rng as _; use test_samples::gen_account_in; @@ -427,7 +427,7 @@ pub mod tests { TransactionBuilder::new_with_time_source(chain_id.clone(), account_id, time_source) .with_instructions(instructions) .sign(key_pair.private_key()); - let limits = TransactionLimits { + let limits = TransactionParameters { max_instructions: nonzero!(4096_u64), smart_contract_size: nonzero!(1024_u64), }; @@ -681,7 +681,7 @@ pub mod tests { .with_instructions(instructions); tx.set_ttl(Duration::from_millis(TTL_MS)); let tx = tx.sign(alice_keypair.private_key()); - let limits = TransactionLimits { + let limits = TransactionParameters { max_instructions: nonzero!(4096_u64), smart_contract_size: nonzero!(1024_u64), }; diff --git a/core/src/smartcontracts/isi/account.rs b/core/src/smartcontracts/isi/account.rs index 2a91d62a6f7..fd5d7c40e05 100644 --- a/core/src/smartcontracts/isi/account.rs +++ b/core/src/smartcontracts/isi/account.rs @@ -119,7 +119,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AccountEvent::Asset(AssetEvent::Remove( + .emit_events(Some(AccountEvent::Asset(AssetEvent::Removed( AssetChanged { asset: asset.id, amount: asset.value, @@ -154,7 +154,7 @@ pub mod isi { asset_definition.owned_by = destination.clone(); state_transaction .world - .emit_events(Some(AssetDefinitionEvent::OwnerChange( + .emit_events(Some(AssetDefinitionEvent::OwnerChanged( AssetDefinitionOwnerChanged { asset_definition: object, new_owner: destination, @@ -186,7 +186,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AccountEvent::MetadataInsert(MetadataChanged { + .emit_events(Some(AccountEvent::MetadataInserted(MetadataChanged { target: account_id, key: self.key, value: self.value, @@ -217,7 +217,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AccountEvent::MetadataRemove(MetadataChanged { + .emit_events(Some(AccountEvent::MetadataRemoved(MetadataChanged { target: account_id, key: self.key, value, @@ -267,7 +267,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AccountEvent::PermissionAdd( + .emit_events(Some(AccountEvent::PermissionAdded( AccountPermissionChanged { account: account_id, permission: permission_id, @@ -300,7 +300,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AccountEvent::PermissionRemove( + .emit_events(Some(AccountEvent::PermissionRemoved( AccountPermissionChanged { account: account_id, permission: permission.id, @@ -357,8 +357,8 @@ pub mod isi { account: account_id, permission: permission_id, }) - .map(AccountEvent::PermissionAdd) - .chain(std::iter::once(AccountEvent::RoleGrant( + .map(AccountEvent::PermissionAdded) + .chain(std::iter::once(AccountEvent::RoleGranted( AccountRoleChanged { account: account_id_clone, role: role_id, @@ -410,8 +410,8 @@ pub mod isi { account: account_id, permission: permission_id, }) - .map(AccountEvent::PermissionRemove) - .chain(std::iter::once(AccountEvent::RoleRevoke( + .map(AccountEvent::PermissionRemoved) + .chain(std::iter::once(AccountEvent::RoleRevoked( AccountRoleChanged { account: account_id_clone, role: role_id, @@ -452,7 +452,7 @@ pub mod isi { .asset_definition_mut(definition_id)?; forbid_minting(asset_definition)?; state_transaction.world.emit_events(Some( - AssetDefinitionEvent::MintabilityChange(definition_id.clone()), + AssetDefinitionEvent::MintabilityChanged(definition_id.clone()), )); } Ok(()) diff --git a/core/src/smartcontracts/isi/asset.rs b/core/src/smartcontracts/isi/asset.rs index 000b036e237..1b6908d71b4 100644 --- a/core/src/smartcontracts/isi/asset.rs +++ b/core/src/smartcontracts/isi/asset.rs @@ -76,7 +76,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AssetEvent::MetadataInsert(MetadataChanged { + .emit_events(Some(AssetEvent::MetadataInserted(MetadataChanged { target: asset_id, key: self.key, value: self.value, @@ -115,7 +115,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AssetEvent::MetadataRemove(MetadataChanged { + .emit_events(Some(AssetEvent::MetadataRemoved(MetadataChanged { target: asset_id, key: self.key, value, @@ -159,8 +159,8 @@ pub mod isi { }; state_transaction.world.emit_events([ - AssetEvent::Delete(asset_id), - AssetEvent::Create(destination_store), + AssetEvent::Deleted(asset_id), + AssetEvent::Created(destination_store), ]); Ok(()) @@ -206,7 +206,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AssetEvent::Add(AssetChanged { + .emit_events(Some(AssetEvent::Added(AssetChanged { asset: asset_id, amount: self.object.into(), }))); @@ -259,7 +259,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AssetEvent::Remove(AssetChanged { + .emit_events(Some(AssetEvent::Removed(AssetChanged { asset: asset_id.clone(), amount: self.object.into(), }))); @@ -323,11 +323,11 @@ pub mod isi { } state_transaction.world.emit_events([ - AssetEvent::Remove(AssetChanged { + AssetEvent::Removed(AssetChanged { asset: source_id, amount: self.object.into(), }), - AssetEvent::Add(AssetChanged { + AssetEvent::Added(AssetChanged { asset: destination_id, amount: self.object.into(), }), @@ -389,11 +389,9 @@ pub mod isi { .world .asset_definition_mut(&asset_definition_id)?; forbid_minting(asset_definition)?; - state_transaction - .world - .emit_events(Some(AssetDefinitionEvent::MintabilityChange( - asset_definition_id, - ))); + state_transaction.world.emit_events(Some( + AssetDefinitionEvent::MintabilityChanged(asset_definition_id), + )); Ok(()) } } diff --git a/core/src/smartcontracts/isi/domain.rs b/core/src/smartcontracts/isi/domain.rs index b77b4acb149..1e4352e7e06 100644 --- a/core/src/smartcontracts/isi/domain.rs +++ b/core/src/smartcontracts/isi/domain.rs @@ -69,7 +69,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(DomainEvent::Account(AccountEvent::Create(account)))); + .emit_events(Some(DomainEvent::Account(AccountEvent::Created(account)))); Ok(()) } @@ -113,7 +113,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AccountEvent::Delete(account_id))); + .emit_events(Some(AccountEvent::Deleted(account_id))); Ok(()) } @@ -147,7 +147,7 @@ pub mod isi { state_transaction .world .emit_events(Some(DomainEvent::AssetDefinition( - AssetDefinitionEvent::Create(asset_definition), + AssetDefinitionEvent::Created(asset_definition), ))); Ok(()) @@ -191,7 +191,7 @@ pub mod isi { error!(%asset_id, "asset not found. This is a bug"); } - events.push(AccountEvent::Asset(AssetEvent::Delete(asset_id)).into()); + events.push(AccountEvent::Asset(AssetEvent::Deleted(asset_id)).into()); } let domain = state_transaction @@ -237,7 +237,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AssetDefinitionEvent::MetadataInsert( + .emit_events(Some(AssetDefinitionEvent::MetadataInserted( MetadataChanged { target: asset_definition_id, key: self.key, @@ -270,7 +270,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(AssetDefinitionEvent::MetadataRemove( + .emit_events(Some(AssetDefinitionEvent::MetadataRemoved( MetadataChanged { target: asset_definition_id, key: self.key, @@ -296,7 +296,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(DomainEvent::MetadataInsert(MetadataChanged { + .emit_events(Some(DomainEvent::MetadataInserted(MetadataChanged { target: domain_id, key: self.key, value: self.value, @@ -323,7 +323,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(DomainEvent::MetadataRemove(MetadataChanged { + .emit_events(Some(DomainEvent::MetadataRemoved(MetadataChanged { target: domain_id, key: self.key, value, @@ -357,7 +357,7 @@ pub mod isi { domain.owned_by = destination.clone(); state_transaction .world - .emit_events(Some(DomainEvent::OwnerChange(DomainOwnerChanged { + .emit_events(Some(DomainEvent::OwnerChanged(DomainOwnerChanged { domain: object, new_owner: destination, }))); diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index e62defc6da3..cb914414d49 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -496,7 +496,7 @@ mod tests { let tx = TransactionBuilder::new(chain_id.clone(), SAMPLE_GENESIS_ACCOUNT_ID.clone()) .with_instructions(instructions) .sign(SAMPLE_GENESIS_ACCOUNT_KEYPAIR.private_key()); - let tx_limits = state_block.transaction_executor().transaction_limits; + let tx_limits = state_block.transaction_executor().limits; assert!(matches!( AcceptedTransaction::accept(tx, &chain_id, tx_limits), Err(AcceptTransactionFail::UnexpectedGenesisAccountSignature) diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index fe382438ffd..2521f0a144d 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -293,7 +293,7 @@ mod tests { use iroha_crypto::{Hash, HashOf, KeyPair}; use iroha_data_model::{ - metadata::MetadataValueBox, param::TransactionLimits, query::error::FindError, + metadata::MetadataValueBox, param::TransactionParameters, query::error::FindError, }; use nonzero_ext::nonzero; use test_samples::{gen_account_in, ALICE_ID, ALICE_KEYPAIR}; @@ -377,16 +377,16 @@ mod tests { let state = State::new(world_with_test_domains(), kura.clone(), query_handle); { let mut state_block = state.block(); - let limits = TransactionLimits { + let limits = TransactionParameters { max_instructions: nonzero!(1000_u64), smart_contract_size: nonzero!(1024_u64), }; - let huge_limits = TransactionLimits { + let huge_limits = TransactionParameters { max_instructions: nonzero!(1000_u64), smart_contract_size: nonzero!(1024_u64), }; - state_block.world.parameters.transaction_limits = limits; + state_block.world.parameters.transaction = limits; let valid_tx = { let instructions: [InstructionBox; 0] = []; @@ -561,7 +561,7 @@ mod tests { .with_instructions(instructions) .sign(ALICE_KEYPAIR.private_key()); - let tx_limits = state_block.transaction_executor().transaction_limits; + let tx_limits = state_block.transaction_executor().limits; let va_tx = AcceptedTransaction::accept(tx, &chain_id, tx_limits)?; let (peer_public_key, _) = KeyPair::random().into_parts(); diff --git a/core/src/smartcontracts/isi/triggers/mod.rs b/core/src/smartcontracts/isi/triggers/mod.rs index f92f2df3438..29a590f8e78 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -107,7 +107,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(TriggerEvent::Create(trigger_id))); + .emit_events(Some(TriggerEvent::Created(trigger_id))); Ok(()) } @@ -126,7 +126,7 @@ pub mod isi { if triggers.remove(trigger_id.clone()) { state_transaction .world - .emit_events(Some(TriggerEvent::Delete(trigger_id))); + .emit_events(Some(TriggerEvent::Deleted(trigger_id))); Ok(()) } else { Err(RepetitionError { @@ -165,7 +165,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(TriggerEvent::Extend( + .emit_events(Some(TriggerEvent::Extended( TriggerNumberOfExecutionsChanged { trigger: id, by: self.object, @@ -193,7 +193,7 @@ pub mod isi { // when they will match some of the events? state_transaction .world - .emit_events(Some(TriggerEvent::Shorten( + .emit_events(Some(TriggerEvent::Shortened( TriggerNumberOfExecutionsChanged { trigger, by: self.object, @@ -225,7 +225,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(TriggerEvent::MetadataInsert(MetadataChanged { + .emit_events(Some(TriggerEvent::MetadataInserted(MetadataChanged { target: trigger_id, key: self.key, value: self.value, @@ -257,7 +257,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(TriggerEvent::MetadataRemove(MetadataChanged { + .emit_events(Some(TriggerEvent::MetadataRemoved(MetadataChanged { target: trigger_id, key: self.key, value, diff --git a/core/src/smartcontracts/isi/world.rs b/core/src/smartcontracts/isi/world.rs index 3797bde1d19..85c2887f109 100644 --- a/core/src/smartcontracts/isi/world.rs +++ b/core/src/smartcontracts/isi/world.rs @@ -21,11 +21,11 @@ pub mod isi { use eyre::Result; use iroha_data_model::{ - isi::error::{InvalidParameterError, RepetitionError}, - param::Parameter, + isi::error::{InstructionExecutionError, InvalidParameterError, RepetitionError}, + param::{CustomParameter, Parameter}, prelude::*, query::error::FindError, - Level, + JsonString, Level, }; use iroha_primitives::unique_vec::PushResult; @@ -50,7 +50,7 @@ pub mod isi { .into()); } - world.emit_events(Some(PeerEvent::Add(peer_id))); + world.emit_events(Some(PeerEvent::Added(peer_id))); Ok(()) } @@ -71,7 +71,7 @@ pub mod isi { world.trusted_peers_ids.remove(index); - world.emit_events(Some(PeerEvent::Remove(peer_id))); + world.emit_events(Some(PeerEvent::Removed(peer_id))); Ok(()) } @@ -87,6 +87,12 @@ pub mod isi { let domain: Domain = self.object.build(authority); let domain_id = domain.id().clone(); + if domain_id == *iroha_genesis::GENESIS_DOMAIN_ID { + return Err(InstructionExecutionError::InvariantViolation( + "Not allowed to register genesis domain".to_owned(), + )); + } + let world = &mut state_transaction.world; if world.domains.get(&domain_id).is_some() { return Err(RepetitionError { @@ -97,8 +103,7 @@ pub mod isi { } world.domains.insert(domain_id, domain.clone()); - - world.emit_events(Some(DomainEvent::Create(domain))); + world.emit_events(Some(DomainEvent::Created(domain))); Ok(()) } @@ -151,7 +156,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(DomainEvent::Delete(domain_id))); + .emit_events(Some(DomainEvent::Deleted(domain_id))); Ok(()) } @@ -189,7 +194,7 @@ pub mod isi { let role_id = role.id().clone(); world.roles.insert(role_id, role.clone()); - world.emit_events(Some(RoleEvent::Create(role))); + world.emit_events(Some(RoleEvent::Created(role))); Ok(()) } @@ -227,7 +232,7 @@ pub mod isi { return Err(FindError::Role(role_id).into()); } - world.emit_events(Some(RoleEvent::Delete(role_id))); + world.emit_events(Some(RoleEvent::Deleted(role_id))); Ok(()) } @@ -267,7 +272,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(RoleEvent::PermissionAdd(RolePermissionChanged { + .emit_events(Some(RoleEvent::PermissionAdded(RolePermissionChanged { role: role_id, permission: permission_id, }))); @@ -297,7 +302,7 @@ pub mod isi { state_transaction .world - .emit_events(Some(RoleEvent::PermissionRemove(RolePermissionChanged { + .emit_events(Some(RoleEvent::PermissionRemoved(RolePermissionChanged { role: role_id, permission: permission_id, }))); @@ -313,90 +318,70 @@ pub mod isi { _authority: &AccountId, state_transaction: &mut StateTransaction<'_, '_>, ) -> Result<(), Error> { - match self.0 { - Parameter::BlockTime(duration) => { - let old_param = core::mem::replace( - &mut state_transaction.world.parameters.block_time, - duration, - ); + macro_rules! set_parameter { + ($($container:ident($param:ident.$field:ident) => $single:ident::$variant:ident),* $(,)?) => { + match self.0 { $( + Parameter::$container(iroha_data_model::param::$single::$variant(next)) => { + let prev = core::mem::replace( + &mut state_transaction.world.parameters.$param.$field, + next, + ); + + state_transaction.world.emit_events( + Some(ConfigurationEvent::Changed(ParameterChanged { + prev: Parameter::$container(iroha_data_model::param::$single::$variant( + prev, + )), + next: Parameter::$container(iroha_data_model::param::$single::$variant( + next, + )), + })) + ); + })* + Parameter::Custom(next) => { + let prev = state_transaction + .world + .parameters + .custom + .insert(next.id.clone(), next.payload.clone()) + .unwrap_or_else(|| { + iroha_logger::error!( + "{}: Initial parameter value not set during executor migration", + next.id + ); + + JsonString::default() + }); + + state_transaction + .world + .emit_events(Some(ConfigurationEvent::Changed(ParameterChanged { + prev: Parameter::Custom(CustomParameter { + id: next.id.clone(), + payload: prev, + }), + next: Parameter::Custom(next), + }))); + } + } + }; + } - state_transaction - .world - .emit_events(Some(ConfigurationEvent::Change(Parameter::BlockTime( - old_param, - )))); - } - Parameter::CommitTime(duration) => { - let old_param = core::mem::replace( - &mut state_transaction.world.parameters.commit_time, - duration, - ); + set_parameter!( + Sumeragi(sumeragi.block_time_ms) => SumeragiParameter::BlockTimeMs, + Sumeragi(sumeragi.commit_time_ms) => SumeragiParameter::CommitTimeMs, - state_transaction - .world - .emit_events(Some(ConfigurationEvent::Change(Parameter::CommitTime( - old_param, - )))); - } - Parameter::BlockLimits(block_limits) => { - let old_param = core::mem::replace( - &mut state_transaction.world.parameters.block_limits, - block_limits, - ); + Block(block.max_transactions) => BlockParameter::MaxTransactions, - state_transaction - .world - .emit_events(Some(ConfigurationEvent::Change(Parameter::BlockLimits( - old_param, - )))); - } - Parameter::TransactionLimits(txn_limits) => { - let old_param = core::mem::replace( - &mut state_transaction.world.parameters.transaction_limits, - txn_limits, - ); + Transaction(transaction.max_instructions) => TransactionParameter::MaxInstructions, + Transaction(transaction.smart_contract_size) => TransactionParameter::SmartContractSize, - state_transaction - .world - .emit_events(Some(ConfigurationEvent::Change( - Parameter::TransactionLimits(old_param), - ))); - } - Parameter::SmartContractLimits(limits) => { - let old_param = core::mem::replace( - &mut state_transaction.world.parameters.smart_contract_limits, - limits, - ); - - state_transaction - .world - .emit_events(Some(ConfigurationEvent::Change( - Parameter::SmartContractLimits(old_param), - ))); - } - Parameter::ExecutorLimits(limits) => { - let old_param = core::mem::replace( - &mut state_transaction.world.parameters.executor_limits, - limits, - ); - - state_transaction - .world - .emit_events(Some(ConfigurationEvent::Change(Parameter::ExecutorLimits( - old_param, - )))); - } - Parameter::Custom(custom) => { - let old_param = - core::mem::replace(&mut state_transaction.world.parameters.custom, custom); + SmartContract(smart_contract.fuel) => SmartContractParameter::Fuel, + SmartContract(smart_contract.memory) => SmartContractParameter::Memory, - state_transaction - .world - .emit_events(Some(ConfigurationEvent::Change(Parameter::Custom( - old_param, - )))); - } - } + Executor(executor.fuel) => SmartContractParameter::Fuel, + Executor(executor.memory) => SmartContractParameter::Memory, + ); Ok(()) } @@ -435,7 +420,7 @@ pub mod isi { state_transaction .world - .emit_events(std::iter::once(ExecutorEvent::Upgrade(ExecutorUpgrade { + .emit_events(std::iter::once(ExecutorEvent::Upgraded(ExecutorUpgrade { new_data_model: state_transaction.world.executor_data_model.clone(), }))); diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index 7b38d8c30d4..1d600cfcd7b 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -10,7 +10,7 @@ use iroha_data_model::{ account::AccountId, executor::{self, ExecutorDataModel, MigrationResult}, isi::InstructionBox, - param::SmartContractLimits as Config, + param::SmartContractParameters as Config, prelude::*, query::{QueryBox, QueryId, QueryOutputBox, QueryRequest, SmartContractQuery}, smart_contract::payloads::{self, Validate}, @@ -348,7 +348,7 @@ pub mod state { .memory .get() .try_into() - .expect("INTERNAL BUG: memory limit exceeds u64::MAX"); + .expect("`SmarContractParameters::memory` exceeds usize::MAX"); StoreLimitsBuilder::new() .memory_size(memory_size) diff --git a/core/src/state.rs b/core/src/state.rs index 21d666be45a..120da84f95a 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -63,7 +63,7 @@ use crate::{ /// For example registration of domain, will have this as an ISI target. #[derive(Default, Serialize)] pub struct World { - /// Iroha on-chain built-in parameters. + /// Iroha on-chain parameters. pub(crate) parameters: Cell, /// Identifications of discovered trusted peers. pub(crate) trusted_peers_ids: Cell, @@ -87,7 +87,7 @@ pub struct World { /// Struct for block's aggregated changes pub struct WorldBlock<'world> { - /// Iroha on-chain built-in parameters. + /// Iroha on-chain parameters. pub parameters: CellBlock<'world, Parameters>, /// Identifications of discovered trusted peers. pub(crate) trusted_peers_ids: CellBlock<'world, PeersIds>, @@ -113,7 +113,7 @@ pub struct WorldBlock<'world> { /// Struct for single transaction's aggregated changes pub struct WorldTransaction<'block, 'world> { - /// Iroha on-chain built-in parameters. + /// Iroha on-chain parameters. pub(crate) parameters: CellTransaction<'block, 'world, Parameters>, /// Identifications of discovered trusted peers. pub(crate) trusted_peers_ids: CellTransaction<'block, 'world, PeersIds>, @@ -147,7 +147,7 @@ struct TransactionEventBuffer<'block> { /// Consistent point in time view of the [`World`] pub struct WorldView<'world> { - /// Iroha on-chain built-in parameters. + /// Iroha on-chain parameters. pub(crate) parameters: CellView<'world, Parameters>, /// Identifications of discovered trusted peers. pub(crate) trusted_peers_ids: CellView<'world, PeersIds>, @@ -762,7 +762,7 @@ impl WorldTransaction<'_, '_> { Self::emit_events_impl( &mut self.triggers, &mut self.events_buffer, - Some(AccountEvent::Asset(AssetEvent::Create(asset.clone()))), + Some(AccountEvent::Asset(AssetEvent::Created(asset.clone()))), ); asset })) @@ -807,7 +807,7 @@ impl WorldTransaction<'_, '_> { self.emit_events({ Some(DomainEvent::AssetDefinition( - AssetDefinitionEvent::TotalQuantityChange(AssetDefinitionTotalQuantityChanged { + AssetDefinitionEvent::TotalQuantityChanged(AssetDefinitionTotalQuantityChanged { asset_definition: definition_id.clone(), total_amount: asset_total_amount, }), @@ -840,7 +840,7 @@ impl WorldTransaction<'_, '_> { self.emit_events({ Some(DomainEvent::AssetDefinition( - AssetDefinitionEvent::TotalQuantityChange(AssetDefinitionTotalQuantityChanged { + AssetDefinitionEvent::TotalQuantityChanged(AssetDefinitionTotalQuantityChanged { asset_definition: definition_id.clone(), total_amount: asset_total_amount, }), @@ -926,18 +926,6 @@ impl Drop for TransactionEventBuffer<'_> { } } -impl StateBlock<'_> { - pub(crate) fn consensus_estimation(&self) -> Duration { - let Parameters { - block_time, - commit_time, - .. - } = self.world.parameters(); - - *block_time + (*commit_time / 2) - } -} - impl State { /// Construct [`State`] with given [`World`]. #[must_use] @@ -1100,7 +1088,7 @@ pub trait StateReadOnly { /// Get transaction executor fn transaction_executor(&self) -> TransactionExecutor { - TransactionExecutor::new(self.world().parameters().transaction_limits) + TransactionExecutor::new(self.world().parameters().transaction) } } @@ -1339,7 +1327,7 @@ impl StateTransaction<'_, '_> { } Executable::Wasm(bytes) => { let mut wasm_runtime = wasm::RuntimeBuilder::::new() - .with_config(self.world().parameters().smart_contract_limits) + .with_config(self.world().parameters().smart_contract) .with_engine(self.engine.clone()) // Cloning engine is cheap .build()?; wasm_runtime @@ -1381,7 +1369,7 @@ impl StateTransaction<'_, '_> { .expect("INTERNAL BUG: contract is not present") .clone(); let mut wasm_runtime = wasm::RuntimeBuilder::::new() - .with_config(self.world().parameters().smart_contract_limits) + .with_config(self.world().parameters().smart_contract) .with_engine(self.engine.clone()) // Cloning engine is cheap .build()?; wasm_runtime diff --git a/core/src/sumeragi/main_loop.rs b/core/src/sumeragi/main_loop.rs index de0eebbba22..0851990c09a 100644 --- a/core/src/sumeragi/main_loop.rs +++ b/core/src/sumeragi/main_loop.rs @@ -2,9 +2,7 @@ use std::{collections::BTreeSet, sync::mpsc}; use iroha_crypto::{HashOf, KeyPair}; -use iroha_data_model::{ - block::*, events::pipeline::PipelineEventBox, param::Parameters, peer::PeerId, -}; +use iroha_data_model::{block::*, events::pipeline::PipelineEventBox, peer::PeerId}; use iroha_p2p::UpdateTopology; use tracing::{span, Level}; @@ -63,10 +61,6 @@ impl Debug for Sumeragi { } impl Sumeragi { - fn pipeline_time(parameters: &Parameters) -> Duration { - parameters.block_time + parameters.commit_time - } - fn role(&self) -> Role { self.topology.role(&self.peer_id) } @@ -791,9 +785,14 @@ impl Sumeragi { #[cfg(debug_assertions)] if is_genesis_peer && self.debug_force_soft_fork { - std::thread::sleep( - Sumeragi::pipeline_time(voting_block.state_block.world.parameters()) * 2, - ); + let pipeline_time = voting_block + .state_block + .world + .parameters() + .sumeragi + .pipeline_time(); + + std::thread::sleep(pipeline_time * 2); } else { let msg = BlockCommitted::from(&committed_block); self.broadcast_packet(msg); @@ -825,11 +824,11 @@ impl Sumeragi { .world .view() .parameters - .block_limits + .block .max_transactions .try_into() .expect("INTERNAL BUG: transactions in block exceed usize::MAX"); - let block_time = state.world.view().parameters.block_time; + let block_time = state.world.view().parameters.sumeragi.block_time(); let tx_cache_full = self.transaction_cache.len() >= max_transactions.get(); let deadline_reached = self.round_start_time.elapsed() > block_time; let tx_cache_non_empty = !self.transaction_cache.is_empty(); @@ -848,7 +847,8 @@ impl Sumeragi { .unpack(|e| self.send_event(e)); let created_in = create_block_start_time.elapsed(); - if created_in > Sumeragi::pipeline_time(state.world.view().parameters()) / 2 { + let pipeline_time = state.world.view().parameters().sumeragi.pipeline_time(); + if created_in > pipeline_time / 2 { warn!( role=%self.role(), peer_id=%self.peer_id, @@ -994,7 +994,7 @@ pub(crate) fn run( let mut should_sleep = false; let mut view_change_proof_chain = ProofChain::default(); // Duration after which a view change is suggested - let mut view_change_time = Sumeragi::pipeline_time(state.world.view().parameters()); + let mut view_change_time = state.world.view().parameters().sumeragi.pipeline_time(); // Instant when the previous view change or round happened. let mut last_view_change_time = Instant::now(); @@ -1028,7 +1028,7 @@ pub(crate) fn run( .world .view() .parameters - .block_limits + .block .max_transactions .try_into() .expect("INTERNAL BUG: transactions in block exceed usize::MAX"), @@ -1044,7 +1044,7 @@ pub(crate) fn run( reset_state( &sumeragi.peer_id, - Sumeragi::pipeline_time(state.world.view().parameters()), + state.world.view().parameters().sumeragi.pipeline_time(), view_change_index, &mut sumeragi.was_commit, &mut sumeragi.topology, @@ -1129,12 +1129,12 @@ pub(crate) fn run( // NOTE: View change must be periodically suggested until it is accepted. // Must be initialized to pipeline time but can increase by chosen amount - view_change_time += Sumeragi::pipeline_time(state.world.view().parameters()); + view_change_time += state.world.view().parameters().sumeragi.pipeline_time(); } reset_state( &sumeragi.peer_id, - Sumeragi::pipeline_time(state.world.view().parameters()), + state.world.view().parameters().sumeragi.pipeline_time(), view_change_index, &mut sumeragi.was_commit, &mut sumeragi.topology, @@ -1368,12 +1368,9 @@ mod tests { let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([fail_box]) .sign(alice_keypair.private_key()); - let tx = AcceptedTransaction::accept( - tx, - chain_id, - state_block.transaction_executor().transaction_limits, - ) - .expect("Valid"); + let tx = + AcceptedTransaction::accept(tx, chain_id, state_block.transaction_executor().limits) + .expect("Valid"); // Creating a block of two identical transactions and validating it let block = BlockBuilder::new(vec![tx.clone(), tx], topology.clone(), Vec::new()) @@ -1405,7 +1402,7 @@ mod tests { let tx1 = AcceptedTransaction::accept( tx1, chain_id, - state_block.transaction_executor().transaction_limits, + state_block.transaction_executor().limits, ) .map(Into::into) .expect("Valid"); @@ -1415,7 +1412,7 @@ mod tests { let tx2 = AcceptedTransaction::accept( tx2, chain_id, - state_block.transaction_executor().transaction_limits, + state_block.transaction_executor().limits, ) .map(Into::into) .expect("Valid"); diff --git a/core/src/tx.rs b/core/src/tx.rs index 798c006bcf5..09f4f059b17 100644 --- a/core/src/tx.rs +++ b/core/src/tx.rs @@ -96,7 +96,7 @@ impl AcceptedTransaction { pub fn accept( tx: SignedTransaction, expected_chain_id: &ChainId, - limits: TransactionLimits, + limits: TransactionParameters, ) -> Result { let actual_chain_id = tx.chain(); @@ -136,7 +136,8 @@ impl AcceptedTransaction { return Err(AcceptTransactionFail::TransactionLimit( TransactionLimitError { reason: format!( - "Wasm binary too large, max size is {}, but got {}", + "WASM binary size is too large: max {}, got {} \ + (configured by \"Parameter::SmartContractLimits\")", limits.smart_contract_size, smart_contract_size ), }, @@ -177,14 +178,16 @@ impl AsRef for AcceptedTransaction { /// Validation is skipped for genesis. #[derive(Clone, Copy)] pub struct TransactionExecutor { - /// [`TransactionLimits`] field - pub transaction_limits: TransactionLimits, + /// [`TransactionParameters`] field + pub limits: TransactionParameters, } impl TransactionExecutor { /// Construct [`TransactionExecutor`] - pub fn new(transaction_limits: TransactionLimits) -> Self { - Self { transaction_limits } + pub fn new(transaction_limits: TransactionParameters) -> Self { + Self { + limits: transaction_limits, + } } /// Move transaction lifecycle forward by checking if the @@ -247,7 +250,7 @@ impl TransactionExecutor { state_transaction, authority, wasm, - self.transaction_limits.max_instructions, + self.limits.max_instructions, ) }) .map_err(|error| WasmExecutionFail { diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index 0c2dac06854..1a92906d561 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -777,8 +777,8 @@ impl TestConfig for Config { } fn pipeline_time() -> Duration { - let defaults = iroha_data_model::param::Parameters::default(); - defaults.block_time + defaults.commit_time + let defaults = iroha_data_model::param::SumeragiParameters::default(); + defaults.block_time() + defaults.commit_time() } fn block_sync_gossip_time() -> Duration { diff --git a/data_model/derive/src/id.rs b/data_model/derive/src/id.rs index c9a64c64537..baaa45daa31 100644 --- a/data_model/derive/src/id.rs +++ b/data_model/derive/src/id.rs @@ -85,29 +85,29 @@ pub fn impl_id_eq_ord_hash(emitter: &mut Emitter, input: &syn::DeriveInput) -> T quote! { #identifiable_derive - impl #impl_generics ::core::cmp::PartialOrd for #name #ty_generics #where_clause where Self: Identifiable { + impl #impl_generics ::core::cmp::PartialOrd for #name #ty_generics #where_clause where Self: crate::Identifiable { #[inline] fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> { Some(self.cmp(other)) } } - impl #impl_generics ::core::cmp::Ord for #name #ty_generics #where_clause where Self: Identifiable { + impl #impl_generics ::core::cmp::Ord for #name #ty_generics #where_clause where Self: crate::Identifiable { fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - self.id().cmp(other.id()) + ::id(self).cmp(::id(other)) } } - impl #impl_generics ::core::cmp::Eq for #name #ty_generics #where_clause where Self: Identifiable {} - impl #impl_generics ::core::cmp::PartialEq for #name #ty_generics #where_clause where Self: Identifiable { + impl #impl_generics ::core::cmp::Eq for #name #ty_generics #where_clause where Self: crate::Identifiable {} + impl #impl_generics ::core::cmp::PartialEq for #name #ty_generics #where_clause where Self: crate::Identifiable { fn eq(&self, other: &Self) -> bool { - self.id() == other.id() + ::id(self) == ::id(other) } } - impl #impl_generics ::core::hash::Hash for #name #ty_generics #where_clause where Self: Identifiable { + impl #impl_generics ::core::hash::Hash for #name #ty_generics #where_clause where Self: crate::Identifiable { fn hash(&self, state: &mut H) { - self.id().hash(state); + ::id(self).hash(state) } } } @@ -119,7 +119,7 @@ fn derive_identifiable(emitter: &mut Emitter, input: &IdDeriveInput) -> TokenStr let (id_type, id_expr) = get_id_type(emitter, input); quote! { - impl #impl_generics Identifiable for #name #ty_generics #where_clause { + impl #impl_generics crate::Identifiable for #name #ty_generics #where_clause { type Id = #id_type; #[inline] @@ -142,8 +142,8 @@ fn get_id_type(emitter: &mut Emitter, input: &IdDeriveInput) -> (syn::Type, syn: } IdAttr::Transparent => { return ( - parse_quote! {<#ty as Identifiable>::Id}, - parse_quote! {Identifiable::id(&self.#field_name)}, + parse_quote! {<#ty as crate::Identifiable>::Id}, + parse_quote! {crate::Identifiable::id(&self.#field_name)}, ); } IdAttr::Missing => { diff --git a/data_model/derive/tests/has_origin_generics.rs b/data_model/derive/tests/has_origin_generics.rs index a1090a312cc..69724714bb1 100644 --- a/data_model/derive/tests/has_origin_generics.rs +++ b/data_model/derive/tests/has_origin_generics.rs @@ -16,12 +16,6 @@ struct Object { id: ObjectId, } -impl Object { - fn id(&self) -> &ObjectId { - &self.id - } -} - #[allow(clippy::enum_variant_names)] // it's a test, duh #[derive(Debug, HasOrigin)] #[has_origin(origin = Object)] diff --git a/data_model/src/account.rs b/data_model/src/account.rs index 6d75fc54358..c8daf5c8cb3 100644 --- a/data_model/src/account.rs +++ b/data_model/src/account.rs @@ -4,7 +4,6 @@ use alloc::{format, string::String, vec::Vec}; use core::str::FromStr; use derive_more::{Constructor, DebugCustom, Display}; -use getset::Getters; use iroha_data_model_derive::{model, IdEqOrdHash}; use iroha_schema::IntoSchema; use parity_scale_codec::{Decode, Encode}; @@ -16,11 +15,13 @@ use crate::{ asset::{Asset, AssetDefinitionId, AssetsMap}, domain::prelude::*, metadata::Metadata, - HasMetadata, Identifiable, ParseError, PublicKey, Registered, + HasMetadata, ParseError, PublicKey, Registered, }; #[model] mod model { + use getset::Getters; + use super::*; /// Identification of [`Account`] by the combination of the [`PublicKey`] as its sole signatory and the [`Domain`](crate::domain::Domain) it belongs to. @@ -66,16 +67,7 @@ mod model { /// Account entity is an authority which is used to execute `Iroha Special Instructions`. #[derive( - Debug, - Display, - Clone, - IdEqOrdHash, - Getters, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, + Debug, Display, Clone, IdEqOrdHash, Decode, Encode, Deserialize, Serialize, IntoSchema, )] #[allow(clippy::multiple_inherent_impl)] #[display(fmt = "({id})")] // TODO: Add more? diff --git a/data_model/src/asset.rs b/data_model/src/asset.rs index 6b3972c1e49..750f261f577 100644 --- a/data_model/src/asset.rs +++ b/data_model/src/asset.rs @@ -7,7 +7,6 @@ use core::{fmt, str::FromStr}; use std::collections::btree_map; use derive_more::{Constructor, DebugCustom, Display}; -use getset::{CopyGetters, Getters}; use iroha_data_model_derive::{model, IdEqOrdHash}; use iroha_primitives::numeric::{Numeric, NumericSpec, NumericSpecParseError}; use iroha_schema::IntoSchema; @@ -17,8 +16,8 @@ use serde_with::{DeserializeFromStr, SerializeDisplay}; pub use self::model::*; use crate::{ - account::prelude::*, domain::prelude::*, ipfs::IpfsPath, metadata::Metadata, HasMetadata, - Identifiable, Name, ParseError, Registered, + account::prelude::*, domain::prelude::*, ipfs::IpfsPath, metadata::Metadata, HasMetadata, Name, + ParseError, Registered, }; /// API to work with collections of [`Id`] : [`Asset`] mappings. @@ -34,6 +33,7 @@ pub type AssetTotalQuantityMap = btree_map::BTreeMap #[model] mod model { + use getset::{CopyGetters, Getters}; use iroha_macro::FromVariant; use super::*; diff --git a/data_model/src/block.rs b/data_model/src/block.rs index e8957749559..48c00a8cc77 100644 --- a/data_model/src/block.rs +++ b/data_model/src/block.rs @@ -14,6 +14,7 @@ use iroha_data_model_derive::model; use iroha_macro::FromVariant; use iroha_schema::IntoSchema; use iroha_version::{declare_versioned, version_with_scale}; +use nonzero_ext::nonzero; use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; @@ -294,7 +295,7 @@ impl SignedBlock { let timestamp_ms = u64::try_from(genesis_transaction.creation_time().as_millis()) .expect("Must fit since Duration was created from u64 in creation_time()"); let header = BlockHeader { - height: 1, + height: nonzero!(1_u64), prev_block_hash: None, transactions_hash, timestamp_ms, @@ -349,7 +350,7 @@ mod candidate { } fn validate_signatures(&self) -> Result<(), &'static str> { - if self.signatures.is_empty() && self.payload.header.height != 1 { + if self.signatures.is_empty() && self.payload.header.height.get() != 1 { return Err("Block missing signatures"); } diff --git a/data_model/src/domain.rs b/data_model/src/domain.rs index db01cd686c1..fba99212f45 100644 --- a/data_model/src/domain.rs +++ b/data_model/src/domain.rs @@ -4,7 +4,6 @@ use alloc::{format, string::String, vec::Vec}; use derive_more::{Constructor, Display, FromStr}; -use getset::Getters; use iroha_data_model_derive::{model, IdEqOrdHash}; use iroha_primitives::numeric::Numeric; use iroha_schema::IntoSchema; @@ -23,6 +22,8 @@ use crate::{ #[model] mod model { + use getset::Getters; + use super::*; /// Identification of a [`Domain`]. diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index efe00d42fae..c041fdb6bff 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -111,16 +111,16 @@ mod asset { #[has_origin(origin = Asset)] pub enum AssetEvent { #[has_origin(asset => asset.id())] - Create(Asset), - Delete(AssetId), + Created(Asset), + Deleted(AssetId), #[has_origin(asset_changed => &asset_changed.asset)] - Add(AssetChanged), + Added(AssetChanged), #[has_origin(asset_changed => &asset_changed.asset)] - Remove(AssetChanged), + Removed(AssetChanged), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataInsert(AssetMetadataChanged), + MetadataInserted(AssetMetadataChanged), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataRemove(AssetMetadataChanged), + MetadataRemoved(AssetMetadataChanged), } } @@ -128,17 +128,17 @@ mod asset { #[has_origin(origin = AssetDefinition)] pub enum AssetDefinitionEvent { #[has_origin(asset_definition => asset_definition.id())] - Create(AssetDefinition), + Created(AssetDefinition), Delete(AssetDefinitionId), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataInsert(AssetDefinitionMetadataChanged), + MetadataInserted(AssetDefinitionMetadataChanged), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataRemove(AssetDefinitionMetadataChanged), - MintabilityChange(AssetDefinitionId), + MetadataRemoved(AssetDefinitionMetadataChanged), + MintabilityChanged(AssetDefinitionId), #[has_origin(total_quantity_changed => &total_quantity_changed.asset_definition)] - TotalQuantityChange(AssetDefinitionTotalQuantityChanged), + TotalQuantityChanged(AssetDefinitionTotalQuantityChanged), #[has_origin(ownership_changed => &ownership_changed.asset_definition)] - OwnerChange(AssetDefinitionOwnerChanged), + OwnerChanged(AssetDefinitionOwnerChanged), } } @@ -224,8 +224,8 @@ mod peer { data_event! { #[has_origin(origin = Peer)] pub enum PeerEvent { - Add(PeerId), - Remove(PeerId), + Added(PeerId), + Removed(PeerId), } } } @@ -242,16 +242,16 @@ mod role { #[has_origin(origin = Role)] pub enum RoleEvent { #[has_origin(role => role.id())] - Create(Role), - Delete(RoleId), + Created(Role), + Deleted(RoleId), /// [`Permission`]s with particular [`PermissionId`] /// were removed added to the role. #[has_origin(permission_added => &permission_added.role)] - PermissionAdd(RolePermissionChanged), + PermissionAdded(RolePermissionChanged), /// [`Permission`]s with particular [`PermissionId`] /// were removed from the role. #[has_origin(permission_removed => &permission_removed.role)] - PermissionRemove(RolePermissionChanged), + PermissionRemoved(RolePermissionChanged), } } @@ -299,24 +299,22 @@ mod account { #[has_origin(origin = Account)] pub enum AccountEvent { #[has_origin(account => account.id())] - Create(Account), - Delete(AccountId), - AuthenticationAdd(AccountId), - AuthenticationRemove(AccountId), + Created(Account), + Deleted(AccountId), #[has_origin(asset_event => &asset_event.origin().account)] Asset(AssetEvent), #[has_origin(permission_changed => &permission_changed.account)] - PermissionAdd(AccountPermissionChanged), + PermissionAdded(AccountPermissionChanged), #[has_origin(permission_changed => &permission_changed.account)] - PermissionRemove(AccountPermissionChanged), + PermissionRemoved(AccountPermissionChanged), #[has_origin(role_changed => &role_changed.account)] - RoleGrant(AccountRoleChanged), + RoleGranted(AccountRoleChanged), #[has_origin(role_changed => &role_changed.account)] - RoleRevoke(AccountRoleChanged), + RoleRevoked(AccountRoleChanged), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataInsert(AccountMetadataChanged), + MetadataInserted(AccountMetadataChanged), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataRemove(AccountMetadataChanged), + MetadataRemoved(AccountMetadataChanged), } } @@ -391,18 +389,18 @@ mod domain { #[has_origin(origin = Domain)] pub enum DomainEvent { #[has_origin(domain => domain.id())] - Create(Domain), - Delete(DomainId), + Created(Domain), + Deleted(DomainId), #[has_origin(asset_definition_event => &asset_definition_event.origin().domain)] AssetDefinition(AssetDefinitionEvent), #[has_origin(account_event => &account_event.origin().domain)] Account(AccountEvent), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataInsert(DomainMetadataChanged), + MetadataInserted(DomainMetadataChanged), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataRemove(DomainMetadataChanged), + MetadataRemoved(DomainMetadataChanged), #[has_origin(owner_changed => &owner_changed.domain)] - OwnerChange(DomainOwnerChanged), + OwnerChanged(DomainOwnerChanged), } } @@ -447,16 +445,16 @@ mod trigger { data_event! { #[has_origin(origin = Trigger)] pub enum TriggerEvent { - Create(TriggerId), - Delete(TriggerId), + Created(TriggerId), + Deleted(TriggerId), #[has_origin(number_of_executions_changed => &number_of_executions_changed.trigger)] - Extend(TriggerNumberOfExecutionsChanged), + Extended(TriggerNumberOfExecutionsChanged), #[has_origin(number_of_executions_changed => &number_of_executions_changed.trigger)] - Shorten(TriggerNumberOfExecutionsChanged), + Shortened(TriggerNumberOfExecutionsChanged), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataInsert(TriggerMetadataChanged), + MetadataInserted(TriggerMetadataChanged), #[has_origin(metadata_changed => &metadata_changed.target)] - MetadataRemove(TriggerMetadataChanged), + MetadataRemoved(TriggerMetadataChanged), } } @@ -497,6 +495,28 @@ mod config { mod model { use super::*; + /// Changed parameter event + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] + #[ffi_type] + pub struct ParameterChanged { + /// Previous value for the parameter + pub prev: Parameter, + /// Next value for the parameter + pub next: Parameter, + } + #[derive( Debug, Clone, @@ -514,7 +534,7 @@ mod config { )] #[ffi_type] pub enum ConfigurationEvent { - Change(Parameter), + Changed(ParameterChanged), } } } @@ -556,7 +576,7 @@ mod executor { #[serde(untagged)] // Unaffected by #3330, as single unit variant #[repr(transparent)] pub enum ExecutorEvent { - Upgrade(ExecutorUpgrade), + Upgraded(ExecutorUpgrade), } /// Information about the updated executor data model. @@ -649,7 +669,7 @@ pub mod prelude { AssetDefinitionOwnerChanged, AssetDefinitionTotalQuantityChanged, AssetEvent, AssetEventSet, }, - config::{ConfigurationEvent, ConfigurationEventSet}, + config::{ConfigurationEvent, ConfigurationEventSet, ParameterChanged}, domain::{DomainEvent, DomainEventSet, DomainOwnerChanged}, executor::{ExecutorEvent, ExecutorEventSet, ExecutorUpgrade}, peer::{PeerEvent, PeerEventSet}, diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 88e044873bc..0bda7058181 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -749,10 +749,10 @@ mod tests { // the first one is just a domain event // the second one is an account event with a domain event inside // the third one is an asset event with an account event with a domain event inside - let domain_created = DomainEvent::Create(domain).into(); - let account_created = DomainEvent::Account(AccountEvent::Create(account)).into(); + let domain_created = DomainEvent::Created(domain).into(); + let account_created = DomainEvent::Account(AccountEvent::Created(account)).into(); let asset_created = - DomainEvent::Account(AccountEvent::Asset(AssetEvent::Create(asset))).into(); + DomainEvent::Account(AccountEvent::Asset(AssetEvent::Created(asset))).into(); // test how the differently nested filters with with the events let domain_filter = DataEventFilter::Domain(DomainEventFilter::new().for_domain(domain_id)); diff --git a/data_model/src/executor.rs b/data_model/src/executor.rs index 8836c40219e..120b7869503 100644 --- a/data_model/src/executor.rs +++ b/data_model/src/executor.rs @@ -5,21 +5,21 @@ use alloc::{collections::BTreeSet, format, string::String, vec::Vec}; #[cfg(feature = "std")] use std::collections::BTreeSet; -use derive_more::{Constructor, Display}; -use getset::Getters; use iroha_data_model_derive::model; -use iroha_schema::IntoSchema; -use parity_scale_codec::{Decode, Encode}; -use serde::{Deserialize, Serialize}; pub use self::model::*; use crate::{permission::PermissionId, transaction::WasmSmartContract, JsonString}; #[model] mod model { - use iroha_schema::Ident; + use derive_more::{Constructor, Display}; + use getset::Getters; + use iroha_schema::{Ident, IntoSchema}; + use parity_scale_codec::{Decode, Encode}; + use serde::{Deserialize, Serialize}; use super::*; + use crate::param::CustomParameterId; /// executor that checks if an operation satisfies some conditions. /// @@ -79,15 +79,22 @@ mod model { #[ffi_type] #[display(fmt = "{self:?}")] pub struct ExecutorDataModel { + /// Corresponds to the id of [`InstructionBox::Custom`]. + /// + /// It should be set during executor migration, + /// so it can be retrieved through Iroha API. + pub custom_instruction: Option, + /// Corresponds to the id of [`Parameter::Custom`]. + /// + /// It should be set during executor migration, + /// so it can be retrieved through Iroha API. + pub parameters: BTreeSet, /// Permission tokens supported by the executor. /// /// These IDs refer to the types in the schema. pub permissions: BTreeSet, - /// Corresponds to the id of [`InstructionBox::Custom`]. - /// - /// It is recommended to set it, so clients can retrieve it through Iroha API. - pub custom_instruction: Option, - /// Data model JSON schema, typically produced by [`IntoSchema`]. + /// Data model JSON schema. Includes description of all executor defined types + /// (permissions, parameters, instructions) pub schema: JsonString, } diff --git a/data_model/src/ipfs.rs b/data_model/src/ipfs.rs index 635900ba5c2..e6dbaca5c76 100644 --- a/data_model/src/ipfs.rs +++ b/data_model/src/ipfs.rs @@ -4,18 +4,19 @@ use alloc::{format, string::String, vec::Vec}; use core::str::FromStr; -use derive_more::Display; use iroha_data_model_derive::model; use iroha_primitives::conststr::ConstString; -use iroha_schema::IntoSchema; use parity_scale_codec::{Decode, Encode, Input}; -use serde_with::{DeserializeFromStr, SerializeDisplay}; pub use self::model::*; use crate::ParseError; #[model] mod model { + use derive_more::Display; + use iroha_schema::IntoSchema; + use serde_with::{DeserializeFromStr, SerializeDisplay}; + use super::*; /// Represents path in IPFS. Performs checks to ensure path validity. diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index 829f82d679a..b241bac89cb 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -17,8 +17,7 @@ use alloc::{ }; use core::{fmt, fmt::Debug, str::FromStr}; -use derive_more::{Constructor, Display, FromStr}; -use getset::Getters; +use derive_more::{Constructor, Display}; use iroha_crypto::PublicKey; use iroha_data_model_derive::{model, EnumRef}; use iroha_macro::FromVariant; @@ -215,6 +214,8 @@ impl std::error::Error for EnumTryAsError a.id().clone().into(), IdentifiableBox::Trigger(a) => a.id().clone().into(), IdentifiableBox::Role(a) => a.id().clone().into(), + IdentifiableBox::CustomParameter(a) => a.id().clone().into(), } } } diff --git a/data_model/src/metadata.rs b/data_model/src/metadata.rs index bf3d1be835d..801f2ce8561 100644 --- a/data_model/src/metadata.rs +++ b/data_model/src/metadata.rs @@ -11,13 +11,8 @@ use core::borrow::Borrow; #[cfg(feature = "std")] use std::collections::btree_map; -use derive_more::Display; use iroha_data_model_derive::model; -use iroha_macro::FromVariant; use iroha_primitives::numeric::Numeric; -use iroha_schema::IntoSchema; -use parity_scale_codec::{Decode, Encode}; -use serde::{Deserialize, Serialize}; pub use self::model::*; use crate::Name; @@ -27,6 +22,12 @@ pub type Path = [Name]; #[model] mod model { + use derive_more::Display; + use iroha_macro::FromVariant; + use iroha_schema::IntoSchema; + use parity_scale_codec::{Decode, Encode}; + use serde::{Deserialize, Serialize}; + use super::*; /// Collection of parameters by their names with checked insertion. @@ -216,9 +217,7 @@ impl Metadata { key: Name, value: impl Into, ) -> Option { - let value = value.into(); - - self.0.insert(key, value) + self.0.insert(key, value.into()) } } diff --git a/data_model/src/name.rs b/data_model/src/name.rs index 6094cb7acf4..bf87b77a275 100644 --- a/data_model/src/name.rs +++ b/data_model/src/name.rs @@ -2,20 +2,21 @@ //! and related implementations and trait implementations. #[cfg(not(feature = "std"))] use alloc::{format, string::String, vec::Vec}; -use core::{borrow::Borrow, ops::RangeInclusive, str::FromStr}; +use core::{borrow::Borrow, str::FromStr}; -use derive_more::{DebugCustom, Display}; use iroha_data_model_derive::model; use iroha_primitives::conststr::ConstString; -use iroha_schema::IntoSchema; use parity_scale_codec::{Decode, Encode, Input}; use serde::{Deserialize, Serialize}; pub use self::model::*; -use crate::{isi::error::InvalidParameterError, ParseError}; +use crate::ParseError; #[model] mod model { + use derive_more::{DebugCustom, Display}; + use iroha_schema::IntoSchema; + use super::*; /// `Name` struct represents the type of Iroha Entities names, such as @@ -41,27 +42,6 @@ mod model { } impl Name { - /// Check if `range` contains the number of chars in the inner `ConstString` of this [`Name`]. - /// - /// # Errors - /// Fails if `range` does not - pub fn validate_len( - &self, - range: impl Into>, - ) -> Result<(), InvalidParameterError> { - let range = range.into(); - let Ok(true) = &self - .0 - .chars() - .count() - .try_into() - .map(|len| range.contains(&len)) - else { - return Err(InvalidParameterError::NameLength); - }; - Ok(()) - } - /// Check if `candidate` string would be valid [`Name`]. /// /// # Errors diff --git a/data_model/src/param.rs b/data_model/src/param.rs index b1a9358c604..f07eaf8b1eb 100644 --- a/data_model/src/param.rs +++ b/data_model/src/param.rs @@ -1,19 +1,53 @@ //! Structures, traits and impls related to `Paramater`s. +#[cfg(not(feature = "std"))] +use alloc::{collections::btree_map, format, string::String, vec::Vec}; use core::{num::NonZeroU64, time::Duration}; +#[cfg(feature = "std")] +use std::collections::btree_map; +use iroha_data_model_derive::model; use nonzero_ext::nonzero; -use strum::EnumDiscriminants; pub use self::model::*; -use super::*; +use crate::{name::Name, JsonString}; + +/// Collection of [`CustomParameter`]s +type CustomParameters = btree_map::BTreeMap; #[model] mod model { - use getset::CopyGetters; + use derive_more::{Constructor, Display, FromStr}; + use getset::{CopyGetters, Getters}; + use iroha_data_model_derive::IdEqOrdHash; + use iroha_schema::IntoSchema; + use parity_scale_codec::{Decode, Encode}; + use serde::{Deserialize, Serialize}; + use strum::EnumDiscriminants; use super::*; - /// Limits that a transaction must obey to be accepted. + /// Id of a custom parameter + #[derive( + Debug, + Display, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + FromStr, + Constructor, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] + #[ffi_type] + pub struct CustomParameterId(pub Name); + + /// Limits that govern consensus operation #[derive( Debug, Display, @@ -23,20 +57,46 @@ mod model { Eq, PartialOrd, Ord, - CopyGetters, Decode, Encode, Deserialize, Serialize, IntoSchema, )] - #[display(fmt = "{max_instructions},{smart_contract_size}_TL")] - #[getset(get_copy = "pub")] - pub struct TransactionLimits { - /// Maximum number of instructions per transaction - pub max_instructions: NonZeroU64, - /// Maximum size of wasm binary in bytes - pub smart_contract_size: NonZeroU64, + #[display(fmt = "{block_time_ms},{commit_time_ms}_SL")] + pub struct SumeragiParameters { + /// Maximal amount of time (in milliseconds) a peer will wait before forcing creation of a new block. + /// + /// A block is created if this limit or [`BlockParameters::max_transactions`] limit is reached, + /// whichever comes first. Regardless of the limits, an empty block is never created. + pub block_time_ms: u64, + /// Time (in milliseconds) a peer will wait for a block to be committed. + /// + /// If this period expires the block will request a view change + pub commit_time_ms: u64, + } + + /// Single Sumeragi parameter + /// + /// Check [`SumeragiParameters`] for more details + #[derive( + Debug, + Display, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Serialize, + Deserialize, + IntoSchema, + )] + pub enum SumeragiParameter { + BlockTimeMs(u64), + CommitTimeMs(u64), } /// Limits that a block must obey to be accepted. @@ -58,15 +118,86 @@ mod model { )] #[display(fmt = "{max_transactions}_BL")] #[getset(get_copy = "pub")] - pub struct BlockLimits { + pub struct BlockParameters { /// Maximal number of transactions in a block. /// - /// A block is created if this limit is reached or `Self::BlockTime` has expired, + /// A block is created if this limit is reached or [`SumeragiParameters::block_time_ms`] has expired, /// whichever comes first. Regardless of the limits, an empty block is never created. pub max_transactions: NonZeroU64, } - /// Limits that a smart contract must obey at runtime to not be considered invalid. + /// Single block parameter + /// + /// Check [`BlockParameters`] for more details + #[derive( + Debug, + Display, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Serialize, + Deserialize, + IntoSchema, + )] + pub enum BlockParameter { + MaxTransactions(NonZeroU64), + } + + /// Limits that a transaction must obey to be accepted. + #[derive( + Debug, + Display, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + CopyGetters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] + #[display(fmt = "{max_instructions},{smart_contract_size}_TL")] + #[getset(get_copy = "pub")] + pub struct TransactionParameters { + /// Maximum number of instructions per transaction + pub max_instructions: NonZeroU64, + /// Maximum size of wasm binary in bytes + pub smart_contract_size: NonZeroU64, + } + + /// Single transaction parameter + /// + /// Check [`TransactionParameters`] for more details + #[derive( + Debug, + Display, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Serialize, + Deserialize, + IntoSchema, + )] + pub enum TransactionParameter { + MaxInstructions(NonZeroU64), + SmartContractSize(NonZeroU64), + } + + /// Limits that a smart contract must obey at runtime to considered valid. #[derive( Debug, Display, @@ -83,56 +214,55 @@ mod model { Deserialize, IntoSchema, )] - #[display(fmt = "{fuel},{memory}_SL")] + #[display(fmt = "{fuel},{memory}_SCL")] #[getset(get_copy = "pub")] - pub struct SmartContractLimits { + pub struct SmartContractParameters { /// Maximum amount of fuel that a smart contract can consume pub fuel: NonZeroU64, /// Maximum amount of memory that a smart contract can use pub memory: NonZeroU64, } - /// Single blockchain [`Parameter`]. Controls how blockchain works. + /// Single smart contract parameter + /// + /// Check [`SmartContractParameters`] for more details #[derive( Debug, + Display, Clone, + Copy, PartialEq, Eq, PartialOrd, Ord, - EnumDiscriminants, Decode, Encode, - Deserialize, Serialize, + Deserialize, IntoSchema, )] - #[ffi_type(opaque)] - pub enum Parameter { - /// Maximal amount of time a peer will wait before forcing creation of a new block. - /// - /// A block is created if this limit or `Self::TransactionsInBlock` limit is reached, - /// whichever comes first. Regardless of the limits, an empty block is never created. - BlockTime(Duration), - /// How long a peer will wait for a block to be committed. + pub enum SmartContractParameter { + Fuel(NonZeroU64), + Memory(NonZeroU64), + } + + /// Blockchain specific parameter defined in the executor + #[derive( + Debug, Display, Clone, IdEqOrdHash, Decode, Encode, Deserialize, Serialize, IntoSchema, + )] + #[ffi_type] + #[display(fmt = "{id}({payload})")] + pub struct CustomParameter { + /// Unique id of the parameter. + pub id: CustomParameterId, + /// Payload containing actual value. /// - /// If this period expires the block will request a view change - CommitTime(Duration), - /// Block limits - BlockLimits(BlockLimits), - /// Transaction limits. - TransactionLimits(TransactionLimits), - /// Smart contract limits (user submitted smart contracts and triggers) - SmartContractLimits(SmartContractLimits), - /// Executor limits - ExecutorLimits(SmartContractLimits), - /// Blockchain specific parameter (defined in the executor) - Custom(JsonString), + /// It is JSON-encoded, and its structure must correspond to the structure of + /// the type defined in [`crate::executor::ExecutorDataModel`]. + pub payload: JsonString, } /// Set of all current blockchain parameter values - /// - /// See [`Parameter`] for details #[derive( Debug, Clone, @@ -140,59 +270,117 @@ mod model { Eq, PartialOrd, Ord, + Default, + Getters, + CopyGetters, Decode, Encode, Deserialize, Serialize, IntoSchema, )] - #[allow(missing_docs)] pub struct Parameters { - pub block_time: Duration, - pub commit_time: Duration, - pub block_limits: BlockLimits, - pub transaction_limits: TransactionLimits, - pub executor_limits: SmartContractLimits, - pub smart_contract_limits: SmartContractLimits, - /// Collection of all custom parameters - pub custom: JsonString, + /// Sumeragi parameters + #[getset(get_copy = "pub")] + pub sumeragi: SumeragiParameters, + /// Block parameters + #[getset(get_copy = "pub")] + pub block: BlockParameters, + /// Transaction parameters + #[getset(get_copy = "pub")] + pub transaction: TransactionParameters, + /// Executor parameters + #[getset(get_copy = "pub")] + pub executor: SmartContractParameters, + /// Smart contract parameters + #[getset(get_copy = "pub")] + pub smart_contract: SmartContractParameters, + /// Collection of blockchain specific parameters + #[getset(get = "pub")] + pub custom: CustomParameters, + } + + /// Single blockchain parameter. + /// + /// Check [`Parameters`] for more details + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + EnumDiscriminants, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] + #[ffi_type(opaque)] + pub enum Parameter { + Sumeragi(SumeragiParameter), + Block(BlockParameter), + Transaction(TransactionParameter), + SmartContract(SmartContractParameter), + Executor(SmartContractParameter), + Custom(CustomParameter), } } impl core::fmt::Display for Parameter { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::BlockTime(v) | Self::CommitTime(v) => core::fmt::Debug::fmt(&v, f), - Self::BlockLimits(v) => core::fmt::Display::fmt(&v, f), - Self::TransactionLimits(v) => core::fmt::Display::fmt(&v, f), - Self::SmartContractLimits(v) | Self::ExecutorLimits(v) => { - core::fmt::Display::fmt(&v, f) - } - Self::Custom(v) => write!(f, "Custom({})", v.0), + Self::Sumeragi(v) => core::fmt::Display::fmt(&v, f), + Self::Block(v) => core::fmt::Display::fmt(&v, f), + Self::Transaction(v) => core::fmt::Display::fmt(&v, f), + Self::SmartContract(v) | Self::Executor(v) => core::fmt::Display::fmt(&v, f), + Self::Custom(v) => write!(f, "{}({})", v.id, v.payload), } } } -impl Default for Parameters { +impl SumeragiParameters { + /// Maximal amount of time (in milliseconds) a peer will wait before forcing creation of a new block. + /// + /// A block is created if this limit or [`BlockParameters::max_transactions`] limit is reached, + /// whichever comes first. Regardless of the limits, an empty block is never created. + pub fn block_time(&self) -> Duration { + Duration::from_millis(self.block_time_ms) + } + + /// Time (in milliseconds) a peer will wait for a block to be committed. + /// + /// If this period expires the block will request a view change + pub fn commit_time(&self) -> Duration { + Duration::from_millis(self.commit_time_ms) + } + + /// Maximal amount of time it takes to commit a block + #[cfg(feature = "transparent_api")] + pub fn pipeline_time(&self) -> Duration { + self.block_time() + self.commit_time() + } + + /// Estimation of consensus duration + #[cfg(feature = "transparent_api")] + pub fn consensus_estimation(&self) -> Duration { + self.block_time() + (self.commit_time() / 2) + } +} + +impl Default for SumeragiParameters { fn default() -> Self { - /// Default value for [`Parameters::BlockTime`] - pub const DEFAULT_BLOCK_TIME: Duration = Duration::from_secs(2); - /// Default value for [`Parameters::CommitTime`] - pub const DEFAULT_COMMIT_TIME: Duration = Duration::from_secs(4); + pub const DEFAULT_BLOCK_TIME: u64 = 2_000; + pub const DEFAULT_COMMIT_TIME: u64 = 4_000; Self { - block_time: DEFAULT_BLOCK_TIME, - commit_time: DEFAULT_COMMIT_TIME, - block_limits: BlockLimits::default(), - transaction_limits: TransactionLimits::default(), - executor_limits: SmartContractLimits::default(), - smart_contract_limits: SmartContractLimits::default(), - custom: JsonString::default(), + block_time_ms: DEFAULT_BLOCK_TIME, + commit_time_ms: DEFAULT_COMMIT_TIME, } } } - -impl Default for BlockLimits { +impl Default for BlockParameters { fn default() -> Self { /// Default value for [`Parameters::MaxTransactionsInBlock`] pub const DEFAULT_TRANSACTIONS_IN_BLOCK: NonZeroU64 = nonzero!(2_u64.pow(9)); @@ -201,7 +389,7 @@ impl Default for BlockLimits { } } -impl Default for TransactionLimits { +impl Default for TransactionParameters { fn default() -> Self { const DEFAULT_INSTRUCTION_NUMBER: NonZeroU64 = nonzero!(2_u64.pow(12)); const DEFAULT_SMART_CONTRACT_SIZE: NonZeroU64 = nonzero!(4 * 2_u64.pow(20)); @@ -210,7 +398,7 @@ impl Default for TransactionLimits { } } -impl Default for SmartContractLimits { +impl Default for SmartContractParameters { fn default() -> Self { const DEFAULT_FUEL: NonZeroU64 = nonzero!(55_000_000_u64); const DEFAULT_MEMORY: NonZeroU64 = nonzero!(55_000_000_u64); @@ -222,14 +410,30 @@ impl Default for SmartContractLimits { } } -impl BlockLimits { +impl SumeragiParameters { + /// Construct [`Self`] + pub fn new(block_time: Duration, commit_time: Duration) -> Self { + Self { + block_time_ms: block_time + .as_millis() + .try_into() + .expect("INTERNAL BUG: Time should fit into u64"), + commit_time_ms: commit_time + .as_millis() + .try_into() + .expect("INTERNAL BUG: Time should fit into u64"), + } + } +} + +impl BlockParameters { /// Construct [`Self`] pub const fn new(max_transactions: NonZeroU64) -> Self { Self { max_transactions } } } -impl TransactionLimits { +impl TransactionParameters { /// Construct [`Self`] pub const fn new(max_instructions: NonZeroU64, smart_contract_size: NonZeroU64) -> Self { Self { @@ -239,8 +443,31 @@ impl TransactionLimits { } } +impl CustomParameterId { + /// Getter for name + pub fn name(&self) -> &Name { + &self.0 + } +} + +impl CustomParameter { + /// Constructor + pub fn new(id: CustomParameterId, payload: impl Into) -> Self { + Self { + id, + payload: payload.into(), + } + } + + /// Getter + // TODO: derive with getset once FFI impl is fixed + pub fn payload(&self) -> &JsonString { + &self.payload + } +} + pub mod prelude { //! Prelude: re-export of most commonly used traits, structs and macros in this crate. - pub use super::{Parameter, Parameters, SmartContractLimits, TransactionLimits}; + pub use super::{Parameter, Parameters, SmartContractParameters, TransactionParameters}; } diff --git a/data_model/src/peer.rs b/data_model/src/peer.rs index ffacb39dd98..72ab6b9a8e8 100644 --- a/data_model/src/peer.rs +++ b/data_model/src/peer.rs @@ -9,18 +9,19 @@ use core::{ }; use derive_more::Display; -use iroha_data_model_derive::{model, IdEqOrdHash}; +use iroha_data_model_derive::model; use iroha_primitives::addr::SocketAddr; -use iroha_schema::IntoSchema; -use parity_scale_codec::{Decode, Encode}; -use serde::{Deserialize, Serialize}; pub use self::model::*; -use crate::{Identifiable, PublicKey, Registered}; +use crate::{PublicKey, Registered}; #[model] mod model { use getset::Getters; + use iroha_data_model_derive::IdEqOrdHash; + use iroha_schema::IntoSchema; + use parity_scale_codec::{Decode, Encode}; + use serde::{Deserialize, Serialize}; use super::*; diff --git a/data_model/src/permission.rs b/data_model/src/permission.rs index 253c1784d37..33cbe408c31 100644 --- a/data_model/src/permission.rs +++ b/data_model/src/permission.rs @@ -6,19 +6,20 @@ use std::collections::BTreeSet; use iroha_data_model_derive::model; use iroha_schema::IntoSchema; -use parity_scale_codec::{Decode, Encode}; -use serde::{Deserialize, Serialize}; pub use self::model::*; -use crate::name::Name; +use crate::{name::Name, JsonString}; -/// Collection of [`Token`]s +/// Collection of [`Permission`]s pub type Permissions = BTreeSet; -use super::*; - #[model] mod model { + use derive_more::{Constructor, Display, FromStr}; + use getset::Getters; + use parity_scale_codec::{Decode, Encode}; + use serde::{Deserialize, Serialize}; + use super::*; /// Identifies a [`Permission`]. @@ -67,7 +68,7 @@ mod model { Getters, )] #[ffi_type] - #[display(fmt = "PERMISSION `{id}` = `{payload}`")] + #[display(fmt = "{id}({payload})")] #[getset(get = "pub")] pub struct Permission { /// Refers to a type defined in [`crate::executor::ExecutorDataModel`]. diff --git a/data_model/src/query/predicate.rs b/data_model/src/query/predicate.rs index a0d7e152900..2eabc6f1116 100644 --- a/data_model/src/query/predicate.rs +++ b/data_model/src/query/predicate.rs @@ -602,6 +602,7 @@ pub mod string { IdBox::TriggerId(id) => self.applies(&id.to_string()), IdBox::RoleId(id) => self.applies(&id.to_string()), IdBox::PermissionId(id) => self.applies(&id.to_string()), + IdBox::CustomParameterId(id) => self.applies(&id.to_string()), } } } diff --git a/data_model/src/role.rs b/data_model/src/role.rs index 45c6b53732a..834ef75e57b 100644 --- a/data_model/src/role.rs +++ b/data_model/src/role.rs @@ -3,21 +3,23 @@ #[cfg(not(feature = "std"))] use alloc::{format, string::String, vec::Vec}; -use derive_more::{Constructor, Display, FromStr}; -use getset::Getters; -use iroha_data_model_derive::{model, IdEqOrdHash}; -use iroha_schema::IntoSchema; -use parity_scale_codec::{Decode, Encode}; -use serde::{Deserialize, Serialize}; +use iroha_data_model_derive::model; pub use self::model::*; use crate::{ permission::{Permission, Permissions}, - Identifiable, Name, Registered, + Name, Registered, }; #[model] mod model { + use derive_more::{Constructor, Display, FromStr}; + use getset::Getters; + use iroha_data_model_derive::IdEqOrdHash; + use iroha_schema::IntoSchema; + use parity_scale_codec::{Decode, Encode}; + use serde::{Deserialize, Serialize}; + use super::*; /// Identification of a role. diff --git a/data_model/src/trigger.rs b/data_model/src/trigger.rs index 8893ff88084..8be9660bc05 100644 --- a/data_model/src/trigger.rs +++ b/data_model/src/trigger.rs @@ -17,9 +17,7 @@ use serde::{Deserialize, Serialize}; use serde_with::{DeserializeFromStr, SerializeDisplay}; pub use self::model::*; -use crate::{ - events::prelude::*, metadata::Metadata, transaction::Executable, Identifiable, Name, Registered, -}; +use crate::{events::prelude::*, metadata::Metadata, transaction::Executable, Name, Registered}; #[model] mod model { diff --git a/default_executor/src/lib.rs b/default_executor/src/lib.rs index a506d4df6dc..9e79fec18a9 100644 --- a/default_executor/src/lib.rs +++ b/default_executor/src/lib.rs @@ -49,7 +49,7 @@ impl Executor { /// If `migrate()` entrypoint fails then the whole `Upgrade` instruction /// will be denied and previous executor will stay unchanged. #[entrypoint] -pub fn migrate(block_height: u64) -> MigrationResult { +fn migrate(block_height: u64) -> MigrationResult { Executor::ensure_genesis(block_height)?; DataModelBuilder::with_default_permissions().build_and_set(); diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 06cb3c9e6fc..210752dae4f 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -18,58 +18,48 @@ "AccountEvent": { "Enum": [ { - "tag": "Create", + "tag": "Created", "discriminant": 0, "type": "Account" }, { - "tag": "Delete", + "tag": "Deleted", "discriminant": 1, "type": "AccountId" }, - { - "tag": "AuthenticationAdd", - "discriminant": 2, - "type": "AccountId" - }, - { - "tag": "AuthenticationRemove", - "discriminant": 3, - "type": "AccountId" - }, { "tag": "Asset", - "discriminant": 4, + "discriminant": 2, "type": "AssetEvent" }, { - "tag": "PermissionAdd", - "discriminant": 5, + "tag": "PermissionAdded", + "discriminant": 3, "type": "AccountPermissionChanged" }, { - "tag": "PermissionRemove", - "discriminant": 6, + "tag": "PermissionRemoved", + "discriminant": 4, "type": "AccountPermissionChanged" }, { - "tag": "RoleGrant", - "discriminant": 7, + "tag": "RoleGranted", + "discriminant": 5, "type": "AccountRoleChanged" }, { - "tag": "RoleRevoke", - "discriminant": 8, + "tag": "RoleRevoked", + "discriminant": 6, "type": "AccountRoleChanged" }, { - "tag": "MetadataInsert", - "discriminant": 9, + "tag": "MetadataInserted", + "discriminant": 7, "type": "MetadataChanged" }, { - "tag": "MetadataRemove", - "discriminant": 10, + "tag": "MetadataRemoved", + "discriminant": 8, "type": "MetadataChanged" } ] @@ -91,48 +81,40 @@ "repr": "u32", "masks": [ { - "name": "Create", + "name": "Created", "mask": 1 }, { - "name": "Delete", + "name": "Deleted", "mask": 2 }, { - "name": "AuthenticationAdd", + "name": "AnyAsset", "mask": 4 }, { - "name": "AuthenticationRemove", + "name": "PermissionAdded", "mask": 8 }, { - "name": "AnyAsset", + "name": "PermissionRemoved", "mask": 16 }, { - "name": "PermissionAdd", + "name": "RoleGranted", "mask": 32 }, { - "name": "PermissionRemove", + "name": "RoleRevoked", "mask": 64 }, { - "name": "RoleGrant", + "name": "MetadataInserted", "mask": 128 }, { - "name": "RoleRevoke", + "name": "MetadataRemoved", "mask": 256 - }, - { - "name": "MetadataInsert", - "mask": 512 - }, - { - "name": "MetadataRemove", - "mask": 1024 } ] } @@ -290,7 +272,7 @@ "AssetDefinitionEvent": { "Enum": [ { - "tag": "Create", + "tag": "Created", "discriminant": 0, "type": "AssetDefinition" }, @@ -300,27 +282,27 @@ "type": "AssetDefinitionId" }, { - "tag": "MetadataInsert", + "tag": "MetadataInserted", "discriminant": 2, "type": "MetadataChanged" }, { - "tag": "MetadataRemove", + "tag": "MetadataRemoved", "discriminant": 3, "type": "MetadataChanged" }, { - "tag": "MintabilityChange", + "tag": "MintabilityChanged", "discriminant": 4, "type": "AssetDefinitionId" }, { - "tag": "TotalQuantityChange", + "tag": "TotalQuantityChanged", "discriminant": 5, "type": "AssetDefinitionTotalQuantityChanged" }, { - "tag": "OwnerChange", + "tag": "OwnerChanged", "discriminant": 6, "type": "AssetDefinitionOwnerChanged" } @@ -343,7 +325,7 @@ "repr": "u32", "masks": [ { - "name": "Create", + "name": "Created", "mask": 1 }, { @@ -351,23 +333,23 @@ "mask": 2 }, { - "name": "MetadataInsert", + "name": "MetadataInserted", "mask": 4 }, { - "name": "MetadataRemove", + "name": "MetadataRemoved", "mask": 8 }, { - "name": "MintabilityChange", + "name": "MintabilityChanged", "mask": 16 }, { - "name": "TotalQuantityChange", + "name": "TotalQuantityChanged", "mask": 32 }, { - "name": "OwnerChange", + "name": "OwnerChanged", "mask": 64 } ] @@ -412,32 +394,32 @@ "AssetEvent": { "Enum": [ { - "tag": "Create", + "tag": "Created", "discriminant": 0, "type": "Asset" }, { - "tag": "Delete", + "tag": "Deleted", "discriminant": 1, "type": "AssetId" }, { - "tag": "Add", + "tag": "Added", "discriminant": 2, "type": "AssetChanged" }, { - "tag": "Remove", + "tag": "Removed", "discriminant": 3, "type": "AssetChanged" }, { - "tag": "MetadataInsert", + "tag": "MetadataInserted", "discriminant": 4, "type": "MetadataChanged" }, { - "tag": "MetadataRemove", + "tag": "MetadataRemoved", "discriminant": 5, "type": "MetadataChanged" } @@ -460,27 +442,27 @@ "repr": "u32", "masks": [ { - "name": "Create", + "name": "Created", "mask": 1 }, { - "name": "Delete", + "name": "Deleted", "mask": 2 }, { - "name": "Add", + "name": "Added", "mask": 4 }, { - "name": "Remove", + "name": "Removed", "mask": 8 }, { - "name": "MetadataInsert", + "name": "MetadataInserted", "mask": 16 }, { - "name": "MetadataRemove", + "name": "MetadataRemoved", "mask": 32 } ] @@ -628,7 +610,17 @@ } ] }, - "BlockLimits": { + "BlockMessage": "SignedBlock", + "BlockParameter": { + "Enum": [ + { + "tag": "MaxTransactions", + "discriminant": 0, + "type": "NonZero" + } + ] + }, + "BlockParameters": { "Struct": [ { "name": "max_transactions", @@ -636,7 +628,6 @@ } ] }, - "BlockMessage": "SignedBlock", "BlockPayload": { "Struct": [ { @@ -781,9 +772,9 @@ "ConfigurationEvent": { "Enum": [ { - "tag": "Change", + "tag": "Changed", "discriminant": 0, - "type": "Parameter" + "type": "ParameterChanged" } ] }, @@ -800,7 +791,7 @@ "repr": "u32", "masks": [ { - "name": "Change", + "name": "Changed", "mask": 1 } ] @@ -833,6 +824,19 @@ } ] }, + "CustomParameter": { + "Struct": [ + { + "name": "id", + "type": "CustomParameterId" + }, + { + "name": "payload", + "type": "JsonString" + } + ] + }, + "CustomParameterId": "Name", "DataEvent": { "Enum": [ { @@ -951,12 +955,12 @@ "DomainEvent": { "Enum": [ { - "tag": "Create", + "tag": "Created", "discriminant": 0, "type": "Domain" }, { - "tag": "Delete", + "tag": "Deleted", "discriminant": 1, "type": "DomainId" }, @@ -971,17 +975,17 @@ "type": "AccountEvent" }, { - "tag": "MetadataInsert", + "tag": "MetadataInserted", "discriminant": 4, "type": "MetadataChanged" }, { - "tag": "MetadataRemove", + "tag": "MetadataRemoved", "discriminant": 5, "type": "MetadataChanged" }, { - "tag": "OwnerChange", + "tag": "OwnerChanged", "discriminant": 6, "type": "DomainOwnerChanged" } @@ -1004,11 +1008,11 @@ "repr": "u32", "masks": [ { - "name": "Create", + "name": "Created", "mask": 1 }, { - "name": "Delete", + "name": "Deleted", "mask": 2 }, { @@ -1020,15 +1024,15 @@ "mask": 8 }, { - "name": "MetadataInsert", + "name": "MetadataInserted", "mask": 16 }, { - "name": "MetadataRemove", + "name": "MetadataRemoved", "mask": 32 }, { - "name": "OwnerChange", + "name": "OwnerChanged", "mask": 64 } ] @@ -1189,14 +1193,18 @@ }, "ExecutorDataModel": { "Struct": [ - { - "name": "permissions", - "type": "SortedVec" - }, { "name": "custom_instruction", "type": "Option" }, + { + "name": "parameters", + "type": "SortedVec" + }, + { + "name": "permissions", + "type": "SortedVec" + }, { "name": "schema", "type": "JsonString" @@ -1206,7 +1214,7 @@ "ExecutorEvent": { "Enum": [ { - "tag": "Upgrade", + "tag": "Upgraded", "discriminant": 0, "type": "ExecutorUpgrade" } @@ -1225,7 +1233,7 @@ "repr": "u32", "masks": [ { - "name": "Upgrade", + "name": "Upgraded", "mask": 1 } ] @@ -1708,6 +1716,11 @@ "tag": "PermissionId", "discriminant": 7, "type": "PermissionId" + }, + { + "tag": "CustomParameterId", + "discriminant": 8, + "type": "CustomParameterId" } ] }, @@ -1767,6 +1780,11 @@ "tag": "Role", "discriminant": 10, "type": "Role" + }, + { + "tag": "CustomParameter", + "discriminant": 11, + "type": "CustomParameter" } ] }, @@ -2449,71 +2467,74 @@ "Parameter": { "Enum": [ { - "tag": "BlockTime", + "tag": "Sumeragi", "discriminant": 0, - "type": "Duration" + "type": "SumeragiParameter" }, { - "tag": "CommitTime", + "tag": "Block", "discriminant": 1, - "type": "Duration" + "type": "BlockParameter" }, { - "tag": "BlockLimits", + "tag": "Transaction", "discriminant": 2, - "type": "BlockLimits" + "type": "TransactionParameter" }, { - "tag": "TransactionLimits", + "tag": "SmartContract", "discriminant": 3, - "type": "TransactionLimits" + "type": "SmartContractParameter" }, { - "tag": "SmartContractLimits", + "tag": "Executor", "discriminant": 4, - "type": "SmartContractLimits" + "type": "SmartContractParameter" }, { - "tag": "ExecutorLimits", + "tag": "Custom", "discriminant": 5, - "type": "SmartContractLimits" + "type": "CustomParameter" + } + ] + }, + "ParameterChanged": { + "Struct": [ + { + "name": "prev", + "type": "Parameter" }, { - "tag": "Custom", - "discriminant": 6, - "type": "JsonString" + "name": "next", + "type": "Parameter" } ] }, "Parameters": { "Struct": [ { - "name": "block_time", - "type": "Duration" - }, - { - "name": "commit_time", - "type": "Duration" + "name": "sumeragi", + "type": "SumeragiParameters" }, { - "name": "block_limits", - "type": "BlockLimits" + "name": "block", + "type": "BlockParameters" }, { - "name": "transaction_limits", - "type": "TransactionLimits" + "name": "transaction", + "type": "TransactionParameters" }, { - "name": "executor_limits", - "type": "SmartContractLimits" + "name": "executor", + "type": "SmartContractParameters" }, { - "name": "smart_contract_limits", - "type": "SmartContractLimits" + "name": "smart_contract", + "type": "SmartContractParameters" }, { "name": "custom", - "type": "JsonString" + "type": "SortedMap" } ] }, @@ -2528,12 +2549,12 @@ "PeerEvent": { "Enum": [ { - "tag": "Add", + "tag": "Added", "discriminant": 0, "type": "PeerId" }, { - "tag": "Remove", + "tag": "Removed", "discriminant": 1, "type": "PeerId" } @@ -2556,11 +2577,11 @@ "repr": "u32", "masks": [ { - "name": "Add", + "name": "Added", "mask": 1 }, { - "name": "Remove", + "name": "Removed", "mask": 2 } ] @@ -3260,22 +3281,22 @@ "RoleEvent": { "Enum": [ { - "tag": "Create", + "tag": "Created", "discriminant": 0, "type": "Role" }, { - "tag": "Delete", + "tag": "Deleted", "discriminant": 1, "type": "RoleId" }, { - "tag": "PermissionAdd", + "tag": "PermissionAdded", "discriminant": 2, "type": "RolePermissionChanged" }, { - "tag": "PermissionRemove", + "tag": "PermissionRemoved", "discriminant": 3, "type": "RolePermissionChanged" } @@ -3298,19 +3319,19 @@ "repr": "u32", "masks": [ { - "name": "Create", + "name": "Created", "mask": 1 }, { - "name": "Delete", + "name": "Deleted", "mask": 2 }, { - "name": "PermissionAdd", + "name": "PermissionAdded", "mask": 4 }, { - "name": "PermissionRemove", + "name": "PermissionRemoved", "mask": 8 } ] @@ -3565,7 +3586,21 @@ } ] }, - "SmartContractLimits": { + "SmartContractParameter": { + "Enum": [ + { + "tag": "Fuel", + "discriminant": 0, + "type": "NonZero" + }, + { + "tag": "Memory", + "discriminant": 1, + "type": "NonZero" + } + ] + }, + "SmartContractParameters": { "Struct": [ { "name": "fuel", @@ -3650,12 +3685,21 @@ "value": "Numeric" } }, + "SortedMap": { + "Map": { + "key": "CustomParameterId", + "value": "JsonString" + } + }, "SortedMap": { "Map": { "key": "Name", "value": "MetadataValueBox" } }, + "SortedVec": { + "Vec": "CustomParameterId" + }, "SortedVec": { "Vec": "Permission" }, @@ -3695,6 +3739,32 @@ } ] }, + "SumeragiParameter": { + "Enum": [ + { + "tag": "BlockTimeMs", + "discriminant": 0, + "type": "u64" + }, + { + "tag": "CommitTimeMs", + "discriminant": 1, + "type": "u64" + } + ] + }, + "SumeragiParameters": { + "Struct": [ + { + "name": "block_time_ms", + "type": "u64" + }, + { + "name": "commit_time_ms", + "type": "u64" + } + ] + }, "TimeEvent": { "Struct": [ { @@ -3760,7 +3830,21 @@ } ] }, - "TransactionLimits": { + "TransactionParameter": { + "Enum": [ + { + "tag": "MaxInstructions", + "discriminant": 0, + "type": "NonZero" + }, + { + "tag": "SmartContractSize", + "discriminant": 1, + "type": "NonZero" + } + ] + }, + "TransactionParameters": { "Struct": [ { "name": "max_instructions", @@ -4014,32 +4098,32 @@ "TriggerEvent": { "Enum": [ { - "tag": "Create", + "tag": "Created", "discriminant": 0, "type": "TriggerId" }, { - "tag": "Delete", + "tag": "Deleted", "discriminant": 1, "type": "TriggerId" }, { - "tag": "Extend", + "tag": "Extended", "discriminant": 2, "type": "TriggerNumberOfExecutionsChanged" }, { - "tag": "Shorten", + "tag": "Shortened", "discriminant": 3, "type": "TriggerNumberOfExecutionsChanged" }, { - "tag": "MetadataInsert", + "tag": "MetadataInserted", "discriminant": 4, "type": "MetadataChanged" }, { - "tag": "MetadataRemove", + "tag": "MetadataRemoved", "discriminant": 5, "type": "MetadataChanged" } @@ -4062,27 +4146,27 @@ "repr": "u32", "masks": [ { - "name": "Create", + "name": "Created", "mask": 1 }, { - "name": "Delete", + "name": "Deleted", "mask": 2 }, { - "name": "Extend", + "name": "Extended", "mask": 4 }, { - "name": "Shorten", + "name": "Shortened", "mask": 8 }, { - "name": "MetadataInsert", + "name": "MetadataInserted", "mask": 16 }, { - "name": "MetadataRemove", + "name": "MetadataRemoved", "mask": 32 } ] diff --git a/smart_contract/executor/derive/src/lib.rs b/smart_contract/executor/derive/src/lib.rs index 4b11347a112..6c3360d5417 100644 --- a/smart_contract/executor/derive/src/lib.rs +++ b/smart_contract/executor/derive/src/lib.rs @@ -7,6 +7,7 @@ use proc_macro2::TokenStream; mod conversion; mod default; mod entrypoint; +mod parameter; mod permission; mod validate; @@ -100,6 +101,16 @@ pub fn derive_permission(input: TokenStream) -> Result { Ok(permission::impl_derive_permission(&input)) } +/// Derive macro for `Parameter` trait. +/// ``` +#[manyhow] +#[proc_macro_derive(Parameter)] +pub fn derive_parameter(input: TokenStream) -> Result { + let input = syn::parse2(input)?; + + Ok(parameter::impl_derive_parameter(&input)) +} + /// Derive macro for `ValidateGrantRevoke` trait. /// /// # Attributes diff --git a/smart_contract/executor/derive/src/parameter.rs b/smart_contract/executor/derive/src/parameter.rs new file mode 100644 index 00000000000..7fcfdbf1176 --- /dev/null +++ b/smart_contract/executor/derive/src/parameter.rs @@ -0,0 +1,37 @@ +//! Module with [`derive_parameter`](crate::derive_parameter) macro implementation + +use proc_macro2::TokenStream; +use quote::quote; + +/// [`derive_parameter`](crate::derive_parameter()) macro implementation +pub fn impl_derive_parameter(input: &syn::DeriveInput) -> TokenStream { + let generics = &input.generics; + let ident = &input.ident; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + impl #impl_generics ::iroha_executor::parameter::Parameter for #ident #ty_generics #where_clause {} + + impl #impl_generics TryFrom<&::iroha_executor::data_model::param::CustomParameter> for #ident #ty_generics #where_clause { + type Error = ::iroha_executor::TryFromDataModelObjectError; + + fn try_from(value: &::iroha_executor::data_model::param::CustomParameter) -> core::result::Result { + if *value.id() != ::id() { + return Err(Self::Error::Id(value.id().name().clone())); + } + + serde_json::from_str::(value.payload().as_ref()).map_err(Self::Error::Deserialize) + } + } + + impl #impl_generics From<#ident #ty_generics> for ::iroha_executor::data_model::param::CustomParameter #where_clause { + fn from(value: #ident #ty_generics) -> Self { + ::iroha_executor::data_model::param::CustomParameter::new( + <#ident as ::iroha_executor::parameter::Parameter>::id(), + ::serde_json::to_value::<#ident #ty_generics>(value) + .expect("INTERNAL BUG: Failed to serialize Executor data model entity"), + ) + } + } + } +} diff --git a/smart_contract/executor/src/lib.rs b/smart_contract/executor/src/lib.rs index 78b34b0f198..747aeeaed78 100644 --- a/smart_contract/executor/src/lib.rs +++ b/smart_contract/executor/src/lib.rs @@ -19,6 +19,7 @@ use iroha_smart_contract_utils::{decode_with_length_prefix_from_raw, encode_and_ pub use smart_contract::{data_model, parse, stub_getrandom}; pub mod default; +pub mod parameter; pub mod permission; pub mod utils { @@ -188,8 +189,9 @@ pub enum TryFromDataModelObjectError { /// A convenience to build [`ExecutorDataModel`] from within the executor #[derive(Debug, Clone)] pub struct DataModelBuilder { - permissions: BTreeSet, custom_instruction: Option, + parameters: BTreeSet, + permissions: BTreeSet, schema: MetaMap, } @@ -199,8 +201,9 @@ impl DataModelBuilder { #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { - permissions: <_>::default(), custom_instruction: None, + parameters: <_>::default(), + permissions: <_>::default(), schema: <_>::default(), } } @@ -229,6 +232,14 @@ impl DataModelBuilder { self } + /// Define a permission in the data model + #[must_use] + pub fn add_parameter(mut self) -> Self { + ::update_schema_map(&mut self.schema); + self.parameters.insert(::id()); + self + } + /// Define a type of custom instruction in the data model. /// Corresponds to payload of `InstructionBox::Custom`. #[must_use] @@ -251,8 +262,9 @@ impl DataModelBuilder { #[cfg(not(test))] pub fn build_and_set(self) { set_data_model(&ExecutorDataModel::new( - self.permissions, self.custom_instruction, + self.parameters, + self.permissions, serde_json::to_value(&self.schema) .expect("INTERNAL BUG: Failed to serialize Executor data model entity") .into(), @@ -278,8 +290,8 @@ pub mod prelude { pub use alloc::vec::Vec; pub use iroha_executor_derive::{ - entrypoint, Constructor, Permission, Validate, ValidateEntrypoints, ValidateGrantRevoke, - Visit, + entrypoint, Constructor, Parameter, Permission, Validate, ValidateEntrypoints, + ValidateGrantRevoke, Visit, }; pub use iroha_smart_contract::prelude::*; @@ -290,6 +302,7 @@ pub mod prelude { ValidationFail, }, deny, execute, + parameter::Parameter as ParameterTrait, permission::Permission as PermissionTrait, DataModelBuilder, Validate, }; diff --git a/smart_contract/executor/src/parameter.rs b/smart_contract/executor/src/parameter.rs new file mode 100644 index 00000000000..41565e96faa --- /dev/null +++ b/smart_contract/executor/src/parameter.rs @@ -0,0 +1,17 @@ +//! Module with parameter related functionality. + +use iroha_schema::IntoSchema; +use iroha_smart_contract::{data_model::param::CustomParameterId, debug::DebugExpectExt}; +use serde::{de::DeserializeOwned, Serialize}; + +/// Blockchain specific parameter +pub trait Parameter: Serialize + DeserializeOwned + IntoSchema { + /// Parameter id, according to [`IntoSchema`]. + fn id() -> CustomParameterId { + CustomParameterId::new( + ::type_name() + .parse() + .dbg_expect("Failed to parse parameter id as `Name`"), + ) + } +} diff --git a/smart_contract/executor/src/permission.rs b/smart_contract/executor/src/permission.rs index a6ead932324..42874c6285a 100644 --- a/smart_contract/executor/src/permission.rs +++ b/smart_contract/executor/src/permission.rs @@ -1,4 +1,4 @@ -//! Module with permission tokens and permission related functionality. +//! Module with permission related functionality. use alloc::borrow::ToOwned as _; @@ -9,7 +9,7 @@ use serde::{de::DeserializeOwned, Serialize}; use crate::prelude::{Permission as PermissionObject, *}; -/// Is used to check if the permission token is owned by the account. +/// Used to check if the permission token is owned by the account. pub trait Permission: Serialize + DeserializeOwned + IntoSchema + PartialEq + ValidateGrantRevoke { diff --git a/torii/src/routing.rs b/torii/src/routing.rs index 10ba3dde66c..3f8dbe997ef 100644 --- a/torii/src/routing.rs +++ b/torii/src/routing.rs @@ -52,7 +52,7 @@ pub async fn handle_transaction( transaction: SignedTransaction, ) -> Result { let state_view = state.view(); - let transaction_limits = state_view.world().parameters().transaction_limits; + let transaction_limits = state_view.world().parameters().transaction; let transaction = AcceptedTransaction::accept(transaction, &chain_id, transaction_limits) .map_err(Error::AcceptTransaction)?; queue