Skip to content

Commit

Permalink
[feature] hyperledger-iroha#3624: general purpose permission tokens
Browse files Browse the repository at this point in the history
Signed-off-by: Marin Veršić <marin.versic101@gmail.com>
  • Loading branch information
mversic committed Jun 20, 2023
1 parent 91ca5de commit 3ff9249
Show file tree
Hide file tree
Showing 39 changed files with 617 additions and 1,147 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
21 changes: 9 additions & 12 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
16 changes: 7 additions & 9 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 @@ -213,10 +214,7 @@ fn permissions_differ_not_only_by_names() {
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(),
)]),
.with_params([("asset_id".parse().expect("Valid"), mouse_hat_id.encode())]),
alice_id.clone(),
);

Expand Down Expand Up @@ -251,7 +249,7 @@ 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())]),
.with_params([("asset_id".parse().expect("Valid"), mouse_shoes_id.encode())]),
alice_id,
);

Expand Down Expand Up @@ -302,7 +300,7 @@ mod token_parameters {
#[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())]);
.with_params([(NUMBER_PARAMETER_NAME.clone(), 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 @@ -313,7 +311,7 @@ mod token_parameters {
#[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()),
(NUMBER_PARAMETER_NAME.clone(), 1_u32.encode()),
(
"it's_a_trap".parse().expect("Valid"),
"test".to_owned().into(),
Expand All @@ -330,7 +328,7 @@ mod token_parameters {
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()),
(STRING_PARAMETER_NAME.clone(), "test".encode()),
(
"extra_param".parse().expect("Valid"),
"extra_test".to_owned().into(),
Expand All @@ -346,7 +344,7 @@ mod token_parameters {
#[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()),
(NUMBER_PARAMETER_NAME.clone(), 1_u32.encode()),
(
STRING_PARAMETER_NAME.clone(),
Value::Name("test".parse().expect("Valid")),
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@

extern crate alloc;

use alloc::{format, string::String};

use iroha_schema::IntoSchema;
use iroha_validator::{
data_model::evaluate::{EvaluationError, ExpressionEvaluator},
permission::Token as _,
prelude::*,
};
use parity_scale_codec::{Decode, Encode};

#[cfg(not(test))]
extern crate panic_halt;
Expand All @@ -22,9 +26,9 @@ mod token {
use super::*;

/// Token to identify if user can (un-)register domains.
#[derive(Token, ValidateGrantRevoke)]
#[derive(Token, ValidateGrantRevoke, Decode, Encode, IntoSchema)]
#[validate(iroha_validator::permission::OnlyGenesis)]
pub struct CanControlDomainsLives;
pub struct CanControlDomainLives;
}

struct CustomValidator(DefaultValidator);
Expand All @@ -38,7 +42,7 @@ macro_rules! delegate {
}

impl CustomValidator {
const CAN_CONTROL_DOMAIN_LIVES: token::CanControlDomainsLives = token::CanControlDomainsLives;
const CAN_CONTROL_DOMAIN_LIVES: token::CanControlDomainLives = token::CanControlDomainLives;
}

impl Visit for CustomValidator {
Expand Down Expand Up @@ -138,7 +142,7 @@ impl Validate for CustomValidator {
tokens.remove(pos);
}

tokens.push(token::CanControlDomainsLives::definition());
tokens.push(token::CanControlDomainLives::definition());
tokens
}

Expand Down
Loading

0 comments on commit 3ff9249

Please sign in to comment.