diff --git a/client/src/client.rs b/client/src/client.rs index f1079c1138a..5c53801742f 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -102,7 +102,7 @@ where You are likely using a version of the client library \ that is incompatible with the version of the peer software", ) - .map_err(Into::into) + .map_err(Into::into) } StatusCode::BAD_REQUEST | StatusCode::UNAUTHORIZED @@ -111,22 +111,22 @@ where | StatusCode::UNPROCESSABLE_ENTITY => Err(ValidationFail::decode_all( &mut resp.body().as_ref(), ) - .map_or_else( - |_| { - ClientQueryError::Other( - ResponseReport::with_msg("Query failed", resp) - .map_or_else( - |_| eyre!( + .map_or_else( + |_| { + ClientQueryError::Other( + ResponseReport::with_msg("Query failed", resp) + .map_or_else( + |_| eyre!( "Failed to decode response from Iroha. \ Response is neither a `ValidationFail` encoded value nor a valid utf-8 string error response. \ You are likely using a version of the client library that is incompatible with the version of the peer software", ), - Into::into - ), - ) - }, - ClientQueryError::Validation, - )), + Into::into + ), + ) + }, + ClientQueryError::Validation, + )), _ => Err(ResponseReport::with_msg("Unexpected query response", resp).unwrap_or_else(core::convert::identity).into()), } } @@ -328,7 +328,7 @@ impl_query_output! { crate::data_model::block::BlockHeader, crate::data_model::metadata::MetadataValueBox, crate::data_model::query::TransactionQueryOutput, - crate::data_model::permission::PermissionSchema, + crate::data_model::executor::ExecutorDataModel, crate::data_model::trigger::Trigger, crate::data_model::prelude::Numeric, } @@ -1517,11 +1517,6 @@ pub mod permission { //! Module with queries for permission tokens use super::*; - /// Construct a query to get all registered [`PermissionDefinition`]s - pub const fn permission_schema() -> FindPermissionSchema { - FindPermissionSchema {} - } - /// Construct a query to get all [`Permission`] granted /// to account with given [`Id`][AccountId] pub fn by_account_id(account_id: AccountId) -> FindPermissionsByAccountId { @@ -1564,6 +1559,16 @@ pub mod parameter { } } +pub mod executor { + //! Queries for executor entities + use super::*; + + /// Retrieve executor data model + pub const fn data_model() -> FindExecutorDataModel { + FindExecutorDataModel + } +} + #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/client/tests/integration/asset.rs b/client/tests/integration/asset.rs index b5912ddf528..e27a69b91de 100644 --- a/client/tests/integration/asset.rs +++ b/client/tests/integration/asset.rs @@ -298,7 +298,7 @@ fn find_rate_and_make_exchange_isi_should_succeed() { let instruction = Grant::permission( Permission::new( "CanTransferUserAsset".parse().unwrap(), - &json!({ "asset_id": asset_id }), + json!({ "asset_id": asset_id }), ), alice_id.clone(), ); diff --git a/client/tests/integration/domain_owner_permissions.rs b/client/tests/integration/domain_owner_permissions.rs index c5dd5d38a52..e9751363444 100644 --- a/client/tests/integration/domain_owner_permissions.rs +++ b/client/tests/integration/domain_owner_permissions.rs @@ -48,7 +48,7 @@ fn domain_owner_domain_permissions() -> Result<()> { // Granting a respective token also allows "bob@kingdom" to do so let token = Permission::new( "CanRegisterAssetDefinitionInDomain".parse().unwrap(), - &json!({ "domain_id": kingdom_id }), + json!({ "domain_id": kingdom_id }), ); test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; let transaction = TransactionBuilder::new(chain_id, bob_id.clone()) @@ -66,7 +66,7 @@ fn domain_owner_domain_permissions() -> Result<()> { // check that "alice@wonderland" as owner of domain can grant and revoke domain related permission tokens let token = Permission::new( "CanUnregisterDomain".parse().unwrap(), - &json!({ "domain_id": kingdom_id }), + json!({ "domain_id": kingdom_id }), ); test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; test_client.submit_blocking(Revoke::permission(token, bob_id))?; @@ -106,7 +106,7 @@ fn domain_owner_account_permissions() -> Result<()> { let bob_id = BOB_ID.clone(); let token = Permission::new( "CanUnregisterAccount".parse().unwrap(), - &json!({ "account_id": mad_hatter_id }), + json!({ "account_id": mad_hatter_id }), ); test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; test_client.submit_blocking(Revoke::permission(token, bob_id))?; @@ -141,7 +141,7 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { // Grant permission to register asset definitions to "bob@kingdom" let token = Permission::new( "CanRegisterAssetDefinitionInDomain".parse().unwrap(), - &json!({ "domain_id": kingdom_id }), + json!({ "domain_id": kingdom_id }), ); test_client.submit_blocking(Grant::permission(token, bob_id.clone()))?; @@ -172,7 +172,7 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { // check that "alice@wonderland" as owner of domain can grant and revoke asset definition related permission tokens in her domain let token = Permission::new( "CanUnregisterAssetDefinition".parse().unwrap(), - &json!({ "asset_definition_id": coin_id }), + json!({ "asset_definition_id": coin_id }), ); test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; test_client.submit_blocking(Revoke::permission(token, bob_id))?; @@ -206,7 +206,7 @@ fn domain_owner_asset_permissions() -> Result<()> { // Grant permission to register asset definitions to "bob@kingdom" let token = Permission::new( "CanRegisterAssetDefinitionInDomain".parse().unwrap(), - &json!({ "domain_id": kingdom_id }), + json!({ "domain_id": kingdom_id }), ); test_client.submit_blocking(Grant::permission(token, bob_id.clone()))?; @@ -242,7 +242,7 @@ fn domain_owner_asset_permissions() -> Result<()> { // check that "alice@wonderland" as owner of domain can grant and revoke asset related permission tokens in her domain let token = Permission::new( "CanUnregisterUserAsset".parse().unwrap(), - &json!({ "asset_id": bob_store_id }), + json!({ "asset_id": bob_store_id }), ); test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; test_client.submit_blocking(Revoke::permission(token, bob_id))?; @@ -293,7 +293,7 @@ fn domain_owner_trigger_permissions() -> Result<()> { // check that "alice@wonderland" as owner of domain can grant and revoke trigger related permission tokens in her domain let token = Permission::new( "CanUnregisterUserTrigger".parse().unwrap(), - &json!({ "account_id": bob_id }), + json!({ "account_id": bob_id }), ); test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; test_client.submit_blocking(Revoke::permission(token, bob_id))?; diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index 9d29901409f..1ce0094bcdd 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -201,11 +201,11 @@ fn produce_multiple_events() -> Result<()> { let role_id = RoleId::from_str("TEST_ROLE")?; let token_1 = Permission::new( "CanRemoveKeyValueInAccount".parse()?, - &json!({ "account_id": alice_id }), + json!({ "account_id": alice_id }), ); let token_2 = Permission::new( "CanSetKeyValueInAccount".parse()?, - &json!({ "account_id": alice_id }), + json!({ "account_id": alice_id }), ); let role = iroha_client::data_model::role::Role::new(role_id.clone()) .add_permission(token_1.clone()) @@ -240,13 +240,13 @@ fn produce_multiple_events() -> Result<()> { DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( AccountPermissionChanged { account_id: bob_id.clone(), - permission_id: token_1.definition_id.clone(), + permission_id: token_1.id.clone(), }, ))), DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( AccountPermissionChanged { account_id: bob_id.clone(), - permission_id: token_2.definition_id.clone(), + permission_id: token_2.id.clone(), }, ))), DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleGranted( @@ -258,13 +258,13 @@ fn produce_multiple_events() -> Result<()> { DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( AccountPermissionChanged { account_id: bob_id.clone(), - permission_id: token_1.definition_id, + permission_id: token_1.id, }, ))), DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( AccountPermissionChanged { account_id: bob_id.clone(), - permission_id: token_2.definition_id, + permission_id: token_2.id, }, ))), DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleRevoked( diff --git a/client/tests/integration/permissions.rs b/client/tests/integration/permissions.rs index 678d7b71b1a..1f47541466b 100644 --- a/client/tests/integration/permissions.rs +++ b/client/tests/integration/permissions.rs @@ -8,6 +8,7 @@ use iroha_client::{ }; use iroha_data_model::{ permission::Permission, role::RoleId, transaction::error::TransactionRejectionReason, + JsonString, }; use iroha_genesis::GenesisNetwork; use serde_json::json; @@ -22,7 +23,7 @@ fn genesis_transactions_are_validated() { // Setting up genesis let genesis = GenesisNetwork::test_with_instructions([Grant::permission( - Permission::new("InvalidToken".parse().unwrap(), &json!(null)), + Permission::new("InvalidToken".parse().unwrap(), json!(null)), ALICE_ID.clone(), ) .into()]); @@ -232,7 +233,7 @@ fn permissions_differ_not_only_by_names() { let allow_alice_to_set_key_value_in_hats = Grant::permission( Permission::new( "CanSetKeyValueInUserAsset".parse().unwrap(), - &json!({ "asset_id": mouse_hat_id }), + json!({ "asset_id": mouse_hat_id }), ), alice_id.clone(), ); @@ -268,7 +269,7 @@ fn permissions_differ_not_only_by_names() { let allow_alice_to_set_key_value_in_shoes = Grant::permission( Permission::new( "CanSetKeyValueInUserAsset".parse().unwrap(), - &json!({ "asset_id": mouse_shoes_id }), + json!({ "asset_id": mouse_shoes_id }), ), alice_id, ); @@ -315,10 +316,14 @@ fn stored_vs_granted_token_payload() -> Result<()> { // Allow alice to mint mouse asset and mint initial value let mouse_asset = AssetId::new(asset_definition_id, mouse_id.clone()); let allow_alice_to_set_key_value_in_mouse_asset = Grant::permission( - Permission::from_str_unchecked( + Permission::new( "CanSetKeyValueInUserAsset".parse().unwrap(), - // NOTE: Introduced additional whitespaces in the serialized form - &*format!(r###"{{ "asset_id" : "xor#wonderland#{mouse_id}" }}"###), + JsonString::from_string_unchecked(format!( + // Introducing some whitespaces + // This way, if the executor compares just JSON strings, this test would fail + r##"{{ "asset_id" : "xor#wonderland#{}" }}"##, + mouse_id + )), ), alice_id, ); @@ -349,19 +354,18 @@ fn permissions_are_unified() { let alice_id = ALICE_ID.clone(); let allow_alice_to_transfer_rose_1 = Grant::permission( - Permission::from_str_unchecked( + Permission::new( "CanTransferUserAsset".parse().unwrap(), - // NOTE: Introduced additional whitespaces in the serialized form - &*format!(r###"{{ "asset_id" : "rose#wonderland#{alice_id}" }}"###), + json!({ "asset_id": format!("rose#wonderland#{alice_id}") }), ), alice_id.clone(), ); let allow_alice_to_transfer_rose_2 = Grant::permission( - Permission::from_str_unchecked( + Permission::new( "CanTransferUserAsset".parse().unwrap(), - // NOTE: Introduced additional whitespaces in the serialized form - &*format!(r###"{{ "asset_id" : "rose##{alice_id}" }}"###), + // different content, but same meaning + json!({ "asset_id": format!("rose##{alice_id}") }), ), alice_id, ); @@ -372,7 +376,7 @@ fn permissions_are_unified() { let _ = iroha_client .submit_blocking(allow_alice_to_transfer_rose_2) - .expect_err("permission tokens are not unified"); + .expect_err("should reject due to duplication"); } #[test] @@ -388,7 +392,7 @@ fn associated_permissions_removed_on_unregister() { let register_domain = Register::domain(kingdom); let bob_to_set_kv_in_domain_token = Permission::new( "CanSetKeyValueInDomain".parse().unwrap(), - &json!({ "domain_id": kingdom_id }), + json!({ "domain_id": kingdom_id }), ); let allow_bob_to_set_kv_in_domain = Grant::permission(bob_to_set_kv_in_domain_token.clone(), bob_id.clone()); @@ -435,7 +439,7 @@ fn associated_permissions_removed_from_role_on_unregister() { let register_domain = Register::domain(kingdom); let set_kv_in_domain_token = Permission::new( "CanSetKeyValueInDomain".parse().unwrap(), - &json!({ "domain_id": kingdom_id }), + json!({ "domain_id": kingdom_id }), ); let role = Role::new(role_id.clone()).add_permission(set_kv_in_domain_token.clone()); let register_role = Register::role(role); diff --git a/client/tests/integration/queries/role.rs b/client/tests/integration/queries/role.rs index 80391bbf673..c537f5b557d 100644 --- a/client/tests/integration/queries/role.rs +++ b/client/tests/integration/queries/role.rs @@ -133,7 +133,7 @@ fn find_roles_by_account_id() -> Result<()> { .map(|role_id| { Register::role(Role::new(role_id).add_permission(Permission::new( "CanSetKeyValueInAccount".parse().unwrap(), - &json!({ "account_id": alice_id }), + json!({ "account_id": alice_id }), ))) }) .collect::>(); diff --git a/client/tests/integration/roles.rs b/client/tests/integration/roles.rs index 6efab725cd5..986f298fc23 100644 --- a/client/tests/integration/roles.rs +++ b/client/tests/integration/roles.rs @@ -28,7 +28,7 @@ fn register_role_with_empty_token_params() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let role_id = "root".parse().expect("Valid"); - let token = Permission::new("token".parse()?, &json!(null)); + let token = Permission::new("token".parse()?, json!(null)); let role = Role::new(role_id).add_permission(token); test_client.submit(Register::role(role))?; @@ -64,11 +64,11 @@ fn register_and_grant_role_for_metadata_access() -> Result<()> { let role = Role::new(role_id.clone()) .add_permission(Permission::new( "CanSetKeyValueInAccount".parse()?, - &json!({ "account_id": mouse_id }), + json!({ "account_id": mouse_id }), )) .add_permission(Permission::new( "CanRemoveKeyValueInAccount".parse()?, - &json!({ "account_id": mouse_id }), + json!({ "account_id": mouse_id }), )); let register_role = Register::role(role); test_client.submit_blocking(register_role)?; @@ -113,7 +113,7 @@ fn unregistered_role_removed_from_account() -> Result<()> { // Register root role let register_role = Register::role(Role::new(role_id.clone()).add_permission(Permission::new( "CanSetKeyValueInAccount".parse()?, - &json!({ "account_id": alice_id }), + json!({ "account_id": alice_id }), ))); test_client.submit_blocking(register_role)?; @@ -151,7 +151,7 @@ fn role_with_invalid_permissions_is_not_accepted() -> Result<()> { .expect("should be valid"); let role = Role::new(role_id).add_permission(Permission::new( "CanSetKeyValueInAccount".parse()?, - &json!({ "account_id": rose_asset_id }), + json!({ "account_id": rose_asset_id }), )); let err = test_client @@ -172,20 +172,19 @@ fn role_with_invalid_permissions_is_not_accepted() -> Result<()> { #[test] #[allow(deprecated)] -fn role_permissions_unified() { +fn role_permissions_are_deduplicated() { let (_rt, _peer, test_client) = ::new().with_port(11_235).start_with_runtime(); wait_for_genesis_committed(&vec![test_client.clone()], 0); - let allow_alice_to_transfer_rose_1 = Permission::from_str_unchecked( + let allow_alice_to_transfer_rose_1 = Permission::new( "CanTransferUserAsset".parse().unwrap(), - // NOTE: Introduced additional whitespaces in the serialized form - "{ \"asset_id\" : \"rose#wonderland#ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland\" }", + json!({ "asset_id": "rose#wonderland#ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" }), ); - let allow_alice_to_transfer_rose_2 = Permission::from_str_unchecked( + // Different content, but same meaning + let allow_alice_to_transfer_rose_2 = Permission::new( "CanTransferUserAsset".parse().unwrap(), - // NOTE: Introduced additional whitespaces in the serialized form - "{ \"asset_id\" : \"rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland\" }", + json!({ "asset_id": "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" }), ); let role_id: RoleId = "role_id".parse().expect("Valid"); @@ -248,7 +247,7 @@ fn grant_revoke_role_permissions() -> Result<()> { ); let permission = Permission::new( "CanSetKeyValueInAccount".parse()?, - &json!({ "account_id": mouse_id }), + json!({ "account_id": mouse_id }), ); let grant_role_permission = Grant::role_permission(permission.clone(), role_id.clone()); let revoke_role_permission = Revoke::role_permission(permission.clone(), role_id.clone()); 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 9ed9fba3b5d..a88a34fd123 100644 --- a/client/tests/integration/smartcontracts/executor_remove_permission/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_remove_permission/src/lib.rs @@ -3,11 +3,12 @@ #![no_std] -extern crate alloc; #[cfg(not(test))] extern crate panic_halt; -use iroha_executor::{default::default_permission_schema, prelude::*}; +use iroha_executor::{ + default::permissions::domain::CanUnregisterDomain, prelude::*, DataModelBuilder, +}; use lol_alloc::{FreeListAllocator, LockedAllocator}; #[global_allocator] @@ -25,13 +26,9 @@ struct Executor { pub 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 - let mut schema = default_permission_schema(); - schema.remove::(); - - let (token_ids, schema_str) = schema.serialize(); - iroha_executor::set_permission_schema( - &iroha_executor::data_model::permission::PermissionSchema::new(token_ids, schema_str), - ); + DataModelBuilder::with_default_permissions() + .remove_permission::() + .build_and_set(); Ok(()) } diff --git a/client/tests/integration/smartcontracts/executor_with_custom_permission/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_custom_permission/src/lib.rs index 3c4033465c1..72d553d5ed1 100644 --- a/client/tests/integration/smartcontracts/executor_with_custom_permission/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_custom_permission/src/lib.rs @@ -3,9 +3,9 @@ //! //! This executor should be applied on top of the blockchain with default validation. //! -//! It also doesn't have [`iroha_executor::default::tokens::domain::CanUnregisterDomain`]. +//! It also doesn't have [`iroha_executor::default::permissions::domain::CanUnregisterDomain`]. //! -//! In migration it replaces [`iroha_executor::default::tokens::domain::CanUnregisterDomain`] +//! In migration it replaces [`iroha_executor::default::permissions::domain::CanUnregisterDomain`] //! with [`token::CanControlDomainLives`] for all accounts. //! So it doesn't matter which domain user was able to unregister before migration, they will //! get access to control all domains. Remember that this is just a test example. @@ -16,10 +16,10 @@ extern crate alloc; #[cfg(not(test))] extern crate panic_halt; -use alloc::{borrow::ToOwned, string::String}; +use alloc::string::String; use anyhow::anyhow; -use iroha_executor::{default::default_permission_schema, permission::Token as _, prelude::*}; +use iroha_executor::{prelude::*, DataModelBuilder}; use iroha_schema::IntoSchema; use lol_alloc::{FreeListAllocator, LockedAllocator}; use parity_scale_codec::{Decode, Encode}; @@ -42,7 +42,7 @@ mod token { #[derive( PartialEq, Eq, - Token, + Permission, ValidateGrantRevoke, Decode, Encode, @@ -95,7 +95,9 @@ impl Executor { })?; if let Ok(can_unregister_domain_token) = - iroha_executor::default::tokens::domain::CanUnregisterDomain::try_from(&token) + iroha_executor::default::permissions::domain::CanUnregisterDomain::try_from( + &token, + ) { found_accounts.push((account, can_unregister_domain_token.domain_id)); break; @@ -107,13 +109,10 @@ impl Executor { } fn replace_token(accounts: &[(Account, DomainId)]) -> MigrationResult { - let can_unregister_domain_definition_id = PermissionId::try_from( - iroha_executor::default::tokens::domain::CanUnregisterDomain::type_name(), - ) - .unwrap(); + let can_unregister_domain_definition_id = + iroha_executor::default::permissions::domain::CanUnregisterDomain::id(); - let can_control_domain_lives_definition_id = - PermissionId::try_from(token::CanControlDomainLives::type_name()).unwrap(); + let can_control_domain_lives_definition_id = token::CanControlDomainLives::id(); accounts .iter() @@ -121,7 +120,7 @@ impl Executor { Revoke::permission( Permission::new( can_unregister_domain_definition_id.clone(), - &json!({ "domain_id": domain_id }), + json!({ "domain_id": domain_id }), ), account.id().clone(), ) @@ -138,7 +137,7 @@ impl Executor { })?; Grant::permission( - Permission::new(can_control_domain_lives_definition_id.clone(), &json!(null)), + Permission::new(can_control_domain_lives_definition_id.clone(), json!(null)), account.id().clone(), ) .execute() @@ -199,14 +198,10 @@ fn visit_unregister_domain( pub fn migrate(_block_height: u64) -> MigrationResult { let accounts = Executor::get_all_accounts_with_can_unregister_domain_permission()?; - let mut schema = default_permission_schema(); - schema.remove::(); - schema.insert::(); - - let (token_ids, schema_str) = schema.serialize(); - iroha_executor::set_permission_schema( - &iroha_executor::data_model::permission::PermissionSchema::new(token_ids, schema_str), - ); + DataModelBuilder::with_default_permissions() + .remove_permission::() + .add_permission::() + .build_and_set(); Executor::replace_token(&accounts) } diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index 3e8f7496336..cd50142186c 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -288,7 +288,7 @@ fn only_account_with_permission_can_register_trigger() -> Result<()> { // on behalf of alice let permission_on_registration = Permission::new( "CanRegisterUserTrigger".parse().unwrap(), - &json!({ "account_id": ALICE_ID.clone(), }), + json!({ "account_id": ALICE_ID.clone(), }), ); // Trigger with 'alice' as authority diff --git a/client/tests/integration/upgrade.rs b/client/tests/integration/upgrade.rs index 8910e7f4abe..622842d8226 100644 --- a/client/tests/integration/upgrade.rs +++ b/client/tests/integration/upgrade.rs @@ -1,6 +1,7 @@ use std::{path::Path, str::FromStr as _}; use eyre::Result; +use futures_util::TryStreamExt as _; use iroha_client::{ client::{self, Client, QueryResult}, crypto::KeyPair, @@ -10,6 +11,7 @@ use iroha_logger::info; use serde_json::json; use test_network::*; use test_samples::ALICE_ID; +use tokio::sync::mpsc; const ADMIN_PUBLIC_KEY_MULTIHASH: &str = "ed012076E5CA9698296AF9BE2CA45F525CB3BCFDEB7EE068BA56F973E9DD90564EF4FC"; @@ -76,8 +78,8 @@ fn executor_upgrade_should_run_migration() -> Result<()> { let can_unregister_domain_token_id = "CanUnregisterDomain".parse().unwrap(); // Check that `CanUnregisterDomain` exists - let definitions = client.request(FindPermissionSchema)?; - assert!(definitions + assert!(client + .request(FindExecutorDataModel)? .permissions() .iter() .any(|id| id == &can_unregister_domain_token_id)); @@ -90,7 +92,7 @@ fn executor_upgrade_should_run_migration() -> Result<()> { .expect("Valid"); assert!(alice_tokens.contains(&Permission::new( can_unregister_domain_token_id.clone(), - &json!({ "domain_id": DomainId::from_str("wonderland").unwrap() }), + json!({ "domain_id": DomainId::from_str("wonderland").unwrap() }), ))); upgrade_executor( @@ -99,15 +101,15 @@ fn executor_upgrade_should_run_migration() -> Result<()> { )?; // Check that `CanUnregisterDomain` doesn't exist - let definitions = client.request(FindPermissionSchema)?; - assert!(!definitions + let data_model = client.request(FindExecutorDataModel)?; + assert!(!data_model .permissions() .iter() .any(|id| id == &can_unregister_domain_token_id)); let can_control_domain_lives_token_id = "CanControlDomainLives".parse().unwrap(); - assert!(definitions + assert!(data_model .permissions() .iter() .any(|id| id == &can_control_domain_lives_token_id)); @@ -119,7 +121,7 @@ fn executor_upgrade_should_run_migration() -> Result<()> { .expect("Valid"); assert!(alice_tokens.contains(&Permission::new( can_control_domain_lives_token_id, - &json!(null), + json!(null), ))); Ok(()) @@ -133,7 +135,7 @@ fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { // Permission which will be removed by executor let can_unregister_domain_token = Permission::new( "CanUnregisterDomain".parse()?, - &json!({ "domain_id": DomainId::from_str("wonderland")? }), + json!({ "domain_id": DomainId::from_str("wonderland")? }), ); // Register `TEST_ROLE` with permission @@ -144,9 +146,9 @@ fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { // Check that permission exists assert!(client - .request(FindPermissionSchema)? + .request(FindExecutorDataModel)? .permissions() - .contains(&can_unregister_domain_token.definition_id)); + .contains(&can_unregister_domain_token.id)); // Check that `TEST_ROLE` has permission assert!(client @@ -172,9 +174,9 @@ fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { // Check that permission doesn't exist assert!(!client - .request(FindPermissionSchema)? + .request(FindExecutorDataModel)? .permissions() - .contains(&can_unregister_domain_token.definition_id)); + .contains(&can_unregister_domain_token.id)); // Check that `TEST_ROLE` doesn't have permission assert!(!client @@ -197,7 +199,7 @@ fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { #[test] fn migration_fail_should_not_cause_any_effects() { - let (_rt, _peer, client) = ::new().with_port(10_995).start_with_runtime(); + let (_rt, _peer, client) = ::new().with_port(10_998).start_with_runtime(); wait_for_genesis_committed(&vec![client.clone()], 0); let assert_domain_does_not_exist = |client: &Client, domain_id: &DomainId| { @@ -225,6 +227,46 @@ fn migration_fail_should_not_cause_any_effects() { // been changed, because `executor_with_migration_fail` does not allow any queries } +#[test] +fn migration_should_cause_upgrade_event() { + let (rt, _peer, client) = ::new().with_port(10_996).start_with_runtime(); + wait_for_genesis_committed(&vec![client.clone()], 0); + + let (sender, mut receiver) = mpsc::channel(1); + let events_client = client.clone(); + + let _handle = rt.spawn(async move { + let mut stream = events_client + .listen_for_events_async([ExecutorEventFilter::new()]) + .await + .unwrap(); + while let Some(event) = stream.try_next().await.unwrap() { + if let EventBox::Data(DataEvent::Executor(ExecutorEvent::Upgraded(ExecutorUpgrade { + new_data_model, + }))) = event + { + let _ = sender.send(new_data_model).await; + } + } + }); + + upgrade_executor( + &client, + "tests/integration/smartcontracts/executor_with_custom_permission", + ) + .unwrap(); + + let data_model = rt + .block_on(async { + tokio::time::timeout(std::time::Duration::from_secs(60), receiver.recv()).await + }) + .ok() + .flatten() + .expect("should receive upgraded event immediately after upgrade"); + + assert!(!data_model.permissions.is_empty()); +} + fn upgrade_executor(client: &Client, executor: impl AsRef) -> Result<()> { info!("Building executor"); diff --git a/client/tests/ui_fail/cant_filter_singular_query.rs b/client/tests/ui_fail/cant_filter_singular_query.rs index f900887c656..45078dbb2cc 100644 --- a/client/tests/ui_fail/cant_filter_singular_query.rs +++ b/client/tests/ui_fail/cant_filter_singular_query.rs @@ -10,7 +10,7 @@ fn main() { let client = Client::new(config); let result = client - .build_query(client::permission::permission_schema()) + .build_query(client::domain::by_id("domain".parse().unwrap())) .with_filter(PredicateBox::new( value::QueryOutputPredicate::Identifiable(string::StringPredicate::starts_with("xor_")), )) diff --git a/client/tests/ui_fail/cant_filter_singular_query.stderr b/client/tests/ui_fail/cant_filter_singular_query.stderr index 6533d07befc..6213c6dfb1e 100644 --- a/client/tests/ui_fail/cant_filter_singular_query.stderr +++ b/client/tests/ui_fail/cant_filter_singular_query.stderr @@ -1,24 +1,24 @@ -error[E0599]: the method `with_filter` exists for struct `QueryRequestBuilder<'_, FindPermissionSchema>`, but its trait bounds were not satisfied +error[E0599]: the method `with_filter` exists for struct `QueryRequestBuilder<'_, FindDomainById>`, but its trait bounds were not satisfied --> tests/ui_fail/cant_filter_singular_query.rs:14:10 | 12 | let result = client | __________________- -13 | | .build_query(client::permission::permission_schema()) +13 | | .build_query(client::domain::by_id("domain".parse().unwrap())) 14 | | .with_filter(PredicateBox::new( - | | -^^^^^^^^^^^ method cannot be called on `QueryRequestBuilder<'_, FindPermissionSchema>` due to unsatisfied trait bounds + | | -^^^^^^^^^^^ method cannot be called on `QueryRequestBuilder<'_, FindDomainById>` due to unsatisfied trait bounds | |_________| | | ::: $WORKSPACE/data_model/src/query/mod.rs | | / queries! { - | | /// Finds all registered permission tokens + | | /// [`FindAllDomains`] Iroha Query finds all [`Domain`]s presented in Iroha [`Peer`]. | | #[derive(Copy, Display)] - | | #[ffi_type] + | | #[display(fmt = "Find all domains")] ... | | | } | | } | |_____- doesn't satisfy `_: IterableQuery` | = note: the following trait bounds were not satisfied: - `iroha_client::iroha_data_model::prelude::FindPermissionSchema: IterableQuery` + `iroha_client::iroha_data_model::prelude::FindDomainById: IterableQuery` diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index 8c552ccf205..fc5dd07b00c 100644 Binary files a/configs/swarm/executor.wasm and b/configs/swarm/executor.wasm differ diff --git a/configs/swarm/genesis.json b/configs/swarm/genesis.json index 5a3633d398d..f4b41b16635 100644 --- a/configs/swarm/genesis.json +++ b/configs/swarm/genesis.json @@ -115,7 +115,7 @@ "Grant": { "Permission": { "object": { - "definition_id": "CanSetParameters", + "id": "CanSetParameters", "payload": null }, "destination_id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" @@ -170,13 +170,13 @@ "id": "ALICE_METADATA_ACCESS", "permissions": [ { - "definition_id": "CanRemoveKeyValueInAccount", + "id": "CanRemoveKeyValueInAccount", "payload": { "account_id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } }, { - "definition_id": "CanSetKeyValueInAccount", + "id": "CanSetKeyValueInAccount", "payload": { "account_id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } diff --git a/core/benches/blocks/common.rs b/core/benches/blocks/common.rs index f2017fa3471..ae0601fbc6c 100644 --- a/core/benches/blocks/common.rs +++ b/core/benches/blocks/common.rs @@ -15,7 +15,7 @@ use iroha_data_model::{ isi::InstructionBox, prelude::*, transaction::TransactionLimits, - ChainId, + ChainId, JsonString, }; use iroha_primitives::unique_vec::UniqueVec; use serde_json::json; @@ -69,7 +69,7 @@ pub fn populate_state( let can_unregister_domain = Grant::permission( Permission::new( "CanUnregisterDomain".parse().unwrap(), - &json!({ "domain_id": domain_id.clone() }), + JsonString::from(&json!({ "domain_id": domain_id.clone() })), ), owner_id.clone(), ); @@ -81,7 +81,7 @@ pub fn populate_state( let can_unregister_account = Grant::permission( Permission::new( "CanUnregisterAccount".parse().unwrap(), - &json!({ "account_id": account_id.clone() }), + JsonString::from(&json!({ "account_id": account_id.clone() })), ), owner_id.clone(), ); @@ -94,7 +94,7 @@ pub fn populate_state( let can_unregister_asset_definition = Grant::permission( Permission::new( "CanUnregisterAssetDefinition".parse().unwrap(), - &json!({ "asset_definition_id": asset_definition_id }), + JsonString::from(&json!({ "asset_definition_id": asset_definition_id })), ), owner_id.clone(), ); diff --git a/core/src/smartcontracts/isi/account.rs b/core/src/smartcontracts/isi/account.rs index 0604680ba00..466a578f13d 100644 --- a/core/src/smartcontracts/isi/account.rs +++ b/core/src/smartcontracts/isi/account.rs @@ -245,15 +245,15 @@ pub mod isi { ) -> Result<(), Error> { let account_id = self.destination_id; let permission = self.object; - let permission_id = permission.definition_id.clone(); + let permission_id = permission.id.clone(); // Check if account exists state_transaction.world.account_mut(&account_id)?; if !state_transaction .world - .permission_schema - .token_ids + .executor_data_model + .permissions .contains(&permission_id) { return Err(FindError::Permission(permission_id).into()); @@ -265,7 +265,7 @@ pub mod isi { { return Err(RepetitionError { instruction_type: InstructionType::Grant, - id: permission.definition_id.into(), + id: permission.id.into(), } .into()); } @@ -304,7 +304,7 @@ pub mod isi { .world .remove_account_permission(&account_id, &permission) { - return Err(FindError::Permission(permission.definition_id).into()); + return Err(FindError::Permission(permission.id).into()); } state_transaction @@ -312,7 +312,7 @@ pub mod isi { .emit_events(Some(AccountEvent::PermissionRemoved( AccountPermissionChanged { account_id, - permission_id: permission.definition_id, + permission_id: permission.id, }, ))); @@ -338,7 +338,7 @@ pub mod isi { .clone() .permissions .into_iter() - .map(|token| token.definition_id); + .map(|token| token.id); state_transaction.world.account(&account_id)?; @@ -397,7 +397,7 @@ pub mod isi { .clone() .permissions .into_iter() - .map(|token| token.definition_id); + .map(|token| token.id); if state_transaction .world diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index 4bb37a6e8d0..26b6d603808 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -162,7 +162,7 @@ impl_lazy! { iroha_data_model::block::BlockHeader, iroha_data_model::metadata::MetadataValueBox, iroha_data_model::query::TransactionQueryOutput, - iroha_data_model::permission::PermissionSchema, + iroha_data_model::executor::ExecutorDataModel, iroha_data_model::trigger::Trigger, } @@ -259,7 +259,7 @@ impl ValidQuery for QueryBox { FindAccountKeyValueByIdAndKey, FindAssetDefinitionKeyValueByIdAndKey, FindTriggerKeyValueByIdAndKey, - FindPermissionSchema, + FindExecutorDataModel, } FindAllAccounts, diff --git a/core/src/smartcontracts/isi/world.rs b/core/src/smartcontracts/isi/world.rs index ec89111cf2c..5c882cd54ed 100644 --- a/core/src/smartcontracts/isi/world.rs +++ b/core/src/smartcontracts/isi/world.rs @@ -17,8 +17,9 @@ impl Registrable for NewRole { /// Iroha Special Instructions that have `World` as their target. pub mod isi { + use std::collections::BTreeSet; + use eyre::Result; - use indexmap::IndexSet; use iroha_data_model::{ isi::error::{InstructionExecutionError, InvalidParameterError, RepetitionError}, prelude::*, @@ -162,11 +163,11 @@ pub mod isi { for permission in &role.permissions { if !state_transaction .world - .permission_schema - .token_ids - .contains(&permission.definition_id) + .executor_data_model + .permissions + .contains(&permission.id) { - return Err(FindError::Permission(permission.definition_id.clone()).into()); + return Err(FindError::Permission(permission.id.clone()).into()); } } @@ -227,12 +228,12 @@ pub mod isi { ) -> Result<(), Error> { let role_id = self.destination_id; let permission = self.object; - let permission_id = permission.definition_id.clone(); + let permission_id = permission.id.clone(); if !state_transaction .world - .permission_schema - .token_ids + .executor_data_model + .permissions .contains(&permission_id) { return Err(FindError::Permission(permission_id).into()); @@ -245,7 +246,7 @@ pub mod isi { if !role.permissions.insert(permission.clone()) { return Err(RepetitionError { instruction_type: InstructionType::Grant, - id: permission.definition_id.into(), + id: permission.id.into(), } .into()); } @@ -270,7 +271,7 @@ pub mod isi { ) -> Result<(), Error> { let role_id = self.destination_id; let permission = self.object; - let permission_id = permission.definition_id.clone(); + let permission_id = permission.id.clone(); let Some(role) = state_transaction.world.roles.get_mut(&role_id) else { return Err(FindError::Role(role_id).into()); @@ -348,7 +349,11 @@ pub mod isi { ) -> Result<(), Error> { let raw_executor = self.executor; - let permissions_before = state_transaction.world.permission_schema.token_ids.clone(); + let permissions_before = state_transaction + .world + .executor_data_model + .permissions + .clone(); // Cloning executor to avoid multiple mutable borrows of `state_transaction`. // Also it's a cheap operation. @@ -368,7 +373,9 @@ pub mod isi { state_transaction .world - .emit_events(std::iter::once(ExecutorEvent::Upgraded)); + .emit_events(std::iter::once(ExecutorEvent::Upgraded(ExecutorUpgrade { + new_data_model: state_transaction.world.executor_data_model.clone(), + }))); Ok(()) } @@ -377,18 +384,14 @@ pub mod isi { fn revoke_removed_permissions( authority: &AccountId, state_transaction: &mut StateTransaction, - permissions_before: Vec, + permissions_before: BTreeSet, ) -> Result<(), Error> { let world = state_transaction.world(); - let permissions_after = world - .permission_schema() - .token_ids - .iter() - .collect::>(); + let permissions_after = world.executor_data_model().permissions(); let permissions_removed = permissions_before .into_iter() .filter(|permission| !permissions_after.contains(permission)) - .collect::>(); + .collect::>(); if permissions_removed.is_empty() { return Ok(()); } @@ -409,7 +412,7 @@ pub mod isi { fn find_related_accounts( world: &impl WorldReadOnly, - permissions: &IndexSet, + permissions: &BTreeSet, ) -> Vec<(AccountId, Permission)> { world .account_permissions() @@ -417,7 +420,7 @@ pub mod isi { .flat_map(|(account_id, account_permissions)| { account_permissions .iter() - .filter(|permission| permissions.contains(&permission.definition_id)) + .filter(|permission| permissions.contains(&permission.id)) .map(|permission| (account_id.clone(), permission.clone())) }) .collect() @@ -425,7 +428,7 @@ pub mod isi { fn find_related_roles( world: &impl WorldReadOnly, - permissions: &IndexSet, + permissions: &BTreeSet, ) -> Vec<(RoleId, Permission)> { world .roles() @@ -433,7 +436,7 @@ pub mod isi { .flat_map(|(role_id, role)| { role.permissions .iter() - .filter(|permission| permissions.contains(&permission.definition_id)) + .filter(|permission| permissions.contains(&permission.id)) .map(|permission| (role_id.clone(), permission.clone())) }) .collect() @@ -466,7 +469,6 @@ pub mod query { use iroha_data_model::{ parameter::Parameter, peer::Peer, - permission::PermissionSchema, prelude::*, query::error::{FindError, QueryExecutionFail as Error}, role::{Role, RoleId}, @@ -534,10 +536,10 @@ pub mod query { } } - impl ValidQuery for FindPermissionSchema { - #[metrics("find_permission_schema")] - fn execute(&self, state_ro: &impl StateReadOnly) -> Result { - Ok(state_ro.world().permission_schema().clone()) + impl ValidQuery for FindExecutorDataModel { + #[metrics("find_executor_data_model")] + fn execute(&self, state_ro: &impl StateReadOnly) -> Result { + Ok(state_ro.world().executor_data_model().clone()) } } diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index 955134976da..1f6d2474193 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -5,13 +5,12 @@ use std::borrow::Borrow; use error::*; -use import::traits::{ExecuteOperations as _, GetExecutorPayloads as _, SetPermissionSchema as _}; +use import::traits::{ExecuteOperations as _, GetExecutorPayloads as _, SetDataModel as _}; use iroha_config::parameters::actual::WasmRuntime as Config; use iroha_data_model::{ account::AccountId, - executor::{self, MigrationResult}, + executor::{self, ExecutorDataModel, MigrationResult}, isi::InstructionBox, - permission::PermissionSchema, prelude::*, query::{QueryBox, QueryId, QueryOutputBox, QueryRequest, SmartContractQuery}, smart_contract::payloads::{self, Validate}, @@ -47,7 +46,7 @@ mod export { pub const GET_VALIDATE_TRANSACTION_PAYLOAD: &str = "get_validate_transaction_payload"; pub const GET_VALIDATE_INSTRUCTION_PAYLOAD: &str = "get_validate_instruction_payload"; pub const GET_VALIDATE_QUERY_PAYLOAD: &str = "get_validate_query_payload"; - pub const SET_PERMISSION_SCHEMA: &str = "set_permission_schema"; + pub const SET_DATA_MODEL: &str = "set_data_model"; pub const DBG: &str = "dbg"; pub const LOG: &str = "log"; @@ -102,9 +101,9 @@ mod import { fn get_validate_query_payload(state: &S) -> Validate; } - pub trait SetPermissionSchema { + pub trait SetDataModel { #[codec::wrap_trait_fn] - fn set_permission_schema(schema: PermissionSchema, state: &mut S); + fn set_data_model(data_model: ExecutorDataModel, state: &mut S); } } } @@ -1076,23 +1075,23 @@ where } } -/// Marker trait to auto-implement [`import_traits::SetPermissionSchema`] for a concrete [`Runtime`]. +/// Marker trait to auto-implement [`import_traits::SetExecutorDataModel`] for a concrete [`Runtime`]. /// /// Useful because *Executor* exposes more entrypoints than just `migrate()` which is the /// only entrypoint allowed to execute operations on permission tokens. -trait FakeSetPermissionSchema { +trait FakeSetExecutorDataModel { /// Entrypoint function name for panic message const ENTRYPOINT_FN_NAME: &'static str; } -impl import::traits::SetPermissionSchema for R +impl import::traits::SetDataModel for R where - R: FakeSetPermissionSchema, + R: FakeSetExecutorDataModel, { #[codec::wrap] - fn set_permission_schema(_schema: PermissionSchema, _state: &mut S) { + fn set_data_model(_model: ExecutorDataModel, _state: &mut S) { panic!( - "Executor `{}()` entrypoint should not set permission token schema", + "Executor `{}()` entrypoint should not set data model", Self::ENTRYPOINT_FN_NAME ) } @@ -1172,7 +1171,7 @@ impl<'wrld, 'block, 'state> } } -impl<'wrld> FakeSetPermissionSchema> +impl<'wrld> FakeSetExecutorDataModel> for Runtime> { const ENTRYPOINT_FN_NAME: &'static str = "validate_transaction"; @@ -1252,7 +1251,7 @@ impl<'wrld, 'block, 'state> } } -impl<'wrld> FakeSetPermissionSchema> +impl<'wrld> FakeSetExecutorDataModel> for Runtime> { const ENTRYPOINT_FN_NAME: &'static str = "validate_instruction"; @@ -1348,7 +1347,7 @@ impl<'wrld, S: StateReadOnly> } } -impl<'wrld, S: StateReadOnly> FakeSetPermissionSchema> +impl<'wrld, S: StateReadOnly> FakeSetExecutorDataModel> for Runtime> { const ENTRYPOINT_FN_NAME: &'static str = "validate_query"; @@ -1447,17 +1446,17 @@ impl<'wrld, 'block, 'state> } impl<'wrld, 'block, 'state> - import::traits::SetPermissionSchema> + import::traits::SetDataModel> for Runtime> { #[codec::wrap] - fn set_permission_schema( - schema: PermissionSchema, + fn set_data_model( + data_model: ExecutorDataModel, state: &mut state::executor::Migrate<'wrld, 'block, 'state>, ) { - debug!(%schema, "Setting permission token schema"); + debug!(%data_model, "Setting executor data model"); - state.state.0.world.set_permission_schema(schema) + state.state.0.world.set_executor_data_model(data_model) } } @@ -1602,7 +1601,7 @@ impl<'wrld, 'block, 'state> export::GET_VALIDATE_TRANSACTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_transaction_payload(caller), export::GET_VALIDATE_INSTRUCTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_instruction_payload(caller), export::GET_VALIDATE_QUERY_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_payload(caller), - export::SET_PERMISSION_SCHEMA => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_permission_schema(caller, offset, len), + export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), )?; Ok(linker) }) @@ -1630,7 +1629,7 @@ impl<'wrld, 'block, 'state> export::GET_VALIDATE_TRANSACTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_transaction_payload(caller), export::GET_VALIDATE_INSTRUCTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_instruction_payload(caller), export::GET_VALIDATE_QUERY_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_payload(caller), - export::SET_PERMISSION_SCHEMA => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_permission_schema(caller, offset, len), + export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), )?; Ok(linker) }) @@ -1655,7 +1654,7 @@ impl<'wrld, S: StateReadOnly> RuntimeBuilder |caller: ::wasmtime::Caller>| Runtime::get_validate_transaction_payload(caller), export::GET_VALIDATE_INSTRUCTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_instruction_payload(caller), export::GET_VALIDATE_QUERY_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_payload(caller), - export::SET_PERMISSION_SCHEMA => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_permission_schema(caller, offset, len), + export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), )?; Ok(linker) }) @@ -1663,6 +1662,7 @@ impl<'wrld, S: StateReadOnly> RuntimeBuilder RuntimeBuilder> { + // FIXME: outdated doc. I guess it executes `migrate` entrypoint? /// Builds the [`Runtime`] to execute `permissions()` entrypoint of *Executor* /// /// # Errors @@ -1679,7 +1679,7 @@ impl<'wrld, 'block, 'state> RuntimeBuilder |caller: ::wasmtime::Caller>| Runtime::get_validate_transaction_payload(caller), export::GET_VALIDATE_INSTRUCTION_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_instruction_payload(caller), export::GET_VALIDATE_QUERY_PAYLOAD => |caller: ::wasmtime::Caller>| Runtime::get_validate_query_payload(caller), - export::SET_PERMISSION_SCHEMA => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_permission_schema(caller, offset, len), + export::SET_DATA_MODEL => |caller: ::wasmtime::Caller>, offset, len| Runtime::set_data_model(caller, offset, len), )?; Ok(linker) }) diff --git a/core/src/state.rs b/core/src/state.rs index 49c2a12fa4d..38a74462a71 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -13,9 +13,10 @@ use iroha_data_model::{ trigger_completed::{TriggerCompletedEvent, TriggerCompletedOutcome}, EventBox, }, + executor::ExecutorDataModel, isi::error::{InstructionExecutionError as Error, MathError}, parameter::{Parameter, ParameterValueBox}, - permission::{PermissionSchema, Permissions}, + permission::Permissions, prelude::*, query::error::{FindError, QueryExecutionFail}, role::RoleId, @@ -73,12 +74,12 @@ pub struct World { pub(crate) account_permissions: Storage, /// Roles of an account. pub(crate) account_roles: Storage, - /// Registered permission token ids. - pub(crate) permission_schema: Cell, /// Triggers pub(crate) triggers: TriggerSet, /// Runtime Executor pub(crate) executor: Cell, + /// Executor-defined data model + pub(crate) executor_data_model: Cell, } /// Struct for block's aggregated changes @@ -95,12 +96,12 @@ pub struct WorldBlock<'world> { pub(crate) account_permissions: StorageBlock<'world, AccountId, Permissions>, /// Roles of an account. pub(crate) account_roles: StorageBlock<'world, RoleIdWithOwner, ()>, - /// Registered permission token ids. - pub(crate) permission_schema: CellBlock<'world, PermissionSchema>, /// Triggers pub(crate) triggers: TriggerSetBlock<'world>, /// Runtime Executor pub(crate) executor: CellBlock<'world, Executor>, + /// Executor-defined data model + pub(crate) executor_data_model: CellBlock<'world, ExecutorDataModel>, /// Events produced during execution of block events_buffer: Vec, } @@ -119,12 +120,12 @@ pub struct WorldTransaction<'block, 'world> { pub(crate) account_permissions: StorageTransaction<'block, 'world, AccountId, Permissions>, /// Roles of an account. pub(crate) account_roles: StorageTransaction<'block, 'world, RoleIdWithOwner, ()>, - /// Registered permission token ids. - pub(crate) permission_schema: CellTransaction<'block, 'world, PermissionSchema>, /// Triggers pub(crate) triggers: TriggerSetTransaction<'block, 'world>, /// Runtime Executor pub(crate) executor: CellTransaction<'block, 'world, Executor>, + /// Executor-defined data model + pub(crate) executor_data_model: CellTransaction<'block, 'world, ExecutorDataModel>, /// Events produced during execution of a transaction events_buffer: TransactionEventBuffer<'block>, } @@ -151,12 +152,12 @@ pub struct WorldView<'world> { pub(crate) account_permissions: StorageView<'world, AccountId, Permissions>, /// Roles of an account. pub(crate) account_roles: StorageView<'world, RoleIdWithOwner, ()>, - /// Registered permission token ids. - pub(crate) permission_schema: CellView<'world, PermissionSchema>, /// Triggers pub(crate) triggers: TriggerSetView<'world>, /// Runtime Executor pub(crate) executor: CellView<'world, Executor>, + /// Executor-defined data model + pub(crate) executor_data_model: CellView<'world, ExecutorDataModel>, } /// Current state of the blockchain @@ -284,9 +285,9 @@ impl World { roles: self.roles.block(), account_permissions: self.account_permissions.block(), account_roles: self.account_roles.block(), - permission_schema: self.permission_schema.block(), triggers: self.triggers.block(), executor: self.executor.block(), + executor_data_model: self.executor_data_model.block(), events_buffer: Vec::new(), } } @@ -300,9 +301,9 @@ impl World { roles: self.roles.block_and_revert(), account_permissions: self.account_permissions.block_and_revert(), account_roles: self.account_roles.block_and_revert(), - permission_schema: self.permission_schema.block_and_revert(), triggers: self.triggers.block_and_revert(), executor: self.executor.block_and_revert(), + executor_data_model: self.executor_data_model.block_and_revert(), events_buffer: Vec::new(), } } @@ -316,9 +317,9 @@ impl World { roles: self.roles.view(), account_permissions: self.account_permissions.view(), account_roles: self.account_roles.view(), - permission_schema: self.permission_schema.view(), triggers: self.triggers.view(), executor: self.executor.view(), + executor_data_model: self.executor_data_model.view(), } } } @@ -332,9 +333,9 @@ pub trait WorldReadOnly { fn roles(&self) -> &impl StorageReadOnly; fn account_permissions(&self) -> &impl StorageReadOnly; fn account_roles(&self) -> &impl StorageReadOnly; - fn permission_schema(&self) -> &PermissionSchema; fn triggers(&self) -> &impl TriggerSetReadOnly; fn executor(&self) -> &Executor; + fn executor_data_model(&self) -> &ExecutorDataModel; // Domain-related methods @@ -578,15 +579,15 @@ macro_rules! impl_world_ro { fn account_roles(&self) -> &impl StorageReadOnly { &self.account_roles } - fn permission_schema(&self) -> &PermissionSchema { - &self.permission_schema - } fn triggers(&self) -> &impl TriggerSetReadOnly { &self.triggers } fn executor(&self) -> &Executor { &self.executor } + fn executor_data_model(&self) -> &ExecutorDataModel { + &self.executor_data_model + } } )*}; } @@ -605,9 +606,9 @@ impl<'world> WorldBlock<'world> { roles: self.roles.transaction(), account_permissions: self.account_permissions.transaction(), account_roles: self.account_roles.transaction(), - permission_schema: self.permission_schema.transaction(), triggers: self.triggers.transaction(), executor: self.executor.transaction(), + executor_data_model: self.executor_data_model.transaction(), events_buffer: TransactionEventBuffer { events_buffer: &mut self.events_buffer, events_created_in_transaction: 0, @@ -618,9 +619,9 @@ impl<'world> WorldBlock<'world> { /// Commit block's changes pub fn commit(self) { // IMPORTANT!!! Commit fields in reverse order, this way consistent results are insured + self.executor_data_model.commit(); self.executor.commit(); self.triggers.commit(); - self.permission_schema.commit(); self.account_roles.commit(); self.account_permissions.commit(); self.roles.commit(); @@ -633,9 +634,9 @@ impl<'world> WorldBlock<'world> { impl WorldTransaction<'_, '_> { /// Apply transaction's changes pub fn apply(mut self) { + self.executor_data_model.apply(); self.executor.apply(); self.triggers.apply(); - self.permission_schema.apply(); self.account_roles.apply(); self.account_permissions.apply(); self.roles.apply(); @@ -835,18 +836,9 @@ impl WorldTransaction<'_, '_> { Ok(()) } - /// Set new permission token schema. - /// - /// Produces [`PermissionSchemaUpdateEvent`]. - pub fn set_permission_schema(&mut self, schema: PermissionSchema) { - let old_schema: PermissionSchema = - std::mem::replace(&mut self.permission_schema, schema.clone()); - self.emit_events(std::iter::once(DataEvent::Permission( - PermissionSchemaUpdateEvent { - old_schema, - new_schema: schema, - }, - ))) + /// Set executor data model. + pub fn set_executor_data_model(&mut self, executor_data_model: ExecutorDataModel) { + *self.executor_data_model.get_mut() = executor_data_model; } /// Execute trigger with `trigger_id` as id and `authority` as owner @@ -1589,9 +1581,9 @@ pub(crate) mod deserialize { let mut roles = None; let mut account_permissions = None; let mut account_roles = None; - let mut permission_schema = None; let mut triggers = None; let mut executor = None; + let mut executor_data_model = None; while let Some(key) = map.next_key::()? { match key.as_str() { @@ -1613,9 +1605,6 @@ pub(crate) mod deserialize { "account_roles" => { account_roles = Some(map.next_value()?); } - "permission_schema" => { - permission_schema = Some(map.next_value()?); - } "triggers" => { triggers = Some(map.next_value_seed(self.loader.cast::())?); @@ -1625,6 +1614,10 @@ pub(crate) mod deserialize { seed: self.loader.cast::(), })?); } + "executor_data_model" => { + executor_data_model = Some(map.next_value()?); + } + _ => { /* Skip unknown fields */ } } } @@ -1642,12 +1635,13 @@ pub(crate) mod deserialize { })?, account_roles: account_roles .ok_or_else(|| serde::de::Error::missing_field("account_roles"))?, - permission_schema: permission_schema - .ok_or_else(|| serde::de::Error::missing_field("permission_schema"))?, triggers: triggers .ok_or_else(|| serde::de::Error::missing_field("triggers"))?, executor: executor .ok_or_else(|| serde::de::Error::missing_field("executor"))?, + executor_data_model: executor_data_model.ok_or_else(|| { + serde::de::Error::missing_field("executor_data_model") + })?, }) } } @@ -1661,9 +1655,9 @@ pub(crate) mod deserialize { "roles", "account_permissions", "account_roles", - "permission_schema", "triggers", "executor", + "executor_data_model", ], WorldVisitor { loader: &self }, ) diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index 363d4be93bb..51108f115e6 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -92,22 +92,22 @@ impl TestGenesis for GenesisNetwork { let mint_rose_permission = Permission::new( "CanMintAssetWithDefinition".parse().unwrap(), - &json!({ "asset_definition_id": rose_definition_id }), + json!({ "asset_definition_id": rose_definition_id }), ); let burn_rose_permission = Permission::new( "CanBurnAssetWithDefinition".parse().unwrap(), - &json!({ "asset_definition_id": rose_definition_id }), + json!({ "asset_definition_id": rose_definition_id }), ); let unregister_any_peer_permission = - Permission::new("CanUnregisterAnyPeer".parse().unwrap(), &json!(null)); + Permission::new("CanUnregisterAnyPeer".parse().unwrap(), json!(null)); let unregister_any_role_permission = - Permission::new("CanUnregisterAnyRole".parse().unwrap(), &json!(null)); + Permission::new("CanUnregisterAnyRole".parse().unwrap(), json!(null)); let unregister_wonderland_domain = Permission::new( "CanUnregisterDomain".parse().unwrap(), - &json!({ "domain_id": DomainId::from_str("wonderland").unwrap() } ), + json!({ "domain_id": DomainId::from_str("wonderland").unwrap() }), ); let upgrade_executor_permission = - Permission::new("CanUpgradeExecutor".parse().unwrap(), &json!(null)); + Permission::new("CanUpgradeExecutor".parse().unwrap(), json!(null)); let first_transaction = genesis .first_transaction_mut() diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 6584e22b9d5..d43e34050aa 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -89,8 +89,6 @@ mod model { Trigger(trigger::TriggerEvent), /// Role event Role(role::RoleEvent), - /// Permission token event - Permission(permission::PermissionSchemaUpdateEvent), /// Configuration event Configuration(config::ConfigurationEvent), /// Executor event @@ -287,44 +285,6 @@ mod role { } } -mod permission { - //! This module contains [`PermissionSchemaUpdateEvent`] - - pub use self::model::*; - use super::*; - use crate::permission::PermissionSchema; - - #[model] - mod model { - use super::*; - - /// Information about permission tokens update. - /// Only happens when registering new executor - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Getters, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[getset(get = "pub")] - #[ffi_type] - pub struct PermissionSchemaUpdateEvent { - /// Previous set of permission tokens - pub old_schema: PermissionSchema, - /// New set of permission tokens - pub new_schema: PermissionSchema, - } - } -} - mod account { //! This module contains `AccountEvent` and its impls @@ -332,7 +292,6 @@ mod account { pub use self::model::*; use super::*; - use crate::name::Name; type AccountMetadataChanged = MetadataChanged; @@ -414,7 +373,7 @@ mod account { impl AccountPermissionChanged { /// Get permission id - pub fn permission_id(&self) -> &Name { + pub fn permission_id(&self) -> &PermissionId { &self.permission_id } } @@ -558,10 +517,10 @@ mod executor { // this is used in no_std #[allow(unused)] use super::*; + use crate::executor::ExecutorDataModel; #[derive( Debug, - Copy, Clone, PartialEq, Eq, @@ -575,11 +534,34 @@ mod executor { EventSet, )] #[non_exhaustive] - #[ffi_type] + #[ffi_type(opaque)] #[serde(untagged)] // Unaffected by #3330, as single unit variant #[repr(transparent)] pub enum ExecutorEvent { - Upgraded, + Upgraded(ExecutorUpgrade), + } + + /// Information about the updated executor data model. + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + Getters, + )] + #[ffi_type] + #[repr(transparent)] + #[getset(get = "pub")] + pub struct ExecutorUpgrade { + /// Updated data model + pub new_data_model: ExecutorDataModel, } } } @@ -616,11 +598,7 @@ impl DataEvent { match self { Self::Domain(event) => Some(event.origin_id()), Self::Trigger(event) => event.origin_id().domain_id.as_ref(), - Self::Peer(_) - | Self::Configuration(_) - | Self::Role(_) - | Self::Permission(_) - | Self::Executor(_) => None, + Self::Peer(_) | Self::Configuration(_) | Self::Role(_) | Self::Executor(_) => None, } } } @@ -635,9 +613,8 @@ pub mod prelude { }, config::{ConfigurationEvent, ConfigurationEventSet}, domain::{DomainEvent, DomainEventSet, DomainOwnerChanged}, - executor::{ExecutorEvent, ExecutorEventSet}, + executor::{ExecutorEvent, ExecutorEventSet, ExecutorUpgrade}, peer::{PeerEvent, PeerEventSet}, - permission::PermissionSchemaUpdateEvent, role::{RoleEvent, RoleEventSet, RolePermissionChanged}, trigger::{TriggerEvent, TriggerEventSet, TriggerNumberOfExecutionsChanged}, DataEvent, HasOrigin, MetadataChanged, diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 03a2048250b..58840eb68bc 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -47,9 +47,6 @@ mod model { Trigger(TriggerEventFilter), /// Matches [`RoleEvent`]s Role(RoleEventFilter), - /// Matches [`PermissionSchemaUpdateEvent`]s - // nothing to filter for, really - PermissionSchemaUpdate, /// Matches [`ConfigurationEvent`]s Configuration(ConfigurationEventFilter), /// Matches [`ExecutorEvent`]s @@ -706,7 +703,6 @@ impl EventFilter for DataEventFilter { (DataEvent::Trigger(event), Trigger(filter)) => filter.matches(event), (DataEvent::Role(event), Role(filter)) => filter.matches(event), (DataEvent::Configuration(event), Configuration(filter)) => filter.matches(event), - (DataEvent::Permission(_), PermissionSchemaUpdate) => true, (DataEvent::Executor(event), Executor(filter)) => filter.matches(event), ( @@ -714,7 +710,6 @@ impl EventFilter for DataEventFilter { | DataEvent::Domain(_) | DataEvent::Trigger(_) | DataEvent::Role(_) - | DataEvent::Permission(_) | DataEvent::Configuration(_) | DataEvent::Executor(_), Any, @@ -724,7 +719,6 @@ impl EventFilter for DataEventFilter { | DataEvent::Domain(_) | DataEvent::Trigger(_) | DataEvent::Role(_) - | DataEvent::Permission(_) | DataEvent::Configuration(_) | DataEvent::Executor(_), _, diff --git a/data_model/src/executor.rs b/data_model/src/executor.rs index 8c147cc477b..d0c0b225efd 100644 --- a/data_model/src/executor.rs +++ b/data_model/src/executor.rs @@ -1,9 +1,11 @@ //! Structures, traits and impls related to *runtime* `Executor`s. #[cfg(not(feature = "std"))] -use alloc::{format, string::String, vec::Vec}; +use alloc::{collections::BTreeSet, format, string::String, vec::Vec}; +#[cfg(feature = "std")] +use std::collections::BTreeSet; -use derive_more::Constructor; +use derive_more::{Constructor, Display}; use getset::Getters; use iroha_data_model_derive::model; use iroha_schema::IntoSchema; @@ -11,7 +13,7 @@ use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; pub use self::model::*; -use crate::transaction::WasmSmartContract; +use crate::{permission::PermissionId, transaction::WasmSmartContract, JsonString}; #[model] mod model { @@ -47,10 +49,60 @@ mod model { pub wasm: WasmSmartContract, } + /// Executor data model. + /// + /// Defined from within the executor, it describes certain structures the executor + /// works with. + /// + /// Executor can define: + /// + /// - Permission tokens (see [`crate::permission::Permission`]) + /// - Configuration parameters (see [`crate::parameter::Parameter`]) + #[derive( + Default, + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Constructor, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + Display, + )] + #[ffi_type] + #[display(fmt = "{self:?}")] + pub struct ExecutorDataModel { + /// Permission tokens supported by the executor. + /// + /// These IDs refer to the types in the schema. + pub permissions: BTreeSet, + /// Data model JSON schema, typically produced by [`IntoSchema`]. + pub schema: JsonString, + } + // TODO: Client doesn't need structures defined inside this macro. When dynamic linking is // implemented use: #[cfg(any(feature = "transparent_api", feature = "ffi_import"))] } +// TODO: derive `Getters` once FFI impl is fixed +// currently it fails for all fields +impl ExecutorDataModel { + /// Getter + pub fn permissions(&self) -> &BTreeSet { + &self.permissions + } + + /// Getter + pub fn schema(&self) -> &JsonString { + &self.schema + } +} + /// Result type that every executor should return. pub type Result = core::result::Result; @@ -62,5 +114,5 @@ pub type MigrationResult = Result<(), MigrationError>; pub mod prelude { //! The prelude re-exports most commonly used traits, structs and macros from this crate. - pub use super::Executor; + pub use super::{Executor, ExecutorDataModel}; } diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index 301b01ba84e..4f411f1dca9 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -154,7 +154,7 @@ mod seal { FindTransactionsByAccountId, FindTransactionByHash, FindPermissionsByAccountId, - FindPermissionSchema, + FindExecutorDataModel, FindAllActiveTriggerIds, FindTriggerById, FindTriggerKeyValueByIdAndKey, @@ -864,6 +864,78 @@ mod model { /// in the next request to continue fetching results of the original query pub cursor: crate::query::cursor::ForwardCursor, } + + /// String containing serialized valid JSON. + /// + /// This string is guaranteed to be parsed as JSON. + #[derive( + Display, Default, Debug, Clone, Encode, Decode, Ord, PartialOrd, Eq, PartialEq, IntoSchema, + )] + #[ffi_type(unsafe {robust})] + #[repr(transparent)] + #[display(fmt = "{}", "0")] + pub struct JsonString(pub(super) String); +} + +impl JsonString { + /// Deserialize JSON into something + /// # Errors + /// See [`serde_json::from_str`]. + pub fn deserialize<'a, T>(&'a self) -> serde_json::Result + where + T: Deserialize<'a>, + { + serde_json::from_str(&self.0) + } + + /// Serializes a value into [`JsonString`] + /// # Errors + /// See [`serde_json::to_string`]. + pub fn serialize(value: &T) -> serde_json::Result { + let serialized = serde_json::to_string(value)?; + // the string was obtained from serde_json serialization, + // so it should be a valid JSON string + Ok(Self(serialized)) + } + + /// Create without checking whether the input is a valid JSON string. + /// + /// The caller must guarantee that the value is valid. + pub fn from_string_unchecked(value: String) -> Self { + Self(value) + } +} + +impl From<&serde_json::Value> for JsonString { + fn from(value: &serde_json::Value) -> Self { + Self(value.to_string()) + } +} + +impl From for JsonString { + fn from(value: serde_json::Value) -> Self { + Self::from(&value) + } +} + +impl<'de> serde::de::Deserialize<'de> for JsonString { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let json = serde_json::Value::deserialize(deserializer)?; + Ok(Self::from(&json)) + } +} + +impl serde::ser::Serialize for JsonString { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let json = serde_json::Value::from_str(&self.0).map_err(serde::ser::Error::custom)?; + json.serialize(serializer) + } } macro_rules! impl_encode_as_id_box { diff --git a/data_model/src/permission.rs b/data_model/src/permission.rs index 4f94ed139d0..253c1784d37 100644 --- a/data_model/src/permission.rs +++ b/data_model/src/permission.rs @@ -1,6 +1,6 @@ //! Permission Token and related impls #[cfg(not(feature = "std"))] -use alloc::{borrow::ToOwned as _, collections::BTreeSet, format, string::String, vec::Vec}; +use alloc::{collections::BTreeSet, format, string::String, vec::Vec}; #[cfg(feature = "std")] use std::collections::BTreeSet; @@ -17,200 +17,87 @@ pub type Permissions = BTreeSet; use super::*; -/// Unique id of [`Permission`] -pub type PermissionId = Name; - #[model] mod model { use super::*; - /// Stored proof of the account having a permission for a certain action. - /// - /// Since permission token is represented opaque to core - /// either executor or client should make sure that tokens are represented uniformly. - /// - /// So that: - /// - payload A is equal to payload B then token A must be equal to token B - /// - and if payload A is't equal to B then token A mustn't be equal to token B + /// Identifies a [`Permission`]. + /// The executor defines available permission names. #[derive( Debug, + Display, Clone, PartialEq, Eq, PartialOrd, Ord, + Hash, + Constructor, + FromStr, + Getters, Decode, Encode, Deserialize, Serialize, IntoSchema, )] - #[ffi_type] - pub struct Permission { - /// Token identifier - pub definition_id: PermissionId, - /// JSON encoded token payload - pub payload: JsonString, + #[getset(get = "pub")] + #[serde(transparent)] + #[repr(transparent)] + #[ffi_type(opaque)] + pub struct PermissionId { + /// Should be unique. + pub name: Name, } - /// Description of tokens defined in the executor + /// Stored proof of the account having a permission for a certain action. #[derive( Debug, - Display, Clone, PartialEq, Eq, PartialOrd, Ord, - Default, Decode, Encode, Deserialize, Serialize, IntoSchema, + Display, + Getters, )] - #[display(fmt = "{token_ids:#?}")] #[ffi_type] - pub struct PermissionSchema { - /// Ids of all permission tokens, sorted. - pub token_ids: Vec, - /// Type schema of permission tokens + #[display(fmt = "PERMISSION `{id}` = `{payload}`")] + #[getset(get = "pub")] + pub struct Permission { + /// Refers to a type defined in [`crate::executor::ExecutorDataModel`]. + pub id: PermissionId, + /// Payload containing actual value. /// - /// At the time of writing this doc a complete schema is returned but it's - /// possible that in the future this field will contain references to types - /// defined in the Iroha schema without defining them itself - pub schema: String, - } - - /// String containing serialized valid JSON. - /// This string is guaranteed to parse as JSON - #[derive(Debug, Clone, Eq, Decode, Encode)] - pub struct JsonString(pub(super) String); -} - -// TODO: Use getset to derive this -impl PermissionSchema { - /// Construct new [`PermissionSchema`] - pub fn new(token_ids: Vec, schema: String) -> Self { - Self { token_ids, schema } - } - - /// Return id of this token - pub fn permissions(&self) -> &[PermissionId] { - &self.token_ids + /// It is JSON-encoded, and its structure must correspond to the structure of + /// the type defined in [`crate::executor::ExecutorDataModel`]. + #[getset(skip)] + pub payload: JsonString, } } impl Permission { - /// Construct [`Self`] from a raw string slice. The caller of the function - /// must make sure that the given string slice can be parsed as valid JSON. - /// - /// Only used in tests - #[cfg(debug_assertions)] - // TODO: Remove after integration tests have been moved to python tests - #[deprecated(note = "Will be removed after integration tests are removed from iroha_client")] - pub fn from_str_unchecked(definition_id: PermissionId, payload: &str) -> Self { - Self { - definition_id, - payload: JsonString(payload.to_owned()), - } - } - - /// Construct [`Self`] - pub fn new(definition_id: PermissionId, payload: &serde_json::Value) -> Self { + /// Constructor + pub fn new(id: PermissionId, payload: impl Into) -> Self { Self { - definition_id, - payload: JsonString::new(payload), - } - } - - /// Return id of this token - // TODO: Use getset to derive this after fixes in FFI - pub fn definition_id(&self) -> &Name { - &self.definition_id - } - - /// Payload of this token - // TODO: Use getset to derive this after fixes in FFI - pub fn payload(&self) -> &String { - &self.payload.0 - } -} - -impl core::fmt::Display for Permission { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", self.definition_id) - } -} - -impl JsonString { - /// Construct [`JsonString`] - pub fn new(payload: &serde_json::Value) -> Self { - Self(payload.to_string()) - } -} - -impl PartialEq for JsonString { - fn eq(&self, other: &Self) -> bool { - serde_json::from_str::(&self.0).unwrap() - == serde_json::from_str::(&other.0).unwrap() - } -} - -impl<'de> serde::de::Deserialize<'de> for JsonString { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let json = serde_json::Value::deserialize(deserializer)?; - Ok(Self::new(&json)) - } -} - -impl serde::ser::Serialize for JsonString { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let json = serde_json::Value::from_str(&self.0).map_err(serde::ser::Error::custom)?; - json.serialize(serializer) - } -} - -impl iroha_schema::TypeId for JsonString { - fn id() -> iroha_schema::Ident { - "JsonString".to_owned() - } -} - -impl IntoSchema for JsonString { - fn type_name() -> iroha_schema::Ident { - ::id() - } - - fn update_schema_map(map: &mut iroha_schema::MetaMap) { - if !map.contains_key::() { - map.insert::(iroha_schema::Metadata::String); + id, + payload: payload.into(), } } -} - -impl PartialOrd for JsonString { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for JsonString { - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - let first = serde_json::from_str::(&self.0).unwrap(); - let second = serde_json::from_str::(&other.0).unwrap(); - first.to_string().cmp(&second.to_string()) + /// Getter + // TODO: derive with getset once FFI impl is fixed + pub fn payload(&self) -> &JsonString { + &self.payload } } pub mod prelude { //! The prelude re-exports most commonly used traits, structs and macros from this crate. - pub use super::{Permission, PermissionId, PermissionSchema}; + pub use super::{Permission, PermissionId}; } diff --git a/data_model/src/query/mod.rs b/data_model/src/query/mod.rs index daed565038f..01ed6624e73 100644 --- a/data_model/src/query/mod.rs +++ b/data_model/src/query/mod.rs @@ -26,8 +26,8 @@ pub use sorting::Sorting; pub use self::model::*; use self::{ - account::*, asset::*, block::*, domain::*, peer::*, permission::*, predicate::*, role::*, - transaction::*, trigger::*, + account::*, asset::*, block::*, domain::*, executor::*, peer::*, permission::*, predicate::*, + role::*, transaction::*, trigger::*, }; use crate::{ account::{Account, AccountId}, @@ -197,7 +197,7 @@ mod model { FindTransactionsByAccountId(FindTransactionsByAccountId), FindTransactionByHash(FindTransactionByHash), FindPermissionsByAccountId(FindPermissionsByAccountId), - FindPermissionSchema(FindPermissionSchema), + FindExecutorDataModel(FindExecutorDataModel), FindAllActiveTriggerIds(FindAllActiveTriggerIds), FindTriggerById(FindTriggerById), FindTriggerKeyValueByIdAndKey(FindTriggerKeyValueByIdAndKey), @@ -230,11 +230,11 @@ mod model { Identifiable(IdentifiableBox), Transaction(TransactionQueryOutput), Permission(crate::permission::Permission), - PermissionSchema(crate::permission::PermissionSchema), LimitedMetadata(MetadataValueBox), Numeric(Numeric), BlockHeader(BlockHeader), Block(crate::block::SignedBlock), + ExecutorDataModel(crate::executor::ExecutorDataModel), Vec( #[skip_from] @@ -356,8 +356,6 @@ impl TryFrom for u64 { /// Implements [`Query`] and, additionally, either [`SingularQuery`] or [`IterableQuery`], /// depending on whether the output type is wrapped into a Vec (purely syntactically) macro_rules! impl_queries { - // base case for the tt-muncher - () => {}; // we can't delegate matching over `Vec<$item:ty>` to an inner macro, // as the moment a fragment is matched as `$output:ty` it becomes opaque and unmatchable to any literal // https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment @@ -399,7 +397,6 @@ impl_queries! { FindAllRoleIds => Vec, FindRolesByAccountId => Vec, FindRoleByRoleId => crate::role::Role, - FindPermissionSchema => crate::permission::PermissionSchema, FindPermissionsByAccountId => Vec, FindAllAccounts => Vec, FindAccountById => crate::account::Account, @@ -434,6 +431,7 @@ impl_queries! { FindAllBlocks => Vec, FindAllBlockHeaders => Vec, FindBlockHeaderByHash => crate::block::BlockHeader, + FindExecutorDataModel => crate::executor::ExecutorDataModel } impl Query for QueryBox { @@ -452,11 +450,11 @@ impl core::fmt::Display for QueryOutputBox { QueryOutputBox::Identifiable(v) => core::fmt::Display::fmt(&v, f), QueryOutputBox::Transaction(_) => write!(f, "TransactionQueryOutput"), QueryOutputBox::Permission(v) => core::fmt::Display::fmt(&v, f), - QueryOutputBox::PermissionSchema(v) => core::fmt::Display::fmt(&v, f), QueryOutputBox::Block(v) => core::fmt::Display::fmt(&v, f), QueryOutputBox::BlockHeader(v) => core::fmt::Display::fmt(&v, f), QueryOutputBox::Numeric(v) => core::fmt::Display::fmt(&v, f), QueryOutputBox::LimitedMetadata(v) => core::fmt::Display::fmt(&v, f), + QueryOutputBox::ExecutorDataModel(v) => core::fmt::Display::fmt(&v, f), QueryOutputBox::Vec(v) => { // TODO: Remove so we can derive. @@ -661,17 +659,9 @@ pub mod permission { use parity_scale_codec::Encode; use super::{Query, QueryType}; - use crate::{ - permission::{self, PermissionSchema}, - prelude::*, - }; + use crate::prelude::*; queries! { - /// Finds all registered permission tokens - #[derive(Copy, Display)] - #[ffi_type] - pub struct FindPermissionSchema; - /// [`FindPermissionsByAccountId`] Iroha Query finds all [`Permission`]s /// for a specified account. #[derive(Display)] @@ -687,7 +677,7 @@ pub mod permission { /// The prelude re-exports most commonly used traits, structs and macros from this module. pub mod prelude { - pub use super::{FindPermissionSchema, FindPermissionsByAccountId}; + pub use super::FindPermissionsByAccountId; } } @@ -994,7 +984,7 @@ pub mod domain { } pub mod peer { - //! Queries related to [`Domain`](crate::domain::Domain). + //! Queries related to [`crate::peer`]. #[cfg(not(feature = "std"))] use alloc::{format, string::String, vec::Vec}; @@ -1010,18 +1000,39 @@ pub mod peer { #[display(fmt = "Find all peers")] #[ffi_type] pub struct FindAllPeers; + } + + /// The prelude re-exports most commonly used traits, structs and macros from this crate. + pub mod prelude { + pub use super::FindAllPeers; + } +} + +pub mod executor { + //! Queries related to [`crate::executor`]. + + #[cfg(not(feature = "std"))] + use alloc::{format, string::String, vec::Vec}; + + use derive_more::Display; + + queries! { + /// [`FindExecutorDataModel`] Iroha Query finds the data model of the current executor. + #[derive(Copy, Display)] + #[display(fmt = "Find executor data model")] + #[ffi_type] + pub struct FindExecutorDataModel; - /// [`FindAllParameters`] Iroha Query finds all [`Peer`]s parameters. + /// [`FindAllParameters`] Iroha Query finds all defined executor configuration parameters. #[derive(Copy, Display)] #[display(fmt = "Find all peers parameters")] - // TODO: Unused query. Remove? #[ffi_type] pub struct FindAllParameters; } /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { - pub use super::{FindAllParameters, FindAllPeers}; + pub use super::{FindAllParameters, FindExecutorDataModel}; } } @@ -1535,7 +1546,8 @@ pub mod prelude { pub use super::http::*; pub use super::{ account::prelude::*, asset::prelude::*, block::prelude::*, domain::prelude::*, - peer::prelude::*, permission::prelude::*, predicate::PredicateTrait, role::prelude::*, - transaction::*, trigger::prelude::*, FetchSize, QueryBox, QueryId, TransactionQueryOutput, + executor::prelude::*, peer::prelude::*, permission::prelude::*, predicate::PredicateTrait, + role::prelude::*, transaction::prelude::*, trigger::prelude::*, FetchSize, QueryBox, + QueryId, TransactionQueryOutput, }; } diff --git a/data_model/src/visit.rs b/data_model/src/visit.rs index 754ee8368c6..f2b16f0b81c 100644 --- a/data_model/src/visit.rs +++ b/data_model/src/visit.rs @@ -58,7 +58,7 @@ pub trait Visit { visit_find_all_domains(&FindAllDomains), visit_find_all_parameters(&FindAllParameters), visit_find_all_peers(&FindAllPeers), - visit_find_permission_schema(&FindPermissionSchema), + visit_find_executor_data_model(&FindExecutorDataModel), visit_find_all_role_ids(&FindAllRoleIds), visit_find_all_roles(&FindAllRoles), visit_find_all_transactions(&FindAllTransactions), @@ -183,7 +183,7 @@ pub fn visit_query(visitor: &mut V, authority: &AccountId, qu visit_find_all_domains(FindAllDomains), visit_find_all_parameters(FindAllParameters), visit_find_all_peers(FindAllPeers), - visit_find_permission_schema(FindPermissionSchema), + visit_find_executor_data_model(FindExecutorDataModel), visit_find_all_role_ids(FindAllRoleIds), visit_find_all_roles(FindAllRoles), visit_find_all_transactions(FindAllTransactions), @@ -444,7 +444,7 @@ leaf_visitors! { visit_find_all_domains(&FindAllDomains), visit_find_all_parameters(&FindAllParameters), visit_find_all_peers(&FindAllPeers), - visit_find_permission_schema(&FindPermissionSchema), + visit_find_executor_data_model(&FindExecutorDataModel), visit_find_all_role_ids(&FindAllRoleIds), visit_find_all_roles(&FindAllRoles), visit_find_all_transactions(&FindAllTransactions), diff --git a/default_executor/src/lib.rs b/default_executor/src/lib.rs index 26b3593f753..a506d4df6dc 100644 --- a/default_executor/src/lib.rs +++ b/default_executor/src/lib.rs @@ -8,7 +8,7 @@ extern crate panic_halt; use alloc::borrow::ToOwned as _; -use iroha_executor::{default::default_permission_schema, prelude::*}; +use iroha_executor::{prelude::*, DataModelBuilder}; use lol_alloc::{FreeListAllocator, LockedAllocator}; #[global_allocator] @@ -52,11 +52,7 @@ impl Executor { pub fn migrate(block_height: u64) -> MigrationResult { Executor::ensure_genesis(block_height)?; - let schema = default_permission_schema(); - let (token_ids, schema_str) = schema.serialize(); - iroha_executor::set_permission_schema( - &iroha_executor::data_model::permission::PermissionSchema::new(token_ids, schema_str), - ); + DataModelBuilder::with_default_permissions().build_and_set(); Ok(()) } diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 3428213f02e..1f11b12abf7 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -157,7 +157,7 @@ }, { "name": "permission_id", - "type": "Name" + "type": "PermissionId" } ] }, @@ -855,19 +855,14 @@ "discriminant": 3, "type": "RoleEvent" }, - { - "tag": "Permission", - "discriminant": 4, - "type": "PermissionSchemaUpdateEvent" - }, { "tag": "Configuration", - "discriminant": 5, + "discriminant": 4, "type": "ConfigurationEvent" }, { "tag": "Executor", - "discriminant": 6, + "discriminant": 5, "type": "ExecutorEvent" } ] @@ -913,18 +908,14 @@ "discriminant": 7, "type": "RoleEventFilter" }, - { - "tag": "PermissionSchemaUpdate", - "discriminant": 8 - }, { "tag": "Configuration", - "discriminant": 9, + "discriminant": 8, "type": "ConfigurationEventFilter" }, { "tag": "Executor", - "discriminant": 10, + "discriminant": 9, "type": "ExecutorEventFilter" } ] @@ -1200,11 +1191,24 @@ } ] }, + "ExecutorDataModel": { + "Struct": [ + { + "name": "permissions", + "type": "SortedVec" + }, + { + "name": "schema", + "type": "JsonString" + } + ] + }, "ExecutorEvent": { "Enum": [ { "tag": "Upgraded", - "discriminant": 0 + "discriminant": 0, + "type": "ExecutorUpgrade" } ] }, @@ -1227,6 +1231,14 @@ ] } }, + "ExecutorUpgrade": { + "Struct": [ + { + "name": "new_data_model", + "type": "ExecutorDataModel" + } + ] + }, "Fail": { "Struct": [ { @@ -1466,7 +1478,7 @@ { "tag": "Permission", "discriminant": 10, - "type": "Name" + "type": "PermissionId" }, { "tag": "Parameter", @@ -1480,7 +1492,7 @@ } ] }, - "FindPermissionSchema": null, + "FindExecutorDataModel": null, "FindPermissionsByAccountId": { "Struct": [ { @@ -1692,7 +1704,7 @@ { "tag": "PermissionId", "discriminant": 7, - "type": "Name" + "type": "PermissionId" }, { "tag": "ParameterId", @@ -2628,8 +2640,8 @@ "Permission": { "Struct": [ { - "name": "definition_id", - "type": "Name" + "name": "id", + "type": "PermissionId" }, { "name": "payload", @@ -2637,27 +2649,11 @@ } ] }, - "PermissionSchema": { + "PermissionId": { "Struct": [ { - "name": "token_ids", - "type": "Vec" - }, - { - "name": "schema", - "type": "String" - } - ] - }, - "PermissionSchemaUpdateEvent": { - "Struct": [ - { - "name": "old_schema", - "type": "PermissionSchema" - }, - { - "name": "new_schema", - "type": "PermissionSchema" + "name": "name", + "type": "Name" } ] }, @@ -2849,9 +2845,9 @@ "type": "FindPermissionsByAccountId" }, { - "tag": "FindPermissionSchema", + "tag": "FindExecutorDataModel", "discriminant": 29, - "type": "FindPermissionSchema" + "type": "FindExecutorDataModel" }, { "tag": "FindAllActiveTriggerIds", @@ -2953,31 +2949,31 @@ "discriminant": 3, "type": "Permission" }, - { - "tag": "PermissionSchema", - "discriminant": 4, - "type": "PermissionSchema" - }, { "tag": "LimitedMetadata", - "discriminant": 5, + "discriminant": 4, "type": "MetadataValueBox" }, { "tag": "Numeric", - "discriminant": 6, + "discriminant": 5, "type": "Numeric" }, { "tag": "BlockHeader", - "discriminant": 7, + "discriminant": 6, "type": "BlockHeader" }, { "tag": "Block", - "discriminant": 8, + "discriminant": 7, "type": "SignedBlock" }, + { + "tag": "ExecutorDataModel", + "discriminant": 8, + "type": "ExecutorDataModel" + }, { "tag": "Vec", "discriminant": 9, @@ -3369,7 +3365,7 @@ }, { "name": "permission_id", - "type": "Name" + "type": "PermissionId" } ] }, @@ -3721,6 +3717,9 @@ "SortedVec": { "Vec": "Permission" }, + "SortedVec": { + "Vec": "PermissionId" + }, "SortedVec>": { "Vec": "SignatureOf" }, @@ -4364,9 +4363,6 @@ "Vec": { "Vec": "MetadataValueBox" }, - "Vec": { - "Vec": "Name" - }, "Vec": { "Vec": "PeerId" }, diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index ff6b9888da7..e0cceca6941 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -137,6 +137,8 @@ types!( ExecutorEvent, ExecutorEventFilter, ExecutorEventSet, + ExecutorUpgrade, + ExecutorDataModel, Fail, EventFilterBox, FetchSize, @@ -170,7 +172,6 @@ types!( FindDomainById, FindDomainKeyValueByIdAndKey, FindError, - FindPermissionSchema, FindPermissionsByAccountId, FindRoleByRoleId, FindRolesByAccountId, @@ -267,8 +268,6 @@ types!( PeerId, RolePermissionChanged, Permission, - PermissionSchema, - PermissionSchemaUpdateEvent, PipelineEventBox, PipelineEventFilterBox, PredicateBox, @@ -396,16 +395,17 @@ types!( u8, ); -#[cfg(test)] -mod tests { - use core::num::{NonZeroU32, NonZeroU64}; - use std::{ +pub mod complete_data_model { + //! Complete set of types participating in the schema + + pub use core::num::{NonZeroU32, NonZeroU64}; + pub use std::{ collections::{BTreeMap, BTreeSet, HashMap, HashSet}, time::Duration, }; - use iroha_crypto::*; - use iroha_data_model::{ + pub use iroha_crypto::*; + pub use iroha_data_model::{ account::NewAccount, asset::NewAssetDefinition, block::{ @@ -415,7 +415,7 @@ mod tests { }, domain::NewDomain, events::pipeline::{BlockEventFilter, TransactionEventFilter}, - executor::Executor, + executor::{Executor, ExecutorDataModel}, ipfs::IpfsPath, isi::{ error::{ @@ -426,7 +426,6 @@ mod tests { }, metadata::{MetadataError, MetadataValueBox, SizeError}, parameter::ParameterValueBox, - permission::JsonString, prelude::*, query::{ error::{FindError, QueryExecutionFail}, @@ -442,17 +441,20 @@ mod tests { error::TransactionLimitError, SignedTransactionV1, TransactionLimits, TransactionPayload, }, - BatchedResponse, BatchedResponseV1, Level, + BatchedResponse, BatchedResponseV1, JsonString, Level, }; - use iroha_primitives::{ + pub use iroha_primitives::{ addr::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrHost, SocketAddrV4, SocketAddrV6}, const_vec::ConstVec, conststr::ConstString, unique_vec::UniqueVec, }; - use iroha_schema::Compact; + pub use iroha_schema::Compact; +} - use super::IntoSchema; +#[cfg(test)] +mod tests { + use super::{complete_data_model::*, IntoSchema}; fn is_const_generic(generic: &str) -> bool { generic.parse::().is_ok() diff --git a/smart_contract/executor/derive/src/entrypoint.rs b/smart_contract/executor/derive/src/entrypoint.rs index 84b685bd64e..c17109def46 100644 --- a/smart_contract/executor/derive/src/entrypoint.rs +++ b/smart_contract/executor/derive/src/entrypoint.rs @@ -145,7 +145,7 @@ fn impl_migrate_entrypoint(fn_item: syn::ItemFn) -> TokenStream { let migrate_fn_name = syn::Ident::new(export::EXECUTOR_MIGRATE, proc_macro2::Span::call_site()); quote! { - /// Executor `permission_schema` entrypoint + /// Executor `migrate` entrypoint /// /// # Memory safety /// diff --git a/smart_contract/executor/derive/src/lib.rs b/smart_contract/executor/derive/src/lib.rs index fa4a4318c8b..962cbd794a1 100644 --- a/smart_contract/executor/derive/src/lib.rs +++ b/smart_contract/executor/derive/src/lib.rs @@ -7,7 +7,7 @@ use proc_macro2::TokenStream; mod conversion; mod default; mod entrypoint; -mod token; +mod permission; mod validate; /// Annotate the user-defined function that starts the execution of a executor. @@ -64,14 +64,14 @@ pub fn entrypoint(attr: TokenStream, item: TokenStream) -> TokenStream { emitter.finish_token_stream_with(result) } -/// Derive macro for `Token` trait. +/// Derive macro for `Permission` trait. /// /// # Example /// /// ```ignore /// use iroha_executor::{permission, prelude::*}; /// -/// #[derive(Token, ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] +/// #[derive(Permission, ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] /// #[validate(permission::asset::Owner)] /// struct CanDoSomethingWithAsset { /// some_data: String, @@ -93,11 +93,11 @@ pub fn entrypoint(attr: TokenStream, item: TokenStream) -> TokenStream { /// } /// ``` #[manyhow] -#[proc_macro_derive(Token)] -pub fn derive_token(input: TokenStream) -> Result { +#[proc_macro_derive(Permission)] +pub fn derive_permission(input: TokenStream) -> Result { let input = syn::parse2(input)?; - Ok(token::impl_derive_token(&input)) + Ok(permission::impl_derive_permission(&input)) } /// Derive macro for `ValidateGrantRevoke` trait. diff --git a/smart_contract/executor/derive/src/permission.rs b/smart_contract/executor/derive/src/permission.rs new file mode 100644 index 00000000000..422580e6316 --- /dev/null +++ b/smart_contract/executor/derive/src/permission.rs @@ -0,0 +1,60 @@ +//! Module with [`derive_permission`](crate::derive_permission) macro implementation + +use proc_macro2::TokenStream; +use quote::quote; + +/// [`derive_permission`](crate::derive_permission()) macro implementation +pub fn impl_derive_permission(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::permission::Permission for #ident #ty_generics #where_clause { + fn is_owned_by(&self, account_id: &::iroha_executor::data_model::account::AccountId) -> bool { + let account_tokens_cursor = + ::iroha_executor::smart_contract::ExecuteQueryOnHost::execute( + &::iroha_executor::data_model::query::permission::FindPermissionsByAccountId::new( + account_id.clone(), + ) + ) + .expect("`FindPermissionsByAccountId` query should never fail, it's a bug"); + + account_tokens_cursor + .into_iter() + .map(|res| ::iroha_executor::smart_contract::debug::DebugExpectExt::dbg_expect( + res, + "Failed to get permission token from cursor" + )) + .filter_map(|token| Self::try_from(&token).ok()) + .any(|token| self == &token) + } + } + + impl #impl_generics TryFrom<&::iroha_executor::data_model::permission::Permission> for #ident #ty_generics #where_clause { + type Error = ::iroha_executor::TryFromDataModelObjectError; + + fn try_from( + value: &::iroha_executor::data_model::permission::Permission, + ) -> core::result::Result { + if *value.id() != ::id() { + return Err(Self::Error::Id(value.id().name().clone())); + } + value + .payload() + .deserialize() + .map_err(Self::Error::Deserialize) + } + } + + impl #impl_generics From<#ident #ty_generics> for ::iroha_executor::data_model::permission::Permission #where_clause { + fn from(value: #ident #ty_generics) -> Self { + ::iroha_executor::data_model::permission::Permission::new( + <#ident as ::iroha_executor::permission::Permission>::id(), + ::iroha_executor::data_model::JsonString::serialize(&value) + .expect("failed to serialize concrete data model entity; this is a bug"), + ) + } + } + } +} diff --git a/smart_contract/executor/derive/src/token.rs b/smart_contract/executor/derive/src/token.rs deleted file mode 100644 index c2ca5adea29..00000000000 --- a/smart_contract/executor/derive/src/token.rs +++ /dev/null @@ -1,80 +0,0 @@ -//! Module with [`derive_token`](crate::derive_token) macro implementation - -use proc_macro2::TokenStream; -use quote::quote; - -/// [`derive_token`](crate::derive_token()) macro implementation -pub fn impl_derive_token(input: &syn::DeriveInput) -> TokenStream { - let generics = &input.generics; - let ident = &input.ident; - - let impl_token = impl_token(ident, generics); - let impl_try_from_permission = impl_try_from_permission(ident, generics); - - quote! { - #impl_token - #impl_try_from_permission - } -} - -fn impl_token(ident: &syn::Ident, generics: &syn::Generics) -> proc_macro2::TokenStream { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - - quote! { - impl #impl_generics ::iroha_executor::permission::Token for #ident #ty_generics #where_clause { - fn is_owned_by(&self, account_id: &::iroha_executor::data_model::account::AccountId) -> bool { - let account_tokens_cursor = ::iroha_executor::smart_contract::debug::DebugExpectExt::dbg_expect( - ::iroha_executor::smart_contract::ExecuteQueryOnHost::execute( - &::iroha_executor::data_model::query::permission::FindPermissionsByAccountId::new( - account_id.clone(), - ) - ), - "Failed to execute `FindPermissionsByAccountId` query" - ); - - account_tokens_cursor - .into_iter() - .map(|res| ::iroha_executor::smart_contract::debug::DebugExpectExt::dbg_expect( - res, - "Failed to get permission token from cursor" - )) - .filter_map(|token| Self::try_from(&token).ok()) - .any(|token| self == &token) - } - } - } -} - -fn impl_try_from_permission(ident: &syn::Ident, generics: &syn::Generics) -> TokenStream { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let token_id = quote! { <#ident #ty_generics as ::iroha_executor::permission::Token>::name() }; - - quote! { - impl #impl_generics ::core::convert::TryFrom<&::iroha_executor::data_model::permission::Permission> for #ident #ty_generics #where_clause { - type Error = ::iroha_executor::permission::PermissionConversionError; - - fn try_from(token: &::iroha_executor::data_model::permission::Permission) -> ::core::result::Result { - if #token_id != *token.definition_id() { - return Err(::iroha_executor::permission::PermissionConversionError::Id( - ToOwned::to_owned(token.definition_id()) - )); - } - ::serde_json::from_str::(token.payload()) - .map_err(::iroha_executor::permission::PermissionConversionError::Deserialize) - } - } - - impl #impl_generics ::core::convert::From<#ident #ty_generics> for ::iroha_executor::data_model::permission::Permission #where_clause { - fn from(token: #ident #ty_generics) -> Self { - let definition_id = #token_id; - - let payload = ::iroha_executor::smart_contract::debug::DebugExpectExt::dbg_expect( - ::serde_json::to_value::<#ident #ty_generics>(token), - "failed to serialize concrete permission token type. This is a bug." - ); - - ::iroha_executor::data_model::permission::Permission::new(definition_id, &payload) - } - } - } -} diff --git a/smart_contract/executor/src/default.rs b/smart_contract/executor/src/default.rs index e2a4e827b9e..ca9fefa1ae0 100644 --- a/smart_contract/executor/src/default.rs +++ b/smart_contract/executor/src/default.rs @@ -1,7 +1,7 @@ //! Definition of Iroha default executor and accompanying validation functions #![allow(missing_docs, clippy::missing_errors_doc)] -pub mod tokens; +pub mod permissions; use alloc::format; @@ -30,6 +30,7 @@ pub use log::visit_log; pub use parameter::{visit_new_parameter, visit_set_parameter}; pub use peer::{visit_register_peer, visit_unregister_peer}; pub use permission::{visit_grant_account_permission, visit_revoke_account_permission}; +use permissions::AnyPermission; pub use role::{ visit_grant_account_role, visit_grant_role_permission, visit_register_role, visit_revoke_account_role, visit_revoke_role_permission, visit_unregister_role, @@ -40,21 +41,10 @@ pub use trigger::{ visit_unregister_trigger, }; -use crate::{permission::Token as _, prelude::*}; - -pub fn default_permission_schema() -> PermissionSchema { - let mut schema = iroha_executor::PermissionSchema::default(); - - macro_rules! add_to_schema { - ($token_ty:ty) => { - schema.insert::<$token_ty>(); - }; - } - - tokens::map_token_type!(add_to_schema); - - schema -} +use crate::{ + permission::Permission as _, + prelude::{Permission, *}, +}; // NOTE: If any new `visit_..` functions are introduced in this module, one should // not forget to update the default executor boilerplate too, specifically the @@ -163,7 +153,7 @@ pub mod peer { if is_genesis(executor) { execute!(executor, isi); } - if tokens::peer::CanUnregisterAnyPeer.is_owned_by(authority) { + if permissions::peer::CanUnregisterAnyPeer.is_owned_by(authority) { execute!(executor, isi); } @@ -172,8 +162,7 @@ pub mod peer { } pub mod domain { - use iroha_smart_contract::data_model::{domain::DomainId, permission::Permission}; - use tokens::AnyPermission; + use iroha_smart_contract::data_model::domain::DomainId; use super::*; use crate::permission::{ @@ -201,7 +190,7 @@ pub mod domain { Ok(is_domain_owner) => is_domain_owner, } || { - let can_unregister_domain_token = tokens::domain::CanUnregisterDomain { + let can_unregister_domain_token = permissions::domain::CanUnregisterDomain { domain_id: domain_id.clone(), }; can_unregister_domain_token.is_owned_by(authority) @@ -268,7 +257,7 @@ pub mod domain { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_set_key_value_in_domain_token = tokens::domain::CanSetKeyValueInDomain { + let can_set_key_value_in_domain_token = permissions::domain::CanSetKeyValueInDomain { domain_id: domain_id.clone(), }; if can_set_key_value_in_domain_token.is_owned_by(authority) { @@ -293,7 +282,7 @@ pub mod domain { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_remove_key_value_in_domain_token = tokens::domain::CanRemoveKeyValueInDomain { + let can_remove_key_value_in_domain_token = permissions::domain::CanRemoveKeyValueInDomain { domain_id: domain_id.clone(), }; if can_remove_key_value_in_domain_token.is_owned_by(authority) { @@ -421,9 +410,6 @@ pub mod domain { } pub mod account { - use iroha_smart_contract::data_model::permission::Permission; - use tokens::AnyPermission; - use super::*; use crate::permission::{account::is_account_owner, accounts_permissions, roles_permissions}; @@ -440,7 +426,7 @@ pub mod account { Ok(false) => {} } - let can_register_account_in_domain = tokens::domain::CanRegisterAccountInDomain { + let can_register_account_in_domain = permissions::domain::CanRegisterAccountInDomain { domain_id: domain_id.clone(), }; if can_register_account_in_domain.is_owned_by(authority) { @@ -466,7 +452,7 @@ pub mod account { Ok(is_account_owner) => is_account_owner, } || { - let can_unregister_user_account = tokens::account::CanUnregisterAccount { + let can_unregister_user_account = permissions::account::CanUnregisterAccount { account_id: account_id.clone(), }; can_unregister_user_account.is_owned_by(authority) @@ -508,9 +494,10 @@ pub mod account { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_set_key_value_in_user_account_token = tokens::account::CanSetKeyValueInAccount { - account_id: account_id.clone(), - }; + let can_set_key_value_in_user_account_token = + permissions::account::CanSetKeyValueInAccount { + account_id: account_id.clone(), + }; if can_set_key_value_in_user_account_token.is_owned_by(authority) { execute!(executor, isi); } @@ -537,7 +524,7 @@ pub mod account { Ok(false) => {} } let can_remove_key_value_in_user_account_token = - tokens::account::CanRemoveKeyValueInAccount { + permissions::account::CanRemoveKeyValueInAccount { account_id: account_id.clone(), }; if can_remove_key_value_in_user_account_token.is_owned_by(authority) { @@ -627,8 +614,7 @@ pub mod account { } pub mod asset_definition { - use iroha_smart_contract::data_model::{asset::AssetDefinitionId, permission::Permission}; - use tokens::AnyPermission; + use iroha_smart_contract::data_model::asset::AssetDefinitionId; use super::*; use crate::permission::{ @@ -650,7 +636,7 @@ pub mod asset_definition { } let can_register_asset_definition_in_domain_token = - tokens::domain::CanRegisterAssetDefinitionInDomain { + permissions::domain::CanRegisterAssetDefinitionInDomain { domain_id: domain_id.clone(), }; if can_register_asset_definition_in_domain_token.is_owned_by(authority) { @@ -677,7 +663,7 @@ pub mod asset_definition { } || { let can_unregister_asset_definition_token = - tokens::asset_definition::CanUnregisterAssetDefinition { + permissions::asset_definition::CanUnregisterAssetDefinition { asset_definition_id: asset_definition_id.clone(), }; can_unregister_asset_definition_token.is_owned_by(authority) @@ -751,7 +737,7 @@ pub mod asset_definition { Ok(false) => {} } let can_set_key_value_in_asset_definition_token = - tokens::asset_definition::CanSetKeyValueInAssetDefinition { + permissions::asset_definition::CanSetKeyValueInAssetDefinition { asset_definition_id: asset_definition_id.clone(), }; if can_set_key_value_in_asset_definition_token.is_owned_by(authority) { @@ -780,7 +766,7 @@ pub mod asset_definition { Ok(false) => {} } let can_remove_key_value_in_asset_definition_token = - tokens::asset_definition::CanRemoveKeyValueInAssetDefinition { + permissions::asset_definition::CanRemoveKeyValueInAssetDefinition { asset_definition_id: asset_definition_id.clone(), }; if can_remove_key_value_in_asset_definition_token.is_owned_by(authority) { @@ -899,7 +885,7 @@ pub mod asset { Ok(false) => {} } let can_register_assets_with_definition_token = - tokens::asset::CanRegisterAssetWithDefinition { + permissions::asset::CanRegisterAssetWithDefinition { asset_definition_id: asset.id().definition_id().clone(), }; if can_register_assets_with_definition_token.is_owned_by(authority) { @@ -933,13 +919,13 @@ pub mod asset { Ok(false) => {} } let can_unregister_assets_with_definition_token = - tokens::asset::CanUnregisterAssetWithDefinition { + permissions::asset::CanUnregisterAssetWithDefinition { asset_definition_id: asset_id.definition_id().clone(), }; if can_unregister_assets_with_definition_token.is_owned_by(authority) { execute!(executor, isi); } - let can_unregister_user_asset_token = tokens::asset::CanUnregisterUserAsset { + let can_unregister_user_asset_token = permissions::asset::CanUnregisterUserAsset { asset_id: asset_id.clone(), }; if can_unregister_user_asset_token.is_owned_by(authority) { @@ -964,13 +950,14 @@ pub mod asset { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_mint_assets_with_definition_token = tokens::asset::CanMintAssetWithDefinition { - asset_definition_id: asset_id.definition_id().clone(), - }; + let can_mint_assets_with_definition_token = + permissions::asset::CanMintAssetWithDefinition { + asset_definition_id: asset_id.definition_id().clone(), + }; if can_mint_assets_with_definition_token.is_owned_by(authority) { execute!(executor, isi); } - let can_mint_user_asset_token = tokens::asset::CanMintUserAsset { + let can_mint_user_asset_token = permissions::asset::CanMintUserAsset { asset_id: asset_id.clone(), }; if can_mint_user_asset_token.is_owned_by(authority) { @@ -1011,13 +998,14 @@ pub mod asset { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_burn_assets_with_definition_token = tokens::asset::CanBurnAssetWithDefinition { - asset_definition_id: asset_id.definition_id().clone(), - }; + let can_burn_assets_with_definition_token = + permissions::asset::CanBurnAssetWithDefinition { + asset_definition_id: asset_id.definition_id().clone(), + }; if can_burn_assets_with_definition_token.is_owned_by(authority) { execute!(executor, isi); } - let can_burn_user_asset_token = tokens::asset::CanBurnUserAsset { + let can_burn_user_asset_token = permissions::asset::CanBurnUserAsset { asset_id: asset_id.clone(), }; if can_burn_user_asset_token.is_owned_by(authority) { @@ -1059,13 +1047,13 @@ pub mod asset { Ok(false) => {} } let can_transfer_assets_with_definition_token = - tokens::asset::CanTransferAssetWithDefinition { + permissions::asset::CanTransferAssetWithDefinition { asset_definition_id: asset_id.definition_id().clone(), }; if can_transfer_assets_with_definition_token.is_owned_by(authority) { execute!(executor, isi); } - let can_transfer_user_asset_token = tokens::asset::CanTransferUserAsset { + let can_transfer_user_asset_token = permissions::asset::CanTransferUserAsset { asset_id: asset_id.clone(), }; if can_transfer_user_asset_token.is_owned_by(authority) { @@ -1107,7 +1095,7 @@ pub mod asset { Ok(false) => {} } - let can_set_key_value_in_user_asset_token = tokens::asset::CanSetKeyValueInUserAsset { + let can_set_key_value_in_user_asset_token = permissions::asset::CanSetKeyValueInUserAsset { asset_id: asset_id.clone(), }; if can_set_key_value_in_user_asset_token.is_owned_by(authority) { @@ -1136,7 +1124,7 @@ pub mod asset { Ok(false) => {} } let can_remove_key_value_in_user_asset_token = - tokens::asset::CanRemoveKeyValueInUserAsset { + permissions::asset::CanRemoveKeyValueInUserAsset { asset_id: asset_id.clone(), }; if can_remove_key_value_in_user_asset_token.is_owned_by(authority) { @@ -1162,7 +1150,7 @@ pub mod parameter { if is_genesis(executor) { execute!(executor, isi); } - if tokens::parameter::CanCreateParameters.is_owned_by(authority) { + if permissions::parameter::CanCreateParameters.is_owned_by(authority) { execute!(executor, isi); } @@ -1181,20 +1169,20 @@ pub mod parameter { if is_genesis(executor) { execute!(executor, isi); } - if tokens::parameter::CanSetParameters.is_owned_by(authority) { + if permissions::parameter::CanSetParameters.is_owned_by(authority) { execute!(executor, isi); } deny!( executor, - "Can't set configuration parameters without permission" + "Can't set executor configuration parameters without permission" ); } } pub mod role { use iroha_smart_contract::data_model::role::Role; - use role::tokens::AnyPermission; + use role::permissions::AnyPermission; use super::*; @@ -1310,7 +1298,7 @@ pub mod role { if is_genesis(executor) { execute!(executor, isi); } - if tokens::role::CanUnregisterAnyRole.is_owned_by(authority) { + if permissions::role::CanUnregisterAnyRole.is_owned_by(authority) { execute!(executor, isi); } @@ -1351,13 +1339,14 @@ pub mod role { } pub mod trigger { - use iroha_executor::permission::trigger::find_trigger; - use iroha_smart_contract::data_model::{permission::Permission, trigger::Trigger}; - use tokens::AnyPermission; + use iroha_smart_contract::data_model::trigger::Trigger; use super::*; use crate::permission::{ - accounts_permissions, domain::is_domain_owner, roles_permissions, trigger::is_trigger_owner, + accounts_permissions, + domain::is_domain_owner, + roles_permissions, + trigger::{find_trigger, is_trigger_owner}, }; pub fn visit_register_trigger( @@ -1375,9 +1364,10 @@ pub mod trigger { } } || { - let can_register_user_trigger_token = tokens::trigger::CanRegisterUserTrigger { - account_id: isi.object().action().authority().clone(), - }; + let can_register_user_trigger_token = + permissions::trigger::CanRegisterUserTrigger { + account_id: isi.object().action().authority().clone(), + }; can_register_user_trigger_token.is_owned_by(authority) } { @@ -1399,13 +1389,14 @@ pub mod trigger { Ok(is_trigger_owner) => is_trigger_owner, } || { - let can_unregister_user_trigger_token = tokens::trigger::CanUnregisterUserTrigger { - account_id: find_trigger(trigger_id) - .unwrap() - .action() - .authority() - .clone(), - }; + let can_unregister_user_trigger_token = + permissions::trigger::CanUnregisterUserTrigger { + account_id: find_trigger(trigger_id) + .unwrap() + .action() + .authority() + .clone(), + }; can_unregister_user_trigger_token.is_owned_by(authority) } { @@ -1448,7 +1439,7 @@ pub mod trigger { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_mint_user_trigger_token = tokens::trigger::CanMintUserTrigger { + let can_mint_user_trigger_token = permissions::trigger::CanMintUserTrigger { trigger_id: trigger_id.clone(), }; if can_mint_user_trigger_token.is_owned_by(authority) { @@ -1476,7 +1467,7 @@ pub mod trigger { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_mint_user_trigger_token = tokens::trigger::CanBurnUserTrigger { + let can_mint_user_trigger_token = permissions::trigger::CanBurnUserTrigger { trigger_id: trigger_id.clone(), }; if can_mint_user_trigger_token.is_owned_by(authority) { @@ -1504,7 +1495,7 @@ pub mod trigger { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_execute_trigger_token = tokens::trigger::CanExecuteUserTrigger { + let can_execute_trigger_token = permissions::trigger::CanExecuteUserTrigger { trigger_id: trigger_id.clone(), }; if can_execute_trigger_token.is_owned_by(authority) { @@ -1529,9 +1520,10 @@ pub mod trigger { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_set_key_value_in_user_trigger_token = tokens::trigger::CanSetKeyValueInTrigger { - trigger_id: trigger_id.clone(), - }; + let can_set_key_value_in_user_trigger_token = + permissions::trigger::CanSetKeyValueInTrigger { + trigger_id: trigger_id.clone(), + }; if can_set_key_value_in_user_trigger_token.is_owned_by(authority) { execute!(executor, isi); } @@ -1557,9 +1549,10 @@ pub mod trigger { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_remove_key_value_in_trigger_token = tokens::trigger::CanRemoveKeyValueInTrigger { - trigger_id: trigger_id.clone(), - }; + let can_remove_key_value_in_trigger_token = + permissions::trigger::CanRemoveKeyValueInTrigger { + trigger_id: trigger_id.clone(), + }; if can_remove_key_value_in_trigger_token.is_owned_by(authority) { execute!(executor, isi); } @@ -1627,8 +1620,6 @@ pub mod trigger { } pub mod permission { - use tokens::AnyPermission; - use super::*; macro_rules! impl_validate { @@ -1701,7 +1692,7 @@ pub mod executor { if is_genesis(executor) { execute!(executor, isi); } - if tokens::executor::CanUpgradeExecutor.is_owned_by(authority) { + if permissions::executor::CanUpgradeExecutor.is_owned_by(authority) { execute!(executor, isi); } diff --git a/smart_contract/executor/src/default/tokens.rs b/smart_contract/executor/src/default/permissions.rs similarity index 77% rename from smart_contract/executor/src/default/tokens.rs rename to smart_contract/executor/src/default/permissions.rs index 283b48858ae..1ac643b451d 100644 --- a/smart_contract/executor/src/default/tokens.rs +++ b/smart_contract/executor/src/default/permissions.rs @@ -6,7 +6,7 @@ use alloc::{borrow::ToOwned, format, string::String, vec::Vec}; use iroha_executor_derive::ValidateGrantRevoke; use iroha_smart_contract::data_model::{executor::Result, prelude::*}; -use crate::permission::{self, Token as _}; +use crate::permission::{self, Permission as _}; /// Declare token types of current module. Use it with a full path to the token. /// Used to iterate over tokens to validate `Grant` and `Revoke` instructions. @@ -27,9 +27,9 @@ use crate::permission::{self, Token as _}; /// pub struct MyToken; /// } /// ``` -macro_rules! declare_tokens { +macro_rules! declare_permissions { ($($($token_path:ident ::)+ { $token_ty:ident }),+ $(,)?) => { - macro_rules! map_token_type { + macro_rules! map_default_permissions { ($callback:ident) => { $( $callback!($($token_path::)+$token_ty); )+ }; @@ -43,15 +43,15 @@ macro_rules! declare_tokens { } impl TryFrom<&$crate::data_model::permission::Permission> for AnyPermission { - type Error = $crate::permission::PermissionConversionError; + type Error = $crate::TryFromDataModelObjectError; fn try_from(token: &$crate::data_model::permission::Permission) -> Result { - match token.definition_id().as_ref() { $( + match token.id().name().as_ref() { $( stringify!($token_ty) => { let token = <$($token_path::)+$token_ty>::try_from(token)?; Ok(Self::$token_ty(token)) } )+ - _ => Err(Self::Error::Id(token.definition_id().clone())) + _ => Err(Self::Error::Id(token.id().name().clone())) } } } @@ -59,7 +59,7 @@ macro_rules! declare_tokens { impl From for $crate::data_model::permission::Permission { fn from(token: AnyPermission) -> Self { match token { $( - AnyPermission::$token_ty(token) => Self::from(token), )* + AnyPermission::$token_ty(token) => token.into(), )* } } } @@ -78,76 +78,76 @@ macro_rules! declare_tokens { } } - pub(crate) use map_token_type; + pub(crate) use map_default_permissions; }; } -macro_rules! token { +macro_rules! permission { ($($meta:meta)* $item:item) => { #[derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)] - #[derive(Clone, iroha_executor_derive::Token)] + #[derive(Clone, iroha_executor_derive::Permission)] #[derive(iroha_schema::IntoSchema)] $($meta)* $item }; } -declare_tokens! { - crate::default::tokens::peer::{CanUnregisterAnyPeer}, - - crate::default::tokens::domain::{CanUnregisterDomain}, - crate::default::tokens::domain::{CanSetKeyValueInDomain}, - crate::default::tokens::domain::{CanRemoveKeyValueInDomain}, - crate::default::tokens::domain::{CanRegisterAccountInDomain}, - crate::default::tokens::domain::{CanRegisterAssetDefinitionInDomain}, - - crate::default::tokens::account::{CanUnregisterAccount}, - crate::default::tokens::account::{CanMintUserPublicKeys}, - crate::default::tokens::account::{CanBurnUserPublicKeys}, - crate::default::tokens::account::{CanMintUserSignatureCheckConditions}, - crate::default::tokens::account::{CanSetKeyValueInAccount}, - crate::default::tokens::account::{CanRemoveKeyValueInAccount}, - - crate::default::tokens::asset_definition::{CanUnregisterAssetDefinition}, - crate::default::tokens::asset_definition::{CanSetKeyValueInAssetDefinition}, - crate::default::tokens::asset_definition::{CanRemoveKeyValueInAssetDefinition}, - - crate::default::tokens::asset::{CanRegisterAssetWithDefinition}, - crate::default::tokens::asset::{CanUnregisterAssetWithDefinition}, - crate::default::tokens::asset::{CanUnregisterUserAsset}, - crate::default::tokens::asset::{CanBurnAssetWithDefinition}, - crate::default::tokens::asset::{CanMintAssetWithDefinition}, - crate::default::tokens::asset::{CanMintUserAsset}, - crate::default::tokens::asset::{CanBurnUserAsset}, - crate::default::tokens::asset::{CanTransferAssetWithDefinition}, - crate::default::tokens::asset::{CanTransferUserAsset}, - crate::default::tokens::asset::{CanSetKeyValueInUserAsset}, - crate::default::tokens::asset::{CanRemoveKeyValueInUserAsset}, - - crate::default::tokens::parameter::{CanGrantPermissionToCreateParameters}, - crate::default::tokens::parameter::{CanRevokePermissionToCreateParameters}, - crate::default::tokens::parameter::{CanCreateParameters}, - crate::default::tokens::parameter::{CanGrantPermissionToSetParameters}, - crate::default::tokens::parameter::{CanRevokePermissionToSetParameters}, - crate::default::tokens::parameter::{CanSetParameters}, - - crate::default::tokens::role::{CanUnregisterAnyRole}, - - crate::default::tokens::trigger::{CanRegisterUserTrigger}, - crate::default::tokens::trigger::{CanExecuteUserTrigger}, - crate::default::tokens::trigger::{CanUnregisterUserTrigger}, - crate::default::tokens::trigger::{CanMintUserTrigger}, - crate::default::tokens::trigger::{CanBurnUserTrigger}, - crate::default::tokens::trigger::{CanSetKeyValueInTrigger}, - crate::default::tokens::trigger::{CanRemoveKeyValueInTrigger}, - - crate::default::tokens::executor::{CanUpgradeExecutor}, +declare_permissions! { + crate::default::permissions::peer::{CanUnregisterAnyPeer}, + + crate::default::permissions::domain::{CanUnregisterDomain}, + crate::default::permissions::domain::{CanSetKeyValueInDomain}, + crate::default::permissions::domain::{CanRemoveKeyValueInDomain}, + crate::default::permissions::domain::{CanRegisterAccountInDomain}, + crate::default::permissions::domain::{CanRegisterAssetDefinitionInDomain}, + + crate::default::permissions::account::{CanUnregisterAccount}, + crate::default::permissions::account::{CanMintUserPublicKeys}, + crate::default::permissions::account::{CanBurnUserPublicKeys}, + crate::default::permissions::account::{CanMintUserSignatureCheckConditions}, + crate::default::permissions::account::{CanSetKeyValueInAccount}, + crate::default::permissions::account::{CanRemoveKeyValueInAccount}, + + crate::default::permissions::asset_definition::{CanUnregisterAssetDefinition}, + crate::default::permissions::asset_definition::{CanSetKeyValueInAssetDefinition}, + crate::default::permissions::asset_definition::{CanRemoveKeyValueInAssetDefinition}, + + crate::default::permissions::asset::{CanRegisterAssetWithDefinition}, + crate::default::permissions::asset::{CanUnregisterAssetWithDefinition}, + crate::default::permissions::asset::{CanUnregisterUserAsset}, + crate::default::permissions::asset::{CanBurnAssetWithDefinition}, + crate::default::permissions::asset::{CanMintAssetWithDefinition}, + crate::default::permissions::asset::{CanMintUserAsset}, + crate::default::permissions::asset::{CanBurnUserAsset}, + crate::default::permissions::asset::{CanTransferAssetWithDefinition}, + crate::default::permissions::asset::{CanTransferUserAsset}, + crate::default::permissions::asset::{CanSetKeyValueInUserAsset}, + crate::default::permissions::asset::{CanRemoveKeyValueInUserAsset}, + + crate::default::permissions::parameter::{CanGrantPermissionToCreateParameters}, + crate::default::permissions::parameter::{CanRevokePermissionToCreateParameters}, + crate::default::permissions::parameter::{CanCreateParameters}, + crate::default::permissions::parameter::{CanGrantPermissionToSetParameters}, + crate::default::permissions::parameter::{CanRevokePermissionToSetParameters}, + crate::default::permissions::parameter::{CanSetParameters}, + + crate::default::permissions::role::{CanUnregisterAnyRole}, + + crate::default::permissions::trigger::{CanRegisterUserTrigger}, + crate::default::permissions::trigger::{CanExecuteUserTrigger}, + crate::default::permissions::trigger::{CanUnregisterUserTrigger}, + crate::default::permissions::trigger::{CanMintUserTrigger}, + crate::default::permissions::trigger::{CanBurnUserTrigger}, + crate::default::permissions::trigger::{CanSetKeyValueInTrigger}, + crate::default::permissions::trigger::{CanRemoveKeyValueInTrigger}, + + crate::default::permissions::executor::{CanUpgradeExecutor}, } pub mod peer { use super::*; - token! { + permission! { #[derive(Copy, ValidateGrantRevoke)] #[validate(permission::OnlyGenesis)] pub struct CanUnregisterAnyPeer; @@ -157,7 +157,7 @@ pub mod peer { pub mod domain { use super::*; - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::domain::Owner)] #[validate(permission::domain::Owner)] pub struct CanUnregisterDomain { @@ -165,7 +165,7 @@ pub mod domain { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::domain::Owner)] #[validate(permission::domain::Owner)] pub struct CanSetKeyValueInDomain { @@ -173,7 +173,7 @@ pub mod domain { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::domain::Owner)] #[validate(permission::domain::Owner)] pub struct CanRemoveKeyValueInDomain { @@ -181,7 +181,7 @@ pub mod domain { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::domain::Owner)] #[validate(permission::domain::Owner)] pub struct CanRegisterAccountInDomain { @@ -189,7 +189,7 @@ pub mod domain { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::domain::Owner)] #[validate(permission::domain::Owner)] pub struct CanRegisterAssetDefinitionInDomain { @@ -201,42 +201,42 @@ pub mod domain { pub mod account { use super::*; - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] pub struct CanUnregisterAccount { pub account_id: AccountId, } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] pub struct CanMintUserPublicKeys { pub account_id: AccountId, } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] pub struct CanBurnUserPublicKeys { pub account_id: AccountId, } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] pub struct CanMintUserSignatureCheckConditions { pub account_id: AccountId, } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] pub struct CanSetKeyValueInAccount { pub account_id: AccountId, } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] pub struct CanRemoveKeyValueInAccount { @@ -248,7 +248,7 @@ pub mod account { pub mod asset_definition { use super::*; - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] pub struct CanUnregisterAssetDefinition { @@ -256,7 +256,7 @@ pub mod asset_definition { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] pub struct CanSetKeyValueInAssetDefinition { @@ -264,7 +264,7 @@ pub mod asset_definition { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] pub struct CanRemoveKeyValueInAssetDefinition { @@ -276,7 +276,7 @@ pub mod asset_definition { pub mod asset { use super::*; - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] pub struct CanRegisterAssetWithDefinition { @@ -284,7 +284,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] pub struct CanUnregisterAssetWithDefinition { @@ -292,7 +292,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] #[validate(permission::asset::Owner)] pub struct CanUnregisterUserAsset { @@ -300,7 +300,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] pub struct CanBurnAssetWithDefinition { @@ -308,7 +308,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] #[validate(permission::asset::Owner)] pub struct CanBurnUserAsset { @@ -316,7 +316,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] pub struct CanMintAssetWithDefinition { @@ -324,7 +324,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] #[validate(permission::asset::Owner)] pub struct CanMintUserAsset { @@ -332,7 +332,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] pub struct CanTransferAssetWithDefinition { @@ -340,7 +340,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] #[validate(permission::asset::Owner)] pub struct CanTransferUserAsset { @@ -348,7 +348,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] #[validate(permission::asset::Owner)] pub struct CanSetKeyValueInUserAsset { @@ -356,7 +356,7 @@ pub mod asset { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] #[validate(permission::asset::Owner)] pub struct CanRemoveKeyValueInUserAsset { @@ -370,36 +370,36 @@ pub mod parameter { use super::*; - token! { + permission! { #[derive(Copy, ValidateGrantRevoke)] #[validate(permission::OnlyGenesis)] pub struct CanGrantPermissionToCreateParameters; } - token! { + permission! { #[derive(Copy, ValidateGrantRevoke)] #[validate(permission::OnlyGenesis)] pub struct CanRevokePermissionToCreateParameters; } - token! { + permission! { #[derive(Copy)] pub struct CanCreateParameters; } - token! { + permission! { #[derive(Copy, ValidateGrantRevoke)] #[validate(permission::OnlyGenesis)] pub struct CanGrantPermissionToSetParameters; } - token! { + permission! { #[derive(Copy, ValidateGrantRevoke)] #[validate(permission::OnlyGenesis)] pub struct CanRevokePermissionToSetParameters; } - token! { + permission! { #[derive(Copy)] pub struct CanSetParameters; } @@ -456,7 +456,7 @@ pub mod parameter { pub mod role { use super::*; - token! { + permission! { #[derive(Copy, ValidateGrantRevoke)] #[validate(permission::OnlyGenesis)] pub struct CanUnregisterAnyRole; @@ -478,7 +478,7 @@ pub mod trigger { )+}; } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] pub struct CanRegisterUserTrigger { @@ -486,7 +486,7 @@ pub mod trigger { } } - token! { + permission! { #[derive(ValidateGrantRevoke)] #[validate(permission::trigger::Owner)] pub struct CanExecuteUserTrigger { @@ -494,7 +494,7 @@ pub mod trigger { } } - token! { + permission! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] pub struct CanUnregisterUserTrigger { @@ -502,7 +502,7 @@ pub mod trigger { } } - token! { + permission! { #[derive(ValidateGrantRevoke)] #[validate(permission::trigger::Owner)] pub struct CanMintUserTrigger { @@ -510,7 +510,7 @@ pub mod trigger { } } - token! { + permission! { #[derive(ValidateGrantRevoke)] #[validate(permission::trigger::Owner)] pub struct CanBurnUserTrigger { @@ -518,7 +518,7 @@ pub mod trigger { } } - token! { + permission! { #[derive(ValidateGrantRevoke)] #[validate(permission::trigger::Owner)] pub struct CanSetKeyValueInTrigger { @@ -526,7 +526,7 @@ pub mod trigger { } } - token! { + permission! { #[derive(ValidateGrantRevoke)] #[validate(permission::trigger::Owner)] pub struct CanRemoveKeyValueInTrigger { @@ -546,7 +546,7 @@ pub mod trigger { pub mod executor { use super::*; - token! { + permission! { #[derive(Copy, ValidateGrantRevoke)] #[validate(permission::OnlyGenesis)] pub struct CanUpgradeExecutor; diff --git a/smart_contract/executor/src/lib.rs b/smart_contract/executor/src/lib.rs index 1e26b7b5c9e..08281ae3b3d 100644 --- a/smart_contract/executor/src/lib.rs +++ b/smart_contract/executor/src/lib.rs @@ -5,9 +5,9 @@ extern crate alloc; extern crate self as iroha_executor; -use alloc::vec::Vec; +use alloc::collections::BTreeSet; -use data_model::{executor::Result, permission::PermissionId, ValidationFail}; +use data_model::{executor::Result, ValidationFail}; #[cfg(not(test))] use data_model::{prelude::*, smart_contract::payloads}; pub use iroha_schema::MetaMap; @@ -78,7 +78,7 @@ pub fn get_migrate_payload() -> payloads::Migrate { unsafe { decode_with_length_prefix_from_raw(host::get_migrate_payload()) } } -/// Set new [`PermissionSchema`]. +/// Set new [`ExecutorDataModel`]. /// /// # Errors /// @@ -89,9 +89,9 @@ pub fn get_migrate_payload() -> payloads::Migrate { /// Host side will generate a trap if this function was not called from a /// executor's `migrate()` entrypoint. #[cfg(not(test))] -pub fn set_permission_schema(schema: &data_model::permission::PermissionSchema) { +pub fn set_data_model(data_model: &ExecutorDataModel) { // Safety: - ownership of the returned result is transferred into `_decode_from_raw` - unsafe { encode_and_execute(&schema, host::set_permission_schema) } + unsafe { encode_and_execute(&data_model, host::set_data_model) } } #[cfg(not(test))] @@ -126,8 +126,8 @@ mod host { /// This function does transfer ownership of the result to the caller pub(super) fn get_migrate_payload() -> *const u8; - /// Set new [`PermissionSchema`]. - pub(super) fn set_permission_schema(ptr: *const u8, len: usize); + /// Set new [`ExecutorDataModel`]. + pub(super) fn set_data_model(ptr: *const u8, len: usize); } } @@ -172,35 +172,77 @@ macro_rules! deny { }}; } -/// Collection of all permission tokens defined by the executor -#[derive(Debug, Clone, Default)] -pub struct PermissionSchema(Vec, MetaMap); +/// An error that might occur while converting a data model object (with id and payload) +/// into a native executor type. +/// +/// Such objects are [`data_model::prelude::Permission`] and [`data_model::prelude::Parameter`]. +#[derive(Debug)] +pub enum TryFromDataModelObjectError { + /// Unexpected object id + Id(data_model::prelude::Name), + /// Failed to deserialize object payload + Deserialize(serde_json::Error), +} + +/// A convenience to build [`ExecutorDataModel`] from within the executor +#[derive(Debug, Clone)] +pub struct DataModelBuilder { + schema: MetaMap, + permissions: BTreeSet, +} + +impl DataModelBuilder { + /// Constructor + // we don't need to confuse with `with_default_permissions` + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { + schema: <_>::default(), + permissions: <_>::default(), + } + } -impl PermissionSchema { - /// Remove permission token from this collection - pub fn remove(&mut self) { - let to_remove = ::name(); + /// Creates a data model with default permissions preset (defined in [`default::permissions`]) + #[must_use] + pub fn with_default_permissions() -> Self { + let mut builder = Self::new(); - if let Some(pos) = self.0.iter().position(|token_id| *token_id == to_remove) { - self.0.remove(pos); - ::remove_from_schema(&mut self.1); + macro_rules! add_to_schema { + ($token_ty:ty) => { + builder = builder.add_permission::<$token_ty>(); + }; } + + default::permissions::map_default_permissions!(add_to_schema); + + builder } - /// Insert new permission token into this collection - pub fn insert(&mut self) { - ::update_schema_map(&mut self.1); - self.0.push(::name()); + /// Define a permission in the data model + #[must_use] + pub fn add_permission(mut self) -> Self { + ::update_schema_map(&mut self.schema); + self.permissions.insert(::id()); + self } - /// Serializes schema into a JSON string representation - pub fn serialize(mut self) -> (Vec, alloc::string::String) { - self.0.sort(); + /// Remove a permission from the data model + #[must_use] + pub fn remove_permission(mut self) -> Self { + ::remove_from_schema(&mut self.schema); + self.permissions + .remove(&::id()); + self + } - ( - self.0, - serde_json::to_string(&self.1).expect("schema serialization must not fail"), - ) + /// Set the data model of the executor via [`set_data_model`] + #[cfg(not(test))] + pub fn build_and_set(self) { + set_data_model(&ExecutorDataModel::new( + self.permissions, + data_model::JsonString::serialize(&self.schema) + .expect("schema serialization must not fail"), + )) } } @@ -222,7 +264,8 @@ pub mod prelude { pub use alloc::vec::Vec; pub use iroha_executor_derive::{ - entrypoint, Constructor, Token, Validate, ValidateEntrypoints, ValidateGrantRevoke, Visit, + entrypoint, Constructor, Permission, Validate, ValidateEntrypoints, ValidateGrantRevoke, + Visit, }; pub use iroha_smart_contract::prelude::*; @@ -232,6 +275,8 @@ pub mod prelude { visit::Visit, ValidationFail, }, - deny, execute, PermissionSchema, Validate, + deny, execute, + permission::Permission as PermissionTrait, + DataModelBuilder, Validate, }; } diff --git a/smart_contract/executor/src/permission.rs b/smart_contract/executor/src/permission.rs index 67f2f6a689a..fbf53365e8a 100644 --- a/smart_contract/executor/src/permission.rs +++ b/smart_contract/executor/src/permission.rs @@ -3,27 +3,27 @@ use alloc::borrow::ToOwned as _; use iroha_schema::IntoSchema; -use iroha_smart_contract::{data_model::permission::Permission, QueryOutputCursor}; +use iroha_smart_contract::QueryOutputCursor; use iroha_smart_contract_utils::debug::DebugExpectExt as _; use serde::{de::DeserializeOwned, Serialize}; -use crate::{data_model::prelude::*, prelude::*}; +use crate::prelude::{Permission as PermissionObject, *}; -/// [`Token`] trait is used to check if the token is owned by the account. -pub trait Token: +/// Is used to check if the permission token is owned by the account. +pub trait Permission: Serialize + DeserializeOwned + IntoSchema + PartialEq + ValidateGrantRevoke -where - for<'a> Self: TryFrom<&'a Permission, Error = PermissionConversionError>, { - /// Return name of this permission token - fn name() -> Name { - ::type_name() - .parse() - .dbg_expect("Failed to parse permission token as `Name`") - } - - /// Check if token is owned by the account + /// Check if the account owns this token fn is_owned_by(&self, account_id: &AccountId) -> bool; + + /// Permission id, according to [`IntoSchema`]. + fn id() -> PermissionId { + PermissionId::new( + ::type_name() + .parse() + .dbg_expect("Failed to parse permission id as `Name`"), + ) + } } /// Trait that should be implemented for all permission tokens. @@ -43,15 +43,6 @@ pub trait PassCondition { fn validate(&self, authority: &AccountId, block_height: u64) -> Result; } -/// Error type for `TryFrom` implementations. -#[derive(Debug)] -pub enum PermissionConversionError { - /// Unexpected token id. - Id(PermissionId), - /// Failed to deserialize JSON - Deserialize(serde_json::Error), -} - pub mod derive_conversions { //! Module with derive macros to generate conversion from custom strongly-typed token //! to some pass condition to successfully derive [`ValidateGrantRevoke`](iroha_executor_derive::ValidateGrantRevoke) @@ -307,7 +298,7 @@ impl PassCondition for AlwaysPass { } } -impl From<&T> for AlwaysPass { +impl From<&T> for AlwaysPass { fn from(_: &T) -> Self { Self } @@ -331,14 +322,14 @@ impl PassCondition for OnlyGenesis { } } -impl From<&T> for OnlyGenesis { +impl From<&T> for OnlyGenesis { fn from(_: &T) -> Self { Self } } /// Iterator over all accounts and theirs permission tokens -pub(crate) fn accounts_permissions() -> impl Iterator { +pub(crate) fn accounts_permissions() -> impl Iterator { FindAllAccounts .execute() .dbg_expect("failed to query all accounts") @@ -355,7 +346,7 @@ pub(crate) fn accounts_permissions() -> impl Iterator impl Iterator { +pub(crate) fn roles_permissions() -> impl Iterator { FindAllRoles .execute() .dbg_expect("failed to query all accounts") @@ -369,3 +360,32 @@ pub(crate) fn roles_permissions() -> impl Iterator .map(move |token| (role.id().clone(), token)) }) } + +#[cfg(test)] +mod tests { + use alloc::{format, string::String}; + + use serde::Deserialize; + use serde_json::json; + + use super::*; + + #[test] + fn convert_token() { + #[derive( + Serialize, Deserialize, IntoSchema, PartialEq, ValidateGrantRevoke, Permission, + )] + #[validate(AlwaysPass)] + struct SampleToken { + can_do_whatever: bool, + } + + let object = PermissionObject::new( + "SampleToken".parse().unwrap(), + json!({ "can_do_whatever": false }), + ); + let parsed = SampleToken::try_from(&object).expect("valid"); + + assert!(!parsed.can_do_whatever); + } +} diff --git a/smart_contract/tests/ui_fail/cant_filter_singular_query.rs b/smart_contract/tests/ui_fail/cant_filter_singular_query.rs index 83d0654e181..40016927f24 100644 --- a/smart_contract/tests/ui_fail/cant_filter_singular_query.rs +++ b/smart_contract/tests/ui_fail/cant_filter_singular_query.rs @@ -4,7 +4,7 @@ use iroha_smart_contract::{ }; fn main() { - FindPermissionSchema + FindDomainById::new("domain".parse().unwrap()) .filter(QueryOutputPredicate::Identifiable( StringPredicate::starts_with("xor_"), )) diff --git a/smart_contract/tests/ui_fail/cant_filter_singular_query.stderr b/smart_contract/tests/ui_fail/cant_filter_singular_query.stderr index e207ea2a095..8bc8b9f6284 100644 --- a/smart_contract/tests/ui_fail/cant_filter_singular_query.stderr +++ b/smart_contract/tests/ui_fail/cant_filter_singular_query.stderr @@ -1,25 +1,25 @@ -error[E0599]: the method `filter` exists for struct `FindPermissionSchema`, but its trait bounds were not satisfied +error[E0599]: the method `filter` exists for struct `FindDomainById`, but its trait bounds were not satisfied --> tests/ui_fail/cant_filter_singular_query.rs:8:10 | -7 | / FindPermissionSchema +7 | / FindDomainById::new("domain".parse().unwrap()) 8 | | .filter(QueryOutputPredicate::Identifiable( - | | -^^^^^^ method cannot be called on `FindPermissionSchema` due to unsatisfied trait bounds + | | -^^^^^^ method cannot be called on `FindDomainById` due to unsatisfied trait bounds | |_________| | | ::: $WORKSPACE/data_model/src/query/mod.rs | | / queries! { - | | /// Finds all registered permission tokens + | | /// [`FindAllDomains`] Iroha Query finds all [`Domain`]s presented in Iroha [`Peer`]. | | #[derive(Copy, Display)] - | | #[ffi_type] + | | #[display(fmt = "Find all domains")] ... | | | } | | } | |_____- doesn't satisfy `_: ExecuteIterableQueryOnHost`, `_: IterableQuery` or `_: Iterator` | = note: the following trait bounds were not satisfied: - `iroha_smart_contract::prelude::FindPermissionSchema: IterableQuery` - which is required by `iroha_smart_contract::prelude::FindPermissionSchema: iroha_smart_contract::ExecuteIterableQueryOnHost` - `iroha_smart_contract::prelude::FindPermissionSchema: Iterator` - which is required by `&mut iroha_smart_contract::prelude::FindPermissionSchema: Iterator` + `iroha_smart_contract::prelude::FindDomainById: IterableQuery` + which is required by `iroha_smart_contract::prelude::FindDomainById: iroha_smart_contract::ExecuteIterableQueryOnHost` + `iroha_smart_contract::prelude::FindDomainById: Iterator` + which is required by `&mut iroha_smart_contract::prelude::FindDomainById: Iterator` diff --git a/tools/kagami/src/genesis.rs b/tools/kagami/src/genesis.rs index 4f5b6203c66..3d9ff06b134 100644 --- a/tools/kagami/src/genesis.rs +++ b/tools/kagami/src/genesis.rs @@ -116,7 +116,7 @@ pub fn generate_default( AssetId::new("cabbage#garden_of_live_flowers".parse()?, ALICE_ID.clone()), ); let grant_permission_to_set_parameters = Grant::permission( - Permission::new("CanSetParameters".parse()?, &json!(null)), + Permission::new("CanSetParameters".parse()?, json!(null)), ALICE_ID.clone(), ); let transfer_rose_ownership = Transfer::asset_definition( @@ -133,11 +133,11 @@ pub fn generate_default( Role::new("ALICE_METADATA_ACCESS".parse()?) .add_permission(Permission::new( "CanSetKeyValueInAccount".parse()?, - &json!({ "account_id": ALICE_ID.clone() }), + json!({ "account_id": ALICE_ID.clone() }), )) .add_permission(Permission::new( "CanRemoveKeyValueInAccount".parse()?, - &json!({ "account_id": ALICE_ID.clone() }), + json!({ "account_id": ALICE_ID.clone() }), )), ) .into(); diff --git a/tools/parity_scale_cli/src/main.rs b/tools/parity_scale_cli/src/main.rs index 9d7f8457a4d..b47530cb08c 100644 --- a/tools/parity_scale_cli/src/main.rs +++ b/tools/parity_scale_cli/src/main.rs @@ -15,51 +15,7 @@ use std::{ use clap::Parser; use colored::*; use eyre::{eyre, Result}; -use iroha_crypto::*; -use iroha_data_model::{ - account::NewAccount, - asset::NewAssetDefinition, - block::{ - error::BlockRejectionReason, - stream::{BlockMessage, BlockSubscriptionRequest}, - BlockHeader, BlockPayload, SignedBlock, SignedBlockV1, - }, - domain::NewDomain, - events::pipeline::{BlockEventFilter, TransactionEventFilter}, - executor::Executor, - ipfs::IpfsPath, - isi::{ - error::{ - InstructionEvaluationError, InstructionExecutionError, InvalidParameterError, - MathError, MintabilityError, Mismatch, RepetitionError, TypeError, - }, - InstructionType, - }, - metadata::{MetadataError, MetadataValueBox, SizeError}, - parameter::ParameterValueBox, - permission::JsonString, - prelude::*, - query::{ - error::{FindError, QueryExecutionFail}, - predicate::{ - numerical::{SemiInterval, SemiRange}, - string::StringPredicate, - value::{AtIndex, Container, QueryOutputPredicate}, - GenericPredicateBox, NonTrivial, PredicateBox, - }, - ForwardCursor, Pagination, QueryOutputBox, Sorting, - }, - transaction::{ - error::TransactionLimitError, SignedTransactionV1, TransactionLimits, TransactionPayload, - }, - BatchedResponse, BatchedResponseV1, Level, -}; -use iroha_primitives::{ - addr::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrHost, SocketAddrV4, SocketAddrV6}, - const_vec::ConstVec, - conststr::ConstString, - unique_vec::UniqueVec, -}; +use iroha_schema_gen::complete_data_model::*; use parity_scale_codec::{DecodeAll, Encode}; use serde::{de::DeserializeOwned, Serialize};