diff --git a/.github/workflows/iroha2-dev-pr-static.yml b/.github/workflows/iroha2-dev-pr-static.yml index 06effe3e687..bc44c92101e 100644 --- a/.github/workflows/iroha2-dev-pr-static.yml +++ b/.github/workflows/iroha2-dev-pr-static.yml @@ -47,10 +47,10 @@ jobs: run: cargo fmt --all -- --check - name: Lints without features if: always() - run: cargo clippy -Zlints --workspace --benches --tests --examples --no-default-features --quiet + run: cargo clippy --workspace --benches --tests --examples --no-default-features --quiet - name: Lints with all features enabled if: always() - run: cargo clippy -Zlints --workspace --benches --tests --examples --all-features --quiet + run: cargo clippy --workspace --benches --tests --examples --all-features --quiet - name: Documentation if: always() run: cargo doc --no-deps --quiet diff --git a/Cargo.lock b/Cargo.lock index 2add67a0266..9e686724df6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3202,7 +3202,7 @@ dependencies = [ "iroha_primitives", "iroha_schema_gen", "iroha_telemetry", - "iroha_torii_macro", + "iroha_torii_derive", "iroha_version", "parity-scale-codec", "serde", @@ -3213,7 +3213,7 @@ dependencies = [ ] [[package]] -name = "iroha_torii_macro" +name = "iroha_torii_derive" version = "2.0.0-pre-rc.20" dependencies = [ "manyhow", diff --git a/Cargo.toml b/Cargo.toml index b128a0bca55..e47154c4890 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ categories = ["cryptography::cryptocurrencies"] iroha = { path = "cli" } iroha_dsl = { version = "=2.0.0-pre-rc.20", path = "dsl" } iroha_torii = { version = "=2.0.0-pre-rc.20", path = "torii" } -iroha_torii_macro = { version = "=2.0.0-pre-rc.20", path = "torii/macro" } +iroha_torii_derive = { version = "=2.0.0-pre-rc.20", path = "torii/derive" } iroha_macro_utils = { version = "=2.0.0-pre-rc.20", path = "macro/utils" } iroha_telemetry = { version = "=2.0.0-pre-rc.20", path = "telemetry" } iroha_telemetry_derive = { version = "=2.0.0-pre-rc.20", path = "telemetry/derive" } @@ -241,7 +241,7 @@ members = [ "tools/wasm_builder_cli", "tools/wasm_test_runner", "torii", - "torii/macro", + "torii/derive", "version", "version/derive", "wasm_codec", diff --git a/client/benches/torii.rs b/client/benches/torii.rs index f73433108a0..f8f51917f1d 100644 --- a/client/benches/torii.rs +++ b/client/benches/torii.rs @@ -70,12 +70,12 @@ fn query_requests(criterion: &mut Criterion) { let mut group = criterion.benchmark_group("query-requests"); let domain_id: DomainId = "domain".parse().expect("Valid"); let create_domain = Register::domain(Domain::new(domain_id.clone())); - let account_id = AccountId::new("account".parse().expect("Valid"), domain_id.clone()); + let account_id = AccountId::new(domain_id.clone(), "account".parse().expect("Valid")); let (public_key, _) = KeyPair::generate() .expect("Failed to generate KeyPair") .into(); let create_account = Register::account(Account::new(account_id.clone(), [public_key])); - let asset_definition_id = AssetDefinitionId::new("xor".parse().expect("Valid"), domain_id); + let asset_definition_id = AssetDefinitionId::new(domain_id, "xor".parse().expect("Valid")); let create_asset = Register::asset_definition(AssetDefinition::quantity(asset_definition_id.clone())); let quantity: u32 = 200; @@ -168,12 +168,12 @@ fn instruction_submits(criterion: &mut Criterion) { let mut group = criterion.benchmark_group("instruction-requests"); let domain_id: DomainId = "domain".parse().expect("Valid"); let create_domain: InstructionBox = Register::domain(Domain::new(domain_id.clone())).into(); - let account_id = AccountId::new("account".parse().expect("Valid"), domain_id.clone()); + let account_id = AccountId::new(domain_id.clone(), "account".parse().expect("Valid")); let (public_key, _) = KeyPair::generate() .expect("Failed to generate Key-pair.") .into(); let create_account = Register::account(Account::new(account_id.clone(), [public_key])).into(); - let asset_definition_id = AssetDefinitionId::new("xor".parse().expect("Valid"), domain_id); + let asset_definition_id = AssetDefinitionId::new(domain_id, "xor".parse().expect("Valid")); let mut client_config = iroha_client::samples::get_client_config(get_chain_id(), &get_key_pair()); client_config.torii_api_url = format!("http://{}", peer.api_address).parse().unwrap(); diff --git a/client/examples/million_accounts_genesis.rs b/client/examples/million_accounts_genesis.rs index ec000d4a0f5..737e9236246 100644 --- a/client/examples/million_accounts_genesis.rs +++ b/client/examples/million_accounts_genesis.rs @@ -77,8 +77,8 @@ fn create_million_accounts_directly() { for i in 0_u32..1_000_000_u32 { let domain_id: DomainId = format!("wonderland-{i}").parse().expect("Valid"); let normal_account_id = AccountId::new( - format!("bob-{i}").parse().expect("Valid"), domain_id.clone(), + format!("bob-{i}").parse().expect("Valid"), ); let create_domain: InstructionBox = Register::domain(Domain::new(domain_id)).into(); let create_account = Register::account(Account::new(normal_account_id.clone(), [])).into(); diff --git a/client/tests/integration/asset.rs b/client/tests/integration/asset.rs index beac868a71a..e1f7723a806 100644 --- a/client/tests/integration/asset.rs +++ b/client/tests/integration/asset.rs @@ -269,7 +269,7 @@ fn find_rate_and_make_exchange_isi_should_succeed() { }; let grant_alice_asset_transfer_permission = |asset_id: AssetId, owner_keypair: KeyPair| { - let allow_alice_to_transfer_asset = Grant::permission_token( + let allow_alice_to_transfer_asset = Grant::permission( PermissionToken::new( "CanTransferUserAsset".parse().unwrap(), &json!({ "asset_id": asset_id }), @@ -426,16 +426,16 @@ fn transfer_asset_definition() { fn account_id_new(account_name: &str, account_domain: &str) -> AccountId { AccountId::new( - account_name.parse().expect("Valid"), account_domain.parse().expect("Valid"), + account_name.parse().expect("Valid"), ) } fn asset_id_new(definition_name: &str, definition_domain: &str, account_id: AccountId) -> AssetId { AssetId::new( AssetDefinitionId::new( - definition_name.parse().expect("Valid"), definition_domain.parse().expect("Valid"), + definition_name.parse().expect("Valid"), ), account_id, ) @@ -451,8 +451,8 @@ mod register { pub fn account(account_name: &str, domain_name: &str) -> Register { Register::account(Account::new( AccountId::new( - account_name.parse().expect("Valid"), domain_name.parse().expect("Valid"), + account_name.parse().expect("Valid"), ), [], )) @@ -460,8 +460,8 @@ mod register { pub fn asset_definition(asset_name: &str, domain_name: &str) -> Register { Register::asset_definition(AssetDefinition::quantity(AssetDefinitionId::new( - asset_name.parse().expect("Valid"), domain_name.parse().expect("Valid"), + asset_name.parse().expect("Valid"), ))) } } diff --git a/client/tests/integration/domain_owner.rs b/client/tests/integration/domain_owner.rs index b159fa34cbd..2ffc467ac42 100644 --- a/client/tests/integration/domain_owner.rs +++ b/client/tests/integration/domain_owner.rs @@ -8,15 +8,59 @@ use test_network::*; #[test] fn domain_owner_domain_permissions() -> Result<()> { + let chain_id = ChainId::new("0"); + let (_rt, _peer, test_client) = ::new().with_port(11_080).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); let kingdom_id: DomainId = "kingdom".parse()?; + let bob_id: AccountId = "bob@kingdom".parse()?; + let coin_id: AssetDefinitionId = "coin#kingdom".parse()?; + let coin = AssetDefinition::quantity(coin_id.clone()); // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id.clone()); test_client.submit_blocking(Register::domain(kingdom))?; + let bob_keypair = KeyPair::generate()?; + let bob = Account::new(bob_id.clone(), [bob_keypair.public_key().clone()]); + test_client.submit_blocking(Register::account(bob))?; + + // Asset definitions can't be registered by "bob@kingdom" by default + let transaction = TransactionBuilder::new(chain_id.clone(), bob_id.clone()) + .with_instructions([Register::asset_definition(coin.clone())]) + .sign(bob_keypair.clone())?; + let err = test_client + .submit_transaction_blocking(&transaction) + .expect_err("Tx should fail due to permissions"); + + let rejection_reason = err + .downcast_ref::() + .unwrap_or_else(|| panic!("Error {err} is not PipelineRejectionReason")); + + assert!(matches!( + rejection_reason, + &PipelineRejectionReason::Transaction(TransactionRejectionReason::Validation( + ValidationFail::NotPermitted(_) + )) + )); + + // "alice@wonderland" owns the domain and can register AssetDefinitions by default as domain owner + test_client.submit_blocking(Register::asset_definition(coin.clone()))?; + test_client.submit_blocking(Unregister::asset_definition(coin_id))?; + + // Granting a respective token also allows "bob@kingdom" to do so + let token = PermissionToken::new( + "CanRegisterAssetDefinitionInDomain".parse().unwrap(), + &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()) + .with_instructions([Register::asset_definition(coin)]) + .sign(bob_keypair)?; + test_client.submit_transaction_blocking(&transaction)?; + test_client.submit_blocking(Revoke::permission(token, bob_id.clone()))?; + // check that "alice@wonderland" as owner of domain can edit metadata in her domain let key: Name = "key".parse()?; let value: Name = "value".parse()?; @@ -24,13 +68,12 @@ fn domain_owner_domain_permissions() -> Result<()> { test_client.submit_blocking(RemoveKeyValue::domain(kingdom_id.clone(), key))?; // check that "alice@wonderland" as owner of domain can grant and revoke domain related permission tokens - let bob_id: AccountId = "bob@wonderland".parse()?; let token = PermissionToken::new( "CanUnregisterDomain".parse().unwrap(), &json!({ "domain_id": kingdom_id }), ); - test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; + test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission(token, bob_id))?; // check that "alice@wonderland" as owner of domain can unregister her domain test_client.submit_blocking(Unregister::domain(kingdom_id))?; @@ -90,8 +133,8 @@ fn domain_owner_account_permissions() -> Result<()> { "CanUnregisterAccount".parse().unwrap(), &json!({ "account_id": mad_hatter_id }), ); - test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; + test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission(token, bob_id))?; // check that "alice@wonderland" as owner of domain can unregister accounts in her domain test_client.submit_blocking(Unregister::account(mad_hatter_id))?; @@ -111,7 +154,7 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { let coin_id: AssetDefinitionId = "coin#kingdom".parse()?; // "alice@wonderland" is owner of "kingdom" domain - let kingdom = Domain::new(kingdom_id); + let kingdom = Domain::new(kingdom_id.clone()); test_client.submit_blocking(Register::domain(kingdom))?; let bob_keypair = KeyPair::generate()?; @@ -121,6 +164,13 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { let rabbit = Account::new(rabbit_id.clone(), []); test_client.submit_blocking(Register::account(rabbit))?; + // Grant permission to register asset definitions to "bob@kingdom" + let token = PermissionToken::new( + "CanRegisterAssetDefinitionInDomain".parse().unwrap(), + &json!({ "domain_id": kingdom_id }), + ); + test_client.submit_blocking(Grant::permission(token, bob_id.clone()))?; + // register asset definitions by "bob@kingdom" so he is owner of it let coin = AssetDefinition::quantity(coin_id.clone()); let transaction = TransactionBuilder::new(chain_id, bob_id.clone()) @@ -151,8 +201,8 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { "CanUnregisterAssetDefinition".parse().unwrap(), &json!({ "asset_definition_id": coin_id }), ); - test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; + test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission(token, bob_id))?; // check that "alice@wonderland" as owner of domain can unregister asset definitions in her domain test_client.submit_blocking(Unregister::asset_definition(coin_id))?; @@ -174,13 +224,20 @@ fn domain_owner_asset_permissions() -> Result<()> { let store_id: AssetDefinitionId = "store#kingdom".parse()?; // "alice@wonderland" is owner of "kingdom" domain - let kingdom = Domain::new(kingdom_id); + let kingdom = Domain::new(kingdom_id.clone()); test_client.submit_blocking(Register::domain(kingdom))?; let bob_keypair = KeyPair::generate()?; let bob = Account::new(bob_id.clone(), [bob_keypair.public_key().clone()]); test_client.submit_blocking(Register::account(bob))?; + // Grant permission to register asset definitions to "bob@kingdom" + let token = PermissionToken::new( + "CanRegisterAssetDefinitionInDomain".parse().unwrap(), + &json!({ "domain_id": kingdom_id }), + ); + test_client.submit_blocking(Grant::permission(token, bob_id.clone()))?; + // register asset definitions by "bob@kingdom" so he is owner of it let coin = AssetDefinition::quantity(coin_id.clone()); let store = AssetDefinition::store(store_id.clone()); @@ -216,8 +273,8 @@ fn domain_owner_asset_permissions() -> Result<()> { "CanUnregisterUserAsset".parse().unwrap(), &json!({ "asset_id": bob_store_id }), ); - test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; + test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission(token, bob_id))?; Ok(()) } @@ -273,8 +330,8 @@ fn domain_owner_trigger_permissions() -> Result<()> { "CanUnregisterUserTrigger".parse().unwrap(), &json!({ "trigger_id": trigger_id }), ); - test_client.submit_blocking(Grant::permission_token(token.clone(), bob_id.clone()))?; - test_client.submit_blocking(Revoke::permission_token(token, bob_id))?; + test_client.submit_blocking(Grant::permission(token.clone(), bob_id.clone()))?; + test_client.submit_blocking(Revoke::permission(token, bob_id))?; // check that "alice@wonderland" as owner of domain can unregister triggers in her domain test_client.submit_blocking(Unregister::trigger(trigger_id))?; diff --git a/client/tests/integration/permissions.rs b/client/tests/integration/permissions.rs index beb8ffd6de0..ec2ea6811e6 100644 --- a/client/tests/integration/permissions.rs +++ b/client/tests/integration/permissions.rs @@ -17,7 +17,7 @@ fn genesis_transactions_are_validated() { // Setting up genesis - let genesis = GenesisNetwork::test_with_instructions([Grant::permission_token( + let genesis = GenesisNetwork::test_with_instructions([Grant::permission( PermissionToken::new("InvalidToken".parse().unwrap(), &json!(null)), AccountId::from_str("alice@wonderland").unwrap(), ) @@ -201,30 +201,38 @@ fn permissions_differ_not_only_by_names() { let (_rt, _not_drop, client) = ::new().with_port(10_745).start_with_runtime(); let alice_id: AccountId = "alice@wonderland".parse().expect("Valid"); - let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); + let mouse_id: AccountId = "mouse@outfit".parse().expect("Valid"); let mouse_keypair = KeyPair::generate().expect("Failed to generate KeyPair."); - // Registering `Store` asset definitions - let hat_definition_id: AssetDefinitionId = "hat#wonderland".parse().expect("Valid"); - let new_hat_definition = AssetDefinition::store(hat_definition_id.clone()); - let shoes_definition_id: AssetDefinitionId = "shoes#wonderland".parse().expect("Valid"); - let new_shoes_definition = AssetDefinition::store(shoes_definition_id.clone()); + // Registering mouse + let outfit_domain: DomainId = "outfit".parse().unwrap(); + let create_outfit_domain = Register::domain(Domain::new(outfit_domain.clone())); + let new_mouse_account = Account::new(mouse_id.clone(), [mouse_keypair.public_key().clone()]); client .submit_all_blocking([ - Register::asset_definition(new_hat_definition), - Register::asset_definition(new_shoes_definition), + InstructionBox::from(create_outfit_domain), + Register::account(new_mouse_account).into(), ]) - .expect("Failed to register new asset definitions"); + .expect("Failed to register mouse"); - // Registering mouse - let new_mouse_account = Account::new(mouse_id.clone(), [mouse_keypair.public_key().clone()]); + // Registering `Store` asset definitions + let hat_definition_id: AssetDefinitionId = "hat#outfit".parse().expect("Valid"); + let new_hat_definition = AssetDefinition::store(hat_definition_id.clone()); + let transfer_shoes_domain = Transfer::domain(alice_id.clone(), outfit_domain, mouse_id.clone()); + let shoes_definition_id: AssetDefinitionId = "shoes#outfit".parse().expect("Valid"); + let new_shoes_definition = AssetDefinition::store(shoes_definition_id.clone()); + let instructions: [InstructionBox; 3] = [ + Register::asset_definition(new_hat_definition).into(), + Register::asset_definition(new_shoes_definition).into(), + transfer_shoes_domain.into(), + ]; client - .submit_blocking(Register::account(new_mouse_account)) - .expect("Failed to register mouse"); + .submit_all_blocking(instructions) + .expect("Failed to register new asset definitions"); // Granting permission to Alice to modify metadata in Mouse's hats let mouse_hat_id = AssetId::new(hat_definition_id, mouse_id.clone()); - let allow_alice_to_set_key_value_in_hats = Grant::permission_token( + let allow_alice_to_set_key_value_in_hats = Grant::permission( PermissionToken::new( "CanSetKeyValueInUserAsset".parse().unwrap(), &json!({ "asset_id": mouse_hat_id }), @@ -261,7 +269,7 @@ fn permissions_differ_not_only_by_names() { .expect_err("Expected Alice to fail to modify Mouse's shoes"); // Granting permission to Alice to modify metadata in Mouse's shoes - let allow_alice_to_set_key_value_in_shoes = Grant::permission_token( + let allow_alice_to_set_key_value_in_shoes = Grant::permission( PermissionToken::new( "CanSetKeyValueInUserAsset".parse().unwrap(), &json!({ "asset_id": mouse_shoes_id }), @@ -312,7 +320,7 @@ fn stored_vs_granted_token_payload() -> Result<()> { // Allow alice to mint mouse asset and mint initial value let mouse_asset = AssetId::new(asset_definition_id, mouse_id.clone()); - let allow_alice_to_set_key_value_in_mouse_asset = Grant::permission_token( + let allow_alice_to_set_key_value_in_mouse_asset = Grant::permission( PermissionToken::from_str_unchecked( "CanSetKeyValueInUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form @@ -347,7 +355,7 @@ fn permission_tokens_are_unified() { // Given let alice_id = AccountId::from_str("alice@wonderland").expect("Valid"); - let allow_alice_to_transfer_rose_1 = Grant::permission_token( + let allow_alice_to_transfer_rose_1 = Grant::permission( PermissionToken::from_str_unchecked( "CanTransferUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form @@ -356,7 +364,7 @@ fn permission_tokens_are_unified() { alice_id.clone(), ); - let allow_alice_to_transfer_rose_2 = Grant::permission_token( + let allow_alice_to_transfer_rose_2 = Grant::permission( PermissionToken::from_str_unchecked( "CanTransferUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form diff --git a/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs b/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs index bce2802adcb..d9df633498d 100644 --- a/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs +++ b/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs @@ -21,9 +21,18 @@ fn main(_owner: AccountId, _event: Event) { let limits = MetadataLimits::new(256, 256); + let bad_domain_ids: [DomainId; 2] = [ + "genesis".parse().dbg_unwrap(), + "garden_of_live_flowers".parse().dbg_unwrap(), + ]; + for account in accounts_cursor { let account = account.dbg_unwrap(); + if bad_domain_ids.contains(account.id().domain_id()) { + continue; + } + let mut metadata = Metadata::new(); let name = format!( "nft_for_{}_in_{}", diff --git a/client/tests/integration/smartcontracts/executor_with_custom_token/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_custom_token/src/lib.rs index bd9322a7f87..65c48e2db59 100644 --- a/client/tests/integration/smartcontracts/executor_with_custom_token/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_custom_token/src/lib.rs @@ -118,7 +118,7 @@ impl Executor { accounts .iter() .try_for_each(|(account, domain_id)| { - Revoke::permission_token( + Revoke::permission( PermissionToken::new( can_unregister_domain_definition_id.clone(), &json!({ "domain_id": domain_id }), @@ -137,7 +137,7 @@ impl Executor { ) })?; - Grant::permission_token( + Grant::permission( PermissionToken::new( can_control_domain_lives_definition_id.clone(), &json!(null), diff --git a/client_cli/pytests/common/consts.py b/client_cli/pytests/common/consts.py index c7f4201a4c4..6987c4b9d41 100644 --- a/client_cli/pytests/common/consts.py +++ b/client_cli/pytests/common/consts.py @@ -17,7 +17,7 @@ class Stderr(Enum): CANNOT_BE_EMPTY = 'cannot be empty\n\nFor more information, try \'--help\'.\n' REPETITION = 'Repetition' TOO_LONG = 'Name length violation' - FAILED_TO_FIND_DOMAIN = 'Entity missing' + FAILED_TO_FIND_DOMAIN = 'Failed to find domain' INVALID_CHARACTER = 'Invalid character' INVALID_VALUE_TYPE = 'Matching variant not found' RESERVED_CHARACTER = 'The `@` character is reserved for `account@domain` constructs,' \ diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index 05b9121302c..2084d35d562 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -724,7 +724,7 @@ mod account { permission, metadata, } = self; - let grant = iroha_client::data_model::isi::Grant::permission_token(permission.0, id); + let grant = iroha_client::data_model::isi::Grant::permission(permission.0, id); submit([grant], metadata.load()?, context) .wrap_err("Failed to grant the permission to the account") } diff --git a/configs/peer/executor.wasm b/configs/peer/executor.wasm index 194481b0e0d..a7abc19985d 100644 Binary files a/configs/peer/executor.wasm and b/configs/peer/executor.wasm differ diff --git a/configs/peer/genesis.json b/configs/peer/genesis.json index a915d22f4f8..22614a1ceb3 100644 --- a/configs/peer/genesis.json +++ b/configs/peer/genesis.json @@ -106,6 +106,15 @@ } } }, + { + "Transfer": { + "Domain": { + "source_id": "genesis@genesis", + "object": "wonderland", + "destination_id": "alice@wonderland" + } + } + }, { "Grant": { "PermissionToken": { diff --git a/core/benches/blocks/common.rs b/core/benches/blocks/common.rs index f8969b2f16b..2905c796435 100644 --- a/core/benches/blocks/common.rs +++ b/core/benches/blocks/common.rs @@ -66,7 +66,7 @@ pub fn populate_wsv( let domain_id = construct_domain_id(i); let domain = Domain::new(domain_id.clone()); instructions.push(Register::domain(domain).into()); - let can_unregister_domain = Grant::permission_token( + let can_unregister_domain = Grant::permission( PermissionToken::new( "CanUnregisterDomain".parse().unwrap(), &json!({ "domain_id": domain_id.clone() }), @@ -78,7 +78,7 @@ pub fn populate_wsv( let account_id = construct_account_id(j, domain_id.clone()); let account = Account::new(account_id.clone(), []); instructions.push(Register::account(account).into()); - let can_unregister_account = Grant::permission_token( + let can_unregister_account = Grant::permission( PermissionToken::new( "CanUnregisterAccount".parse().unwrap(), &json!({ "account_id": account_id.clone() }), @@ -94,7 +94,7 @@ pub fn populate_wsv( iroha_data_model::asset::AssetValueType::Quantity, ); instructions.push(Register::asset_definition(asset_definition).into()); - let can_unregister_asset_definition = Grant::permission_token( + let can_unregister_asset_definition = Grant::permission( PermissionToken::new( "CanUnregisterAssetDefinition".parse().unwrap(), &json!({ "asset_definition_id": asset_definition_id }), @@ -203,14 +203,14 @@ fn construct_domain_id(i: usize) -> DomainId { fn construct_account_id(i: usize, domain_id: DomainId) -> AccountId { AccountId::new( - Name::from_str(&format!("non_inlinable_account_name_{i}")).unwrap(), domain_id, + Name::from_str(&format!("non_inlinable_account_name_{i}")).unwrap(), ) } fn construct_asset_definition_id(i: usize, domain_id: DomainId) -> AssetDefinitionId { AssetDefinitionId::new( - Name::from_str(&format!("non_inlinable_asset_definition_name_{i}")).unwrap(), domain_id, + Name::from_str(&format!("non_inlinable_asset_definition_name_{i}")).unwrap(), ) } diff --git a/core/benches/validation.rs b/core/benches/validation.rs index a7c41a024c6..93d1b8b5356 100644 --- a/core/benches/validation.rs +++ b/core/benches/validation.rs @@ -33,8 +33,8 @@ fn build_test_transaction(keys: KeyPair, chain_id: ChainId) -> SignedTransaction .into(); let create_account = Register::account(Account::new( AccountId::new( - account_name.parse().expect("Valid"), domain_name.parse().expect("Valid"), + account_name.parse().expect("Valid"), ), [public_key], )) @@ -50,8 +50,8 @@ fn build_test_transaction(keys: KeyPair, chain_id: ChainId) -> SignedTransaction TransactionBuilder::new( chain_id, AccountId::new( - START_ACCOUNT.parse().expect("Valid"), START_DOMAIN.parse().expect("Valid"), + START_ACCOUNT.parse().expect("Valid"), ), ) .with_instructions(instructions) @@ -68,8 +68,8 @@ fn build_test_and_transient_wsv(keys: KeyPair) -> WorldStateView { { let domain_id = DomainId::from_str(START_DOMAIN).expect("Valid"); let account_id = AccountId::new( - Name::from_str(START_ACCOUNT).expect("Valid"), domain_id.clone(), + Name::from_str(START_ACCOUNT).expect("Valid"), ); let mut domain = Domain::new(domain_id).build(&account_id); let account = Account::new(account_id.clone(), [public_key]).build(&account_id); diff --git a/core/src/smartcontracts/isi/account.rs b/core/src/smartcontracts/isi/account.rs index ec6ce9d0a6a..7c803c76b43 100644 --- a/core/src/smartcontracts/isi/account.rs +++ b/core/src/smartcontracts/isi/account.rs @@ -198,12 +198,26 @@ pub mod isi { impl Execute for Transfer { fn execute(self, _authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - wsv.asset_definition_mut(&self.object)?.owned_by = self.destination_id.clone(); + let Transfer { + source_id, + object, + destination_id, + } = self; + let _ = wsv.account(&source_id)?; + let _ = wsv.account(&destination_id)?; + + let asset_definition = wsv.asset_definition_mut(&object)?; + + if asset_definition.owned_by != source_id { + return Err(Error::Find(FindError::Account(source_id))); + } + + asset_definition.owned_by = destination_id.clone(); wsv.emit_events(Some(AssetDefinitionEvent::OwnerChanged( AssetDefinitionOwnerChanged { - asset_definition_id: self.object, - new_owner: self.destination_id, + asset_definition_id: object, + new_owner: destination_id, }, ))); diff --git a/core/src/smartcontracts/isi/domain.rs b/core/src/smartcontracts/isi/domain.rs index 21de19e9e8d..de0374be2ad 100644 --- a/core/src/smartcontracts/isi/domain.rs +++ b/core/src/smartcontracts/isi/domain.rs @@ -287,11 +287,25 @@ pub mod isi { impl Execute for Transfer { fn execute(self, _authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { - wsv.domain_mut(&self.object)?.owned_by = self.destination_id.clone(); + let Transfer { + source_id, + object, + destination_id, + } = self; + let _ = wsv.account(&source_id)?; + let _ = wsv.account(&destination_id)?; + + let domain = wsv.domain_mut(&object)?; + + if domain.owned_by != source_id { + return Err(Error::Find(FindError::Account(source_id))); + } + + domain.owned_by = destination_id.clone(); wsv.emit_events(Some(DomainEvent::OwnerChanged(DomainOwnerChanged { - domain_id: self.object, - new_owner: self.destination_id, + domain_id: object, + new_owner: destination_id, }))); Ok(()) diff --git a/core/src/smartcontracts/isi/triggers/mod.rs b/core/src/smartcontracts/isi/triggers/mod.rs index 2b8da8ed19f..fd5459cacad 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -112,7 +112,7 @@ pub mod isi { Err(MathError::Overflow.into()) } }) - .ok_or_else(|| Error::Find(Box::new(FindError::Trigger(id.clone()))))??; + .ok_or_else(|| Error::Find(FindError::Trigger(id.clone())))??; triggers.mod_repeats(&id, |n| { n.checked_add(self.object) @@ -181,7 +181,7 @@ pub mod isi { ))) } }) - .ok_or_else(|| Error::Find(Box::new(FindError::Trigger(id.clone())))) + .ok_or_else(|| Error::Find(FindError::Trigger(id.clone()))) .and_then(core::convert::identity)?; wsv.execute_trigger(id.clone(), authority); diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index 90686cde43f..d138addc7aa 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -94,11 +94,11 @@ impl TestGenesis for GenesisNetwork { let alice_id = AccountId::from_str("alice@wonderland").expect("valid names"); let mint_rose_permission = PermissionToken::new( - "CanMintAssetsWithDefinition".parse().unwrap(), + "CanMintAssetWithDefinition".parse().unwrap(), &json!({ "asset_definition_id": rose_definition_id }), ); let burn_rose_permission = PermissionToken::new( - "CanBurnAssetsWithDefinition".parse().unwrap(), + "CanBurnAssetWithDefinition".parse().unwrap(), &json!({ "asset_definition_id": rose_definition_id }), ); let unregister_any_peer_permission = @@ -124,7 +124,7 @@ impl TestGenesis for GenesisNetwork { upgrade_executor_permission, ] { first_transaction - .append_instruction(Grant::permission_token(permission, alice_id.clone()).into()); + .append_instruction(Grant::permission(permission, alice_id.clone()).into()); } for isi in extra_isi.into_iter() { diff --git a/data_model/src/account.rs b/data_model/src/account.rs index c66163920c0..f472b3152b7 100644 --- a/data_model/src/account.rs +++ b/data_model/src/account.rs @@ -10,7 +10,7 @@ use core::str::FromStr; #[cfg(feature = "std")] use std::collections::{btree_map, btree_set}; -use derive_more::{DebugCustom, Display}; +use derive_more::{Constructor, DebugCustom, Display}; use getset::Getters; use iroha_data_model_derive::{model, IdEqOrdHash}; use iroha_primitives::{const_vec::ConstVec, must_use::MustUse}; @@ -34,12 +34,6 @@ use crate::{ /// API to work with collections of [`Id`] : [`Account`] mappings. pub type AccountsMap = btree_map::BTreeMap; -// The size of the array must be fixed. If we use more than `1` we -// waste all of that space for all non-multisig accounts. If we -// have 1 signatory per account, we keep the signature on the -// stack. If we have more than 1, we keep everything on the -// heap. Thanks to the union feature, we're not wasting `8Bytes` -// of space, over `Vec`. type Signatories = btree_set::BTreeSet; #[model] @@ -64,6 +58,7 @@ pub mod model { PartialOrd, Ord, Hash, + Constructor, Getters, Decode, Encode, @@ -114,7 +109,7 @@ pub mod model { /// Builder which should be submitted in a transaction to create a new [`Account`] #[derive( - DebugCustom, Display, Clone, IdEqOrdHash, Decode, Encode, Deserialize, Serialize, IntoSchema, + DebugCustom, Display, Clone, IdEqOrdHash, Decode, Encode, Serialize, Deserialize, IntoSchema, )] #[display(fmt = "[{id}]")] #[debug(fmt = "[{id:?}] {{ signatories: {signatories:?}, metadata: {metadata} }}")] @@ -153,14 +148,6 @@ pub mod model { } } -impl AccountId { - /// Construct [`Self`]. - // NOTE: not derived to preserve order of fields in which [`Self`] is parsed from string - pub fn new(name: Name, domain_id: DomainId) -> Self { - Self { domain_id, name } - } -} - impl Account { /// Construct builder for [`Account`] identifiable by [`Id`] containing the given signatories. #[inline] @@ -259,6 +246,7 @@ impl Registered for Account { type With = NewAccount; } +#[cfg(feature = "transparent_api")] impl FromIterator for crate::Value { fn from_iter>(iter: T) -> Self { iter.into_iter() @@ -447,7 +435,7 @@ mod tests { let mut account_ids = Vec::new(); for name in [&name_a, &name_b] { for domain_id in [&domain_id_a, &domain_id_b] { - account_ids.push(AccountId::new(name.clone(), domain_id.clone())); + account_ids.push(AccountId::new(domain_id.clone(), name.clone())); } } diff --git a/data_model/src/asset.rs b/data_model/src/asset.rs index ba693a8c3f8..c439a5e58ef 100644 --- a/data_model/src/asset.rs +++ b/data_model/src/asset.rs @@ -69,10 +69,10 @@ pub mod model { #[getset(get = "pub")] #[ffi_type] pub struct AssetDefinitionId { - /// Asset name. - pub name: Name, /// Domain id. pub domain_id: DomainId, + /// Asset name. + pub name: Name, } /// Identification of an Asset's components include Entity Id ([`Asset::Id`]) and [`Account::Id`]. @@ -488,11 +488,12 @@ impl FromStr for AssetId { if let Ok(def_id) = asset_definition_candidate.parse() { def_id } else if let Some((name, "")) = asset_definition_candidate.rsplit_once('#') { - AssetDefinitionId::new(name.parse() - .map_err(|_e| ParseError { - reason: "The `name` part of the `definition_id` part of the `asset_id` failed to parse as a valid `Name`. You might have forbidden characters like `#` or `@` in the first part." - })?, - account_id.domain_id.clone()) + AssetDefinitionId::new( + account_id.domain_id.clone(), + name.parse().map_err(|_e| ParseError { + reason: "The `name` part of the `definition_id` part of the `asset_id` failed to parse as a valid `Name`. You might have forbidden characters like `#` or `@` in the first part." + })? + ) } else { return Err(ParseError { reason: "The `definition_id` part of the `asset_id` failed to parse. Ensure that you have it in the right format: `name#domain_of_asset#account_name@domain_of_account` or `name##account_name@domain_of_account` in case of same domain" }); } diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index c03b9b7c6b6..9a4d760ea5b 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -222,7 +222,7 @@ mod tests { metadata: Metadata::default(), owned_by: domain_owner_id, }; - let account_id = AccountId::new(account_name, domain_id.clone()); + let account_id = AccountId::new(domain_id.clone(), account_name); let account = Account { id: account_id.clone(), assets: AssetsMap::default(), @@ -231,7 +231,7 @@ mod tests { metadata: Metadata::default(), }; let asset_id = AssetId::new( - AssetDefinitionId::new(asset_name, domain_id.clone()), + AssetDefinitionId::new(domain_id.clone(), asset_name), account_id.clone(), ); let asset = Asset::new(asset_id.clone(), 0u32); diff --git a/data_model/src/isi.rs b/data_model/src/isi.rs index 4bbfa0de0d7..22460378365 100644 --- a/data_model/src/isi.rs +++ b/data_model/src/isi.rs @@ -902,7 +902,7 @@ mod transparent { impl Grant { /// Constructs a new [`Grant`] for a [`PermissionToken`]. - pub fn permission_token(permission_token: PermissionToken, to: AccountId) -> Self { + pub fn permission(permission_token: PermissionToken, to: AccountId) -> Self { Self { object: permission_token, destination_id: to, @@ -947,7 +947,7 @@ mod transparent { impl Revoke { /// Constructs a new [`Revoke`] for a [`PermissionToken`]. - pub fn permission_token(permission_token: PermissionToken, from: AccountId) -> Self { + pub fn permission(permission_token: PermissionToken, from: AccountId) -> Self { Self { object: permission_token, destination_id: from, @@ -1279,7 +1279,7 @@ pub mod error { String, ), /// Entity missing - Find(#[cfg_attr(feature = "std", source)] Box), + Find(#[cfg_attr(feature = "std", source)] FindError), /// Repeated instruction Repetition(#[cfg_attr(feature = "std", source)] RepetitionError), /// Mintability assertion failed diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index c66139a6dda..63895fe10aa 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -423,13 +423,13 @@ }, "AssetDefinitionId": { "Struct": [ - { - "name": "name", - "type": "Name" - }, { "name": "domain_id", "type": "DomainId" + }, + { + "name": "name", + "type": "Name" } ] }, diff --git a/genesis/src/lib.rs b/genesis/src/lib.rs index e36f2b904b3..2df43091b4d 100644 --- a/genesis/src/lib.rs +++ b/genesis/src/lib.rs @@ -25,7 +25,7 @@ pub static GENESIS_DOMAIN_ID: Lazy = Lazy::new(|| "genesis".parse().ex /// [`AccountId`] of the genesis account. pub static GENESIS_ACCOUNT_ID: Lazy = - Lazy::new(|| AccountId::new("genesis".parse().expect("Valid"), GENESIS_DOMAIN_ID.clone())); + Lazy::new(|| AccountId::new(GENESIS_DOMAIN_ID.clone(), "genesis".parse().expect("Valid"))); /// Genesis transaction #[derive(Debug, Clone)] @@ -315,7 +315,7 @@ impl RawGenesisDomainBuilder { /// Add an account to this domain without a public key. #[cfg(test)] fn account_without_public_key(mut self, account_name: Name) -> Self { - let account_id = AccountId::new(account_name, self.domain_id.clone()); + let account_id = AccountId::new(self.domain_id.clone(), account_name); self.transaction .isi .push(Register::account(Account::new(account_id, [])).into()); @@ -334,7 +334,7 @@ impl RawGenesisDomainBuilder { public_key: PublicKey, metadata: Metadata, ) -> Self { - let account_id = AccountId::new(account_name, self.domain_id.clone()); + let account_id = AccountId::new(self.domain_id.clone(), account_name); let register = Register::account(Account::new(account_id, [public_key]).with_metadata(metadata)); self.transaction.isi.push(register.into()); @@ -343,7 +343,7 @@ impl RawGenesisDomainBuilder { /// Add [`AssetDefinition`] to current domain. pub fn asset(mut self, asset_name: Name, asset_value_type: AssetValueType) -> Self { - let asset_definition_id = AssetDefinitionId::new(asset_name, self.domain_id.clone()); + let asset_definition_id = AssetDefinitionId::new(self.domain_id.clone(), asset_name); let asset_definition = match asset_value_type { AssetValueType::Quantity => AssetDefinition::quantity(asset_definition_id), AssetValueType::BigQuantity => AssetDefinition::big_quantity(asset_definition_id), @@ -417,7 +417,7 @@ mod tests { assert_eq!( finished_genesis_block.transactions[0].isi[1], Register::account(Account::new( - AccountId::new("alice".parse().unwrap(), domain_id.clone()), + AccountId::new(domain_id.clone(), "alice".parse().unwrap()), [] )) .into() @@ -425,7 +425,7 @@ mod tests { assert_eq!( finished_genesis_block.transactions[0].isi[2], Register::account(Account::new( - AccountId::new("bob".parse().unwrap(), domain_id), + AccountId::new(domain_id, "bob".parse().unwrap()), [] )) .into() @@ -440,7 +440,7 @@ mod tests { assert_eq!( finished_genesis_block.transactions[0].isi[4], Register::account(Account::new( - AccountId::new("Cheshire_Cat".parse().unwrap(), domain_id), + AccountId::new(domain_id, "Cheshire_Cat".parse().unwrap()), [] )) .into() @@ -455,7 +455,7 @@ mod tests { assert_eq!( finished_genesis_block.transactions[0].isi[6], Register::account(Account::new( - AccountId::new("Mad_Hatter".parse().unwrap(), domain_id), + AccountId::new(domain_id, "Mad_Hatter".parse().unwrap()), [public_key.parse().unwrap()], )) .into() diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index ef3c1cab1f8..fa572e164f6 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -105,7 +105,6 @@ types!( BlockMessage, BlockRejectionReason, BlockSubscriptionRequest, - Box, Box>, Box, Box, diff --git a/smart_contract/executor/derive/src/lib.rs b/smart_contract/executor/derive/src/lib.rs index 71d682c974c..c9bc81dc6d8 100644 --- a/smart_contract/executor/derive/src/lib.rs +++ b/smart_contract/executor/derive/src/lib.rs @@ -128,6 +128,7 @@ pub fn derive_token(input: TokenStream) -> Result { /// - `asset_definition::Owner` - checks if the authority is the asset definition owner; /// - `asset::Owner` - checks if the authority is the asset owner; /// - `account::Owner` - checks if the authority is the account owner. +/// - `domain::Owner` - checks if the authority is the domain owner. /// - `AlwaysPass` - checks nothing and always passes. /// - `OnlyGenesis` - checks that block height is 0. /// diff --git a/smart_contract/executor/src/default.rs b/smart_contract/executor/src/default.rs index 0c7eafa30f2..2c6e32c2932 100644 --- a/smart_contract/executor/src/default.rs +++ b/smart_contract/executor/src/default.rs @@ -57,6 +57,11 @@ pub fn default_permission_token_schema() -> PermissionTokenSchema { schema } +// NOTE: If any new `visit_..` functions are introduced in this module, one should +// not forget to update the default executor boilerplate too, specifically the +// `iroha_executor::derive::default::impl_derive_visit` function +// signature list. + /// Default validation for [`SignedTransaction`]. /// /// # Warning @@ -168,7 +173,7 @@ pub mod peer { } pub mod domain { - use permission::domain::is_domain_owner; + use permission::{account::is_account_owner, domain::is_domain_owner}; use super::*; @@ -210,12 +215,18 @@ pub mod domain { authority: &AccountId, isi: &Transfer, ) { - let destination_id = isi.object(); + let source_id = isi.source_id(); + let domain_id = isi.object(); if is_genesis(executor) { execute!(executor, isi); } - match is_domain_owner(destination_id, authority) { + match is_account_owner(source_id, authority) { + Err(err) => deny!(executor, err), + Ok(true) => execute!(executor, isi), + Ok(false) => {} + } + match is_domain_owner(domain_id, source_id) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} @@ -282,10 +293,28 @@ pub mod account { pub fn visit_register_account( executor: &mut V, - _authority: &AccountId, + authority: &AccountId, isi: &Register, ) { - execute!(executor, isi) + let domain_id = isi.object().id().domain_id(); + + match permission::domain::is_domain_owner(domain_id, authority) { + Err(err) => deny!(executor, err), + Ok(true) => execute!(executor, isi), + Ok(false) => {} + } + + let can_register_account_in_domain = tokens::domain::CanRegisterAccountInDomain { + domain_id: domain_id.clone(), + }; + if can_register_account_in_domain.is_owned_by(authority) { + execute!(executor, isi); + } + + deny!( + executor, + "Can't register account in a domain owned by another account" + ); } pub fn visit_unregister_account( @@ -458,10 +487,29 @@ pub mod asset_definition { pub fn visit_register_asset_definition( executor: &mut V, - _authority: &AccountId, + authority: &AccountId, isi: &Register, ) { - execute!(executor, isi); + let domain_id = isi.object().id().domain_id(); + + match permission::domain::is_domain_owner(domain_id, authority) { + Err(err) => deny!(executor, err), + Ok(true) => execute!(executor, isi), + Ok(false) => {} + } + + let can_register_asset_definition_in_domain_token = + tokens::domain::CanRegisterAssetDefinitionInDomain { + domain_id: domain_id.clone(), + }; + if can_register_asset_definition_in_domain_token.is_owned_by(authority) { + execute!(executor, isi); + } + + deny!( + executor, + "Can't register asset definition in a domain owned by another account" + ); } pub fn visit_unregister_asset_definition( @@ -489,7 +537,7 @@ pub mod asset_definition { deny!( executor, - "Can't unregister assets registered by other accounts" + "Can't unregister asset definition in a domain owned by another account" ); } @@ -603,7 +651,7 @@ pub mod asset { Ok(false) => {} } let can_register_assets_with_definition_token = - tokens::asset::CanRegisterAssetsWithDefinition { + tokens::asset::CanRegisterAssetWithDefinition { asset_definition_id: asset.id().definition_id().clone(), }; if can_register_assets_with_definition_token.is_owned_by(authority) { @@ -637,7 +685,7 @@ pub mod asset { Ok(false) => {} } let can_unregister_assets_with_definition_token = - tokens::asset::CanUnregisterAssetsWithDefinition { + tokens::asset::CanUnregisterAssetWithDefinition { asset_definition_id: asset_id.definition_id().clone(), }; if can_unregister_assets_with_definition_token.is_owned_by(authority) { @@ -668,12 +716,18 @@ pub mod asset { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_mint_assets_with_definition_token = tokens::asset::CanMintAssetsWithDefinition { + let can_mint_assets_with_definition_token = tokens::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 { + asset_id: asset_id.clone(), + }; + if can_mint_user_asset_token.is_owned_by(authority) { + execute!(executor, isi); + } deny!( executor, @@ -725,7 +779,7 @@ pub mod asset { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_burn_assets_with_definition_token = tokens::asset::CanBurnAssetsWithDefinition { + let can_burn_assets_with_definition_token = tokens::asset::CanBurnAssetWithDefinition { asset_definition_id: asset_id.definition_id().clone(), }; if can_burn_assets_with_definition_token.is_owned_by(authority) { @@ -789,7 +843,7 @@ pub mod asset { Ok(false) => {} } let can_transfer_assets_with_definition_token = - tokens::asset::CanTransferAssetsWithDefinition { + tokens::asset::CanTransferAssetWithDefinition { asset_definition_id: asset_id.definition_id().clone(), }; if can_transfer_assets_with_definition_token.is_owned_by(authority) { @@ -1182,7 +1236,7 @@ pub mod permission_token { macro_rules! visit_internal { ($token:ident) => { let token = PermissionToken::from($token.clone()); - let isi = <$isi_type>::permission_token(token, account_id); + let isi = <$isi_type>::permission(token, account_id); if is_genesis($executor) { execute!($executor, isi); } diff --git a/smart_contract/executor/src/default/tokens.rs b/smart_contract/executor/src/default/tokens.rs index 97382cc7806..3deb532f5eb 100644 --- a/smart_contract/executor/src/default/tokens.rs +++ b/smart_contract/executor/src/default/tokens.rs @@ -70,6 +70,8 @@ declare_tokens! { 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}, @@ -82,13 +84,14 @@ declare_tokens! { crate::default::tokens::asset_definition::{CanSetKeyValueInAssetDefinition}, crate::default::tokens::asset_definition::{CanRemoveKeyValueInAssetDefinition}, - crate::default::tokens::asset::{CanRegisterAssetsWithDefinition}, - crate::default::tokens::asset::{CanUnregisterAssetsWithDefinition}, + crate::default::tokens::asset::{CanRegisterAssetWithDefinition}, + crate::default::tokens::asset::{CanUnregisterAssetWithDefinition}, crate::default::tokens::asset::{CanUnregisterUserAsset}, - crate::default::tokens::asset::{CanBurnAssetsWithDefinition}, + crate::default::tokens::asset::{CanBurnAssetWithDefinition}, + crate::default::tokens::asset::{CanMintAssetWithDefinition}, + crate::default::tokens::asset::{CanMintUserAsset}, crate::default::tokens::asset::{CanBurnUserAsset}, - crate::default::tokens::asset::{CanMintAssetsWithDefinition}, - crate::default::tokens::asset::{CanTransferAssetsWithDefinition}, + crate::default::tokens::asset::{CanTransferAssetWithDefinition}, crate::default::tokens::asset::{CanTransferUserAsset}, crate::default::tokens::asset::{CanSetKeyValueInUserAsset}, crate::default::tokens::asset::{CanRemoveKeyValueInUserAsset}, @@ -146,6 +149,22 @@ pub mod domain { pub domain_id: DomainId, } } + + token! { + #[derive(ValidateGrantRevoke, permission::derive_conversions::domain::Owner)] + #[validate(permission::domain::Owner)] + pub struct CanRegisterAccountInDomain { + pub domain_id: DomainId, + } + } + + token! { + #[derive(ValidateGrantRevoke, permission::derive_conversions::domain::Owner)] + #[validate(permission::domain::Owner)] + pub struct CanRegisterAssetDefinitionInDomain { + pub domain_id: DomainId, + } + } } pub mod account { @@ -229,7 +248,7 @@ pub mod asset { token! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] - pub struct CanRegisterAssetsWithDefinition { + pub struct CanRegisterAssetWithDefinition { pub asset_definition_id: AssetDefinitionId, } } @@ -237,7 +256,7 @@ pub mod asset { token! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] - pub struct CanUnregisterAssetsWithDefinition { + pub struct CanUnregisterAssetWithDefinition { pub asset_definition_id: AssetDefinitionId, } } @@ -253,7 +272,7 @@ pub mod asset { token! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] - pub struct CanBurnAssetsWithDefinition { + pub struct CanBurnAssetWithDefinition { pub asset_definition_id: AssetDefinitionId, } } @@ -269,15 +288,23 @@ pub mod asset { token! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] - pub struct CanMintAssetsWithDefinition { + pub struct CanMintAssetWithDefinition { pub asset_definition_id: AssetDefinitionId, } } + token! { + #[derive(ValidateGrantRevoke, permission::derive_conversions::asset::Owner)] + #[validate(permission::asset::Owner)] + pub struct CanMintUserAsset { + pub asset_id: AssetId, + } + } + token! { #[derive(ValidateGrantRevoke, permission::derive_conversions::asset_definition::Owner)] #[validate(permission::asset_definition::Owner)] - pub struct CanTransferAssetsWithDefinition { + pub struct CanTransferAssetWithDefinition { pub asset_definition_id: AssetDefinitionId, } } diff --git a/tools/kagami/src/genesis.rs b/tools/kagami/src/genesis.rs index 6036e4723ab..c679e4c01b0 100644 --- a/tools/kagami/src/genesis.rs +++ b/tools/kagami/src/genesis.rs @@ -127,21 +127,21 @@ pub fn generate_default(executor: ExecutorMode) -> color_eyre::Result color_eyre::Result color_eyre::Result(Result); -/// use iroha_torii_macro::generate_endpoints; +/// use iroha_torii_derive::generate_endpoints; /// /// // An example with arguments of both acceptable kinds. /// // This would generate endpoints accepting functions with diff --git a/torii/src/utils.rs b/torii/src/utils.rs index 805917872bb..eb7a5e30d7b 100644 --- a/torii/src/utils.rs +++ b/torii/src/utils.rs @@ -81,4 +81,4 @@ impl Reply for WarpResult { } } -iroha_torii_macro::generate_endpoints!(2, 3, 4, 5, 6, 7); +iroha_torii_derive::generate_endpoints!(2, 3, 4, 5, 6, 7);