Skip to content

Commit

Permalink
[feature] hyperledger-iroha#3624: introduce general purpose permissio…
Browse files Browse the repository at this point in the history
…n tokens

Signed-off-by: Marin Veršić <marin.versic101@gmail.com>
  • Loading branch information
mversic committed Jun 20, 2023
1 parent c332dc4 commit bf54f2f
Show file tree
Hide file tree
Showing 44 changed files with 741 additions and 1,282 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 9 additions & 4 deletions client/benches/tps/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use iroha_data_model::{
parameter::{default::MAX_TRANSACTIONS_IN_BLOCK, ParametersBuilder},
prelude::*,
};
use parity_scale_codec::Encode as _;
use serde::Deserialize;
use test_network::*;

Expand Down Expand Up @@ -173,11 +174,15 @@ impl MeasurerUnit {
));
self.client.submit_blocking(register_me)?;

let can_burn_my_asset = PermissionToken::new("can_burn_user_asset".parse()?)
.with_params([("asset_id".parse()?, asset_id.clone().into())]);
let can_burn_my_asset = PermissionToken {
definition_id: "CanBurnUserAsset".to_owned(),
payload: ("asset_id", &asset_id).encode(),
};
let allow_alice_to_burn_my_asset = GrantBox::new(can_burn_my_asset, alice_id.clone());
let can_transfer_my_asset = PermissionToken::new("can_transfer_user_asset".parse()?)
.with_params([("asset_id".parse()?, asset_id.clone().into())]);
let can_transfer_my_asset = PermissionToken {
definition_id: "CanTransferUserAsset".to_owned(),
payload: ("asset_id", &asset_id).encode(),
};
let allow_alice_to_transfer_my_asset = GrantBox::new(can_transfer_my_asset, alice_id);
let grant_tx = TransactionBuilder::new(account_id)
.with_instructions([
Expand Down
7 changes: 5 additions & 2 deletions client/tests/integration/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use iroha_client::client;
use iroha_crypto::{KeyPair, PublicKey};
use iroha_data_model::prelude::*;
use iroha_primitives::fixed::Fixed;
use parity_scale_codec::Encode as _;
use test_network::*;

use super::Configuration;
Expand Down Expand Up @@ -259,8 +260,10 @@ 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 = GrantBox::new(
PermissionToken::new("can_transfer_user_asset".parse().expect("Valid"))
.with_params([("asset_id".parse().expect("Valid"), asset_id.clone().into())]),
PermissionToken {
definition_id: "CanTransferUserAsset".to_owned(),
payload: asset_id.encode(),
},
alice_id.clone(),
);

Expand Down
29 changes: 13 additions & 16 deletions client/tests/integration/events/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{fmt::Write as _, str::FromStr, sync::mpsc, thread};

use eyre::Result;
use iroha_data_model::{prelude::*, transaction::WasmSmartContract};
use parity_scale_codec::Encode;
use parity_scale_codec::Encode as _;
use test_network::*;

use crate::wasm::utils::wasm_template;
Expand Down Expand Up @@ -163,17 +163,14 @@ fn produce_multiple_events() -> Result<()> {
// Registering role
let alice_id = <Account as Identifiable>::Id::from_str("alice@wonderland")?;
let role_id = <Role as Identifiable>::Id::from_str("TEST_ROLE")?;
let token_1 = PermissionToken::new(
"can_remove_key_value_in_user_account"
.parse()
.expect("valid"),
)
.with_params([(
"account_id".parse().expect("valid"),
alice_id.clone().into(),
)]);
let token_2 = PermissionToken::new("can_set_key_value_in_user_account".parse().expect("valid"))
.with_params([("account_id".parse().expect("valid"), alice_id.into())]);
let token_1 = PermissionToken {
definition_id: "CanRemoveKeyValueInUserAccount".to_owned(),
payload: alice_id.encode(),
};
let token_2 = PermissionToken {
definition_id: "CanSetKeyValueInUserAccount".to_owned(),
payload: alice_id.encode(),
};
let role = iroha_data_model::role::Role::new(role_id.clone())
.add_permission(token_1.clone())
.add_permission(token_2.clone());
Expand Down Expand Up @@ -207,13 +204,13 @@ fn produce_multiple_events() -> Result<()> {
WorldEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded(
AccountPermissionChanged {
account_id: bob_id.clone(),
permission_id: token_1.definition_id().clone(),
permission_id: token_1.definition_id.clone(),
},
))),
WorldEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded(
AccountPermissionChanged {
account_id: bob_id.clone(),
permission_id: token_2.definition_id().clone(),
permission_id: token_2.definition_id.clone(),
},
))),
WorldEvent::Domain(DomainEvent::Account(AccountEvent::RoleGranted(
Expand All @@ -225,13 +222,13 @@ fn produce_multiple_events() -> Result<()> {
WorldEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved(
AccountPermissionChanged {
account_id: bob_id.clone(),
permission_id: token_1.definition_id().clone(),
permission_id: token_1.definition_id,
},
))),
WorldEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved(
AccountPermissionChanged {
account_id: bob_id.clone(),
permission_id: token_2.definition_id().clone(),
permission_id: token_2.definition_id,
},
))),
WorldEvent::Domain(DomainEvent::Account(AccountEvent::RoleRevoked(
Expand Down
75 changes: 31 additions & 44 deletions client/tests/integration/permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{str::FromStr as _, thread};
use eyre::Result;
use iroha_client::client::{self, Client};
use iroha_data_model::prelude::*;
use parity_scale_codec::Encode as _;
use test_network::{PeerBuilder, *};

use super::Configuration;
Expand Down Expand Up @@ -181,11 +182,10 @@ fn permissions_differ_not_only_by_names() {
// Granting permission to Alice to modify metadata in Mouse's hats
let mouse_hat_id = <Asset as Identifiable>::Id::new(hat_definition_id, mouse_id.clone());
let allow_alice_to_set_key_value_in_hats = GrantBox::new(
PermissionToken::new("can_set_key_value_in_user_asset".parse().expect("Valid"))
.with_params([(
"asset_id".parse().expect("Valid"),
mouse_hat_id.clone().into(),
)]),
PermissionToken {
definition_id: "CanSetKeyValueInUserAsset".to_owned(),
payload: mouse_hat_id.encode(),
},
alice_id.clone(),
);

Expand Down Expand Up @@ -219,8 +219,10 @@ fn permissions_differ_not_only_by_names() {

// Granting permission to Alice to modify metadata in Mouse's shoes
let allow_alice_to_set_key_value_in_shoes = GrantBox::new(
PermissionToken::new("can_set_key_value_in_user_asset".parse().expect("Valid"))
.with_params([("asset_id".parse().expect("Valid"), mouse_shoes_id.into())]),
PermissionToken {
definition_id: "CanSetKeyValueInUserAsset".to_owned(),
payload: mouse_shoes_id.encode(),
},
alice_id,
);

Expand All @@ -242,23 +244,16 @@ fn permissions_differ_not_only_by_names() {
mod token_parameters {
use super::*;

static TEST_TOKEN_DEFINITION_ID: once_cell::sync::Lazy<
<PermissionTokenDefinition as Identifiable>::Id,
> = once_cell::sync::Lazy::new(|| {
<PermissionTokenDefinition as Identifiable>::Id::new(
"test_permission_token_definition".parse().expect("Valid"),
)
});

static NUMBER_PARAMETER_NAME: once_cell::sync::Lazy<Name> =
once_cell::sync::Lazy::new(|| "number".parse().expect("Valid"));
static STRING_PARAMETER_NAME: once_cell::sync::Lazy<Name> =
once_cell::sync::Lazy::new(|| "string".parse().expect("Valid"));
static TEST_TOKEN_DEFINITION_ID: once_cell::sync::Lazy<PermissionTokenId> =
once_cell::sync::Lazy::new(|| "TestPermissionTokenDefinition".parse().expect("Valid"));

#[ignore = "ignore, more in #2851"]
#[test]
fn token_with_missing_parameters_is_not_accepted() {
let token = PermissionToken::new(TEST_TOKEN_DEFINITION_ID.clone());
let token = PermissionToken {
definition_id: TEST_TOKEN_DEFINITION_ID.clone(),
payload: Vec::new(),
};
let expect = "Expected to fail to grant permission token without parameters";

run_grant_token_error_test(token.clone(), expect);
Expand All @@ -268,8 +263,10 @@ mod token_parameters {
#[ignore = "ignore, more in #2851"]
#[test]
fn token_with_one_missing_parameter_is_not_accepted() {
let token = PermissionToken::new(TEST_TOKEN_DEFINITION_ID.clone())
.with_params([(NUMBER_PARAMETER_NAME.clone(), 1_u32.into())]);
let token = PermissionToken {
definition_id: TEST_TOKEN_DEFINITION_ID.clone(),
payload: 1_u32.encode(),
};
let expect = "Expected to fail to grant permission token with one missing parameter";

run_grant_token_error_test(token.clone(), expect);
Expand All @@ -279,13 +276,10 @@ mod token_parameters {
#[ignore = "ignore, more in #2851"]
#[test]
fn token_with_changed_parameter_name_is_not_accepted() {
let token = PermissionToken::new(TEST_TOKEN_DEFINITION_ID.clone()).with_params([
(NUMBER_PARAMETER_NAME.clone(), 1_u32.into()),
(
"it's_a_trap".parse().expect("Valid"),
"test".to_owned().into(),
),
]);
let token = PermissionToken {
definition_id: TEST_TOKEN_DEFINITION_ID.clone(),
payload: (1_u32, "test").encode(),
};
let expect = "Expected to fail to grant permission token with one changed parameter";

run_grant_token_error_test(token.clone(), expect);
Expand All @@ -295,14 +289,10 @@ mod token_parameters {
#[ignore = "ignore, more in #2851"]
#[test]
fn token_with_extra_parameter_is_not_accepted() {
let token = PermissionToken::new(TEST_TOKEN_DEFINITION_ID.clone()).with_params([
(NUMBER_PARAMETER_NAME.clone(), 1_u32.into()),
(STRING_PARAMETER_NAME.clone(), "test".to_owned().into()),
(
"extra_param".parse().expect("Valid"),
"extra_test".to_owned().into(),
),
]);
let token = PermissionToken {
definition_id: TEST_TOKEN_DEFINITION_ID.clone(),
payload: (1_u32, "test", "extra_test").encode(),
};
let expect = "Expected to fail to grant permission token with extra parameter";

run_grant_token_error_test(token.clone(), expect);
Expand All @@ -312,13 +302,10 @@ mod token_parameters {
#[ignore = "ignore, more in #2851"]
#[test]
fn token_with_wrong_parameter_type_is_not_accepted() {
let token = PermissionToken::new(TEST_TOKEN_DEFINITION_ID.clone()).with_params([
(NUMBER_PARAMETER_NAME.clone(), 1_u32.into()),
(
STRING_PARAMETER_NAME.clone(),
Value::Name("test".parse().expect("Valid")),
),
]);
let token = PermissionToken {
definition_id: TEST_TOKEN_DEFINITION_ID.clone(),
payload: (91_u32, Value::Name("test".parse().expect("Valid"))).encode(),
};
let expect = "Expected to fail to grant permission token with wrong parameter type";

run_grant_token_error_test(token.clone(), expect);
Expand Down
16 changes: 5 additions & 11 deletions client/tests/integration/queries/role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::collections::HashSet;
use eyre::Result;
use iroha_client::client;
use iroha_data_model::{prelude::*, query::error::QueryExecutionFail};
use parity_scale_codec::Encode as _;
use test_network::*;

fn create_role_ids() -> [<Role as Identifiable>::Id; 5] {
Expand Down Expand Up @@ -124,17 +125,10 @@ fn find_roles_by_account_id() -> Result<()> {
.iter()
.cloned()
.map(|role_id| {
RegisterBox::new(
Role::new(role_id).add_permission(
PermissionToken::new(
"can_set_key_value_in_user_account".parse().expect("Valid"),
)
.with_params([(
"account_id".parse().expect("Valid"),
alice_id.clone().into(),
)]),
),
)
RegisterBox::new(Role::new(role_id).add_permission(PermissionToken {
definition_id: "CanSetKeyValueInUserAccount".to_owned(),
payload: alice_id.encode(),
}))
})
.collect::<Vec<_>>();
test_client.submit_all_blocking(register_roles)?;
Expand Down
33 changes: 18 additions & 15 deletions client/tests/integration/roles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::str::FromStr as _;
use eyre::Result;
use iroha_client::client;
use iroha_data_model::prelude::*;
use parity_scale_codec::Encode as _;
use test_network::*;

#[test]
Expand All @@ -25,7 +26,10 @@ 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 = PermissionToken::new("token".parse().expect("Valid"));
let token = PermissionToken {
definition_id: "token".to_owned(),
payload: Vec::new(),
};
let role = Role::new(role_id).add_permission(token);

test_client.submit(RegisterBox::new(role))?;
Expand Down Expand Up @@ -61,14 +65,14 @@ fn register_and_grant_role_for_metadata_access() -> Result<()> {
// Registering role
let role_id = <Role as Identifiable>::Id::from_str("ACCESS_TO_MOUSE_METADATA")?;
let role = Role::new(role_id.clone())
.add_permission(
PermissionToken::new("can_set_key_value_in_user_account".parse()?)
.with_params([("account_id".parse()?, mouse_id.clone().into())]),
)
.add_permission(
PermissionToken::new("can_remove_key_value_in_user_account".parse()?)
.with_params([("account_id".parse()?, mouse_id.clone().into())]),
);
.add_permission(PermissionToken {
definition_id: "CanSetKeyValueInUserAccount".to_owned(),
payload: mouse_id.encode(),
})
.add_permission(PermissionToken {
definition_id: "CanRemoveKeyValueInUserAccount".to_owned(),
payload: mouse_id.encode(),
});
let register_role = RegisterBox::new(role);
test_client.submit_blocking(register_role)?;

Expand Down Expand Up @@ -108,12 +112,11 @@ fn unregistered_role_removed_from_account() -> Result<()> {
test_client.submit_blocking(register_mouse)?;

// Register root role
let register_role = RegisterBox::new(
Role::new(role_id.clone()).add_permission(
PermissionToken::new("can_set_key_value_in_user_account".parse()?)
.with_params([("account_id".parse()?, alice_id.into())]),
),
);
let register_role =
RegisterBox::new(Role::new(role_id.clone()).add_permission(PermissionToken {
definition_id: "CanSetKeyValueInUserAccount".to_owned(),
payload: alice_id.encode(),
}));
test_client.submit_blocking(register_role)?;

// Grant root role to Mouse
Expand Down
4 changes: 4 additions & 0 deletions client/tests/integration/smartcontracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ codegen-units = 1 # Further reduces binary size but increases compilation time
[workspace.dependencies]
iroha_validator = { version = "=2.0.0-pre-rc.16", path = "../../../../wasm/validator", features = ["default-validator"] }
iroha_wasm = { version = "=2.0.0-pre-rc.16", path = "../../../../wasm", features = ["debug"]}
iroha_schema = { version = "=2.0.0-pre-rc.16", path = "../../../../schema" }

parity-scale-codec = { version = "3.2.1", default-features = false }
serde_json = { version = "1.0.91", default-features = false }
panic-halt = "0.2.0"
6 changes: 3 additions & 3 deletions client/tests/integration/smartcontracts/mint_rose/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ use iroha_wasm::data_model::prelude::*;

/// Mint 1 rose for authority
#[iroha_wasm::main(params = "[authority]")]
fn main(authority: <Account as Identifiable>::Id) {
let rose_definition_id = <AssetDefinition as Identifiable>::Id::from_str("rose#wonderland")
fn main(authority: AccountId) {
let rose_definition_id = AssetDefinitionId::from_str("rose#wonderland")
.dbg_expect("Failed to parse `rose#wonderland` asset definition id");
let rose_id = <Asset as Identifiable>::Id::new(rose_definition_id, authority);
let rose_id = AssetId::new(rose_definition_id, authority);

MintBox::new(1_u32, rose_id)
.execute()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ crate-type = ['cdylib']

[dependencies]
iroha_validator.workspace = true
iroha_schema.workspace = true

parity-scale-codec.workspace = true
serde_json.workspace = true
panic-halt.workspace = true
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ crate-type = ['cdylib']

[dependencies]
iroha_validator.workspace = true
iroha_schema.workspace = true

parity-scale-codec.workspace = true
serde_json.workspace = true
panic-halt.workspace = true
Loading

0 comments on commit bf54f2f

Please sign in to comment.