diff --git a/.rustfmt.toml b/.rustfmt.toml index 0f32415c590..f9b0b3f3643 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,5 +1,5 @@ -newline_style="Unix" -use_field_init_shorthand=true -format_code_in_doc_comments = true # unstable (https://github.com/rust-lang/rustfmt/issues/3348) -group_imports="StdExternalCrate" # unstable (https://github.com/rust-lang/rustfmt/issues/5083) -imports_granularity="Crate" # unstable (https://github.com/rust-lang/rustfmt/issues/4991) +newline_style = "Unix" +use_field_init_shorthand = true +format_code_in_doc_comments = true # unstable (https://github.com/rust-lang/rustfmt/issues/3348) +group_imports = "StdExternalCrate" # unstable (https://github.com/rust-lang/rustfmt/issues/5083) +imports_granularity = "Crate" # unstable (https://github.com/rust-lang/rustfmt/issues/4991) diff --git a/Cargo.lock b/Cargo.lock index dff2ee23c08..54c8e2a54cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2855,6 +2855,7 @@ dependencies = [ "serde_with", "tempfile", "test_network", + "test_samples", "thiserror", "tokio", "tokio-tungstenite", @@ -2967,6 +2968,7 @@ dependencies = [ "serde_json", "storage", "tempfile", + "test_samples", "thiserror", "tokio", "uuid", @@ -3176,6 +3178,7 @@ dependencies = [ "once_cell", "serde", "serde_json", + "test_samples", "tracing", ] @@ -3681,6 +3684,7 @@ dependencies = [ "parity-scale-codec", "serde", "serde_json", + "test_samples", ] [[package]] @@ -4251,6 +4255,7 @@ dependencies = [ "parity-scale-codec", "serde", "serde_json", + "test_samples", ] [[package]] @@ -5711,10 +5716,22 @@ dependencies = [ "rand", "serde_json", "tempfile", + "test_samples", "tokio", "unique_port", ] +[[package]] +name = "test_samples" +version = "2.0.0-pre-rc.21" +dependencies = [ + "iroha_crypto", + "iroha_data_model", + "once_cell", + "serde", + "toml 0.8.12", +] + [[package]] name = "thiserror" version = "1.0.59" diff --git a/Cargo.toml b/Cargo.toml index 6625d6e2f9f..085f34fea5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,8 @@ iroha_executor_derive = { version = "=2.0.0-pre-rc.21", path = "smart_contract/e iroha_trigger_derive = { version = "=2.0.0-pre-rc.21", path = "smart_contract/trigger/derive" } test_network = { version = "=2.0.0-pre-rc.21", path = "core/test_network" } +test_samples = { version = "=2.0.0-pre-rc.21", path = "test_samples" } + proc-macro2 = "1.0.81" syn = { version = "2.0.60", default-features = false } quote = "1.0.36" @@ -228,6 +230,7 @@ members = [ "smart_contract/executor", "smart_contract/executor/derive", "telemetry", + "test_samples", "tools/kagami", "tools/kura_inspector", "tools/parity_scale_cli", diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 947f0a96321..ab9f3b40689 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -486,18 +486,18 @@ impl Iroha { } fn genesis_account(public_key: PublicKey) -> Account { - Account::new(iroha_genesis::GENESIS_ACCOUNT_ID.clone(), public_key) - .build(&iroha_genesis::GENESIS_ACCOUNT_ID) + let genesis_account_id = AccountId::new(iroha_genesis::GENESIS_DOMAIN_ID.clone(), public_key); + Account::new(genesis_account_id.clone()).build(&genesis_account_id) } fn genesis_domain(public_key: PublicKey) -> Domain { - let mut domain = Domain::new(iroha_genesis::GENESIS_DOMAIN_ID.clone()) - .build(&iroha_genesis::GENESIS_ACCOUNT_ID); + let genesis_account = genesis_account(public_key); + let mut domain = + Domain::new(iroha_genesis::GENESIS_DOMAIN_ID.clone()).build(&genesis_account.id); - domain.accounts.insert( - iroha_genesis::GENESIS_ACCOUNT_ID.clone(), - genesis_account(public_key), - ); + domain + .accounts + .insert(genesis_account.id.clone(), genesis_account); domain } diff --git a/cli/src/samples.rs b/cli/src/samples.rs index 26fc0acd300..fe45f22e104 100644 --- a/cli/src/samples.rs +++ b/cli/src/samples.rs @@ -62,18 +62,24 @@ pub fn get_trusted_peers(public_key: Option<&PublicKey>) -> HashSet { pub fn get_user_config( peers: &UniqueVec, chain_id: Option, - key_pair: Option, + peer_key_pair: Option, + genesis_key_pair: Option, ) -> UserConfig { let chain_id = chain_id.unwrap_or_else(|| ChainId::from("0")); - let (public_key, private_key) = key_pair.unwrap_or_else(KeyPair::random).into_parts(); - iroha_logger::info!(%public_key); + let (peer_public_key, peer_private_key) = + peer_key_pair.unwrap_or_else(KeyPair::random).into_parts(); + iroha_logger::info!(%peer_public_key); + let (genesis_public_key, genesis_private_key) = genesis_key_pair + .unwrap_or_else(KeyPair::random) + .into_parts(); + iroha_logger::info!(%genesis_public_key); let mut config = UserConfig::new(); config.chain_id.set(chain_id); - config.public_key.set(public_key.clone()); - config.private_key.set(private_key.clone()); + config.public_key.set(peer_public_key); + config.private_key.set(peer_private_key); config.network.address.set(DEFAULT_P2P_ADDR); config .chain_wide @@ -89,8 +95,8 @@ pub fn get_user_config( .network .block_gossip_period .set(HumanDuration(Duration::from_millis(500))); - config.genesis.private_key.set(private_key); - config.genesis.public_key.set(public_key); + config.genesis.private_key.set(genesis_private_key); + config.genesis.public_key.set(genesis_public_key); config.genesis.file.set("./genesis.json".into()); // There is no need in persistency in tests // If required to should be set explicitly not to overlap with other existing tests @@ -109,9 +115,10 @@ pub fn get_user_config( pub fn get_config( trusted_peers: &UniqueVec, chain_id: Option, - key_pair: Option, + peer_key_pair: Option, + genesis_key_pair: Option, ) -> Config { - get_user_config(trusted_peers, chain_id, key_pair) + get_user_config(trusted_peers, chain_id, peer_key_pair, genesis_key_pair) .unwrap_partial() .expect("config should build as all required fields were provided") .parse(CliContext { diff --git a/client/Cargo.toml b/client/Cargo.toml index cb1363174e2..f9f316fa0a9 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -56,6 +56,7 @@ iroha_logger = { workspace = true } iroha_telemetry = { workspace = true } iroha_torii_const = { workspace = true } iroha_version = { workspace = true, features = ["http"] } +test_samples = { workspace = true } attohttpc = { version = "0.28.0", default-features = false } eyre = { workspace = true } diff --git a/client/benches/torii.rs b/client/benches/torii.rs index bc3f5117cfe..a8bc5c97ab0 100644 --- a/client/benches/torii.rs +++ b/client/benches/torii.rs @@ -6,13 +6,13 @@ use criterion::{criterion_group, criterion_main, Criterion, Throughput}; use iroha::samples::{construct_executor, get_config}; use iroha_client::{ client::{asset, Client}, - crypto::KeyPair, data_model::prelude::*, }; use iroha_genesis::{GenesisNetwork, RawGenesisBlockBuilder}; use iroha_primitives::unique_vec; use iroha_version::Encode; use test_network::{get_chain_id, get_key_pair, Peer as TestPeer, PeerBuilder, TestRuntime}; +use test_samples::gen_account_in; use tokio::runtime::Runtime; const MINIMUM_SUCCESS_REQUEST_RATIO: f32 = 0.9; @@ -24,17 +24,15 @@ fn query_requests(criterion: &mut Criterion) { let configuration = get_config( &unique_vec![peer.id.clone()], Some(chain_id.clone()), - Some(get_key_pair()), + Some(get_key_pair(test_network::Signatory::Peer)), + Some(get_key_pair(test_network::Signatory::Genesis)), ); let rt = Runtime::test(); let genesis = GenesisNetwork::new( RawGenesisBlockBuilder::default() .domain("wonderland".parse().expect("Valid")) - .account( - "alice".parse().expect("Valid"), - get_key_pair().public_key().clone(), - ) + .account(get_key_pair(test_network::Signatory::Alice).into_parts().0) .finish_domain() .executor_blob( construct_executor("../default_executor").expect("Failed to construct executor"), @@ -60,11 +58,10 @@ 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(domain_id.clone(), "account".parse().expect("Valid")); - let (public_key, _) = KeyPair::random().into_parts(); - let create_account = Register::account(Account::new(account_id.clone(), public_key)); - let asset_definition_id = AssetDefinitionId::new(domain_id, "xor".parse().expect("Valid")); + let create_domain = Register::domain(Domain::new(domain_id)); + let (account_id, _account_keypair) = gen_account_in("domain"); + let create_account = Register::account(Account::new(account_id.clone())); + let asset_definition_id: AssetDefinitionId = "xor#domain".parse().expect("Valid"); let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); let mint_asset = Mint::asset_numeric( @@ -73,7 +70,7 @@ fn query_requests(criterion: &mut Criterion) { ); let client_config = iroha_client::samples::get_client_config( get_chain_id(), - get_key_pair(), + get_key_pair(test_network::Signatory::Alice), format!("http://{}", peer.api_address).parse().unwrap(), ); @@ -132,15 +129,13 @@ fn instruction_submits(criterion: &mut Criterion) { let configuration = get_config( &unique_vec![peer.id.clone()], Some(chain_id.clone()), - Some(get_key_pair()), + Some(get_key_pair(test_network::Signatory::Peer)), + Some(get_key_pair(test_network::Signatory::Genesis)), ); let genesis = GenesisNetwork::new( RawGenesisBlockBuilder::default() .domain("wonderland".parse().expect("Valid")) - .account( - "alice".parse().expect("Valid"), - configuration.common.key_pair.public_key().clone(), - ) + .account(configuration.common.key_pair.public_key().clone()) .finish_domain() .executor_blob( construct_executor("../default_executor").expect("Failed to construct executor"), @@ -158,14 +153,13 @@ fn instruction_submits(criterion: &mut Criterion) { rt.block_on(builder.start_with_peer(&mut peer)); 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(domain_id.clone(), "account".parse().expect("Valid")); - let (public_key, _) = KeyPair::random().into_parts(); - let create_account = Register::account(Account::new(account_id.clone(), public_key)).into(); - let asset_definition_id = AssetDefinitionId::new(domain_id, "xor".parse().expect("Valid")); + let create_domain: InstructionBox = Register::domain(Domain::new(domain_id)).into(); + let (account_id, _account_keypair) = gen_account_in("domain"); + let create_account = Register::account(Account::new(account_id.clone())).into(); + let asset_definition_id: AssetDefinitionId = "xor#domain".parse().expect("Valid"); let client_config = iroha_client::samples::get_client_config( get_chain_id(), - get_key_pair(), + get_key_pair(test_network::Signatory::Alice), format!("http://{}", peer.api_address).parse().unwrap(), ); let iroha_client = Client::new(client_config); diff --git a/client/benches/tps/utils.rs b/client/benches/tps/utils.rs index ca63d75d89b..afc4cb5d598 100644 --- a/client/benches/tps/utils.rs +++ b/client/benches/tps/utils.rs @@ -1,8 +1,9 @@ -use std::{fmt, fs::File, io::BufReader, path::Path, str::FromStr as _, sync::mpsc, thread, time}; +use std::{fmt, fs::File, io::BufReader, path::Path, sync::mpsc, thread, time}; use eyre::{Result, WrapErr}; use iroha_client::{ client::Client, + crypto::KeyPair, data_model::{ parameter::{default::MAX_TRANSACTIONS_IN_BLOCK, ParametersBuilder}, prelude::*, @@ -12,6 +13,7 @@ use iroha_data_model::events::pipeline::{BlockEventFilter, BlockStatus}; use nonzero_ext::nonzero; use serde::Deserialize; use test_network::*; +use test_samples::ALICE_ID; pub type Tps = f64; @@ -68,6 +70,7 @@ impl Config { config: self, client, name, + signatory: KeyPair::random().into_parts().0, }; unit.ready() }) @@ -136,6 +139,7 @@ struct MeasurerUnit { pub config: Config, pub client: Client, pub name: UnitName, + pub signatory: PublicKey, } type UnitName = u32; @@ -146,15 +150,10 @@ impl MeasurerUnit { /// Submit initial transactions for measurement fn ready(self) -> Result { - let keypair = iroha_client::crypto::KeyPair::random(); - - let account_id = account_id(self.name); - let asset_id = asset_id(self.name); - - let register_me = Register::account(Account::new(account_id, keypair.public_key().clone())); + let register_me = Register::account(Account::new(self.account_id())); self.client.submit_blocking(register_me)?; - let mint_a_rose = Mint::asset_numeric(1_u32, asset_id); + let mint_a_rose = Mint::asset_numeric(1_u32, self.asset_id()); self.client.submit_blocking(mint_a_rose)?; Ok(self) @@ -193,7 +192,7 @@ impl MeasurerUnit { let submitter = self.client.clone(); let interval_us_per_tx = self.config.interval_us_per_tx; let instructions = self.instructions(); - let alice_id = AccountId::from_str("alice@wonderland").expect("Failed to parse account id"); + let alice_id = ALICE_ID.clone(); let mut nonce = nonzero!(1_u32); @@ -231,17 +230,14 @@ impl MeasurerUnit { } fn mint(&self) -> InstructionBox { - Mint::asset_numeric(1_u32, asset_id(self.name)).into() + Mint::asset_numeric(1_u32, self.asset_id()).into() } -} -fn asset_id(account_name: UnitName) -> AssetId { - AssetId::new( - "rose#wonderland".parse().expect("Valid"), - account_id(account_name), - ) -} + fn account_id(&self) -> AccountId { + AccountId::new("wonderland".parse().expect("Valid"), self.signatory.clone()) + } -fn account_id(name: UnitName) -> AccountId { - format!("{name}@wonderland").parse().expect("Valid") + fn asset_id(&self) -> AssetId { + AssetId::new("rose#wonderland".parse().expect("Valid"), self.account_id()) + } } diff --git a/client/examples/million_accounts_genesis.rs b/client/examples/million_accounts_genesis.rs index 5a6b1dc6692..03114c82088 100644 --- a/client/examples/million_accounts_genesis.rs +++ b/client/examples/million_accounts_genesis.rs @@ -2,8 +2,7 @@ use std::{thread, time::Duration}; use iroha::samples::{construct_executor, get_config}; -use iroha_client::data_model::prelude::*; -use iroha_crypto::KeyPair; +use iroha_client::{crypto::KeyPair, data_model::prelude::*}; use iroha_data_model::isi::InstructionBox; use iroha_genesis::{GenesisNetwork, RawGenesisBlock, RawGenesisBlockBuilder}; use iroha_primitives::unique_vec; @@ -16,14 +15,11 @@ use tokio::runtime::Runtime; fn generate_genesis(num_domains: u32) -> RawGenesisBlock { let mut builder = RawGenesisBlockBuilder::default(); - let key_pair = get_key_pair(); + let signatory_alice = get_key_pair(test_network::Signatory::Alice).into_parts().0; for i in 0_u32..num_domains { builder = builder .domain(format!("wonderland-{i}").parse().expect("Valid")) - .account( - format!("Alice-{i}").parse().expect("Valid"), - key_pair.public_key().clone(), - ) + .account(signatory_alice.clone()) .asset( format!("xor-{i}").parse().expect("Valid"), AssetValueType::Numeric(NumericSpec::default()), @@ -45,7 +41,8 @@ fn main_genesis() { let configuration = get_config( &unique_vec![peer.id.clone()], Some(chain_id.clone()), - Some(get_key_pair()), + Some(get_key_pair(test_network::Signatory::Peer)), + Some(get_key_pair(test_network::Signatory::Genesis)), ); let rt = Runtime::test(); let genesis = GenesisNetwork::new( @@ -74,16 +71,9 @@ fn create_million_accounts_directly() { wait_for_genesis_committed(&vec![test_client.clone()], 0); 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( - domain_id.clone(), - format!("bob-{i}").parse().expect("Valid"), - ); + let normal_account_id = AccountId::new(domain_id.clone(), KeyPair::random().into_parts().0); let create_domain: InstructionBox = Register::domain(Domain::new(domain_id)).into(); - let create_account = Register::account(Account::new( - normal_account_id.clone(), - KeyPair::random().into_parts().0, - )) - .into(); + let create_account = Register::account(Account::new(normal_account_id.clone())).into(); if test_client .submit_all([create_domain, create_account]) .is_err() diff --git a/client/examples/register_1000_triggers.rs b/client/examples/register_1000_triggers.rs index 6de1efd77bc..56ab3c01567 100644 --- a/client/examples/register_1000_triggers.rs +++ b/client/examples/register_1000_triggers.rs @@ -8,8 +8,8 @@ use iroha_data_model::trigger::TriggerId; use iroha_genesis::{GenesisNetwork, RawGenesisBlock, RawGenesisBlockBuilder}; use iroha_primitives::unique_vec; use test_network::{ - get_chain_id, wait_for_genesis_committed_with_max_retries, Peer as TestPeer, PeerBuilder, - TestClient, TestRuntime, + get_chain_id, get_key_pair, wait_for_genesis_committed_with_max_retries, Peer as TestPeer, + PeerBuilder, TestClient, TestRuntime, }; use tokio::runtime::Runtime; @@ -55,13 +55,14 @@ fn generate_genesis(num_triggers: u32) -> Result Result<(), Box> { - let mut peer = ::new().expect("Failed to create peer"); + let mut peer: TestPeer = ::new().expect("Failed to create peer"); let chain_id = get_chain_id(); let mut configuration = get_config( &unique_vec![peer.id.clone()], Some(chain_id.clone()), - Some(peer.key_pair.clone()), + Some(get_key_pair(test_network::Signatory::Peer)), + Some(get_key_pair(test_network::Signatory::Genesis)), ); // Increase executor limits for large genesis diff --git a/client/examples/tutorial.rs b/client/examples/tutorial.rs index f4b36283ac6..a5194db6f3d 100644 --- a/client/examples/tutorial.rs +++ b/client/examples/tutorial.rs @@ -75,14 +75,16 @@ fn domain_registration_test(config: Config) -> Result<(), Error> { fn account_definition_test() -> Result<(), Error> { // #region account_definition_comparison - use iroha_client::data_model::prelude::AccountId; + use iroha_client::{crypto::KeyPair, data_model::prelude::AccountId}; - // Create an `iroha_client::data_model::AccountId` instance - // with a DomainId instance and a Domain ID for an account - let longhand_account_id = AccountId::new("white_rabbit".parse()?, "looking_glass".parse()?); - let account_id: AccountId = "white_rabbit@looking_glass" + // Generate a new public key for a new account + let (public_key, _) = KeyPair::random().into_parts(); + // Create an AccountId instance by providing a DomainId instance and the public key + let longhand_account_id = AccountId::new("looking_glass".parse()?, public_key.clone()); + // Create an AccountId instance by parsing the serialized format "signatory@domain" + let account_id: AccountId = format!("{public_key}@looking_glass") .parse() - .expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after"); + .expect("Valid, because before @ is a valid public key and after @ is a valid name i.e. a string with no spaces or forbidden chars"); // Check that two ways to define an account match assert_eq!(account_id, longhand_account_id); @@ -109,19 +111,17 @@ fn account_registration_test(config: Config) -> Result<(), Error> { let iroha_client = Client::new(config); // #region register_account_create - // Create an AccountId instance by providing the account and domain name - let account_id: AccountId = "white_rabbit@looking_glass" - .parse() - .expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after"); - // #endregion register_account_create - - // TODO: consider getting a key from white_rabbit // Generate a new public key for a new account let (public_key, _) = KeyPair::random().into_parts(); + // Create an AccountId instance by parsing the serialized format "signatory@domain" + let account_id: AccountId = format!("{public_key}@looking_glass") + .parse() + .expect("Valid, because before @ is a valid public key and after @ is a valid name i.e. a string with no spaces or forbidden chars"); + // #endregion register_account_create // #region register_account_generate // Generate a new account - let create_account = Register::account(Account::new(account_id, public_key)); + let create_account = Register::account(Account::new(account_id)); // #endregion register_account_generate // #region register_account_prepare_tx @@ -147,6 +147,7 @@ fn asset_registration_test(config: Config) -> Result<(), Error> { use iroha_client::{ client::Client, + crypto::KeyPair, data_model::prelude::{ numeric, AccountId, AssetDefinition, AssetDefinitionId, AssetId, Mint, Register, }, @@ -171,10 +172,12 @@ fn asset_registration_test(config: Config) -> Result<(), Error> { iroha_client.submit(register_time)?; // #endregion register_asset_init_submit - // Create an account using the previously defined asset - let account_id: AccountId = "white_rabbit@looking_glass" + // Generate a new public key for a new account + let (public_key, _) = KeyPair::random().into_parts(); + // Create an AccountId instance by parsing the serialized format "signatory@domain" + let account_id: AccountId = format!("{public_key}@looking_glass") .parse() - .expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after"); + .expect("Valid, because before @ is a valid public key and after @ is a valid name i.e. a string with no spaces or forbidden chars"); // #region register_asset_mint_submit // Create a MintBox using a previous asset and account @@ -205,8 +208,8 @@ fn asset_minting_test(config: Config) -> Result<(), Error> { // #region mint_asset_define_asset_account let roses = AssetDefinitionId::from_str("rose#wonderland") .expect("Valid, because the string contains no whitespace, has a single '#' character and is not empty after"); - let alice: AccountId = "alice@wonderland".parse() - .expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after"); + let alice: AccountId = "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland".parse() + .expect("Valid, because before @ is a valid public key and after @ is a valid name i.e. a string with no spaces or forbidden chars"); // #endregion mint_asset_define_asset_account // Mint the Asset instance @@ -222,11 +225,14 @@ fn asset_minting_test(config: Config) -> Result<(), Error> { // #region mint_asset_mint_alt // Mint the Asset instance (alternate syntax). - // The syntax is `asset_name#asset_domain#account_name@account_domain`, + // The syntax is `asset_name#asset_domain#account_signatory@account_domain`, // or `roses.to_string() + "#" + alice.to_string()`. // The `##` is a short-hand for the rose `which belongs to the same domain as the account // to which it belongs to. - let mint_roses_alt = Mint::asset_numeric(10u32, "rose##alice@wonderland".parse()?); + let alice_roses: AssetId = + "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" + .parse()?; + let mint_roses_alt = Mint::asset_numeric(10u32, alice_roses); // #endregion mint_asset_mint_alt // #region mint_asset_submit_tx_alt @@ -256,8 +262,8 @@ fn asset_burning_test(config: Config) -> Result<(), Error> { // Define the instances of an Asset and Account let roses = AssetDefinitionId::from_str("rose#wonderland") .expect("Valid, because the string contains no whitespace, has a single '#' character and is not empty after"); - let alice: AccountId = "alice@wonderland".parse() - .expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after"); + let alice: AccountId = "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland".parse() + .expect("Valid, because before @ is a valid public key and after @ is a valid name i.e. a string with no spaces or forbidden chars"); // #endregion burn_asset_define_asset_account // #region burn_asset_burn @@ -273,11 +279,14 @@ fn asset_burning_test(config: Config) -> Result<(), Error> { // #region burn_asset_burn_alt // Burn the Asset instance (alternate syntax). - // The syntax is `asset_name#asset_domain#account_name@account_domain`, + // The syntax is `asset_name#asset_domain#account_signatory@account_domain`, // or `roses.to_string() + "#" + alice.to_string()`. // The `##` is a short-hand for the rose `which belongs to the same domain as the account // to which it belongs to. - let burn_roses_alt = Burn::asset_numeric(10u32, "rose##alice@wonderland".parse()?); + let alice_roses: AssetId = + "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" + .parse()?; + let burn_roses_alt = Burn::asset_numeric(10u32, alice_roses); // #endregion burn_asset_burn_alt // #region burn_asset_submit_tx_alt diff --git a/client/src/client.rs b/client/src/client.rs index 2a4eed202d7..b725f9592aa 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -1575,6 +1575,7 @@ mod tests { use std::str::FromStr; use iroha_primitives::small::SmallStr; + use test_samples::gen_account_in; use super::*; use crate::config::{BasicAuth, Config, WebLogin}; @@ -1585,12 +1586,11 @@ mod tests { const ENCRYPTED_CREDENTIALS: &str = "bWFkX2hhdHRlcjppbG92ZXRlYQ=="; fn config_factory() -> Config { + let (account_id, key_pair) = gen_account_in("wonderland"); Config { chain_id: ChainId::from("0"), - key_pair: KeyPair::random(), - account_id: "alice@wonderland" - .parse() - .expect("This account ID should be valid"), + key_pair, + account_id, torii_api_url: "http://127.0.0.1:8080".parse().unwrap(), basic_auth: None, transaction_add_nonce: false, diff --git a/client/src/config.rs b/client/src/config.rs index e93b119a43b..70a8f1bab3a 100644 --- a/client/src/config.rs +++ b/client/src/config.rs @@ -109,9 +109,9 @@ mod tests { password = "ilovetea" [account] - id = "alice@wonderland" - public_key = "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" - private_key = "8026409AC47ABF59B356E0BD7DCBBBB4DEC080E302156A48CA907E47CB6AEA1D32719E7233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" + domain_id = "wonderland" + public_key = "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03" + private_key = "802640CCF31D85E3B32A4BEA59987CE0C78E3B8E2DB93881468AB2435FE45D5C9DCD53CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03" [transaction] time_to_live = 100_000 diff --git a/client/src/config/user.rs b/client/src/config/user.rs index 30a684e5bac..1ebb11e3a9c 100644 --- a/client/src/config/user.rs +++ b/client/src/config/user.rs @@ -8,7 +8,7 @@ pub use boilerplate::*; use eyre::{eyre, Context, Report}; use iroha_config::base::{Emitter, ErrorsCollection}; use iroha_crypto::{KeyPair, PrivateKey, PublicKey}; -use iroha_data_model::{account::AccountId, ChainId}; +use iroha_data_model::prelude::{AccountId, ChainId, DomainId}; use merge::Merge; use serde_with::DeserializeFromStr; use url::Url; @@ -67,7 +67,7 @@ impl Root { basic_auth, account: Account { - id: account_id, + domian_id, public_key, private_key, }, @@ -93,6 +93,8 @@ impl Root { )) } + let account_id = AccountId::new(domian_id, public_key.clone()); + let key_pair = KeyPair::new(public_key, private_key) .wrap_err("failed to construct a key pair") .map_or_else( @@ -121,7 +123,7 @@ impl Root { #[derive(Debug, Clone)] #[allow(missing_docs)] pub struct Account { - pub id: AccountId, + pub domian_id: DomainId, pub public_key: PublicKey, pub private_key: PrivateKey, } diff --git a/client/src/config/user/boilerplate.rs b/client/src/config/user/boilerplate.rs index 500b13afecb..635f9ebb153 100644 --- a/client/src/config/user/boilerplate.rs +++ b/client/src/config/user/boilerplate.rs @@ -9,7 +9,7 @@ use iroha_config::base::{ UserField, }; use iroha_crypto::{PrivateKey, PublicKey}; -use iroha_data_model::{account::AccountId, ChainId}; +use iroha_data_model::{domain::DomainId, ChainId}; use serde::Deserialize; use crate::config::{ @@ -89,7 +89,7 @@ impl UnwrapPartial for RootPartial { #[derive(Debug, Clone, Deserialize, Eq, PartialEq, Default, Merge)] #[serde(deny_unknown_fields, default)] pub struct AccountPartial { - pub id: UserField, + pub domain_id: UserField, pub public_key: UserField, pub private_key: UserField, } @@ -100,8 +100,8 @@ impl UnwrapPartial for AccountPartial { fn unwrap_partial(self) -> UnwrapPartialResult { let mut emitter = Emitter::new(); - if self.id.is_none() { - emitter.emit_missing_field("account.id"); + if self.domain_id.is_none() { + emitter.emit_missing_field("account.domain_id"); } if self.public_key.is_none() { emitter.emit_missing_field("account.public_key"); @@ -113,7 +113,7 @@ impl UnwrapPartial for AccountPartial { emitter.finish()?; Ok(Account { - id: self.id.get().unwrap(), + domian_id: self.domain_id.get().unwrap(), public_key: self.public_key.get().unwrap(), private_key: self.private_key.get().unwrap(), }) diff --git a/client/src/lib.rs b/client/src/lib.rs index fc518a0cf6a..a551c23adc3 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -27,13 +27,14 @@ pub mod samples { /// Get sample client configuration. pub fn get_client_config(chain_id: ChainId, key_pair: KeyPair, torii_api_url: Url) -> Config { + let account_id = format!("{}@wonderland", key_pair.public_key()) + .parse() + .expect("should be valid"); Config { chain_id, key_pair, torii_api_url, - account_id: "alice@wonderland" - .parse() - .expect("This account ID should be valid"), + account_id, basic_auth: None, transaction_ttl: DEFAULT_TRANSACTION_TIME_TO_LIVE, transaction_status_timeout: DEFAULT_TRANSACTION_STATUS_TIMEOUT, diff --git a/client/tests/integration/add_account.rs b/client/tests/integration/add_account.rs deleted file mode 100644 index 58c5e35e3c9..00000000000 --- a/client/tests/integration/add_account.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::thread; - -use eyre::Result; -use iroha_client::{client, data_model::prelude::*}; -use iroha_config::parameters::actual::Root as Config; -use test_network::*; - -use crate::integration::new_account_with_random_public_key; - -#[test] -// This test suite is also covered at the UI level in the iroha_client_cli tests -// in test_register_accounts.py -fn client_add_account_with_name_length_more_than_limit_should_not_commit_transaction() -> Result<()> -{ - let (_rt, _peer, test_client) = ::new().with_port(10_505).start_with_runtime(); - wait_for_genesis_committed(&vec![test_client.clone()], 0); - - let pipeline_time = Config::pipeline_time(); - - let normal_account_id: AccountId = "bob@wonderland".parse().expect("Valid"); - let create_account = Register::account(new_account_with_random_public_key( - normal_account_id.clone(), - )); - test_client.submit(create_account)?; - - let too_long_account_name = "0".repeat(2_usize.pow(14)); - let incorrect_account_id: AccountId = (too_long_account_name + "@wonderland") - .parse() - .expect("Valid"); - let create_account = Register::account(new_account_with_random_public_key( - incorrect_account_id.clone(), - )); - test_client.submit(create_account)?; - - thread::sleep(pipeline_time * 2); - - assert!(test_client - .request(client::account::by_id(normal_account_id)) - .is_ok()); - assert!(test_client - .request(client::account::by_id(incorrect_account_id)) - .is_err()); - - Ok(()) -} diff --git a/client/tests/integration/asset.rs b/client/tests/integration/asset.rs index 34a102afd93..b6ca37c691e 100644 --- a/client/tests/integration/asset.rs +++ b/client/tests/integration/asset.rs @@ -3,7 +3,7 @@ use std::{str::FromStr as _, thread}; use eyre::Result; use iroha_client::{ client::{self, QueryResult}, - crypto::{KeyPair, PublicKey}, + crypto::KeyPair, data_model::prelude::*, }; use iroha_config::parameters::actual::Root as Config; @@ -14,6 +14,7 @@ use iroha_data_model::{ }; use serde_json::json; use test_network::*; +use test_samples::{gen_account_in, ALICE_ID, BOB_ID}; #[test] // This test is also covered at the UI level in the iroha_client_cli tests @@ -23,7 +24,7 @@ fn client_register_asset_should_add_asset_once_but_not_twice() -> Result<()> { wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("test_asset#wonderland").expect("Valid"); let create_asset: InstructionBox = @@ -59,7 +60,7 @@ fn unregister_asset_should_remove_asset_from_account() -> Result<()> { wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("test_asset#wonderland").expect("Valid"); let asset_id = AssetId::new(asset_definition_id.clone(), account_id.clone()); @@ -101,7 +102,7 @@ fn client_add_asset_quantity_to_existing_asset_should_increase_asset_amount() -> wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); @@ -132,7 +133,7 @@ fn client_add_big_asset_quantity_to_existing_asset_should_increase_asset_amount( wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); @@ -163,7 +164,7 @@ fn client_add_asset_with_decimal_should_increase_asset_amount() -> Result<()> { wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let asset_definition = AssetDefinition::numeric(asset_definition_id.clone()); let create_asset = Register::asset_definition(asset_definition); @@ -262,135 +263,95 @@ fn find_rate_and_make_exchange_isi_should_succeed() { let (_rt, _peer, test_client) = ::new().with_port(10_675).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); - let alice_id: AccountId = "alice@wonderland".parse().expect("Valid."); - let seller_id: AccountId = "seller@company".parse().expect("Valid."); - let buyer_id: AccountId = "buyer@company".parse().expect("Valid."); - - let seller_btc: AssetId = "btc#crypto#seller@company".parse().expect("Valid."); - let buyer_eth: AssetId = "eth#crypto#buyer@company".parse().expect("Valid."); - - let seller_keypair = KeyPair::random(); - let buyer_keypair = KeyPair::random(); - - let register_account = |account_id: AccountId, signature: PublicKey| { - Register::account(Account::new(account_id, signature)) - }; + let (dex_id, _dex_keypair) = gen_account_in("exchange"); + let (seller_id, seller_keypair) = gen_account_in("company"); + let (buyer_id, buyer_keypair) = gen_account_in("company"); + let rate: AssetId = format!("btc/eth##{}", &dex_id) + .parse() + .expect("should be valid"); + let seller_btc: AssetId = format!("btc#crypto#{}", &seller_id) + .parse() + .expect("should be valid"); + let buyer_eth: AssetId = format!("eth#crypto#{}", &buyer_id) + .parse() + .expect("should be valid"); + let instructions: [InstructionBox; 12] = [ + register::domain("exchange").into(), + register::domain("company").into(), + register::domain("crypto").into(), + register::account(dex_id.clone()).into(), + register::account(seller_id.clone()).into(), + register::account(buyer_id.clone()).into(), + register::asset_definition_numeric("btc/eth#exchange").into(), + register::asset_definition_numeric("btc#crypto").into(), + register::asset_definition_numeric("eth#crypto").into(), + Mint::asset_numeric(20_u32, rate.clone()).into(), + Mint::asset_numeric(10_u32, seller_btc.clone()).into(), + Mint::asset_numeric(200_u32, buyer_eth.clone()).into(), + ]; + test_client + .submit_all_blocking(instructions) + .expect("transaction should be committed"); - let grant_alice_asset_transfer_permission = |asset_id: AssetId, owner_keypair: KeyPair| { - let allow_alice_to_transfer_asset = Grant::permission( + let alice_id = ALICE_ID.clone(); + let alice_can_transfer_asset = |asset_id: AssetId, owner_key_pair: KeyPair| { + let instruction = Grant::permission( PermissionToken::new( "CanTransferUserAsset".parse().unwrap(), &json!({ "asset_id": asset_id }), ), alice_id.clone(), ); - - let chain_id = ChainId::from("0"); - let grant_asset_transfer_tx = - TransactionBuilder::new(chain_id, asset_id.account_id().clone()) - .with_instructions([allow_alice_to_transfer_asset]) - .sign(&owner_keypair); + let transaction = + TransactionBuilder::new(ChainId::from("0"), asset_id.account_id().clone()) + .with_instructions([instruction]) + .sign(&owner_key_pair); test_client - .submit_transaction_blocking(&grant_asset_transfer_tx) - .expect(&format!( - "Failed to grant permission alice to transfer {asset_id}", - )); + .submit_transaction_blocking(&transaction) + .expect("transaction should be committed"); }; - - let buyer_account_id = account_id_new("buyer", "company"); - let seller_account_id = account_id_new("seller", "company"); - let asset_id = asset_id_new( - "btc2eth_rate", - "exchange", - account_id_new("dex", "exchange"), - ); - let instructions: [InstructionBox; 12] = [ - register::domain("exchange").into(), - register::domain("company").into(), - register::domain("crypto").into(), - register_account(seller_id, seller_keypair.public_key().clone()).into(), - register_account(buyer_id, buyer_keypair.public_key().clone()).into(), - register::account("dex", "exchange").into(), - register::asset_definition("btc", "crypto").into(), - register::asset_definition("eth", "crypto").into(), - register::asset_definition("btc2eth_rate", "exchange").into(), - Mint::asset_numeric( - 200u32, - asset_id_new("eth", "crypto", buyer_account_id.clone()), - ) - .into(), - Mint::asset_numeric( - 20u32, - asset_id_new("btc", "crypto", seller_account_id.clone()), - ) - .into(), - Mint::asset_numeric(20u32, asset_id.clone()).into(), - ]; - test_client - .submit_all_blocking(instructions) - .expect("Failed to prepare accounts."); - - grant_alice_asset_transfer_permission(seller_btc, seller_keypair); - grant_alice_asset_transfer_permission(buyer_eth, buyer_keypair); - - let to_transfer = test_client - .request(FindAssetQuantityById::new(asset_id)) - .expect("Failed to execute query to find asset quantity by id."); + alice_can_transfer_asset(seller_btc.clone(), seller_keypair); + alice_can_transfer_asset(buyer_eth.clone(), buyer_keypair); + + let assert_balance = |asset_id: AssetId, expected: Numeric| { + let got = test_client + .request(FindAssetQuantityById::new(asset_id)) + .expect("query should succeed"); + assert_eq!(got, expected); + }; + // before: seller has $BTC10 and buyer has $ETH200 + assert_balance(seller_btc.clone(), numeric!(10)); + assert_balance(buyer_eth.clone(), numeric!(200)); + + let rate: u32 = test_client + .request(FindAssetQuantityById::new(rate)) + .expect("query should succeed") + .try_into() + .expect("numeric should be u32 originally"); test_client .submit_all_blocking([ - Transfer::asset_numeric( - asset_id_new("btc", "crypto", seller_account_id.clone()), - to_transfer, - buyer_account_id.clone(), - ), - Transfer::asset_numeric( - asset_id_new("eth", "crypto", buyer_account_id), - to_transfer, - seller_account_id, - ), + Transfer::asset_numeric(seller_btc.clone(), 10_u32, buyer_id.clone()), + Transfer::asset_numeric(buyer_eth.clone(), 10_u32 * rate, seller_id.clone()), ]) - .expect("Failed to exchange eth for btc."); - - let expected_seller_eth = numeric!(20); - let expected_buyer_eth = numeric!(180); - let expected_buyer_btc = numeric!(20); - - let eth_quantity = test_client - .request(FindAssetQuantityById::new(asset_id_new( - "eth", - "crypto", - account_id_new("seller", "company"), - ))) - .expect("Failed to execute Iroha Query"); - assert_eq!(expected_seller_eth, eth_quantity); - - // For the btc amount we expect an error, as zero assets are purged from accounts - test_client - .request(FindAssetQuantityById::new(asset_id_new( - "btc", - "crypto", - account_id_new("seller", "company"), - ))) - .expect_err("Query must fail"); + .expect("transaction should be committed"); - let buyer_eth_quantity = test_client - .request(FindAssetQuantityById::new(asset_id_new( - "eth", - "crypto", - account_id_new("buyer", "company"), - ))) - .expect("Failed to execute Iroha Query"); - assert_eq!(expected_buyer_eth, buyer_eth_quantity); - - let buyer_btc_quantity = test_client - .request(FindAssetQuantityById::new(asset_id_new( - "btc", - "crypto", - account_id_new("buyer", "company"), - ))) - .expect("Failed to execute Iroha Query"); - assert_eq!(expected_buyer_btc, buyer_btc_quantity); + let assert_purged = |asset_id: AssetId| { + let _err = test_client + .request(FindAssetQuantityById::new(asset_id)) + .expect_err("query should fail, as zero assets are purged from accounts"); + }; + let seller_eth: AssetId = format!("eth#crypto#{}", &seller_id) + .parse() + .expect("should be valid"); + let buyer_btc: AssetId = format!("btc#crypto#{}", &buyer_id) + .parse() + .expect("should be valid"); + // after: seller has $ETH200 and buyer has $BTC10 + assert_purged(seller_btc); + assert_purged(buyer_eth); + assert_balance(seller_eth, numeric!(200)); + assert_balance(buyer_btc, numeric!(10)); } #[test] @@ -398,8 +359,8 @@ fn transfer_asset_definition() { let (_rt, _peer, test_client) = ::new().with_port(11_060).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); - let alice_id: AccountId = "alice@wonderland".parse().expect("Valid."); - let bob_id: AccountId = "bob@wonderland".parse().expect("Valid."); + let alice_id = ALICE_ID.clone(); + let bob_id = BOB_ID.clone(); let asset_definition_id: AssetDefinitionId = "asset#wonderland".parse().expect("Valid"); test_client @@ -432,8 +393,8 @@ fn fail_if_dont_satisfy_spec() { let (_rt, _peer, test_client) = ::new().with_port(11_125).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); - let alice_id: AccountId = "alice@wonderland".parse().expect("Valid."); - let bob_id: AccountId = "bob@wonderland".parse().expect("Valid."); + let alice_id = ALICE_ID.clone(); + let bob_id = BOB_ID.clone(); let asset_definition_id: AssetDefinitionId = "asset#wonderland".parse().expect("Valid"); let asset_id: AssetId = AssetId::new(asset_definition_id.clone(), alice_id.clone()); // Create asset definition which accepts only integers @@ -490,46 +451,20 @@ fn fail_if_dont_satisfy_spec() { } } -fn account_id_new(account_name: &str, account_domain: &str) -> AccountId { - AccountId::new( - account_domain.parse().expect("Valid"), - account_name.parse().expect("Valid"), - ) -} - -pub fn asset_id_new( - definition_name: &str, - definition_domain: &str, - account_id: AccountId, -) -> AssetId { - AssetId::new( - AssetDefinitionId::new( - definition_domain.parse().expect("Valid"), - definition_name.parse().expect("Valid"), - ), - account_id, - ) -} - mod register { use super::*; - use crate::integration::new_account_with_random_public_key; - pub fn domain(name: &str) -> Register { - Register::domain(Domain::new(DomainId::from_str(name).expect("Valid"))) + pub fn domain(id: &str) -> Register { + Register::domain(Domain::new(id.parse().expect("should parse to DomainId"))) } - pub fn account(account_name: &str, domain_name: &str) -> Register { - Register::account(new_account_with_random_public_key(AccountId::new( - domain_name.parse().expect("Valid"), - account_name.parse().expect("Valid"), - ))) + pub fn account(id: AccountId) -> Register { + Register::account(Account::new(id)) } - pub fn asset_definition(asset_name: &str, domain_name: &str) -> Register { - Register::asset_definition(AssetDefinition::numeric(AssetDefinitionId::new( - domain_name.parse().expect("Valid"), - asset_name.parse().expect("Valid"), - ))) + pub fn asset_definition_numeric(id: &str) -> Register { + Register::asset_definition(AssetDefinition::numeric( + id.parse().expect("should parse to AssetDefinitionId"), + )) } } diff --git a/client/tests/integration/asset_propagation.rs b/client/tests/integration/asset_propagation.rs index 48129d2f3e1..84396976c85 100644 --- a/client/tests/integration/asset_propagation.rs +++ b/client/tests/integration/asset_propagation.rs @@ -3,7 +3,6 @@ use std::{str::FromStr as _, thread}; use eyre::Result; use iroha_client::{ client::{self, QueryResult}, - crypto::KeyPair, data_model::{ parameter::{default::MAX_TRANSACTIONS_IN_BLOCK, ParametersBuilder}, prelude::*, @@ -11,6 +10,7 @@ use iroha_client::{ }; use iroha_config::parameters::actual::Root as Config; use test_network::*; +use test_samples::gen_account_in; #[test] // This test is also covered at the UI level in the iroha_client_cli tests @@ -30,9 +30,8 @@ fn client_add_asset_quantity_to_existing_asset_should_increase_asset_amount_on_a let create_domain: InstructionBox = Register::domain(Domain::new(DomainId::from_str("domain")?)).into(); - let account_id = AccountId::from_str("account@domain")?; - let (public_key, _) = KeyPair::random().into_parts(); - let create_account = Register::account(Account::new(account_id.clone(), public_key)).into(); + let (account_id, _account_keypair) = gen_account_in("domain"); + let create_account = Register::account(Account::new(account_id.clone())).into(); let asset_definition_id = AssetDefinitionId::from_str("xor#domain")?; let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())).into(); diff --git a/client/tests/integration/burn_public_keys.rs b/client/tests/integration/burn_public_keys.rs deleted file mode 100644 index 8d245051aea..00000000000 --- a/client/tests/integration/burn_public_keys.rs +++ /dev/null @@ -1,110 +0,0 @@ -use iroha_client::{ - client::{account, transaction, Client}, - crypto::{HashOf, KeyPair, PublicKey}, - data_model::{isi::Instruction, prelude::*}, -}; -use iroha_data_model::query::TransactionQueryOutput; -use test_network::*; - -fn submit( - client: &Client, - instructions: impl IntoIterator, - submitter: Option<(AccountId, KeyPair)>, -) -> ( - HashOf, - eyre::Result>, -) { - let chain_id = ChainId::from("0"); - - let tx = if let Some((account_id, keypair)) = submitter { - TransactionBuilder::new(chain_id, account_id) - .with_instructions(instructions) - .sign(&keypair) - } else { - let tx = client.build_transaction(instructions, UnlimitedMetadata::default()); - client.sign_transaction(tx) - }; - - (tx.hash(), client.submit_transaction_blocking(&tx)) -} - -fn get(client: &Client, hash: HashOf) -> TransactionQueryOutput { - client.request(transaction::by_hash(hash)).unwrap() -} - -fn account_keys_count(client: &Client, account_id: AccountId) -> usize { - let account = client.request(account::by_id(account_id)).unwrap(); - let signatories = account.signatories(); - signatories.len() -} - -#[test] -fn public_keys_cannot_be_burned_to_nothing() { - const KEYS_COUNT: usize = 3; - let charlie_id: AccountId = "charlie@wonderland".parse().expect("Valid"); - let charlie_keys_count = |client: &Client| account_keys_count(client, charlie_id.clone()); - - let (_rt, _peer, client) = ::new().with_port(10_045).start_with_runtime(); - wait_for_genesis_committed(&vec![client.clone()], 0); - - let charlie_initial_keypair = KeyPair::random(); - let register_charlie = Register::account(Account::new( - charlie_id.clone(), - charlie_initial_keypair.public_key().clone(), - )); - - let (tx_hash, res) = submit(&client, [register_charlie], None); - res.unwrap(); - get(&client, tx_hash); - let mut keys_count = charlie_keys_count(&client); - assert_eq!(keys_count, 1); - - let mint_keys = (0..KEYS_COUNT - 1).map(|_| { - let (public_key, _) = KeyPair::random().into_parts(); - Mint::account_public_key(public_key, charlie_id.clone()) - }); - - let (tx_hash, res) = submit( - &client, - mint_keys, - Some((charlie_id.clone(), charlie_initial_keypair.clone())), - ); - res.unwrap(); - get(&client, tx_hash); - keys_count = charlie_keys_count(&client); - assert_eq!(keys_count, KEYS_COUNT); - - let charlie = client.request(account::by_id(charlie_id.clone())).unwrap(); - let mut keys = charlie.signatories(); - let burn = - |key: PublicKey| InstructionBox::from(Burn::account_public_key(key, charlie_id.clone())); - let burn_keys_leaving_one = keys - .by_ref() - .filter(|pub_key| pub_key != &charlie_initial_keypair.public_key()) - .cloned() - .map(burn); - - let (tx_hash, res) = submit( - &client, - burn_keys_leaving_one, - Some((charlie_id.clone(), charlie_initial_keypair.clone())), - ); - res.unwrap(); - let committed_txn = get(&client, tx_hash); - keys_count = charlie_keys_count(&client); - assert_eq!(keys_count, 1); - assert!(committed_txn.as_ref().error.is_none()); - - let burn_the_last_key = burn(charlie_initial_keypair.public_key().clone()); - - let (tx_hash, res) = submit( - &client, - std::iter::once(burn_the_last_key), - Some((charlie_id.clone(), charlie_initial_keypair)), - ); - assert!(res.is_err()); - let committed_txn = get(&client, tx_hash); - keys_count = charlie_keys_count(&client); - assert_eq!(keys_count, 1); - assert!(committed_txn.as_ref().error.is_some()); -} diff --git a/client/tests/integration/domain_owner_permissions.rs b/client/tests/integration/domain_owner_permissions.rs index af78eff12ac..0e64d8667c0 100644 --- a/client/tests/integration/domain_owner_permissions.rs +++ b/client/tests/integration/domain_owner_permissions.rs @@ -1,13 +1,9 @@ use eyre::Result; -use iroha_client::{ - crypto::KeyPair, - data_model::{account::SignatureCheckCondition, prelude::*}, -}; +use iroha_client::data_model::prelude::*; use iroha_data_model::transaction::error::TransactionRejectionReason; use serde_json::json; use test_network::*; - -use super::new_account_with_random_public_key; +use test_samples::{gen_account_in, ALICE_ID, BOB_ID}; #[test] fn domain_owner_domain_permissions() -> Result<()> { @@ -17,7 +13,7 @@ fn domain_owner_domain_permissions() -> Result<()> { wait_for_genesis_committed(&[test_client.clone()], 0); let kingdom_id: DomainId = "kingdom".parse()?; - let bob_id: AccountId = "bob@kingdom".parse()?; + let (bob_id, bob_keypair) = gen_account_in("kingdom"); let coin_id: AssetDefinitionId = "coin#kingdom".parse()?; let coin = AssetDefinition::numeric(coin_id.clone()); @@ -25,8 +21,7 @@ fn domain_owner_domain_permissions() -> Result<()> { let kingdom = Domain::new(kingdom_id.clone()); test_client.submit_blocking(Register::domain(kingdom))?; - let bob_keypair = KeyPair::random(); - let bob = Account::new(bob_id.clone(), bob_keypair.public_key().clone()); + let bob = Account::new(bob_id.clone()); test_client.submit_blocking(Register::account(bob))?; // Asset definitions can't be registered by "bob@kingdom" by default @@ -88,36 +83,15 @@ fn domain_owner_account_permissions() -> Result<()> { wait_for_genesis_committed(&[test_client.clone()], 0); let kingdom_id: DomainId = "kingdom".parse()?; - let mad_hatter_id: AccountId = "mad_hatter@kingdom".parse()?; + let (mad_hatter_id, _mad_hatter_keypair) = gen_account_in("kingdom"); // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id); test_client.submit_blocking(Register::domain(kingdom))?; - let mad_hatter_keypair = KeyPair::random(); - let mad_hatter = Account::new( - mad_hatter_id.clone(), - mad_hatter_keypair.public_key().clone(), - ); + let mad_hatter = Account::new(mad_hatter_id.clone()); test_client.submit_blocking(Register::account(mad_hatter))?; - // check that "alice@wonderland" as owner of domain can burn and mint public keys for accounts in her domain - let mad_hatter_new_keypair = KeyPair::random(); - test_client.submit_blocking(Mint::account_public_key( - mad_hatter_new_keypair.public_key().clone(), - mad_hatter_id.clone(), - ))?; - test_client.submit_blocking(Burn::account_public_key( - mad_hatter_new_keypair.public_key().clone(), - mad_hatter_id.clone(), - ))?; - - // check that "alice@wonderland" as owner of domain can change signature check condition for accounts in her domain - test_client.submit_blocking(Mint::account_signature_check_condition( - SignatureCheckCondition::AnyAccountSignatureOr(Vec::new().into()), - mad_hatter_id.clone(), - ))?; - // check that "alice@wonderland" as owner of domain can edit metadata of account in her domain let key: Name = "key".parse()?; let value: Name = "value".parse()?; @@ -129,7 +103,7 @@ fn domain_owner_account_permissions() -> Result<()> { test_client.submit_blocking(RemoveKeyValue::account(mad_hatter_id.clone(), key))?; // check that "alice@wonderland" as owner of domain can grant and revoke account related permission tokens in her domain - let bob_id: AccountId = "bob@wonderland".parse()?; + let bob_id = BOB_ID.clone(); let token = PermissionToken::new( "CanUnregisterAccount".parse().unwrap(), &json!({ "account_id": mad_hatter_id }), @@ -150,19 +124,18 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { let chain_id = ChainId::from("0"); let kingdom_id: DomainId = "kingdom".parse()?; - let bob_id: AccountId = "bob@kingdom".parse()?; - let rabbit_id: AccountId = "rabbit@kingdom".parse()?; + let (bob_id, bob_keypair) = gen_account_in("kingdom"); + let (rabbit_id, _rabbit_keypair) = gen_account_in("kingdom"); let coin_id: AssetDefinitionId = "coin#kingdom".parse()?; // "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::random(); - let bob = Account::new(bob_id.clone(), bob_keypair.public_key().clone()); + let bob = Account::new(bob_id.clone()); test_client.submit_blocking(Register::account(bob))?; - let rabbit = new_account_with_random_public_key(rabbit_id.clone()); + let rabbit = Account::new(rabbit_id.clone()); test_client.submit_blocking(Register::account(rabbit))?; // Grant permission to register asset definitions to "bob@kingdom" @@ -181,7 +154,7 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { // check that "alice@wonderland" as owner of domain can transfer asset definitions in her domain test_client.submit_blocking(Transfer::asset_definition( - bob_id, + bob_id.clone(), coin_id.clone(), rabbit_id, ))?; @@ -197,7 +170,6 @@ fn domain_owner_asset_definition_permissions() -> Result<()> { test_client.submit_blocking(RemoveKeyValue::asset_definition(coin_id.clone(), key))?; // check that "alice@wonderland" as owner of domain can grant and revoke asset definition related permission tokens in her domain - let bob_id: AccountId = "bob@wonderland".parse()?; let token = PermissionToken::new( "CanUnregisterAssetDefinition".parse().unwrap(), &json!({ "asset_definition_id": coin_id }), @@ -218,9 +190,9 @@ fn domain_owner_asset_permissions() -> Result<()> { let (_rt, _peer, test_client) = ::new().with_port(11_090).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); - let alice_id: AccountId = "alice@wonderland".parse()?; + let alice_id = ALICE_ID.clone(); let kingdom_id: DomainId = "kingdom".parse()?; - let bob_id: AccountId = "bob@kingdom".parse()?; + let (bob_id, bob_keypair) = gen_account_in("kingdom"); let coin_id: AssetDefinitionId = "coin#kingdom".parse()?; let store_id: AssetDefinitionId = "store#kingdom".parse()?; @@ -228,8 +200,7 @@ fn domain_owner_asset_permissions() -> Result<()> { let kingdom = Domain::new(kingdom_id.clone()); test_client.submit_blocking(Register::domain(kingdom))?; - let bob_keypair = KeyPair::random(); - let bob = Account::new(bob_id.clone(), bob_keypair.public_key().clone()); + let bob = Account::new(bob_id.clone()); test_client.submit_blocking(Register::account(bob))?; // Grant permission to register asset definitions to "bob@kingdom" @@ -264,12 +235,11 @@ fn domain_owner_asset_permissions() -> Result<()> { // check that "alice@wonderland" as owner of domain can edit metadata of store asset in her domain let key: Name = "key".parse()?; let value: Name = "value".parse()?; - let bob_store_id = AssetId::new(store_id, bob_id); + let bob_store_id = AssetId::new(store_id, bob_id.clone()); test_client.submit_blocking(SetKeyValue::asset(bob_store_id.clone(), key.clone(), value))?; test_client.submit_blocking(RemoveKeyValue::asset(bob_store_id.clone(), key))?; // check that "alice@wonderland" as owner of domain can grant and revoke asset related permission tokens in her domain - let bob_id: AccountId = "bob@wonderland".parse()?; let token = PermissionToken::new( "CanUnregisterUserAsset".parse().unwrap(), &json!({ "asset_id": bob_store_id }), @@ -285,16 +255,15 @@ fn domain_owner_trigger_permissions() -> Result<()> { let (_rt, _peer, test_client) = ::new().with_port(11_095).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); - let alice_id: AccountId = "alice@wonderland".parse()?; + let alice_id = ALICE_ID.clone(); let kingdom_id: DomainId = "kingdom".parse()?; - let bob_id: AccountId = "bob@kingdom".parse()?; + let (bob_id, _bob_keypair) = gen_account_in("kingdom"); // "alice@wonderland" is owner of "kingdom" domain let kingdom = Domain::new(kingdom_id); test_client.submit_blocking(Register::domain(kingdom))?; - let bob_keypair = KeyPair::random(); - let bob = Account::new(bob_id.clone(), bob_keypair.public_key().clone()); + let bob = Account::new(bob_id.clone()); test_client.submit_blocking(Register::account(bob))?; let asset_definition_id = "rose#wonderland".parse()?; @@ -307,7 +276,7 @@ fn domain_owner_trigger_permissions() -> Result<()> { Action::new( trigger_instructions, Repeats::from(2_u32), - bob_id, + bob_id.clone(), ExecuteTriggerEventFilter::new().for_trigger(trigger_id.clone()), ), )); @@ -322,7 +291,6 @@ fn domain_owner_trigger_permissions() -> Result<()> { let _result = test_client.submit_blocking(execute_trigger)?; // check that "alice@wonderland" as owner of domain can grant and revoke trigger related permission tokens in her domain - let bob_id: AccountId = "bob@wonderland".parse()?; let token = PermissionToken::new( "CanUnregisterUserTrigger".parse().unwrap(), &json!({ "trigger_id": trigger_id }), @@ -342,16 +310,15 @@ fn domain_owner_transfer() -> Result<()> { let (_rt, _peer, test_client) = ::new().with_port(11_100).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); - let alice_id: AccountId = "alice@wonderland".parse()?; + let alice_id = ALICE_ID.clone(); let kingdom_id: DomainId = "kingdom".parse()?; - let bob_id: AccountId = "bob@kingdom".parse()?; + let (bob_id, _bob_keypair) = gen_account_in("kingdom"); // "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::random(); - let bob = Account::new(bob_id.clone(), bob_keypair.public_key().clone()); + let bob = Account::new(bob_id.clone()); test_client.submit_blocking(Register::account(bob))?; let domain = test_client.request(FindDomainById::new(kingdom_id.clone()))?; @@ -365,8 +332,8 @@ fn domain_owner_transfer() -> Result<()> { )) .expect("Failed to submit transaction"); - let asset_definition = test_client.request(FindDomainById::new(kingdom_id))?; - assert_eq!(asset_definition.owned_by(), &bob_id); + let domain = test_client.request(FindDomainById::new(kingdom_id))?; + assert_eq!(domain.owned_by(), &bob_id); Ok(()) } diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index d77e303c9c9..1c6fdcfe0b8 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -5,6 +5,7 @@ use iroha_client::data_model::{prelude::*, transaction::WasmSmartContract}; use parity_scale_codec::Encode as _; use serde_json::json; use test_network::*; +use test_samples::{ALICE_ID, BOB_ID}; /// Return string containing exported memory, dummy allocator, and /// host function imports which you can embed into your wasm module. @@ -196,7 +197,7 @@ fn produce_multiple_events() -> Result<()> { init_receiver.recv()?; // Registering role - let alice_id = AccountId::from_str("alice@wonderland")?; + let alice_id = ALICE_ID.clone(); let role_id = RoleId::from_str("TEST_ROLE")?; let token_1 = PermissionToken::new( "CanRemoveKeyValueInAccount".parse()?, @@ -213,7 +214,7 @@ fn produce_multiple_events() -> Result<()> { client.submit_all_blocking(instructions)?; // Grants role to Bob - let bob_id = AccountId::from_str("bob@wonderland")?; + let bob_id = BOB_ID.clone(); let grant_role = Grant::role(role_id.clone(), bob_id.clone()); client.submit_blocking(grant_role)?; diff --git a/client/tests/integration/events/notification.rs b/client/tests/integration/events/notification.rs index c060d1e1e64..093fd213bc3 100644 --- a/client/tests/integration/events/notification.rs +++ b/client/tests/integration/events/notification.rs @@ -3,6 +3,7 @@ use std::{str::FromStr as _, sync::mpsc, thread, time::Duration}; use eyre::{eyre, Result, WrapErr}; use iroha_client::data_model::prelude::*; use test_network::*; +use test_samples::ALICE_ID; #[test] fn trigger_completion_success_should_produce_event() -> Result<()> { @@ -10,7 +11,7 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id: AccountId = "alice@wonderland".parse()?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id); let trigger_id = TriggerId::from_str("mint_rose")?; @@ -55,7 +56,7 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { let (_rt, _peer, test_client) = ::new().with_port(11_055).start_with_runtime(); wait_for_genesis_committed(&vec![test_client.clone()], 0); - let account_id: AccountId = "alice@wonderland".parse()?; + let account_id = ALICE_ID.clone(); let trigger_id = TriggerId::from_str("fail_box")?; let instruction = Fail::new("Fail box".to_owned()); diff --git a/client/tests/integration/extra_functional/multiple_blocks_created.rs b/client/tests/integration/extra_functional/multiple_blocks_created.rs index ee229fa1dfd..0c96b849824 100644 --- a/client/tests/integration/extra_functional/multiple_blocks_created.rs +++ b/client/tests/integration/extra_functional/multiple_blocks_created.rs @@ -3,7 +3,6 @@ use std::thread; use eyre::Result; use iroha_client::{ client::{self, Client, QueryResult}, - crypto::KeyPair, data_model::{ parameter::{default::MAX_TRANSACTIONS_IN_BLOCK, ParametersBuilder}, prelude::*, @@ -11,6 +10,7 @@ use iroha_client::{ }; use iroha_config::parameters::actual::Root as Config; use test_network::*; +use test_samples::gen_account_in; const N_BLOCKS: usize = 510; @@ -29,9 +29,8 @@ fn long_multiple_blocks_created() -> Result<()> { )?; let create_domain: InstructionBox = Register::domain(Domain::new("domain".parse()?)).into(); - let account_id: AccountId = "account@domain".parse()?; - let (public_key, _) = KeyPair::random().into_parts(); - let create_account = Register::account(Account::new(account_id.clone(), public_key)).into(); + let (account_id, _account_keypair) = gen_account_in("domain"); + let create_account = Register::account(Account::new(account_id.clone())).into(); let asset_definition_id: AssetDefinitionId = "xor#domain".parse()?; let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())).into(); diff --git a/client/tests/integration/extra_functional/offline_peers.rs b/client/tests/integration/extra_functional/offline_peers.rs index 988b0271acb..b6455eed100 100644 --- a/client/tests/integration/extra_functional/offline_peers.rs +++ b/client/tests/integration/extra_functional/offline_peers.rs @@ -1,15 +1,16 @@ use eyre::Result; use iroha_client::{ client::{self, Client, QueryResult}, + crypto::KeyPair, data_model::{ peer::{Peer as DataModelPeer, PeerId}, prelude::*, }, }; use iroha_config::parameters::actual::Root as Config; -use iroha_crypto::KeyPair; use iroha_primitives::addr::socket_addr; use test_network::*; +use test_samples::ALICE_ID; use tokio::runtime::Runtime; #[test] @@ -25,7 +26,7 @@ fn genesis_block_is_committed_with_some_offline_peers() -> Result<()> { wait_for_genesis_committed(&network.clients(), 1); //When - let alice_id: AccountId = "alice@wonderland".parse()?; + let alice_id = ALICE_ID.clone(); let roses = "rose#wonderland".parse()?; let alice_has_roses = numeric!(13); diff --git a/client/tests/integration/extra_functional/restart_peer.rs b/client/tests/integration/extra_functional/restart_peer.rs index 3172e6d4492..5b1995ad2d2 100644 --- a/client/tests/integration/extra_functional/restart_peer.rs +++ b/client/tests/integration/extra_functional/restart_peer.rs @@ -8,11 +8,12 @@ use iroha_client::{ use iroha_config::parameters::actual::Root as Config; use rand::{seq::SliceRandom, thread_rng, Rng}; use test_network::*; +use test_samples::ALICE_ID; use tokio::runtime::Runtime; #[test] fn restarted_peer_should_have_the_same_asset_amount() -> Result<()> { - let account_id = AccountId::from_str("alice@wonderland").unwrap(); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").unwrap(); let quantity = numeric!(200); diff --git a/client/tests/integration/extra_functional/unregister_peer.rs b/client/tests/integration/extra_functional/unregister_peer.rs index f653e07890f..5742025cc01 100644 --- a/client/tests/integration/extra_functional/unregister_peer.rs +++ b/client/tests/integration/extra_functional/unregister_peer.rs @@ -3,7 +3,6 @@ use std::thread; use eyre::Result; use iroha_client::{ client::{self, QueryResult}, - crypto::KeyPair, data_model::{ parameter::{default::MAX_TRANSACTIONS_IN_BLOCK, ParametersBuilder}, prelude::*, @@ -11,6 +10,7 @@ use iroha_client::{ }; use iroha_config::parameters::actual::Root as Config; use test_network::*; +use test_samples::gen_account_in; // Note the test is marked as `unstable`, not the network. #[ignore = "ignore, more in #2851"] @@ -121,9 +121,8 @@ fn init() -> Result<( .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? .into_set_parameters(); let create_domain = Register::domain(Domain::new("domain".parse()?)); - let account_id: AccountId = "account@domain".parse()?; - let (public_key, _) = KeyPair::random().into_parts(); - let create_account = Register::account(Account::new(account_id.clone(), public_key)); + let (account_id, _account_keypair) = gen_account_in("domain"); + let create_account = Register::account(Account::new(account_id.clone())); let asset_definition_id: AssetDefinitionId = "xor#domain".parse()?; let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); diff --git a/client/tests/integration/extra_functional/unstable_network.rs b/client/tests/integration/extra_functional/unstable_network.rs index 836f263f45a..52b2b9ad851 100644 --- a/client/tests/integration/extra_functional/unstable_network.rs +++ b/client/tests/integration/extra_functional/unstable_network.rs @@ -8,6 +8,7 @@ use iroha_client::{ use iroha_config::parameters::actual::Root as Config; use rand::seq::SliceRandom; use test_network::*; +use test_samples::ALICE_ID; use tokio::runtime::Runtime; const MAX_TRANSACTIONS_IN_BLOCK: u32 = 5; @@ -75,7 +76,7 @@ fn unstable_network( let pipeline_time = Config::pipeline_time(); - let account_id: AccountId = "alice@wonderland".parse().expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id: AssetDefinitionId = "camomile#wonderland".parse().expect("Valid"); let register_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); diff --git a/client/tests/integration/mod.rs b/client/tests/integration/mod.rs index 98b17659895..37299969665 100644 --- a/client/tests/integration/mod.rs +++ b/client/tests/integration/mod.rs @@ -1,16 +1,9 @@ -use iroha_crypto::KeyPair; -use iroha_data_model::account::{Account, AccountId, NewAccount}; - -mod add_account; mod add_domain; mod asset; mod asset_propagation; -mod burn_public_keys; mod domain_owner_permissions; mod events; mod extra_functional; -mod multisignature_account; -mod multisignature_transaction; mod non_mintable; mod pagination; mod permissions; @@ -25,7 +18,3 @@ mod tx_chain_id; mod tx_history; mod tx_rollback; mod upgrade; - -fn new_account_with_random_public_key(account_id: AccountId) -> NewAccount { - Account::new(account_id, KeyPair::random().into_parts().0) -} diff --git a/client/tests/integration/multisignature_account.rs b/client/tests/integration/multisignature_account.rs deleted file mode 100644 index bdb290f0bc4..00000000000 --- a/client/tests/integration/multisignature_account.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::thread; - -use eyre::Result; -use iroha_client::{ - client::{self, Client, QueryResult}, - crypto::KeyPair, - data_model::prelude::*, -}; -use iroha_config::parameters::actual::Root as Config; -use test_network::*; - -#[test] -fn transaction_signed_by_new_signatory_of_account_should_pass() -> Result<()> { - let (_rt, peer, client) = ::new().with_port(10_605).start_with_runtime(); - wait_for_genesis_committed(&[client.clone()], 0); - let pipeline_time = Config::pipeline_time(); - - // Given - let account_id: AccountId = "alice@wonderland".parse().expect("Valid"); - let asset_definition_id: AssetDefinitionId = "xor#wonderland".parse().expect("Valid"); - let create_asset = - Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); - let key_pair = KeyPair::random(); - let add_signatory = Mint::account_public_key(key_pair.public_key().clone(), account_id.clone()); - - let instructions: [InstructionBox; 2] = [create_asset.into(), add_signatory.into()]; - client.submit_all(instructions)?; - thread::sleep(pipeline_time * 2); - //When - let quantity = numeric!(200); - let mint_asset = Mint::asset_numeric( - quantity, - AssetId::new(asset_definition_id.clone(), account_id.clone()), - ); - Client::test_with_key(&peer.api_address, key_pair).submit_till( - mint_asset, - client::asset::by_account_id(account_id), - |result| { - let assets = result.collect::>>().expect("Valid"); - - assets.iter().any(|asset| { - asset.id().definition_id == asset_definition_id - && *asset.value() == AssetValue::Numeric(quantity) - }) - }, - )?; - Ok(()) -} diff --git a/client/tests/integration/multisignature_transaction.rs b/client/tests/integration/multisignature_transaction.rs deleted file mode 100644 index d319c4178f7..00000000000 --- a/client/tests/integration/multisignature_transaction.rs +++ /dev/null @@ -1,101 +0,0 @@ -use std::{str::FromStr as _, thread}; - -use eyre::Result; -use iroha_client::{ - client, - client::{Client, QueryResult}, - config::Config as ClientConfig, - crypto::KeyPair, - data_model::{ - parameter::{default::MAX_TRANSACTIONS_IN_BLOCK, ParametersBuilder}, - prelude::*, - }, -}; -use iroha_config::parameters::actual::Root as Config; -use test_network::*; - -#[allow(clippy::too_many_lines)] -#[test] -fn multisignature_transactions_should_be_accepted_after_fully_signed() -> Result<()> { - let (_rt, network, client) = Network::start_test_with_runtime(4, Some(10_945)); - wait_for_genesis_committed(&network.clients(), 0); - let pipeline_time = Config::pipeline_time(); - - client.submit_all_blocking( - ParametersBuilder::new() - .add_parameter(MAX_TRANSACTIONS_IN_BLOCK, 1u32)? - .into_set_parameters(), - )?; - - let alice_id = AccountId::from_str("alice@wonderland")?; - let alice_key_pair = get_key_pair(); - let key_pair_2 = KeyPair::random(); - let asset_definition_id = AssetDefinitionId::from_str("camomile#wonderland")?; - let create_asset = - Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); - let set_signature_condition = Mint::account_signature_check_condition( - SignatureCheckCondition::AllAccountSignaturesAnd( - vec![key_pair_2.public_key().clone()].into(), - ), - alice_id.clone(), - ); - - let mut client_config = ClientConfig::test(&network.genesis.api_address); - let client = Client::new(client_config.clone()); - let instructions: [InstructionBox; 2] = [create_asset.into(), set_signature_condition.into()]; - client.submit_all_blocking(instructions)?; - - //When - let quantity = numeric!(200); - let asset_id = AssetId::new(asset_definition_id, alice_id.clone()); - let mint_asset = Mint::asset_numeric(quantity, asset_id.clone()); - - client_config.account_id = alice_id.clone(); - client_config.key_pair = alice_key_pair; - let client = Client::new(client_config.clone()); - let instructions = [mint_asset.clone()]; - let transaction = client.build_transaction(instructions, UnlimitedMetadata::new()); - // The tx signed by the first account - let _ = client - .submit_transaction(&client.sign_transaction(transaction.clone())) - .expect_err("Transaction should not be added into the queue"); - - thread::sleep(pipeline_time); - - //Then - client_config.torii_api_url = format!( - "http://{}", - &network.peers.values().last().unwrap().api_address, - ) - .parse() - .unwrap(); - let client_1 = Client::new(client_config.clone()); - let request = client::asset::by_account_id(alice_id); - let assets = client_1 - .request(request.clone())? - .collect::>>()?; - assert_eq!( - assets.len(), - 2, // Alice has roses and cabbage from Genesis, but doesn't yet have camomile - "Multisignature transaction was committed before all required signatures were added" - ); - - client_config.key_pair = key_pair_2; - let client_2 = Client::new(client_config); - // The tx signed by the second account - client_2.submit_transaction(&client_2.sign_transaction(transaction))?; - - thread::sleep(pipeline_time); - - let assets = client_1 - .request(request)? - .collect::>>()?; - assert!(!assets.is_empty()); - let camomile_asset = assets - .iter() - .find(|asset| *asset.id() == asset_id) - .expect("Failed to find expected asset"); - assert_eq!(AssetValue::Numeric(quantity), *camomile_asset.value()); - - Ok(()) -} diff --git a/client/tests/integration/non_mintable.rs b/client/tests/integration/non_mintable.rs index e9652f29390..301ecb93b81 100644 --- a/client/tests/integration/non_mintable.rs +++ b/client/tests/integration/non_mintable.rs @@ -7,6 +7,7 @@ use iroha_client::{ }; use iroha_data_model::isi::InstructionBox; use test_network::*; +use test_samples::ALICE_ID; #[test] fn non_mintable_asset_can_be_minted_once_but_not_twice() -> Result<()> { @@ -14,7 +15,7 @@ fn non_mintable_asset_can_be_minted_once_but_not_twice() -> Result<()> { wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset = Register::asset_definition( AssetDefinition::numeric(asset_definition_id.clone()).mintable_once(), @@ -62,7 +63,7 @@ fn non_mintable_asset_cannot_be_minted_if_registered_with_non_zero_value() -> Re wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset: InstructionBox = Register::asset_definition( AssetDefinition::numeric(asset_definition_id.clone()).mintable_once(), @@ -99,7 +100,7 @@ fn non_mintable_asset_can_be_minted_if_registered_with_zero_value() -> Result<() wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset = Register::asset_definition( AssetDefinition::numeric(asset_definition_id.clone()).mintable_once(), diff --git a/client/tests/integration/pagination.rs b/client/tests/integration/pagination.rs index c8b4360ed28..176e3726e2e 100644 --- a/client/tests/integration/pagination.rs +++ b/client/tests/integration/pagination.rs @@ -16,12 +16,12 @@ fn limits_should_work() -> Result<()> { let vec = &client .build_query(asset::all_definitions()) .with_pagination(Pagination { - limit: Some(nonzero!(5_u32)), - start: Some(nonzero!(5_u64)), + limit: Some(nonzero!(7_u32)), + start: Some(nonzero!(1_u64)), }) .execute()? .collect::>>()?; - assert_eq!(vec.len(), 5); + assert_eq!(vec.len(), 7); Ok(()) } @@ -35,17 +35,18 @@ fn fetch_size_should_work() -> Result<()> { let iter = client .build_query(asset::all_definitions()) .with_pagination(Pagination { - limit: Some(nonzero!(20_u32)), - start: None, + limit: Some(nonzero!(7_u32)), + start: Some(nonzero!(1_u64)), }) - .with_fetch_size(FetchSize::new(Some(nonzero!(12_u32)))) + .with_fetch_size(FetchSize::new(Some(nonzero!(3_u32)))) .execute()?; - assert_eq!(iter.batch_len(), 12); + assert_eq!(iter.batch_len(), 3); Ok(()) } fn register_assets(client: &Client) -> Result<()> { - let register: Vec = ('a'..='z') + // FIXME transaction is rejected for more than a certain number of instructions + let register: Vec = ('a'..='j') .map(|c| c.to_string()) .map(|name| (name + "#wonderland").parse().expect("Valid")) .map(|asset_definition_id| { diff --git a/client/tests/integration/permissions.rs b/client/tests/integration/permissions.rs index 16a4c85140a..475066db77d 100644 --- a/client/tests/integration/permissions.rs +++ b/client/tests/integration/permissions.rs @@ -12,6 +12,7 @@ use iroha_data_model::{ use iroha_genesis::GenesisNetwork; use serde_json::json; use test_network::{PeerBuilder, *}; +use test_samples::{gen_account_in, ALICE_ID, BOB_ID}; #[test] fn genesis_transactions_are_validated() { @@ -22,7 +23,7 @@ fn genesis_transactions_are_validated() { let genesis = GenesisNetwork::test_with_instructions([Grant::permission( PermissionToken::new("InvalidToken".parse().unwrap(), &json!(null)), - AccountId::from_str("alice@wonderland").unwrap(), + ALICE_ID.clone(), ) .into()]); @@ -71,9 +72,9 @@ fn permissions_disallow_asset_transfer() { wait_for_genesis_committed(&[iroha_client.clone()], 0); // Given - let alice_id = "alice@wonderland".parse().expect("Valid"); - let bob_id: AccountId = "bob@wonderland".parse().expect("Valid"); - let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); + let alice_id = ALICE_ID.clone(); + let bob_id = BOB_ID.clone(); + let (mouse_id, _mouse_keypair) = gen_account_in("wonderland"); let asset_definition_id: AssetDefinitionId = "xor#wonderland".parse().expect("Valid"); let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); @@ -124,9 +125,9 @@ fn permissions_disallow_asset_burn() { let (_rt, _peer, iroha_client) = ::new().with_port(10_735).start_with_runtime(); - let alice_id = "alice@wonderland".parse().expect("Valid"); - let bob_id: AccountId = "bob@wonderland".parse().expect("Valid"); - let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); + let alice_id = ALICE_ID.clone(); + let bob_id = BOB_ID.clone(); + let (mouse_id, _mouse_keypair) = gen_account_in("wonderland"); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").expect("Valid"); let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); @@ -197,14 +198,13 @@ 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@outfit".parse().expect("Valid"); - let mouse_keypair = KeyPair::random(); + let alice_id = ALICE_ID.clone(); + let (mouse_id, mouse_keypair) = gen_account_in("outfit"); // 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()); + let new_mouse_account = Account::new(mouse_id.clone()); client .submit_all_blocking([ InstructionBox::from(create_outfit_domain), @@ -296,15 +296,14 @@ fn stored_vs_granted_token_payload() -> Result<()> { wait_for_genesis_committed(&[iroha_client.clone()], 0); // Given - let alice_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let alice_id = ALICE_ID.clone(); // Registering mouse and asset definition let asset_definition_id: AssetDefinitionId = "xor#wonderland".parse().expect("Valid"); let create_asset = Register::asset_definition(AssetDefinition::store(asset_definition_id.clone())); - let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); - let mouse_keypair = KeyPair::random(); - let new_mouse_account = Account::new(mouse_id.clone(), mouse_keypair.public_key().clone()); + let (mouse_id, mouse_keypair) = gen_account_in("wonderland"); + let new_mouse_account = Account::new(mouse_id.clone()); let instructions: [InstructionBox; 2] = [ Register::account(new_mouse_account).into(), create_asset.into(), @@ -319,7 +318,7 @@ fn stored_vs_granted_token_payload() -> Result<()> { PermissionToken::from_str_unchecked( "CanSetKeyValueInUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form - "{ \"asset_id\" : \"xor#wonderland#mouse@wonderland\" }", + &*format!(r###"{{ "asset_id" : "xor#wonderland#{mouse_id}" }}"###), ), alice_id, ); @@ -347,13 +346,13 @@ fn permission_tokens_are_unified() { wait_for_genesis_committed(&[iroha_client.clone()], 0); // Given - let alice_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let alice_id = ALICE_ID.clone(); let allow_alice_to_transfer_rose_1 = Grant::permission( PermissionToken::from_str_unchecked( "CanTransferUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form - "{ \"asset_id\" : \"rose#wonderland#alice@wonderland\" }", + &*format!(r###"{{ "asset_id" : "rose#wonderland#{alice_id}" }}"###), ), alice_id.clone(), ); @@ -362,7 +361,7 @@ fn permission_tokens_are_unified() { PermissionToken::from_str_unchecked( "CanTransferUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form - "{ \"asset_id\" : \"rose##alice@wonderland\" }", + &*format!(r###"{{ "asset_id" : "rose##{alice_id}" }}"###), ), alice_id, ); @@ -381,7 +380,7 @@ fn associated_permission_tokens_removed_on_unregister() { let (_rt, _peer, iroha_client) = ::new().with_port(11_240).start_with_runtime(); wait_for_genesis_committed(&[iroha_client.clone()], 0); - let bob_id: AccountId = "bob@wonderland".parse().expect("Valid"); + let bob_id = BOB_ID.clone(); let kingdom_id: DomainId = "kingdom".parse().expect("Valid"); let kingdom = Domain::new(kingdom_id.clone()); diff --git a/client/tests/integration/queries/account.rs b/client/tests/integration/queries/account.rs index d8137dbc704..eb047c732cc 100644 --- a/client/tests/integration/queries/account.rs +++ b/client/tests/integration/queries/account.rs @@ -6,8 +6,7 @@ use iroha_client::{ data_model::prelude::*, }; use test_network::*; - -use crate::integration::new_account_with_random_public_key; +use test_samples::{gen_account_in, ALICE_ID}; #[test] fn find_accounts_with_asset() -> Result<()> { @@ -30,11 +29,11 @@ fn find_accounts_with_asset() -> Result<()> { )); let accounts: [AccountId; 5] = [ - "alice@wonderland".parse().expect("Valid"), - "mad_hatter@wonderland".parse().expect("Valid"), - "cheshire_cat@wonderland".parse().expect("Valid"), - "caterpillar@wonderland".parse().expect("Valid"), - "white_rabbit@wonderland".parse().expect("Valid"), + ALICE_ID.clone(), + gen_account_in("wonderland").0, + gen_account_in("wonderland").0, + gen_account_in("wonderland").0, + gen_account_in("wonderland").0, ]; // Registering accounts @@ -42,7 +41,7 @@ fn find_accounts_with_asset() -> Result<()> { .iter() .skip(1) // Alice has already been registered in genesis .cloned() - .map(|account_id| Register::account(new_account_with_random_public_key(account_id))) + .map(|account_id| Register::account(Account::new(account_id))) .collect::>(); test_client.submit_all_blocking(register_accounts)?; diff --git a/client/tests/integration/queries/asset.rs b/client/tests/integration/queries/asset.rs index 5ef6115078c..68ce747732f 100644 --- a/client/tests/integration/queries/asset.rs +++ b/client/tests/integration/queries/asset.rs @@ -1,7 +1,6 @@ use eyre::Result; use iroha_client::{ client::{Client, ClientQueryError}, - crypto::KeyPair, data_model::{ asset::AssetValue, isi::Instruction, @@ -10,6 +9,7 @@ use iroha_client::{ }, }; use test_network::*; +use test_samples::{gen_account_in, ALICE_ID}; #[test] #[allow(clippy::too_many_lines)] @@ -23,24 +23,19 @@ fn find_asset_total_quantity() -> Result<()> { test_client.submit_blocking(Register::domain(domain))?; let accounts: [AccountId; 5] = [ - "alice@wonderland".parse()?, - "mad_hatter@wonderland".parse()?, - "cheshire_cat@wonderland".parse()?, - "caterpillar@wonderland".parse()?, - "white_rabbit@looking_glass".parse()?, + ALICE_ID.clone(), + gen_account_in("wonderland").0, + gen_account_in("wonderland").0, + gen_account_in("wonderland").0, + gen_account_in("looking_glass").0, ]; - let keys = core::iter::repeat_with(KeyPair::random) - .take(accounts.len() - 1) - .collect::>(); - // Registering accounts let register_accounts = accounts .iter() .skip(1) // Alice has already been registered in genesis .cloned() - .zip(keys.iter().map(KeyPair::public_key).cloned()) - .map(|(account_id, public_key)| Register::account(Account::new(account_id, public_key))) + .map(|account_id| Register::account(Account::new(account_id))) .collect::>(); test_client.submit_all_blocking(register_accounts)?; diff --git a/client/tests/integration/queries/query_errors.rs b/client/tests/integration/queries/query_errors.rs index 9a27cb7740c..5d8194fc043 100644 --- a/client/tests/integration/queries/query_errors.rs +++ b/client/tests/integration/queries/query_errors.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use iroha_client::{ client::{self, ClientQueryError}, data_model::{ @@ -7,6 +5,7 @@ use iroha_client::{ query::error::{FindError, QueryExecutionFail}, }, }; +use test_samples::gen_account_in; #[test] fn non_existent_account_is_specific_error() { @@ -16,9 +15,7 @@ fn non_existent_account_is_specific_error() { // we cannot wait for genesis committment let err = client - .request(client::account::by_id( - AccountId::from_str("john_doe@regalia").unwrap(), - )) + .request(client::account::by_id(gen_account_in("regalia").0)) .expect_err("Should error"); match err { diff --git a/client/tests/integration/queries/role.rs b/client/tests/integration/queries/role.rs index d437b6f6926..76de3ef1681 100644 --- a/client/tests/integration/queries/role.rs +++ b/client/tests/integration/queries/role.rs @@ -7,6 +7,7 @@ use iroha_client::{ }; use serde_json::json; use test_network::*; +use test_samples::ALICE_ID; fn create_role_ids() -> [RoleId; 5] { [ @@ -123,7 +124,7 @@ fn find_roles_by_account_id() -> Result<()> { wait_for_genesis_committed(&[test_client.clone()], 0); let role_ids = create_role_ids(); - let alice_id: AccountId = "alice@wonderland".parse().expect("Valid"); + let alice_id = ALICE_ID.clone(); // Registering roles let register_roles = role_ids diff --git a/client/tests/integration/roles.rs b/client/tests/integration/roles.rs index 3a3bcd7aff6..5199da7d77f 100644 --- a/client/tests/integration/roles.rs +++ b/client/tests/integration/roles.rs @@ -3,14 +3,12 @@ use std::str::FromStr as _; use eyre::Result; use iroha_client::{ client::{self, QueryResult}, - crypto::KeyPair, data_model::prelude::*, }; use iroha_data_model::transaction::error::TransactionRejectionReason; use serde_json::json; use test_network::*; - -use crate::integration::new_account_with_random_public_key; +use test_samples::{gen_account_in, ALICE_ID}; #[test] fn register_empty_role() -> Result<()> { @@ -54,15 +52,11 @@ fn register_and_grant_role_for_metadata_access() -> Result<()> { let (_rt, _peer, test_client) = ::new().with_port(10_700).start_with_runtime(); wait_for_genesis_committed(&vec![test_client.clone()], 0); - let alice_id = AccountId::from_str("alice@wonderland")?; - let mouse_id = AccountId::from_str("mouse@wonderland")?; + let alice_id = ALICE_ID.clone(); + let (mouse_id, mouse_keypair) = gen_account_in("wonderland"); // Registering Mouse - let mouse_key_pair = KeyPair::random(); - let register_mouse = Register::account(Account::new( - mouse_id.clone(), - mouse_key_pair.public_key().clone(), - )); + let register_mouse = Register::account(Account::new(mouse_id.clone())); test_client.submit_blocking(register_mouse)?; // Registering role @@ -83,7 +77,7 @@ fn register_and_grant_role_for_metadata_access() -> Result<()> { let grant_role = Grant::role(role_id.clone(), alice_id.clone()); let grant_role_tx = TransactionBuilder::new(chain_id, mouse_id.clone()) .with_instructions([grant_role]) - .sign(&mouse_key_pair); + .sign(&mouse_keypair); test_client.submit_transaction_blocking(&grant_role_tx)?; // Alice modifies Mouse's metadata @@ -109,11 +103,11 @@ fn unregistered_role_removed_from_account() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let role_id: RoleId = "root".parse().expect("Valid"); - let alice_id: AccountId = "alice@wonderland".parse().expect("Valid"); - let mouse_id: AccountId = "mouse@wonderland".parse().expect("Valid"); + let alice_id = ALICE_ID.clone(); + let (mouse_id, _mouse_keypair) = gen_account_in("wonderland"); // Registering Mouse - let register_mouse = Register::account(new_account_with_random_public_key(mouse_id.clone())); + let register_mouse = Register::account(Account::new(mouse_id.clone())); test_client.submit_blocking(register_mouse)?; // Register root role @@ -154,7 +148,9 @@ fn role_with_invalid_permissions_is_not_accepted() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let role_id = RoleId::from_str("ACCESS_TO_ACCOUNT_METADATA")?; - let rose_asset_id = AssetId::from_str("rose##alice@wonderland")?; + let rose_asset_id: AssetId = format!("rose##{}", ALICE_ID.clone()) + .parse() + .expect("should be valid"); let role = Role::new(role_id).add_permission(PermissionToken::new( "CanSetKeyValueInAccount".parse()?, &json!({ "account_id": rose_asset_id }), @@ -185,13 +181,13 @@ fn role_permissions_unified() { let allow_alice_to_transfer_rose_1 = PermissionToken::from_str_unchecked( "CanTransferUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form - "{ \"asset_id\" : \"rose#wonderland#alice@wonderland\" }", + "{ \"asset_id\" : \"rose#wonderland#ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland\" }", ); let allow_alice_to_transfer_rose_2 = PermissionToken::from_str_unchecked( "CanTransferUserAsset".parse().unwrap(), // NOTE: Introduced additional whitespaces in the serialized form - "{ \"asset_id\" : \"rose##alice@wonderland\" }", + "{ \"asset_id\" : \"rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland\" }", ); let role_id: RoleId = "role_id".parse().expect("Valid"); @@ -222,15 +218,11 @@ fn grant_revoke_role_permissions() -> Result<()> { let (_rt, _peer, test_client) = ::new().with_port(11_245).start_with_runtime(); wait_for_genesis_committed(&vec![test_client.clone()], 0); - let alice_id = AccountId::from_str("alice@wonderland")?; - let mouse_id = AccountId::from_str("mouse@wonderland")?; + let alice_id = ALICE_ID.clone(); + let (mouse_id, mouse_keypair) = gen_account_in("wonderland"); // Registering Mouse - let mouse_key_pair = KeyPair::random(); - let register_mouse = Register::account(Account::new( - mouse_id.clone(), - mouse_key_pair.public_key().clone(), - )); + let register_mouse = Register::account(Account::new(mouse_id.clone())); test_client.submit_blocking(register_mouse)?; // Registering role @@ -248,7 +240,7 @@ fn grant_revoke_role_permissions() -> Result<()> { let grant_role = Grant::role(role_id.clone(), alice_id.clone()); let grant_role_tx = TransactionBuilder::new(chain_id.clone(), mouse_id.clone()) .with_instructions([grant_role]) - .sign(&mouse_key_pair); + .sign(&mouse_keypair); test_client.submit_transaction_blocking(&grant_role_tx)?; let set_key_value = SetKeyValue::account( @@ -275,7 +267,7 @@ fn grant_revoke_role_permissions() -> Result<()> { // Alice can modify Mouse's metadata after permission token is granted to role let grant_role_permission_tx = TransactionBuilder::new(chain_id.clone(), mouse_id.clone()) .with_instructions([grant_role_permission]) - .sign(&mouse_key_pair); + .sign(&mouse_keypair); test_client.submit_transaction_blocking(&grant_role_permission_tx)?; let found_permissions = test_client .request(FindPermissionTokensByAccountId::new(alice_id.clone()))? @@ -286,7 +278,7 @@ fn grant_revoke_role_permissions() -> Result<()> { // Alice can't modify Mouse's metadata after permission token is removed from role let revoke_role_permission_tx = TransactionBuilder::new(chain_id.clone(), mouse_id.clone()) .with_instructions([revoke_role_permission]) - .sign(&mouse_key_pair); + .sign(&mouse_keypair); test_client.submit_transaction_blocking(&revoke_role_permission_tx)?; let found_permissions = test_client .request(FindPermissionTokensByAccountId::new(alice_id.clone()))? 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 1f62efe9689..4ae58d430b7 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 @@ -38,7 +38,7 @@ fn main(_id: TriggerId, _owner: AccountId, _event: EventBox) { let mut metadata = Metadata::new(); let name = format!( "nft_for_{}_in_{}", - account.id().name(), + account.id().signatory(), account.id().domain_id() ) .parse() @@ -78,7 +78,7 @@ fn generate_new_nft_id(account_id: &AccountId) -> AssetDefinitionId { format!( "nft_number_{}_for_{}#{}", new_number, - account_id.name(), + account_id.signatory(), account_id.domain_id() ) .parse() diff --git a/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs index d861b6e13fd..f34d4f2eb57 100644 --- a/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_admin/src/lib.rs @@ -1,5 +1,5 @@ -//! Runtime Executor which allows any instruction executed by `admin@admin` account. -//! If authority is not `admin@admin` then default validation is used as a backup. +//! Runtime Executor which allows any instruction executed by [admin](crate::integration::upgrade::ADMIN_ID) account. +//! If authority is not admin then default validation is used as a backup. #![no_std] @@ -22,7 +22,9 @@ struct Executor { } fn visit_instruction(executor: &mut Executor, authority: &AccountId, isi: &InstructionBox) { - if parse!("admin@admin" as AccountId) == *authority { + // multihash equals to integration::upgrade::ADMIN_PUBLIC_KEY_MULTIHASH + let admin_id = "ed012076E5CA9698296AF9BE2CA45F525CB3BCFDEB7EE068BA56F973E9DD90564EF4FC@admin"; + if *authority == parse!(AccountId, admin_id) { execute!(executor, isi); } diff --git a/client/tests/integration/smartcontracts/executor_with_migration_fail/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_migration_fail/src/lib.rs index 1b04091ace8..0aaa7907707 100644 --- a/client/tests/integration/smartcontracts/executor_with_migration_fail/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_migration_fail/src/lib.rs @@ -28,7 +28,7 @@ pub fn migrate(_block_height: u64) -> MigrationResult { // Performing side-effects to check in the test that it won't be applied after failure // Registering a new domain (using ISI) - let domain_id = parse!("failed_migration_test_domain" as DomainId); + let domain_id = parse!(DomainId, "failed_migration_test_domain"); Register::domain(Domain::new(domain_id)) .execute() .map_err(|error| { diff --git a/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs b/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs index dacc5b9789c..74ee7b4377d 100644 --- a/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs +++ b/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs @@ -46,7 +46,7 @@ fn main(owner: AccountId) { SetKeyValue::account( owner, - parse!("cursor" as Name), + parse!(Name, "cursor"), MetadataValueBox::String( serde_json::to_value(&asset_cursor.cursor) .dbg_expect("Failed to convert cursor to JSON") diff --git a/client/tests/integration/sorting.rs b/client/tests/integration/sorting.rs index bddfcd7ee39..5e8fa205021 100644 --- a/client/tests/integration/sorting.rs +++ b/client/tests/integration/sorting.rs @@ -3,6 +3,7 @@ use std::{collections::HashSet, str::FromStr as _}; use eyre::{Result, WrapErr as _}; use iroha_client::{ client::{self, QueryResult}, + crypto::KeyPair, data_model::{ account::Account, prelude::*, @@ -12,121 +13,127 @@ use iroha_client::{ }, }, }; -use iroha_data_model::isi::InstructionBox; use nonzero_ext::nonzero; +use rand::{seq::SliceRandom, thread_rng}; use test_network::*; - -use crate::integration::new_account_with_random_public_key; +use test_samples::ALICE_ID; #[test] +#[allow(clippy::cast_possible_truncation)] fn correct_pagination_assets_after_creating_new_one() { - let (_rt, _peer, test_client) = ::new().with_port(10_635).start_with_runtime(); - + // FIXME transaction is rejected for more than a certain number of instructions + const N_ASSETS: usize = 12; + // 0 < pagination.start < missing_idx < pagination.end < N_ASSETS + let missing_indices = vec![N_ASSETS / 2]; + let pagination = Pagination { + limit: Some(nonzero!(N_ASSETS as u32 / 3)), + start: Some(nonzero!(N_ASSETS as u64 / 3)), + }; + let xor_filter = PredicateBox::new(value::QueryOutputPredicate::Identifiable( + string::StringPredicate::starts_with("xor"), + )); let sort_by_metadata_key = Name::from_str("sort").expect("Valid"); + let sorting = Sorting::by_metadata_key(sort_by_metadata_key.clone()); + let account_id = ALICE_ID.clone(); - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let (_rt, _peer, test_client) = ::new().with_port(10_635).start_with_runtime(); + wait_for_genesis_committed(&[test_client.clone()], 0); - let mut assets = vec![]; - let mut instructions = vec![]; + let mut tester_assets = vec![]; + let mut register_asset_definitions = vec![]; + let mut register_assets = vec![]; - for i in 0..20_u32 { + let mut missing_tester_assets = vec![]; + let mut missing_register_asset_definitions = vec![]; + let mut missing_register_assets = vec![]; + + for i in 0..N_ASSETS { let asset_definition_id = AssetDefinitionId::from_str(&format!("xor{i}#wonderland")).expect("Valid"); let asset_definition = AssetDefinition::store(asset_definition_id.clone()); let mut asset_metadata = Metadata::new(); asset_metadata - .insert_with_limits(sort_by_metadata_key.clone(), i, MetadataLimits::new(10, 23)) + .insert_with_limits( + sort_by_metadata_key.clone(), + i as u32, + MetadataLimits::new(10, 23), + ) .expect("Valid"); let asset = Asset::new( AssetId::new(asset_definition_id, account_id.clone()), AssetValue::Store(asset_metadata), ); - assets.push(asset.clone()); - - let create_asset_definition: InstructionBox = - Register::asset_definition(asset_definition).into(); - let create_asset = Register::asset(asset).into(); - - instructions.push(create_asset_definition); - instructions.push(create_asset); + if missing_indices.contains(&i) { + missing_tester_assets.push(asset.clone()); + missing_register_asset_definitions.push(Register::asset_definition(asset_definition)); + missing_register_assets.push(Register::asset(asset)); + } else { + tester_assets.push(asset.clone()); + register_asset_definitions.push(Register::asset_definition(asset_definition)); + register_assets.push(Register::asset(asset)); + } } + register_asset_definitions.shuffle(&mut thread_rng()); + register_assets.shuffle(&mut thread_rng()); test_client - .submit_all_blocking(instructions) + .submit_all_blocking(register_asset_definitions) + .expect("Valid"); + test_client + .submit_all_blocking(register_assets) .expect("Valid"); - let sorting = Sorting::by_metadata_key(sort_by_metadata_key.clone()); - - let res = test_client - .build_query(client::asset::by_account_id(account_id.clone())) - .with_pagination(Pagination { - limit: Some(nonzero!(5_u32)), - start: None, - }) + let queried_assets = test_client + .build_query(client::asset::all()) + .with_filter(xor_filter.clone()) + .with_pagination(pagination) .with_sorting(sorting.clone()) .execute() .expect("Valid") .collect::>>() .expect("Valid"); - assert!(res + tester_assets .iter() - .map(|asset| &asset.id().definition_id.name) - .eq(assets - .iter() - .take(5) - .map(|asset| &asset.id().definition_id.name))); - - let new_asset_definition_id = AssetDefinitionId::from_str("xor20#wonderland").expect("Valid"); - let new_asset_definition = AssetDefinition::store(new_asset_definition_id.clone()); - let mut new_asset_metadata = Metadata::new(); - new_asset_metadata - .insert_with_limits( - sort_by_metadata_key, - numeric!(20), - MetadataLimits::new(10, 23), - ) - .expect("Valid"); - let new_asset = Asset::new( - AssetId::new(new_asset_definition_id, account_id.clone()), - AssetValue::Store(new_asset_metadata), - ); - - let create_asset_definition: InstructionBox = - Register::asset_definition(new_asset_definition).into(); - let create_asset = Register::asset(new_asset.clone()).into(); + .skip(N_ASSETS / 3) + .take(N_ASSETS / 3) + .zip(queried_assets) + .for_each(|(tester, queried)| assert_eq!(*tester, queried)); + for (i, missing_idx) in missing_indices.into_iter().enumerate() { + tester_assets.insert(missing_idx, missing_tester_assets[i].clone()); + } + test_client + .submit_all_blocking(missing_register_asset_definitions) + .expect("Valid"); test_client - .submit_all_blocking([create_asset_definition, create_asset]) + .submit_all_blocking(missing_register_assets) .expect("Valid"); - let res = test_client - .build_query(client::asset::by_account_id(account_id)) - .with_pagination(Pagination { - limit: Some(nonzero!(13_u32)), - start: Some(nonzero!(8_u64)), - }) + let queried_assets = test_client + .build_query(client::asset::all()) + .with_filter(xor_filter) + .with_pagination(pagination) .with_sorting(sorting) .execute() .expect("Valid") .collect::>>() .expect("Valid"); - assert!(res + tester_assets .iter() - .map(|asset| &asset.id().definition_id.name) - .eq(assets - .iter() - .skip(8) - .chain(core::iter::once(&new_asset)) - .map(|asset| &asset.id().definition_id.name))); + .skip(N_ASSETS / 3) + .take(N_ASSETS / 3) + .zip(queried_assets) + .for_each(|(tester, queried)| assert_eq!(*tester, queried)); } #[test] #[allow(clippy::too_many_lines)] fn correct_sorting_of_entities() { let (_rt, _peer, test_client) = ::new().with_port(10_640).start_with_runtime(); + wait_for_genesis_committed(&[test_client.clone()], 0); let sort_by_metadata_key = Name::from_str("test_sort").expect("Valid"); @@ -183,13 +190,23 @@ fn correct_sorting_of_entities() { // Test sorting accounts + let domain_name = "_neverland"; + let domain_id: DomainId = domain_name.parse().unwrap(); + test_client + .submit_blocking(Register::domain(Domain::new(domain_id.clone()))) + .expect("should be committed"); + let mut accounts = vec![]; let mut metadata_of_accounts = vec![]; let mut instructions = vec![]; let n = 10u32; + let mut public_keys = (0..n) + .map(|_| KeyPair::random().into_parts().0) + .collect::>(); + public_keys.sort_unstable(); for i in 0..n { - let account_id = AccountId::from_str(&format!("charlie{i}@wonderland")).expect("Valid"); + let account_id = AccountId::new(domain_id.clone(), public_keys[i as usize].clone()); let mut account_metadata = Metadata::new(); account_metadata .insert_with_limits( @@ -198,8 +215,7 @@ fn correct_sorting_of_entities() { MetadataLimits::new(10, 28), ) .expect("Valid"); - let account = new_account_with_random_public_key(account_id.clone()) - .with_metadata(account_metadata.clone()); + let account = Account::new(account_id.clone()).with_metadata(account_metadata.clone()); accounts.push(account_id); metadata_of_accounts.push(account_metadata); @@ -216,8 +232,8 @@ fn correct_sorting_of_entities() { .build_query(client::account::all()) .with_sorting(Sorting::by_metadata_key(sort_by_metadata_key.clone())) .with_filter(PredicateBox::new( - value::QueryOutputPredicate::Identifiable(string::StringPredicate::starts_with( - "charlie", + value::QueryOutputPredicate::Identifiable(string::StringPredicate::ends_with( + domain_name, )), )) .execute() @@ -328,7 +344,15 @@ fn correct_sorting_of_entities() { #[test] fn sort_only_elements_which_have_sorting_key() -> Result<()> { + const TEST_DOMAIN: &str = "neverland"; + let (_rt, _peer, test_client) = ::new().with_port(10_680).start_with_runtime(); + wait_for_genesis_committed(&[test_client.clone()], 0); + + let domain_id: DomainId = TEST_DOMAIN.parse().unwrap(); + test_client + .submit_blocking(Register::domain(Domain::new(domain_id.clone()))) + .expect("should be committed"); let sort_by_metadata_key = Name::from_str("test_sort").expect("Valid"); @@ -341,10 +365,14 @@ fn sort_only_elements_which_have_sorting_key() -> Result<()> { skip_set.insert(7); let n = 10u32; + let mut public_keys = (0..n) + .map(|_| KeyPair::random().into_parts().0) + .collect::>(); + public_keys.sort_unstable(); for i in 0..n { - let account_id = AccountId::from_str(&format!("charlie{i}@wonderland")).expect("Valid"); + let account_id = AccountId::new(domain_id.clone(), public_keys[i as usize].clone()); let account = if skip_set.contains(&i) { - let account = new_account_with_random_public_key(account_id.clone()); + let account = Account::new(account_id.clone()); accounts_b.push(account_id); account } else { @@ -356,8 +384,7 @@ fn sort_only_elements_which_have_sorting_key() -> Result<()> { MetadataLimits::new(10, 28), ) .expect("Valid"); - let account = new_account_with_random_public_key(account_id.clone()) - .with_metadata(account_metadata); + let account = Account::new(account_id.clone()).with_metadata(account_metadata); accounts_a.push(account_id); account }; @@ -374,8 +401,8 @@ fn sort_only_elements_which_have_sorting_key() -> Result<()> { .build_query(client::account::all()) .with_sorting(Sorting::by_metadata_key(sort_by_metadata_key)) .with_filter(PredicateBox::new( - value::QueryOutputPredicate::Identifiable(string::StringPredicate::starts_with( - "charlie", + value::QueryOutputPredicate::Identifiable(string::StringPredicate::ends_with( + TEST_DOMAIN, )), )) .execute() diff --git a/client/tests/integration/status_response.rs b/client/tests/integration/status_response.rs index a0bf6c87d97..8209d46b5dd 100644 --- a/client/tests/integration/status_response.rs +++ b/client/tests/integration/status_response.rs @@ -4,6 +4,7 @@ use eyre::Result; use iroha_client::{data_model::prelude::*, samples::get_status_json}; use iroha_telemetry::metrics::Status; use test_network::*; +use test_samples::gen_account_in; fn status_eq_excluding_uptime_and_queue(lhs: &Status, rhs: &Status) -> bool { lhs.peers == rhs.peers @@ -29,8 +30,7 @@ fn json_and_scale_statuses_equality() -> Result<()> { let coins = ["xor", "btc", "eth", "doge"]; - let domain_id: DomainId = "test_domain".parse().expect("Should be valid"); - let account_id = AccountId::new(domain_id, "test_account".parse().expect("Should be valid")); + let (account_id, _account_keypair) = gen_account_in("domain"); for coin in coins { let asset_definition_id = AssetDefinitionId::from_str(&format!("{coin}#wonderland"))?; diff --git a/client/tests/integration/transfer_asset.rs b/client/tests/integration/transfer_asset.rs index 31c2750068f..f58d479e49c 100644 --- a/client/tests/integration/transfer_asset.rs +++ b/client/tests/integration/transfer_asset.rs @@ -2,7 +2,6 @@ use std::str::FromStr; use iroha_client::{ client::{self, QueryResult}, - crypto::KeyPair, data_model::{isi::Instruction, prelude::*, Registered}, }; use iroha_data_model::{ @@ -12,6 +11,7 @@ use iroha_data_model::{ name::Name, }; use test_network::*; +use test_samples::{gen_account_in, ALICE_ID}; #[test] // This test suite is also covered at the UI level in the iroha_client_cli tests @@ -135,12 +135,11 @@ fn simulate_transfer( } fn generate_two_ids() -> (AccountId, AccountId) { - let alice_id: AccountId = "alice@wonderland".parse().unwrap(); - let mouse_id: AccountId = "mouse@wonderland".parse().unwrap(); + let alice_id = ALICE_ID.clone(); + let (mouse_id, _mouse_keypair) = gen_account_in("wonderland"); (alice_id, mouse_id) } fn create_mouse(mouse_id: AccountId) -> Register { - let (mouse_public_key, _) = KeyPair::random().into_parts(); - Register::account(Account::new(mouse_id, mouse_public_key)) + Register::account(Account::new(mouse_id)) } diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index 37ccf66d12e..4c93ebacdc4 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -12,6 +12,7 @@ use iroha_client::{ use iroha_genesis::GenesisNetwork; use iroha_logger::info; use test_network::*; +use test_samples::ALICE_ID; const TRIGGER_NAME: &str = "mint_rose"; @@ -21,7 +22,7 @@ fn call_execute_trigger() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id = "alice@wonderland".parse()?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id); let prev_value = get_asset_value(&mut test_client, asset_id.clone()); @@ -45,7 +46,7 @@ fn execute_trigger_should_produce_event() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id: AccountId = "alice@wonderland".parse()?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let instruction = Mint::asset_numeric(1u32, asset_id.clone()); @@ -81,7 +82,7 @@ fn infinite_recursion_should_produce_one_call_per_block() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id = "alice@wonderland".parse()?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id); let trigger_id = TriggerId::from_str(TRIGGER_NAME)?; let call_trigger = ExecuteTrigger::new(trigger_id); @@ -108,7 +109,7 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); // Registering trigger that should fail on execution @@ -164,7 +165,7 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let trigger_id = TriggerId::from_str("self_modifying_trigger")?; @@ -224,7 +225,7 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let trigger_id = TriggerId::from_str("self_modifying_trigger")?; @@ -270,7 +271,7 @@ fn unregister_trigger() -> Result<()> { let (_rt, _peer, test_client) = ::new().with_port(10_035).start_with_runtime(); wait_for_genesis_committed(&vec![test_client.clone()], 0); - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); // Registering trigger let trigger_id = TriggerId::from_str("empty_trigger")?; @@ -346,7 +347,7 @@ fn trigger_in_genesis_using_base64() -> Result<()> { let engine = base64::engine::general_purpose::STANDARD; let wasm_base64 = serde_json::json!(base64::engine::Engine::encode(&engine, wasm)).to_string(); - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let trigger_id = TriggerId::from_str("genesis_trigger")?; let trigger = Trigger::new( @@ -399,7 +400,7 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let trigger_id_unregister = TriggerId::from_str("unregister_other_trigger")?; let trigger_id_to_be_unregistered = TriggerId::from_str("should_be_unregistered_trigger")?; @@ -459,7 +460,7 @@ fn trigger_burn_repetitions() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let trigger_id = TriggerId::from_str("trigger")?; @@ -494,7 +495,7 @@ fn unregistering_one_of_two_triggers_with_identical_wasm_should_not_cause_origin let (_rt, _peer, test_client) = ::new().with_port(11_105).start_with_runtime(); wait_for_genesis_committed(&vec![test_client.clone()], 0); - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let first_trigger_id = TriggerId::from_str("mint_rose_1")?; let second_trigger_id = TriggerId::from_str("mint_rose_2")?; diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index 46f505a9f9f..3f070c2e4a2 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -2,15 +2,14 @@ use eyre::Result; use iroha_client::{client, data_model::prelude::*}; use iroha_data_model::asset::AssetValue; use test_network::*; - -use crate::integration::new_account_with_random_public_key; +use test_samples::{gen_account_in, ALICE_ID}; #[test] fn must_execute_both_triggers() -> Result<()> { let (_rt, _peer, test_client) = ::new().with_port(10_650).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); - let account_id: AccountId = "alice@wonderland".parse()?; + let account_id = ALICE_ID.clone(); let asset_definition_id = "rose#wonderland".parse()?; let asset_id = AssetId::new(asset_definition_id, account_id.clone()); @@ -39,8 +38,8 @@ fn must_execute_both_triggers() -> Result<()> { )); test_client.submit_blocking(register_trigger)?; - test_client.submit_blocking(Register::account(new_account_with_random_public_key( - "bunny@wonderland".parse()?, + test_client.submit_blocking(Register::account(Account::new( + gen_account_in("wonderland").0, )))?; test_client.submit_blocking(Register::domain(Domain::new("neverland".parse()?)))?; @@ -58,9 +57,8 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu let create_neverland_domain: InstructionBox = Register::domain(Domain::new("neverland".parse()?)).into(); - let account_id: AccountId = "sapporo@neverland".parse()?; - let create_sapporo_account = - Register::account(new_account_with_random_public_key(account_id.clone())).into(); + let (account_id, _account_keypair) = gen_account_in("neverland"); + let create_sapporo_account = Register::account(Account::new(account_id.clone())).into(); let asset_definition_id: AssetDefinitionId = "sakura#neverland".parse()?; let create_sakura_asset_definition = @@ -89,12 +87,12 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu )); test_client.submit_blocking(register_trigger)?; - test_client.submit_blocking(Register::account(new_account_with_random_public_key( - "asahi@wonderland".parse()?, + test_client.submit_blocking(Register::account(Account::new( + gen_account_in("wonderland").0, )))?; - test_client.submit_blocking(Register::account(new_account_with_random_public_key( - "asahi@neverland".parse()?, + test_client.submit_blocking(Register::account(Account::new( + gen_account_in("neverland").0, )))?; let new_value = get_asset_value(&test_client, asset_id); diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index 12a5dca633c..756a2ee6ac3 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -1,11 +1,10 @@ -use std::str::FromStr; - use eyre::Result; use iroha_client::{ client::{self, Client}, data_model::prelude::*, }; use test_network::*; +use test_samples::ALICE_ID; #[test] fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { @@ -13,7 +12,7 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse()?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let prev_value = get_asset_value(&mut test_client, asset_id.clone()); diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index 8a9bb9fb034..a7d161eb033 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -9,8 +9,7 @@ use iroha_config::parameters::defaults::chain_wide::DEFAULT_CONSENSUS_ESTIMATION use iroha_data_model::events::pipeline::{BlockEventFilter, BlockStatus}; use iroha_logger::info; use test_network::*; - -use crate::integration::new_account_with_random_public_key; +use test_samples::{gen_account_in, ALICE_ID}; fn curr_time() -> core::time::Duration { use std::time::SystemTime; @@ -47,7 +46,7 @@ fn time_trigger_execution_count_error_should_be_less_than_15_percent() -> Result // Start listening BEFORE submitting any transaction not to miss any block committed event let event_listener = get_block_committed_event_listener(&test_client)?; - let account_id: AccountId = "alice@wonderland".parse().expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_definition_id = "rose#wonderland".parse().expect("Valid"); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); @@ -107,7 +106,7 @@ fn change_asset_metadata_after_1_sec() -> Result<()> { let event_listener = get_block_committed_event_listener(&test_client)?; let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland").expect("Valid"); - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let account_id = ALICE_ID.clone(); let key = Name::from_str("petal")?; let schedule = TimeSchedule::starting_at(start_time + PERIOD); @@ -148,7 +147,7 @@ fn pre_commit_trigger_should_be_executed() -> Result<()> { wait_for_genesis_committed(&vec![test_client.clone()], 0); let asset_definition_id = "rose#wonderland".parse().expect("Valid"); - let account_id: AccountId = "alice@wonderland".parse().expect("Valid"); + let account_id = ALICE_ID.clone(); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); let mut prev_value = get_asset_value(&mut test_client, asset_id.clone()); @@ -193,14 +192,14 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { let (_rt, _peer, mut test_client) = ::new().with_port(10_780).start_with_runtime(); wait_for_genesis_committed(&vec![test_client.clone()], 0); - let alice_id = "alice@wonderland".parse::().expect("Valid"); + let alice_id = ALICE_ID.clone(); let accounts: Vec = vec![ alice_id.clone(), - "mad_hatter@wonderland".parse().expect("Valid"), - "cheshire_cat@wonderland".parse().expect("Valid"), - "caterpillar@wonderland".parse().expect("Valid"), - "white_rabbit@wonderland".parse().expect("Valid"), + gen_account_in("wonderland").0, + gen_account_in("wonderland").0, + gen_account_in("wonderland").0, + gen_account_in("wonderland").0, ]; // Registering accounts @@ -208,7 +207,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { .iter() .skip(1) // Alice has already been registered in genesis .cloned() - .map(|account_id| Register::account(new_account_with_random_public_key(account_id))) + .map(|account_id| Register::account(Account::new(account_id))) .collect::>(); test_client.submit_all_blocking(register_accounts)?; @@ -255,7 +254,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { // Checking results for account_id in accounts { let start_pattern = "nft_number_"; - let end_pattern = format!("_for_{}#{}", account_id.name, account_id.domain_id); + let end_pattern = format!("_for_{}#{}", account_id.signatory, account_id.domain_id); let assets = test_client .request(client::asset::by_account_id(account_id.clone()))? .collect::>>()?; diff --git a/client/tests/integration/triggers/trigger_rollback.rs b/client/tests/integration/triggers/trigger_rollback.rs index 6f61cae9835..1eb6188d916 100644 --- a/client/tests/integration/triggers/trigger_rollback.rs +++ b/client/tests/integration/triggers/trigger_rollback.rs @@ -6,6 +6,7 @@ use iroha_client::{ data_model::{prelude::*, query::asset::FindAllAssetsDefinitions, trigger::TriggerId}, }; use test_network::*; +use test_samples::ALICE_ID; #[test] fn failed_trigger_revert() -> Result<()> { @@ -14,7 +15,7 @@ fn failed_trigger_revert() -> Result<()> { //When let trigger_id = TriggerId::from_str("trigger")?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland")?; let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); diff --git a/client/tests/integration/tx_chain_id.rs b/client/tests/integration/tx_chain_id.rs index 9e16a90a898..e439361c728 100644 --- a/client/tests/integration/tx_chain_id.rs +++ b/client/tests/integration/tx_chain_id.rs @@ -1,38 +1,28 @@ use std::str::FromStr; -use iroha_crypto::KeyPair; use iroha_data_model::prelude::*; use iroha_primitives::numeric::numeric; use test_network::*; - -use crate::integration::asset::asset_id_new; +use test_samples::gen_account_in; #[test] fn send_tx_with_different_chain_id() { let (_rt, _peer, test_client) = ::new().with_port(11_250).start_with_runtime(); wait_for_genesis_committed(&[test_client.clone()], 0); // Given - let sender_account_id = AccountId::from_str("sender@wonderland").unwrap(); - let sender_keypair = KeyPair::random(); - let receiver_account_id = AccountId::from_str("receiver@wonderland").unwrap(); - let receiver_keypair = KeyPair::random(); + let (sender_id, sender_keypair) = gen_account_in("wonderland"); + let (receiver_id, _receiver_keypair) = gen_account_in("wonderland"); let asset_definition_id = AssetDefinitionId::from_str("test_asset#wonderland").unwrap(); let to_transfer = numeric!(1); - let create_sender_account: InstructionBox = Register::account(Account::new( - sender_account_id.clone(), - sender_keypair.public_key().clone(), - )) - .into(); - let create_receiver_account: InstructionBox = Register::account(Account::new( - receiver_account_id.clone(), - receiver_keypair.public_key().clone(), - )) - .into(); + let create_sender_account: InstructionBox = + Register::account(Account::new(sender_id.clone())).into(); + let create_receiver_account: InstructionBox = + Register::account(Account::new(receiver_id.clone())).into(); let register_asset_definition: InstructionBox = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())).into(); let register_asset: InstructionBox = Register::asset(Asset::new( - AssetId::new(asset_definition_id.clone(), sender_account_id.clone()), + AssetId::new(asset_definition_id.clone(), sender_id.clone()), numeric!(10), )) .into(); @@ -48,14 +38,14 @@ fn send_tx_with_different_chain_id() { let chain_id_1 = ChainId::from("1"); let transfer_instruction = Transfer::asset_numeric( - asset_id_new("test_asset", "wonderland", sender_account_id.clone()), + AssetId::new("test_asset#wonderland".parse().unwrap(), sender_id.clone()), to_transfer, - receiver_account_id.clone(), + receiver_id.clone(), ); - let asset_transfer_tx_0 = TransactionBuilder::new(chain_id_0, sender_account_id.clone()) + let asset_transfer_tx_0 = TransactionBuilder::new(chain_id_0, sender_id.clone()) .with_instructions([transfer_instruction.clone()]) .sign(&sender_keypair); - let asset_transfer_tx_1 = TransactionBuilder::new(chain_id_1, sender_account_id.clone()) + let asset_transfer_tx_1 = TransactionBuilder::new(chain_id_1, sender_id.clone()) .with_instructions([transfer_instruction]) .sign(&sender_keypair); test_client diff --git a/client/tests/integration/tx_history.rs b/client/tests/integration/tx_history.rs index fb8b22ea604..19a57bd638e 100644 --- a/client/tests/integration/tx_history.rs +++ b/client/tests/integration/tx_history.rs @@ -8,6 +8,7 @@ use iroha_client::{ use iroha_config::parameters::actual::Root as Config; use nonzero_ext::nonzero; use test_network::*; +use test_samples::ALICE_ID; #[ignore = "ignore, more in #2851"] #[test] @@ -18,7 +19,7 @@ fn client_has_rejected_and_acepted_txs_should_return_tx_history() -> Result<()> let pipeline_time = Config::pipeline_time(); // Given - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland")?; let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); diff --git a/client/tests/integration/tx_rollback.rs b/client/tests/integration/tx_rollback.rs index 181e0242cd2..a5cc76ad759 100644 --- a/client/tests/integration/tx_rollback.rs +++ b/client/tests/integration/tx_rollback.rs @@ -6,6 +6,7 @@ use iroha_client::{ data_model::prelude::*, }; use test_network::*; +use test_samples::ALICE_ID; #[test] fn client_sends_transaction_with_invalid_instruction_should_not_see_any_changes() -> Result<()> { @@ -13,7 +14,7 @@ fn client_sends_transaction_with_invalid_instruction_should_not_see_any_changes( wait_for_genesis_committed(&[client.clone()], 0); //When - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland")?; let wrong_asset_definition_id = AssetDefinitionId::from_str("ksor#wonderland")?; let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id)); diff --git a/client/tests/integration/upgrade.rs b/client/tests/integration/upgrade.rs index 3d4106c79f5..4cc36f6cfbb 100644 --- a/client/tests/integration/upgrade.rs +++ b/client/tests/integration/upgrade.rs @@ -9,29 +9,41 @@ use iroha_client::{ use iroha_logger::info; use serde_json::json; use test_network::*; +use test_samples::ALICE_ID; + +const ADMIN_PUBLIC_KEY_MULTIHASH: &str = + "ed012076E5CA9698296AF9BE2CA45F525CB3BCFDEB7EE068BA56F973E9DD90564EF4FC"; +const ADMIN_PRIVATE_KEY_MULTIHASH: &str = "802640A4DE33BCA99A254ED6265D1F0FB69DFE42B77F89F6C2E478498E1831BF6D81F276E5CA9698296AF9BE2CA45F525CB3BCFDEB7EE068BA56F973E9DD90564EF4FC"; #[test] fn executor_upgrade_should_work() -> Result<()> { let chain_id = ChainId::from("0"); + let admin_id: AccountId = format!("{ADMIN_PUBLIC_KEY_MULTIHASH}@admin") + .parse() + .unwrap(); + let admin_keypair = KeyPair::new( + admin_id.signatory().clone(), + ADMIN_PRIVATE_KEY_MULTIHASH.parse().unwrap(), + ) + .unwrap(); let (_rt, _peer, client) = ::new().with_port(10_795).start_with_runtime(); wait_for_genesis_committed(&vec![client.clone()], 0); // Register `admin` domain and account - let admin_domain = Domain::new("admin".parse()?); + let admin_domain = Domain::new(admin_id.domain_id().clone()); let register_admin_domain = Register::domain(admin_domain); client.submit_blocking(register_admin_domain)?; - let admin_id: AccountId = "admin@admin".parse()?; - let admin_keypair = KeyPair::random(); - let admin_account = Account::new(admin_id.clone(), admin_keypair.public_key().clone()); + let admin_account = Account::new(admin_id.clone()); let register_admin_account = Register::account(admin_account); client.submit_blocking(register_admin_account)?; // Check that admin isn't allowed to transfer alice's rose by default - let alice_rose: AssetId = "rose##alice@wonderland".parse()?; - let admin_rose: AccountId = "admin@admin".parse()?; - let transfer_alice_rose = Transfer::asset_numeric(alice_rose, 1u32, admin_rose); + let alice_rose: AssetId = format!("rose##{}", ALICE_ID.clone()) + .parse() + .expect("should be valid"); + let transfer_alice_rose = Transfer::asset_numeric(alice_rose, 1u32, admin_id.clone()); let transfer_rose_tx = TransactionBuilder::new(chain_id.clone(), admin_id.clone()) .with_instructions([transfer_alice_rose.clone()]) .sign(&admin_keypair); @@ -46,7 +58,7 @@ fn executor_upgrade_should_work() -> Result<()> { // Check that admin can transfer alice's rose now // Creating new transaction instead of cloning, because we need to update it's creation time - let transfer_rose_tx = TransactionBuilder::new(chain_id, admin_id) + let transfer_rose_tx = TransactionBuilder::new(chain_id, admin_id.clone()) .with_instructions([transfer_alice_rose]) .sign(&admin_keypair); client @@ -71,7 +83,7 @@ fn executor_upgrade_should_run_migration() -> Result<()> { .any(|id| id == &can_unregister_domain_token_id)); // Check that Alice has permission to unregister Wonderland - let alice_id: AccountId = "alice@wonderland".parse().unwrap(); + let alice_id = ALICE_ID.clone(); let alice_tokens = client .request(FindPermissionTokensByAccountId::new(alice_id.clone()))? .collect::>>() @@ -147,7 +159,7 @@ fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { .contains(&can_unregister_domain_token)); // Check that Alice has permission - let alice_id: AccountId = "alice@wonderland".parse()?; + let alice_id = ALICE_ID.clone(); assert!(client .request(FindPermissionTokensByAccountId::new(alice_id.clone()))? .collect::>>()? diff --git a/client_cli/.gitignore b/client_cli/.gitignore new file mode 100644 index 00000000000..d7b89fefd49 --- /dev/null +++ b/client_cli/.gitignore @@ -0,0 +1,2 @@ +peers_configs/ +isi_unregister_asset.json diff --git a/client_cli/README.md b/client_cli/README.md index 6cb5dfbc644..9cb7fdf4d29 100644 --- a/client_cli/README.md +++ b/client_cli/README.md @@ -60,20 +60,27 @@ Check the [Bash guide in Iroha Tutorial](https://hyperledger.github.io/iroha-2-d ```bash ./iroha_client_cli domain register --id="Soramitsu" -./iroha_client_cli account register --id="White Rabbit@Soramitsu" --key="" +./iroha_client_cli account register --id="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" ./iroha_client_cli asset register --id="XOR#Soramitsu" --value-type=Numeric -./iroha_client_cli asset mint --account="White Rabbit@Soramitsu" --asset="XOR#Soramitsu" --quantity=1010 -./iroha_client_cli asset get --account="White Rabbit@Soramitsu" --asset="XOR#Soramitsu" +./iroha_client_cli asset mint --account="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" --asset="XOR#Soramitsu" --quantity=1010 +./iroha_client_cli asset get --account="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" --asset="XOR#Soramitsu" ``` In this section we will show you how to use Iroha CLI Client to do the following: -- [Create new Domain](#create-new-domain) -- [Create new Account](#create-new-account) -- [Mint Asset to Account](#mint-asset-to-account) -- [Query Account Assets Quantity](#query-account-assets-quantity) -- [Execute WASM transaction](#execute-wasm-transaction) -- [Execute Multi-instruction Transactions](#execute-multi-instruction-instructions) +- [Iroha CLI Client](#iroha-cli-client) + - [Features](#features) + - [Installation](#installation) + - [Usage](#usage) + - [Options](#options) + - [Subcommands](#subcommands) + - [Examples](#examples) + - [Create new Domain](#create-new-domain) + - [Create new Account](#create-new-account) + - [Mint Asset to Account](#mint-asset-to-account) + - [Query Account Assets Quantity](#query-account-assets-quantity) + - [Execute WASM transaction](#execute-wasm-transaction) + - [Execute Multi-instruction Transactions](#execute-multi-instruction-transactions) ### Create new Domain @@ -89,12 +96,10 @@ Now you have a domain without any accounts. ### Create new Account -Let's create a new account. Like in the previous example, specify the entity type (`account`) and the command (`register`). Then define the account name as the value of the `id` argument. - -Additionally, you need to provide the `key` argument with the account's public key as a double-quoted multihash representation of the key. Providing an empty string also works (but is highly discouraged), while omitting the argument altogether will produce an error. +Let's create a new account. Like in the previous example, specify the entity type (`account`) and the command (`register`). Then define the value of the `id` argument in "signatory@domain" format, where signatory is the account's public key in multihash representation. ```bash -./iroha_client_cli account register --id="White Rabbit@Soramitsu" --key="" +./iroha_client_cli account register --id="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" ``` ### Mint Asset to Account @@ -107,10 +112,10 @@ Every asset has its own value spec. In this example, it is defined as `Numeric`, ```bash ./iroha_client_cli asset register --id="XOR#Soramitsu" --value-type=Numeric -./iroha_client_cli asset mint --account="White Rabbit@Soramitsu" --asset="XOR#Soramitsu" --quantity=1010 +./iroha_client_cli asset mint --account="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" --asset="XOR#Soramitsu" --quantity=1010 ``` -You created `XOR#Soramitsu`, an asset of type `Numeric`, and then gave `1010` units of this asset to the account `White Rabbit@Soramitsu`. +You created `XOR#Soramitsu`, an asset of type `Numeric`, and then gave `1010` units of this asset to the account `ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu`. ### Query Account Assets Quantity @@ -128,10 +133,10 @@ Let's use Get Account Assets Query as an example. To know how many units of a particular asset an account has, use `asset get` with the specified account and asset: ```bash -./iroha_client_cli asset get --account="White Rabbit@Soramitsu" --asset="XOR#Soramitsu" +./iroha_client_cli asset get --account="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" --asset="XOR#Soramitsu" ``` -This query returns the quantity of `XOR#Soramitsu` asset for the `White Rabbit@Soramitsu` account. +This query returns the quantity of `XOR#Soramitsu` asset for the `ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu` account. It's possible to filter based on either account, asset or domain id by using the filtering API provided by the Iroha client CLI. diff --git a/client_cli/pytests/README.md b/client_cli/pytests/README.md index f702ab4f6ab..6aefb69e900 100644 --- a/client_cli/pytests/README.md +++ b/client_cli/pytests/README.md @@ -4,14 +4,15 @@ This directory contains the `pytest` framework with test suites for the Iroha 2 For quick access to a topic that interests you, select one of the following: -- [Framework Structure](#framework-structure) -- [Iroha 2 Test Model](#iroha-2-test-model) -- [Using Test Suites](#using-test-suites) - - [Custom Test Environment with Docker Compose](#custom-test-environment-with-docker-compose) - - [Poetry Configuration](#poetry-configuration) - - [Tests Configuration](#tests-configuration) -- [Running Tests](#running-tests) -- [Viewing Test Reports](#viewing-test-reports) +- [Overview](#overview) + - [Framework Structure](#framework-structure) + - [Iroha 2 Test Model](#iroha-2-test-model) + - [Using Test Suites](#using-test-suites) + - [Custom Test Environment with Docker Compose](#custom-test-environment-with-docker-compose) + - [Poetry Configuration](#poetry-configuration) + - [Tests Configuration](#tests-configuration) + - [Running Tests](#running-tests) + - [Viewing Test Reports](#viewing-test-reports) ## Framework Structure @@ -105,20 +106,20 @@ To do so, perform the following steps: cargo build --bin iroha_client_cli ``` -3. Create a new directory, then copy the `iroha_client_cli` binary and its `config.json` configuration file into it: +3. Create a new directory, then copy the `iroha_client_cli` binary and its `client.toml` configuration file into it: ```shell # Create a new directory: - mkdir test_client + mkdir test # Copy the files: - cp configs/client/config.json test_client - cp target/debug/iroha_client_cli test_client + cp configs/swarm/client.toml test + cp target/debug/iroha_client_cli test ``` 4. Proceed with _Step 2_ of the [Using Test Suites](#using-test-suites) instructions. > [!NOTE] -> Don't forget to specify the path to the directory created for the `iroha_client_cli` binary and its `config.json` configuration file (see Step 3) in the `CLIENT_CLI_DIR` variable of the `.env` file. +> Don't forget to specify the path to the directory created for the `iroha_client_cli` binary and its `client.toml` configuration file (see Step 3) in the `CLIENT_CLI_DIR` variable of the `.env` file. > For details, see [Tests Configuration](#tests-configuration) below. ### Poetry Configuration diff --git a/client_cli/pytests/common/consts.py b/client_cli/pytests/common/consts.py index fadc52223ae..2f4d2b7dc26 100644 --- a/client_cli/pytests/common/consts.py +++ b/client_cli/pytests/common/consts.py @@ -15,11 +15,11 @@ class Stderr(Enum): Enum for standard error messages. """ - CANNOT_BE_EMPTY = "cannot be empty\n\nFor more information, try '--help'.\n" + EMPTY = "Empty" REPETITION = "Repetition" TOO_LONG = "Name length violation" FAILED_TO_FIND_DOMAIN = "Failed to find domain" - INVALID_CHARACTER = "Invalid character" + INVALID_CHARACTER = "Failed to parse" INVALID_VALUE_TYPE = "should be either `Store` or `Numeric`" RESERVED_CHARACTER = ( "The `@` character is reserved for `account@domain` constructs," diff --git a/client_cli/pytests/common/helpers.py b/client_cli/pytests/common/helpers.py index 6145ea35557..aa55466ec9c 100644 --- a/client_cli/pytests/common/helpers.py +++ b/client_cli/pytests/common/helpers.py @@ -19,7 +19,7 @@ def extract_hash(stdout): """ Extracts a SHA-256 hash from the given string. - :param stdout: The string from which to extract the hash. + :param stdout: The string from which to extract the hash. :return: The extracted hash if found, otherwise None. """ if not isinstance(stdout, str) or not stdout.strip(): @@ -98,7 +98,7 @@ def generate_public_key(): encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw ) ).decode() - return public_key + return "ed0120" + public_key.upper() def generate_random_string(length, allowed_chars): diff --git a/client_cli/pytests/common/json_isi_examples/unregister_asset.json b/client_cli/pytests/common/json_isi_examples/unregister_asset.json index ac3d7f314f9..837355581fb 100644 --- a/client_cli/pytests/common/json_isi_examples/unregister_asset.json +++ b/client_cli/pytests/common/json_isi_examples/unregister_asset.json @@ -1,7 +1,7 @@ [{ "Unregister": { "Asset": { - "object_id": "rose#alice@wonderland" + "object_id": "rose#ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } } -}] \ No newline at end of file +}] diff --git a/client_cli/pytests/models/account.py b/client_cli/pytests/models/account.py index 7f3acb01d67..7e15d614919 100644 --- a/client_cli/pytests/models/account.py +++ b/client_cli/pytests/models/account.py @@ -10,17 +10,14 @@ class Account: """ Account class represents an Iroha account. - :param name: The name of the account. - :type name: str + :param signatory: The signatory of the account. + :type signatory: str :param domain: The domain of the account. :type domain: str - :param public_key: The public key of the account. - :type public_key: str """ - name: str + signatory: str domain: str - public_key: str = "" def __repr__(self): - return f"{self.name}@{self.domain}" + return f"{self.signatory}@{self.domain}" diff --git a/client_cli/pytests/src/client_cli/client_cli.py b/client_cli/pytests/src/client_cli/client_cli.py index fd751c77f65..c78373fa2cf 100644 --- a/client_cli/pytests/src/client_cli/client_cli.py +++ b/client_cli/pytests/src/client_cli/client_cli.py @@ -134,22 +134,19 @@ def domain(self, domain: str): self.execute() return self - def account(self, account: str, domain: str, key: str): + def account(self, signatory: str, domain: str): """ - Executes the 'account' command for the given account, domain, and key. + Executes the 'account' command for the given signatory and domain. - :param account: The account to be queried. - :type account: str + :param signatory: The signatory of the account. + :type signatory: str :param domain: The domain of the account. :type domain: str - :param key: The key for the account. - :type key: str :return: The current ClientCli object. :rtype: ClientCli """ self.command.insert(2, "account") - self.command.append("--id=" + account + "@" + domain) - self.command.append("--key=ed0120" + key) + self.command.append("--id=" + signatory + "@" + domain) self.execute() return self @@ -172,11 +169,11 @@ def asset(self, asset_definition=None, account=None, value_of_value_type=None): "--asset-id=" + asset_definition.name + "#" - + account.domain + + asset_definition.domain + "#" - + account.name + + account.signatory + "@" - + asset_definition.domain + + account.domain ) self.command.append("--quantity=" + value_of_value_type) self.execute() @@ -204,11 +201,11 @@ def transfer(self, asset, source_account, target_account, quantity: str): "--asset-id=" + asset.name + "#" - + source_account.domain + + asset.domain + "#" - + source_account.name + + source_account.signatory + "@" - + asset.domain + + source_account.domain ) self.command.append("--quantity=" + quantity) self.execute() @@ -232,11 +229,11 @@ def burn(self, account, asset, quantity: str): "--asset-id=" + asset.name + "#" - + account.domain + + asset.domain + "#" - + account.name + + account.signatory + "@" - + asset.domain + + account.domain ) self.command.append("--quantity=" + quantity) self.execute() diff --git a/client_cli/pytests/src/client_cli/configuration.py b/client_cli/pytests/src/client_cli/configuration.py index 5e04cdfbecd..897eec066f8 100644 --- a/client_cli/pytests/src/client_cli/configuration.py +++ b/client_cli/pytests/src/client_cli/configuration.py @@ -122,42 +122,22 @@ def env(self): # return self._config['TORII_API_URL' return {**os.environ, **self._envs} - @property - def account_id(self): - """ - Get the ACCOUNT_ID configuration value. - - :return: The ACCOUNT_ID. - :rtype: str - """ - return self._config["account"]["id"] - - @property - def account_name(self): - """ - Get the account name from the ACCOUNT_ID configuration value. - - :return: The account name. - :rtype: str - """ - return self.account_id.split("@")[0] - @property def account_domain(self): """ - Get the account domain from the ACCOUNT_ID configuration value. + Get the ACCOUNT_DOMAIN configuration value. :return: The account domain. :rtype: str """ - return self.account_id.split("@")[1] + return self._config["account"]["domain_id"] @property - def public_key(self): + def account_signatory(self): """ Get the PUBLIC_KEY configuration value. - :return: The public key. + :return: The account signatory. :rtype: str """ - return self._config["account"]["public_key"].split("ed0120")[1] + return self._config["account"]["public_key"] diff --git a/client_cli/pytests/src/client_cli/iroha.py b/client_cli/pytests/src/client_cli/iroha.py index 8c35810c21a..7bfa0ba3af6 100644 --- a/client_cli/pytests/src/client_cli/iroha.py +++ b/client_cli/pytests/src/client_cli/iroha.py @@ -87,7 +87,7 @@ def assets(self) -> Dict[str, str]: Retrieve assets from the Iroha network and return them as a dictionary where the keys are asset ids and the values are the corresponding asset objects. - :return: Dictionary of assets. + :return: Dictionary of assets. :rtype: Dict[str, Any] """ self._execute_command("asset") diff --git a/client_cli/pytests/test/__init__.py b/client_cli/pytests/test/__init__.py index ab75290e556..1ca1a357dae 100644 --- a/client_cli/pytests/test/__init__.py +++ b/client_cli/pytests/test/__init__.py @@ -3,7 +3,6 @@ """ from .conftest import ( - GIVEN_127_length_name, GIVEN_128_length_name, GIVEN_129_length_name, GIVEN_currently_account_quantity_with_two_quantity_of_asset, diff --git a/client_cli/pytests/test/accounts/conftest.py b/client_cli/pytests/test/accounts/conftest.py index 7329c22d45f..f92932bfcb9 100644 --- a/client_cli/pytests/test/accounts/conftest.py +++ b/client_cli/pytests/test/accounts/conftest.py @@ -1,5 +1,4 @@ from test import ( - GIVEN_127_length_name, GIVEN_129_length_name, GIVEN_fake_name, GIVEN_key_with_invalid_character_in_key, diff --git a/client_cli/pytests/test/accounts/test_accounts_query_filters.py b/client_cli/pytests/test/accounts/test_accounts_query_filters.py index bb13afe52bf..6ff50159468 100644 --- a/client_cli/pytests/test/accounts/test_accounts_query_filters.py +++ b/client_cli/pytests/test/accounts/test_accounts_query_filters.py @@ -26,28 +26,10 @@ def condition(): client_cli.wait_for(condition) -def test_filter_by_account_name(GIVEN_registered_account): - def condition(): - name = GIVEN_registered_account.name - with allure.step(f'WHEN client_cli query accounts with name "{name}"'): - accounts = iroha.list_filter( - {"Identifiable": {"StartsWith": f"{name}@"}} - ).accounts() - with allure.step("THEN Iroha should return only accounts with this name"): - allure.attach( - json.dumps(accounts), - name="accounts", - attachment_type=allure.attachment_type.JSON, - ) - return accounts and all(account.startswith(name) for account in accounts) - - client_cli.wait_for(condition) - - def test_filter_by_account_id(GIVEN_registered_account): def condition(): account_id = ( - GIVEN_registered_account.name + "@" + GIVEN_registered_account.domain + GIVEN_registered_account.signatory + "@" + GIVEN_registered_account.domain ) with allure.step( f'WHEN client_cli query accounts with account id "{account_id}"' diff --git a/client_cli/pytests/test/accounts/test_register_accounts.py b/client_cli/pytests/test/accounts/test_register_accounts.py index 17b82efa853..4c0dec1b293 100644 --- a/client_cli/pytests/test/accounts/test_register_accounts.py +++ b/client_cli/pytests/test/accounts/test_register_accounts.py @@ -12,67 +12,39 @@ def story_account_register_account(): @allure.label("sdk_test_id", "register_account") -def test_register_account(GIVEN_fake_name, GIVEN_registered_domain, GIVEN_public_key): +def test_register_account(GIVEN_public_key, GIVEN_registered_domain): with allure.step( - f'WHEN client_cli registers the account "{GIVEN_fake_name}" ' + f'WHEN client_cli registers the account "{GIVEN_public_key}" ' f'in the "{GIVEN_registered_domain.name}" domain' ): client_cli.register().account( - account=GIVEN_fake_name, + signatory=GIVEN_public_key, domain=GIVEN_registered_domain.name, - key=GIVEN_public_key, ) - registered = GIVEN_fake_name + "@" + GIVEN_registered_domain.name + registered = GIVEN_public_key + "@" + GIVEN_registered_domain.name with allure.step(f'THEN Iroha should have the "{registered}" account'): iroha.should(have.account(registered)) -@allure.label("sdk_test_id", "register_account_with_two_public_keys") -@pytest.mark.xfail(reason="TO DO") -def test_register_account_with_two_public_keys( - GIVEN_fake_name, GIVEN_registered_domain, GIVEN_public_key -): - assert 0 - - -@allure.label("sdk_test_id", "register_account_with_empty_name") -def test_register_account_with_empty_name(GIVEN_registered_domain, GIVEN_public_key): - with allure.step( - f"WHEN client_cli tries to register an account with an empty name " - f'in the "{GIVEN_registered_domain.name}" domain' - ): - client_cli.register().account( - account="", domain=GIVEN_registered_domain.name, key=GIVEN_public_key - ) - with allure.step( - f'THEN сlient_cli should have the account error: "{Stderr.CANNOT_BE_EMPTY}"' - ): - client_cli.should(have.error(Stderr.CANNOT_BE_EMPTY.value)) - - -@allure.label("sdk_test_id", "register_account_with_existing_name") -def test_register_account_with_existing_name( - GIVEN_registered_domain, GIVEN_public_key, GIVEN_registered_account +@allure.label("sdk_test_id", "register_account_with_existing_signatory") +def test_register_account_with_existing_signatory( + GIVEN_registered_domain, GIVEN_registered_account ): with allure.step( f"WHEN client_cli tries to register an account " - f'with the same name "{GIVEN_registered_domain.name}" ' + f'with the same signatory "{GIVEN_registered_account.signatory}" ' f'in the "{GIVEN_registered_domain.name}" domain' ): client_cli.register().account( - account=GIVEN_registered_account.name, + signatory=GIVEN_registered_account.signatory, domain=GIVEN_registered_account.domain, - key=GIVEN_registered_account.public_key, ) - with allure.step( - f'THEN client_cli should have the account error: "{GIVEN_registered_domain.name}"' - ): + with allure.step("THEN client_cli should have the account error"): client_cli.should(have.error(Stderr.REPETITION.value)) @allure.label("sdk_test_id", "register_account_with_invalid_domain") def test_register_account_with_invalid_domain( - GIVEN_fake_name, GIVEN_not_existing_name, GIVEN_public_key, ): @@ -80,9 +52,8 @@ def test_register_account_with_invalid_domain( "WHEN client_cli tries to register an account with an invalid domain" ): client_cli.register().account( - account=GIVEN_fake_name, + signatory=GIVEN_public_key, domain=GIVEN_not_existing_name, - key=GIVEN_public_key, ) with allure.step("THEN client_cli should have the error"): client_cli.should(have.error(Stderr.FAILED_TO_FIND_DOMAIN.value)) @@ -90,61 +61,19 @@ def test_register_account_with_invalid_domain( @allure.label("sdk_test_id", "register_account_with_invalid_character_in_key") def test_register_account_with_invalid_character_in_key( - GIVEN_fake_name, GIVEN_registered_domain, GIVEN_key_with_invalid_character_in_key + GIVEN_registered_domain, GIVEN_key_with_invalid_character_in_key ): with allure.step( "WHEN client_cli tries to register an account with invalid character in the key" ): client_cli.register().account( - account=GIVEN_fake_name, + signatory=GIVEN_key_with_invalid_character_in_key, domain=GIVEN_registered_domain.name, - key=GIVEN_key_with_invalid_character_in_key, ) with allure.step("THEN client_cli should have the error"): client_cli.should(have.error(Stderr.INVALID_CHARACTER.value)) -@allure.label("sdk_test_id", "register_account_with_max_name") -def test_register_account_with_max_name( - GIVEN_127_length_name, GIVEN_registered_domain, GIVEN_public_key -): - with allure.step("WHEN client_cli register an account with the 127 length name"): - client_cli.register().account( - account=GIVEN_127_length_name, - domain=GIVEN_registered_domain.name, - key=GIVEN_public_key, - ) - registered = GIVEN_127_length_name + "@" + GIVEN_registered_domain.name - with allure.step(f'THEN Iroha should have the "{registered}" account'): - iroha.should(have.account(registered)) - - -@allure.label("sdk_test_id", "register_account_with_special_characters") -@pytest.mark.xfail(reason="TO DO") -def test_register_account_with_special_characters( - GIVEN_registered_domain, GIVEN_public_key -): - assert 0 - - -@allure.label("sdk_test_id", "register_account_with_long_account_name") -def test_register_account_with_long_account_name( - GIVEN_registered_domain, GIVEN_129_length_name, GIVEN_public_key -): - with allure.step( - "WHEN client_cli tries to register an account with a name with 129 characters" - ): - client_cli.register().account( - account=GIVEN_129_length_name, - domain=GIVEN_registered_domain.name, - key=GIVEN_public_key, - ) - with allure.step( - f'THEN client_cli should have the name error: "{Stderr.TOO_LONG}"' - ): - client_cli.should(have.error(Stderr.TOO_LONG.value)) - - @allure.label("sdk_test_id", "register_account_with_metadata") @pytest.mark.xfail(reason="TO DO") def test_register_account_with_metadata( diff --git a/client_cli/pytests/test/assets/test_assets_query_filters.py b/client_cli/pytests/test/assets/test_assets_query_filters.py index 1a44e6e8683..918a255079d 100644 --- a/client_cli/pytests/test/assets/test_assets_query_filters.py +++ b/client_cli/pytests/test/assets/test_assets_query_filters.py @@ -69,7 +69,7 @@ def condition(): asset_id = ( GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition.name + "##" - + GIVEN_currently_authorized_account.name + + GIVEN_currently_authorized_account.signatory + "@" + GIVEN_currently_authorized_account.domain ) diff --git a/client_cli/pytests/test/assets/test_burn_assets.py b/client_cli/pytests/test/assets/test_burn_assets.py index fdbc9a40864..b7d22f3ab3b 100644 --- a/client_cli/pytests/test/assets/test_burn_assets.py +++ b/client_cli/pytests/test/assets/test_burn_assets.py @@ -16,7 +16,7 @@ def test_burn_asset_for_account_in_same_domain( GIVEN_currently_account_quantity_with_two_quantity_of_asset, ): with allure.step( - f"WHEN {GIVEN_currently_authorized_account.name} burns 1" + f"WHEN {GIVEN_currently_authorized_account.signatory} burns 1" f"of {GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition.name}" ): client_cli.burn( @@ -25,7 +25,7 @@ def test_burn_asset_for_account_in_same_domain( quantity="1", ) with allure.step( - f"THEN {GIVEN_currently_authorized_account.name} " + f"THEN {GIVEN_currently_authorized_account.signatory} " f"has 1 of {GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition.name}" ): iroha.should( diff --git a/client_cli/pytests/test/assets/test_mint_assets.py b/client_cli/pytests/test/assets/test_mint_assets.py index 869049434e4..ef83e794df0 100644 --- a/client_cli/pytests/test/assets/test_mint_assets.py +++ b/client_cli/pytests/test/assets/test_mint_assets.py @@ -16,9 +16,9 @@ def test_mint_asset_for_account_in_same_domain( GIVEN_numeric_value, ): with allure.step( - f'WHEN client_cli mint the asset "{GIVEN_registered_asset_definition_with_numeric_value_type.name}" ' - f'for the "{GIVEN_registered_account.name}" ' - f'in the "{GIVEN_registered_asset_definition_with_numeric_value_type.domain}" domain' + f'WHEN client_cli mint "{GIVEN_numeric_value}" of ' + f'"{GIVEN_registered_asset_definition_with_numeric_value_type}" ' + f'for the "{GIVEN_registered_account}"' ): client_cli.mint().asset( account=GIVEN_registered_account, @@ -26,8 +26,9 @@ def test_mint_asset_for_account_in_same_domain( value_of_value_type=GIVEN_numeric_value, ) with allure.step( - f'THEN "{GIVEN_registered_account}" account ' - f'should have the "{GIVEN_registered_asset_definition_with_numeric_value_type}" asset definition' + f'THEN "{GIVEN_registered_account}" ' + f'should have the "{GIVEN_numeric_value}" of ' + f'"{GIVEN_registered_asset_definition_with_numeric_value_type}"' ): iroha.should( have.asset( @@ -59,8 +60,8 @@ def test_mint_asset_quantity_after_minting(GIVEN_minted_asset_quantity): expected_quantity = int(GIVEN_minted_asset_quantity.value) + 1 with allure.step( f'THEN "{GIVEN_minted_asset_quantity.account}" account ' - f'should have the "{expected_quantity}" asset definition ' - f"with updated quantity" + f'should have the "{GIVEN_minted_asset_quantity.definition}" asset ' + f'with updated quantity "{expected_quantity}"' ): iroha.should( have.asset_has_quantity( diff --git a/client_cli/pytests/test/assets/test_register_asset_definitions.py b/client_cli/pytests/test/assets/test_register_asset_definitions.py index 9110cd3bb16..03233ccc373 100644 --- a/client_cli/pytests/test/assets/test_register_asset_definitions.py +++ b/client_cli/pytests/test/assets/test_register_asset_definitions.py @@ -119,10 +119,8 @@ def test_register_asset_with_empty_name(GIVEN_registered_domain): client_cli.register().asset().definition( asset="", domain=GIVEN_registered_domain.name, value_type="Numeric" ) - with allure.step( - f'THEN сlient_cli should have the asset error: "{Stderr.CANNOT_BE_EMPTY}"' - ): - client_cli.should(have.error(Stderr.CANNOT_BE_EMPTY.value)) + with allure.step(f'THEN сlient_cli should have the asset error: "{Stderr.EMPTY}"'): + client_cli.should(have.error(Stderr.EMPTY.value)) @allure.label("sdk_test_id", "register_asset_with_not_existing_domain") diff --git a/client_cli/pytests/test/assets/test_transfer_assets.py b/client_cli/pytests/test/assets/test_transfer_assets.py index f78a2da2daa..4e842185c58 100644 --- a/client_cli/pytests/test/assets/test_transfer_assets.py +++ b/client_cli/pytests/test/assets/test_transfer_assets.py @@ -18,9 +18,9 @@ def test_transfer_asset( GIVEN_currently_account_quantity_with_two_quantity_of_asset, ): with allure.step( - f"WHEN {GIVEN_currently_authorized_account.name} transfers 1 Quantity" + f"WHEN {GIVEN_currently_authorized_account.signatory} transfers 1 Quantity" f"of {GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition.name}" - f"to {GIVEN_registered_account.name}" + f"to {GIVEN_registered_account.signatory}" ): client_cli.transfer( asset=GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition, @@ -30,7 +30,7 @@ def test_transfer_asset( ) with allure.step( - f"THEN {GIVEN_currently_authorized_account.name} has 1 Quantity " + f"THEN {GIVEN_currently_authorized_account.signatory} has 1 Quantity " f"of {GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition.name}" f"AND {GIVEN_registered_account} has 1 more Quantity" ): @@ -51,9 +51,9 @@ def test_transfer_with_insufficient_funds( GIVEN_currently_account_quantity_with_two_quantity_of_asset, ): with allure.step( - f"WHEN {GIVEN_currently_authorized_account.name} attempts to transfer more than available Quantity" - f"of {GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition.name}" - f"to {GIVEN_registered_account.name}" + f"WHEN {GIVEN_currently_authorized_account.signatory} attempts to transfer more than available " + f"Quantity of {GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition.name}" + f"to {GIVEN_registered_account.signatory}" ): client_cli.transfer( asset=GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition, @@ -65,9 +65,9 @@ def test_transfer_with_insufficient_funds( ), ) with allure.step( - f"THEN {GIVEN_currently_authorized_account.name} still has the original Quantity " + f"THEN {GIVEN_currently_authorized_account.signatory} still has the original Quantity " f"of {GIVEN_currently_account_quantity_with_two_quantity_of_asset.definition.name}" - f"AND {GIVEN_registered_account.name} does not receive any additional Quantity" + f"AND {GIVEN_registered_account.signatory} does not receive any additional Quantity" ): client_cli.should(have.error(Stderr.INSUFFICIENT_FUNDS.value)) @@ -82,8 +82,8 @@ def test_exchange_asset_through_intermediary( GIVEN_buyer_account_with_eth, ): # with allure.step(f'WHEN {GIVEN_intermediary_with_transfer_permission.name}' - # f'exchanges BTC from {GIVEN_seller_account_with_btc.name}' - # f'with ETH from {GIVEN_buyer_account_with_eth.name}'): + # f'exchanges BTC from {GIVEN_seller_account_with_btc.signatory}' + # f'with ETH from {GIVEN_buyer_account_with_eth.signatory}'): # client_cli.exchange_assets( # intermediary_account=GIVEN_intermediary_with_transfer_permission, # seller_account=GIVEN_seller_account_with_btc, @@ -91,8 +91,8 @@ def test_exchange_asset_through_intermediary( # btc_quantity="1", # eth_quantity="10") # - # with allure.step(f'THEN {GIVEN_seller_account_with_btc.name} receives ETH ' - # f'AND {GIVEN_buyer_account_with_eth.name} receives BTC'): + # with allure.step(f'THEN {GIVEN_seller_account_with_btc.signatory} receives ETH ' + # f'AND {GIVEN_buyer_account_with_eth.signatory} receives BTC'): # iroha.should(have.asset( # f'eth#{GIVEN_seller_account_with_btc.domain}', quantity="10")) # iroha.should(have.asset( diff --git a/client_cli/pytests/test/assets/test_unregister_asset.py b/client_cli/pytests/test/assets/test_unregister_asset.py index 997240e516a..bd48a79e0c2 100644 --- a/client_cli/pytests/test/assets/test_unregister_asset.py +++ b/client_cli/pytests/test/assets/test_unregister_asset.py @@ -12,7 +12,11 @@ def story_account_unregisters_asset(): @allure.label("sdk_test_id", "unregister_asset") @pytest.mark.parametrize( - "GIVEN_numeric_asset_for_account", ["alice@wonderland"], indirect=True + "GIVEN_numeric_asset_for_account", + [ + "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" + ], + indirect=True, ) @pytest.mark.xfail(reason="wait for #4039") def test_unregister_asset( diff --git a/client_cli/pytests/test/conftest.py b/client_cli/pytests/test/conftest.py index fbfb96ee4b8..364456252ff 100644 --- a/client_cli/pytests/test/conftest.py +++ b/client_cli/pytests/test/conftest.py @@ -67,15 +67,12 @@ def GIVEN_registered_domain_with_uppercase_letter(GIVEN_registered_domain): @pytest.fixture() def GIVEN_registered_account(GIVEN_registered_domain, GIVEN_public_key): """Fixture to create an account.""" - name = fake_name() - account = Account( - name=name, domain=GIVEN_registered_domain.name, public_key=GIVEN_public_key - ) + account = Account(signatory=GIVEN_public_key, domain=GIVEN_registered_domain.name) with allure.step( - f'GIVEN the account "{name}" in the "{GIVEN_registered_domain.name}" domain' + f'GIVEN the account "{GIVEN_public_key}" in the "{GIVEN_registered_domain.name}" domain' ): client_cli.register().account( - account=account.name, domain=account.domain, key=account.public_key + signatory=account.signatory, domain=account.domain ) return account @@ -84,12 +81,11 @@ def GIVEN_registered_account(GIVEN_registered_domain, GIVEN_public_key): def GIVEN_currently_authorized_account(): """Fixture to get the currently authorized account.""" account: Account = Account( - name=config.account_name, + signatory=config.account_signatory, domain=config.account_domain, - public_key=config.public_key, ) with allure.step( - f'GIVEN the currently authorized account "{account.name}" ' + f'GIVEN the currently authorized account "{account.signatory}" ' f'in the "{account.domain}" domain' ): return account @@ -106,7 +102,7 @@ def GIVEN_currently_account_quantity_with_two_quantity_of_asset( value_type=GIVEN_numeric_value_type, ) asset = Asset( - definition=asset_def, value="2", account=GIVEN_currently_authorized_account.name + definition=asset_def, value="2", account=GIVEN_currently_authorized_account ) name = fake_name() with allure.step( @@ -132,12 +128,14 @@ def GIVEN_numeric_asset_for_account( ): """Fixture to get an asset for a given account and domain with specified quantity.""" account, domain = request.param.split("@") - account = Account(name=account, domain=domain) + account = Account(signatory=account, domain=domain) asset_def = AssetDefinition( name=GIVEN_fake_asset_name, domain=domain, value_type=GIVEN_numeric_value_type ) - asset = Asset(definition=asset_def, value=GIVEN_numeric_value, account=account.name) + asset = Asset( + definition=asset_def, value=GIVEN_numeric_value, account=account.signatory + ) with allure.step( f'GIVEN the asset_definition "{asset_def.name}" ' f'in the "{domain}" domain' @@ -328,13 +326,6 @@ def GIVEN_129_length_name(): return ident -@pytest.fixture() -def GIVEN_127_length_name(): - ident = generate_random_string_without_reserved_chars(127) - with allure.step(f'GIVEN a name with 127 length "{ident}"'): - return ident - - @pytest.fixture() def GIVEN_string_with_reserved_character(): """Fixture to provide a random string with reserved characters.""" diff --git a/client_cli/pytests/test/domains/test_register_domains.py b/client_cli/pytests/test/domains/test_register_domains.py index d369aba3b89..7f01073934e 100644 --- a/client_cli/pytests/test/domains/test_register_domains.py +++ b/client_cli/pytests/test/domains/test_register_domains.py @@ -25,10 +25,8 @@ def test_register_empty_domain( ): with allure.step("WHEN client_cli registers an empty domain"): client_cli.register().domain("") - with allure.step( - f'THEN client_cli should have the domain error: "{Stderr.CANNOT_BE_EMPTY}"' - ): - client_cli.should(have.error(Stderr.CANNOT_BE_EMPTY.value)) + with allure.step(f'THEN client_cli should have the domain error: "{Stderr.EMPTY}"'): + client_cli.should(have.error(Stderr.EMPTY.value)) @allure.label("sdk_test_id", "register_existing_domain") @@ -38,7 +36,7 @@ def test_register_existing_domain(GIVEN_registered_domain): ): client_cli.register().domain(GIVEN_registered_domain.name) with allure.step( - f'THEN client_cli should have the domain error: "{GIVEN_registered_domain.name}"' + f'THEN client_cli should have the domain error: "{GIVEN_registered_domain.name}"' ): client_cli.should(have.error(Stderr.REPETITION.value)) diff --git a/client_cli/pytests/test/triggers/test_register_trigger.py b/client_cli/pytests/test/triggers/test_register_trigger.py index e1c0e5169a2..b9164bbabe5 100644 --- a/client_cli/pytests/test/triggers/test_register_trigger.py +++ b/client_cli/pytests/test/triggers/test_register_trigger.py @@ -18,6 +18,14 @@ def test_register_trigger(GIVEN_currently_authorized_account): ): client_cli.register_trigger(GIVEN_currently_authorized_account) with allure.step( - "THEN Iroha should have the asset with nft_number_1_for_genesis##genesis@genesis" + "THEN Iroha should have the asset with nft_number_1_for_genesis##\ + ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis" + # TODO use the same source as GENESIS_PUBLIC_KEY of peer ): - iroha.should(have.asset("nft_number_1_for_genesis##genesis@genesis")) + iroha.should( + have.asset( + "nft_number_1_for_genesis##\ + ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis" + # TODO use the same source as GENESIS_PUBLIC_KEY of peer + ) + ) diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index 666f6902c91..1cfa5487f2d 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -504,9 +504,6 @@ mod account { pub enum Args { /// Register account Register(Register), - /// Set something in account - #[command(subcommand)] - Set(Set), /// List accounts #[command(subcommand)] List(List), @@ -520,7 +517,6 @@ mod account { fn run(self, context: &mut dyn RunContext) -> Result<()> { match_all!((self, context), { Args::Register, - Args::Set, Args::List, Args::Grant, Args::ListPermissions, @@ -534,74 +530,19 @@ mod account { /// Id of account in form `name@domain_name` #[arg(short, long)] pub id: AccountId, - /// Its public key - #[arg(short, long)] - pub key: PublicKey, #[command(flatten)] pub metadata: MetadataArgs, } impl RunArgs for Register { fn run(self, context: &mut dyn RunContext) -> Result<()> { - let Self { id, key, metadata } = self; - let create_account = - iroha_client::data_model::isi::Register::account(Account::new(id, key)); + let Self { id, metadata } = self; + let create_account = iroha_client::data_model::isi::Register::account(Account::new(id)); submit([create_account], metadata.load()?, context) .wrap_err("Failed to register account") } } - /// Set subcommand of account - #[derive(clap::Subcommand, Debug)] - pub enum Set { - /// Signature condition - SignatureCondition(SignatureCondition), - } - - impl RunArgs for Set { - fn run(self, context: &mut dyn RunContext) -> Result<()> { - match_all!((self, context), { Set::SignatureCondition }) - } - } - - #[derive(Debug, Clone)] - pub struct Signature(SignatureCheckCondition); - - impl FromStr for Signature { - type Err = Error; - fn from_str(s: &str) -> Result { - let err_msg = format!("Failed to open the signature condition file {}", &s); - let deser_err_msg = - format!("Failed to deserialize signature condition from file {}", &s); - let content = fs::read_to_string(s).wrap_err(err_msg)?; - let condition: SignatureCheckCondition = - json5::from_str(&content).wrap_err(deser_err_msg)?; - Ok(Self(condition)) - } - } - - /// Set accounts signature condition - #[derive(clap::Args, Debug)] - pub struct SignatureCondition { - /// Signature condition file - pub condition: Signature, - #[command(flatten)] - pub metadata: MetadataArgs, - } - - impl RunArgs for SignatureCondition { - fn run(self, context: &mut dyn RunContext) -> Result<()> { - let account_id = context.configuration().account_id.clone(); - let Self { - condition: Signature(condition), - metadata, - } = self; - let mint_box = Mint::account_signature_check_condition(condition, account_id); - submit([mint_box], metadata.load()?, context) - .wrap_err("Failed to set signature condition") - } - } - /// List accounts with this command #[derive(clap::Subcommand, Debug, Clone)] pub enum List { diff --git a/config/iroha_test_config.toml b/config/iroha_test_config.toml index 5279f76639c..f56d5dfe1bb 100644 --- a/config/iroha_test_config.toml +++ b/config/iroha_test_config.toml @@ -6,8 +6,8 @@ private_key = "802640282ED9F3CF92811C3818DBC4AE594ED59DC1A2F78E4241E31924E101D6B address = "127.0.0.1:1337" [genesis] -public_key = "ed01204CFFD0EE429B1BDD36B3910EC570852B8BB63F18750341772FB46BC856C5CAAF" file = "./genesis.json" +public_key = "ed01204CFFD0EE429B1BDD36B3910EC570852B8BB63F18750341772FB46BC856C5CAAF" private_key = "802640D748E18CE60CB30DEA3E73C9019B7AF45A8D465E3D71BCC9A5EF99A008205E534CFFD0EE429B1BDD36B3910EC570852B8BB63F18750341772FB46BC856C5CAAF" [torii] @@ -31,4 +31,3 @@ public_key = "ed01208E351A70B6A603ED285D666B8D689B680865913BA03CE29FB7D13A166C4E [logger] format = "pretty" - diff --git a/configs/client.template.toml b/configs/client.template.toml index 7322b788374..858a4c1df8e 100644 --- a/configs/client.template.toml +++ b/configs/client.template.toml @@ -8,7 +8,7 @@ # password = [account] -# id = +# domain_id = # public_key = # private_key = diff --git a/configs/swarm/client.toml b/configs/swarm/client.toml index 750be32505b..f8fd0815237 100644 --- a/configs/swarm/client.toml +++ b/configs/swarm/client.toml @@ -6,6 +6,6 @@ web_login = "mad_hatter" password = "ilovetea" [account] -id = "alice@wonderland" -public_key = "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" -private_key = "8026409AC47ABF59B356E0BD7DCBBBB4DEC080E302156A48CA907E47CB6AEA1D32719E7233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" +domain_id = "wonderland" +public_key = "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03" +private_key = "802640CCF31D85E3B32A4BEA59987CE0C78E3B8E2DB93881468AB2435FE45D5C9DCD53CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03" diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index 9a8965b42ff..dc5f312aef7 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 e7126967f9e..91e1e0780eb 100644 --- a/configs/swarm/genesis.json +++ b/configs/swarm/genesis.json @@ -17,10 +17,7 @@ { "Register": { "Account": { - "id": "alice@wonderland", - "signatories": [ - "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" - ], + "id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland", "metadata": { "key": { "String": "value" @@ -32,10 +29,7 @@ { "Register": { "Account": { - "id": "bob@wonderland", - "signatories": [ - "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" - ], + "id": "ed012004FF5B81046DDCCF19E2E451C45DFB6F53759D4EB30FA2EFA807284D1CC33016@wonderland", "metadata": { "key": { "String": "value" @@ -67,10 +61,7 @@ { "Register": { "Account": { - "id": "carpenter@garden_of_live_flowers", - "signatories": [ - "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" - ], + "id": "ed0120E9F632D3034BAB6BB26D92AC8FD93EF878D9C5E69E01B61B4C47101884EE2F99@garden_of_live_flowers", "metadata": {} } } @@ -90,7 +81,7 @@ "Mint": { "Asset": { "object": "13", - "destination_id": "rose##alice@wonderland" + "destination_id": "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } } }, @@ -98,16 +89,25 @@ "Mint": { "Asset": { "object": "44", - "destination_id": "cabbage#garden_of_live_flowers#alice@wonderland" + "destination_id": "cabbage#garden_of_live_flowers#ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" + } + } + }, + { + "Transfer": { + "AssetDefinition": { + "source_id": "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis", + "object": "rose#wonderland", + "destination_id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } } }, { "Transfer": { "Domain": { - "source_id": "genesis@genesis", + "source_id": "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4@genesis", "object": "wonderland", - "destination_id": "alice@wonderland" + "destination_id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } } }, @@ -118,7 +118,7 @@ "definition_id": "CanSetParameters", "payload": null }, - "destination_id": "alice@wonderland" + "destination_id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } } }, @@ -172,13 +172,13 @@ { "definition_id": "CanRemoveKeyValueInAccount", "payload": { - "account_id": "alice@wonderland" + "account_id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } }, { "definition_id": "CanSetKeyValueInAccount", "payload": { - "account_id": "alice@wonderland" + "account_id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } } ] diff --git a/core/Cargo.toml b/core/Cargo.toml index c351be1cb0c..46b8ff1cc1d 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -68,6 +68,8 @@ uuid = { version = "1.8.0", features = ["v4"] } indexmap = "2.2.6" [dev-dependencies] +test_samples = { workspace = true } + criterion = { workspace = true } hex = { workspace = true } once_cell = { workspace = true } diff --git a/core/benches/blocks/apply_blocks.rs b/core/benches/blocks/apply_blocks.rs index bdf75e9e215..28daef9e720 100644 --- a/core/benches/blocks/apply_blocks.rs +++ b/core/benches/blocks/apply_blocks.rs @@ -1,6 +1,6 @@ use eyre::Result; use iroha_core::{block::CommittedBlock, prelude::*, state::State}; -use iroha_data_model::prelude::*; +use test_samples::gen_account_in; #[path = "./common.rs"] mod common; @@ -19,24 +19,23 @@ impl StateApplyBlocks { /// - Failed to parse [`AccountId`] /// - Failed to generate [`KeyPair`] /// - Failed to create instructions for block - pub fn setup(rt: &tokio::runtime::Handle) -> Result { + pub fn setup(rt: &tokio::runtime::Handle) -> Self { let domains = 100; let accounts_per_domain = 1000; let assets_per_domain = 1000; - let account_id: AccountId = "alice@wonderland".parse()?; - let key_pair = KeyPair::random(); - let state = build_state(rt, &account_id, &key_pair); + let (alice_id, alice_keypair) = gen_account_in("wonderland"); + let state = build_state(rt, &alice_id); let nth = 100; let instructions = [ - populate_state(domains, accounts_per_domain, assets_per_domain, &account_id), + populate_state(domains, accounts_per_domain, assets_per_domain, &alice_id), delete_every_nth(domains, accounts_per_domain, assets_per_domain, nth), restore_every_nth(domains, accounts_per_domain, assets_per_domain, nth), ]; let blocks = { // Create empty state because it will be changed during creation of block - let state = build_state(rt, &account_id, &key_pair); + let state = build_state(rt, &alice_id); instructions .into_iter() .map(|instructions| { @@ -44,8 +43,8 @@ impl StateApplyBlocks { let block = create_block( &mut state_block, instructions, - account_id.clone(), - &key_pair, + alice_id.clone(), + &alice_keypair, ); let _events = state_block.apply_without_execution(&block); state_block.commit(); @@ -54,7 +53,7 @@ impl StateApplyBlocks { .collect::>() }; - Ok(Self { state, blocks }) + Self { state, blocks } } /// Run benchmark body. diff --git a/core/benches/blocks/apply_blocks_benchmark.rs b/core/benches/blocks/apply_blocks_benchmark.rs index 93b1c56c5ef..27a4f381954 100644 --- a/core/benches/blocks/apply_blocks_benchmark.rs +++ b/core/benches/blocks/apply_blocks_benchmark.rs @@ -14,7 +14,7 @@ fn apply_blocks(c: &mut Criterion) { group.significance_level(0.1).sample_size(10); group.bench_function("apply_blocks", |b| { b.iter_batched_ref( - || StateApplyBlocks::setup(rt.handle()).expect("Failed to setup benchmark"), + || StateApplyBlocks::setup(rt.handle()), |bench| { StateApplyBlocks::measure(bench).expect("Failed to execute benchmark"); }, diff --git a/core/benches/blocks/apply_blocks_oneshot.rs b/core/benches/blocks/apply_blocks_oneshot.rs index db09e9d427f..6492d17e2c7 100644 --- a/core/benches/blocks/apply_blocks_oneshot.rs +++ b/core/benches/blocks/apply_blocks_oneshot.rs @@ -19,6 +19,6 @@ fn main() { iroha_logger::test_logger(); } iroha_logger::info!("Starting..."); - let bench = StateApplyBlocks::setup(rt.handle()).expect("Failed to setup benchmark"); + let bench = StateApplyBlocks::setup(rt.handle()); StateApplyBlocks::measure(&bench).expect("Failed to execute benchmark"); } diff --git a/core/benches/blocks/common.rs b/core/benches/blocks/common.rs index d88514f7c9f..996a40f29de 100644 --- a/core/benches/blocks/common.rs +++ b/core/benches/blocks/common.rs @@ -74,9 +74,9 @@ pub fn populate_state( owner_id.clone(), ); instructions.push(can_unregister_domain.into()); - for j in 0..accounts_per_domain { - let account_id = construct_account_id(j, domain_id.clone()); - let account = Account::new(account_id.clone(), KeyPair::random().into_parts().0); + for _ in 0..accounts_per_domain { + let account_id = generate_account_id(domain_id.clone()); + let account = Account::new(account_id.clone()); instructions.push(Register::account(account).into()); let can_unregister_account = Grant::permission( PermissionToken::new( @@ -118,7 +118,7 @@ pub fn delete_every_nth( } else { for j in 0..accounts_per_domain { if j % nth == 0 { - let account_id = construct_account_id(j, domain_id.clone()); + let account_id = generate_account_id(domain_id.clone()); instructions.push(Unregister::account(account_id.clone()).into()); } } @@ -148,8 +148,8 @@ pub fn restore_every_nth( } for j in 0..accounts_per_domain { if j % nth == 0 || i % nth == 0 { - let account_id = construct_account_id(j, domain_id.clone()); - let account = Account::new(account_id.clone(), KeyPair::random().into_parts().0); + let account_id = generate_account_id(domain_id.clone()); + let account = Account::new(account_id.clone()); instructions.push(Register::account(account).into()); } } @@ -164,11 +164,7 @@ pub fn restore_every_nth( instructions } -pub fn build_state( - rt: &tokio::runtime::Handle, - account_id: &AccountId, - key_pair: &KeyPair, -) -> State { +pub fn build_state(rt: &tokio::runtime::Handle, account_id: &AccountId) -> State { let kura = iroha_core::kura::Kura::blank_kura_for_testing(); let query_handle = { let _guard = rt.enter(); @@ -177,7 +173,7 @@ pub fn build_state( let mut domain = Domain::new(account_id.domain_id.clone()).build(account_id); domain.accounts.insert( account_id.clone(), - Account::new(account_id.clone(), key_pair.public_key().clone()).build(account_id), + Account::new(account_id.clone()).build(account_id), ); let state = State::new(World::with([domain], UniqueVec::new()), kura, query_handle); @@ -209,11 +205,8 @@ fn construct_domain_id(i: usize) -> DomainId { DomainId::from_str(&format!("non_inlinable_domain_name_{i}")).unwrap() } -fn construct_account_id(i: usize, domain_id: DomainId) -> AccountId { - AccountId::new( - domain_id, - Name::from_str(&format!("non_inlinable_account_name_{i}")).unwrap(), - ) +fn generate_account_id(domain_id: DomainId) -> AccountId { + AccountId::new(domain_id, KeyPair::random().into_parts().0) } fn construct_asset_definition_id(i: usize, domain_id: DomainId) -> AssetDefinitionId { diff --git a/core/benches/blocks/validate_blocks.rs b/core/benches/blocks/validate_blocks.rs index ac6de7fa5d5..0d26e9ed407 100644 --- a/core/benches/blocks/validate_blocks.rs +++ b/core/benches/blocks/validate_blocks.rs @@ -1,5 +1,6 @@ use iroha_core::{prelude::*, state::State}; use iroha_data_model::{isi::InstructionBox, prelude::*}; +use test_samples::gen_account_in; #[path = "./common.rs"] mod common; @@ -16,7 +17,8 @@ pub struct StateValidateBlocks { impl StateValidateBlocks { /// Create [`State`] and blocks for benchmarking /// - /// # Errors + /// # Panics + /// /// - Failed to parse [`AccountId`] /// - Failed to generate [`KeyPair`] /// - Failed to create instructions for block @@ -24,13 +26,12 @@ impl StateValidateBlocks { let domains = 100; let accounts_per_domain = 1000; let assets_per_domain = 1000; - let account_id: AccountId = "alice@wonderland".parse().unwrap(); - let key_pair = KeyPair::random(); - let state = build_state(rt, &account_id, &key_pair); + let (alice_id, alice_keypair) = gen_account_in("wonderland"); + let state = build_state(rt, &alice_id); let nth = 100; let instructions = [ - populate_state(domains, accounts_per_domain, assets_per_domain, &account_id), + populate_state(domains, accounts_per_domain, assets_per_domain, &alice_id), delete_every_nth(domains, accounts_per_domain, assets_per_domain, nth), restore_every_nth(domains, accounts_per_domain, assets_per_domain, nth), ] @@ -40,8 +41,8 @@ impl StateValidateBlocks { Self { state, instructions, - key_pair, - account_id, + key_pair: alice_keypair, + account_id: alice_id, } } diff --git a/core/benches/kura.rs b/core/benches/kura.rs index f9b53e25190..a0ba9fb1139 100644 --- a/core/benches/kura.rs +++ b/core/benches/kura.rs @@ -16,23 +16,20 @@ use iroha_core::{ use iroha_crypto::KeyPair; use iroha_data_model::{prelude::*, transaction::TransactionLimits}; use iroha_primitives::unique_vec::UniqueVec; +use test_samples::gen_account_in; use tokio::{fs, runtime::Runtime}; async fn measure_block_size_for_n_executors(n_executors: u32) { let chain_id = ChainId::from("0"); - let alice_id = AccountId::from_str("alice@test").expect("tested"); - let bob_id = AccountId::from_str("bob@test").expect("tested"); + let (alice_id, alice_keypair) = gen_account_in("test"); + let (bob_id, _bob_keypair) = gen_account_in("test"); let xor_id = AssetDefinitionId::from_str("xor#test").expect("tested"); - let alice_xor_id = AssetId::new(xor_id, alice_id); + let alice_xor_id = AssetId::new(xor_id, alice_id.clone()); let transfer = Transfer::asset_numeric(alice_xor_id, 10u32, bob_id); - let keypair = KeyPair::random(); - let tx = TransactionBuilder::new( - chain_id.clone(), - AccountId::from_str("alice@wonderland").expect("checked"), - ) - .with_instructions([transfer]) - .sign(&keypair); + let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) + .with_instructions([transfer]) + .sign(&alice_keypair); let transaction_limits = TransactionLimits { max_instruction_number: 4096, max_wasm_size_bytes: 0, diff --git a/core/benches/validation.rs b/core/benches/validation.rs index d7e5459f090..da0917a18ef 100644 --- a/core/benches/validation.rs +++ b/core/benches/validation.rs @@ -1,7 +1,5 @@ #![allow(missing_docs)] -use std::str::FromStr as _; - use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use iroha_core::{ block::*, @@ -12,64 +10,46 @@ use iroha_core::{ sumeragi::network_topology::Topology, tx::TransactionExecutor, }; -use iroha_data_model::{isi::InstructionBox, prelude::*, transaction::TransactionLimits}; +use iroha_data_model::{ + account::AccountId, isi::InstructionBox, prelude::*, transaction::TransactionLimits, +}; use iroha_primitives::unique_vec::UniqueVec; +use once_cell::sync::Lazy; +use test_samples::gen_account_in; -const START_DOMAIN: &str = "start"; -const START_ACCOUNT: &str = "starter"; +static STARTER_DOMAIN: Lazy = Lazy::new(|| "start".parse().unwrap()); +static STARTER_KEYPAIR: Lazy = Lazy::new(|| KeyPair::random()); +static STARTER_ID: Lazy = + Lazy::new(|| AccountId::new(STARTER_DOMAIN.clone(), STARTER_KEYPAIR.public_key().clone())); const TRANSACTION_LIMITS: TransactionLimits = TransactionLimits { max_instruction_number: 4096, max_wasm_size_bytes: 0, }; -fn build_test_transaction(keys: &KeyPair, chain_id: ChainId) -> SignedTransaction { - let domain_name = "domain"; - let domain_id = DomainId::from_str(domain_name).expect("does not panic"); - let create_domain: InstructionBox = Register::domain(Domain::new(domain_id)).into(); - let account_name = "account"; - let (public_key, _) = KeyPair::random().into_parts(); - let create_account = Register::account(Account::new( - AccountId::new( - domain_name.parse().expect("Valid"), - account_name.parse().expect("Valid"), - ), - public_key, - )) - .into(); - let asset_definition_id = AssetDefinitionId::new( - "xor".parse().expect("Valid"), - domain_name.parse().expect("Valid"), - ); +fn build_test_transaction(chain_id: ChainId) -> SignedTransaction { + let domain_id: DomainId = "domain".parse().unwrap(); + let create_domain: InstructionBox = Register::domain(Domain::new(domain_id.clone())).into(); + let create_account = Register::account(Account::new(gen_account_in(&domain_id).0)).into(); + let asset_definition_id = "xor#domain".parse().unwrap(); let create_asset = Register::asset_definition(AssetDefinition::numeric(asset_definition_id)).into(); let instructions = [create_domain, create_account, create_asset]; - TransactionBuilder::new( - chain_id, - AccountId::new( - START_DOMAIN.parse().expect("Valid"), - START_ACCOUNT.parse().expect("Valid"), - ), - ) - .with_instructions(instructions) - .sign(keys) + TransactionBuilder::new(chain_id, STARTER_ID.clone()) + .with_instructions(instructions) + .sign(&STARTER_KEYPAIR) } -fn build_test_and_transient_state(keys: KeyPair) -> State { +fn build_test_and_transient_state() -> State { let kura = iroha_core::kura::Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let (public_key, _) = keys.into_parts(); let state = State::new( { - let domain_id = DomainId::from_str(START_DOMAIN).expect("Valid"); - let account_id = AccountId::new( - 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); + let (account_id, _account_keypair) = gen_account_in(&*STARTER_DOMAIN); + let mut domain = Domain::new(STARTER_DOMAIN.clone()).build(&account_id); + let account = Account::new(account_id.clone()).build(&account_id); assert!(domain.add_account(account).is_none()); World::with([domain], UniqueVec::new()) }, @@ -85,7 +65,7 @@ fn build_test_and_transient_state(keys: KeyPair) -> State { let wasm = std::fs::read(&path_to_executor) .unwrap_or_else(|_| panic!("Failed to read file: {}", path_to_executor.display())); let executor = Executor::new(WasmSmartContract::from_compiled(wasm)); - let authority = "genesis@genesis".parse().expect("Valid"); + let (authority, _authority_keypair) = gen_account_in("genesis"); Upgrade::new(executor) .execute(&authority, &mut state_transaction) .expect("Failed to load executor"); @@ -99,8 +79,7 @@ fn build_test_and_transient_state(keys: KeyPair) -> State { fn accept_transaction(criterion: &mut Criterion) { let chain_id = ChainId::from("0"); - let keys = KeyPair::random(); - let transaction = build_test_transaction(&keys, chain_id.clone()); + let transaction = build_test_transaction(chain_id.clone()); let mut success_count = 0; let mut failures_count = 0; let _ = criterion.bench_function("accept", |b| { @@ -117,8 +96,7 @@ fn accept_transaction(criterion: &mut Criterion) { fn sign_transaction(criterion: &mut Criterion) { let chain_id = ChainId::from("0"); - let keys = KeyPair::random(); - let transaction = build_test_transaction(&keys, chain_id); + let transaction = build_test_transaction(chain_id); let key_pair = KeyPair::random(); let mut count = 0; let _ = criterion.bench_function("sign", |b| { @@ -137,16 +115,15 @@ fn sign_transaction(criterion: &mut Criterion) { fn validate_transaction(criterion: &mut Criterion) { let chain_id = ChainId::from("0"); - let keys = KeyPair::random(); let transaction = AcceptedTransaction::accept( - build_test_transaction(&keys, chain_id.clone()), + build_test_transaction(chain_id.clone()), &chain_id, &TRANSACTION_LIMITS, ) .expect("Failed to accept transaction."); let mut success_count = 0; let mut failure_count = 0; - let state = build_test_and_transient_state(keys); + let state = build_test_and_transient_state(); let _ = criterion.bench_function("validate", move |b| { let transaction_executor = TransactionExecutor::new(TRANSACTION_LIMITS); b.iter(|| { @@ -163,9 +140,8 @@ fn validate_transaction(criterion: &mut Criterion) { fn sign_blocks(criterion: &mut Criterion) { let chain_id = ChainId::from("0"); - let keys = KeyPair::random(); let transaction = AcceptedTransaction::accept( - build_test_transaction(&keys, chain_id.clone()), + build_test_transaction(chain_id.clone()), &chain_id, &TRANSACTION_LIMITS, ) diff --git a/core/src/block.rs b/core/src/block.rs index 68df8771241..7a7dc967399 100644 --- a/core/src/block.rs +++ b/core/src/block.rs @@ -800,7 +800,8 @@ mod tests { use iroha_crypto::SignatureVerificationFail; use iroha_data_model::prelude::*; - use iroha_genesis::{GENESIS_ACCOUNT_ID, GENESIS_DOMAIN_ID}; + use iroha_genesis::GENESIS_DOMAIN_ID; + use test_samples::gen_account_in; use super::*; use crate::{ @@ -826,10 +827,8 @@ mod tests { let chain_id = ChainId::from("0"); // Predefined world state - let alice_id = AccountId::from_str("alice@wonderland").expect("Valid"); - let alice_keys = KeyPair::random(); - let account = - Account::new(alice_id.clone(), alice_keys.public_key().clone()).build(&alice_id); + let (alice_id, alice_keypair) = gen_account_in("wonderland"); + let account = Account::new(alice_id.clone()).build(&alice_id); let domain_id = DomainId::from_str("wonderland").expect("Valid"); let mut domain = Domain::new(domain_id).build(&alice_id); assert!(domain.add_account(account).is_none()); @@ -848,7 +847,7 @@ mod tests { let transaction_limits = &state_block.transaction_executor().transaction_limits; let tx = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions([create_asset_definition]) - .sign(&alice_keys); + .sign(&alice_keypair); let tx = AcceptedTransaction::accept(tx, &chain_id, transaction_limits).expect("Valid"); // Creating a block of two identical transactions and validating it @@ -856,7 +855,7 @@ mod tests { let topology = Topology::new(UniqueVec::new()); let valid_block = BlockBuilder::new(transactions, topology, Vec::new()) .chain(0, &mut state_block) - .sign(&alice_keys) + .sign(&alice_keypair) .unpack(|_| {}); // The first transaction should be confirmed @@ -883,10 +882,8 @@ mod tests { let chain_id = ChainId::from("0"); // Predefined world state - let alice_id = AccountId::from_str("alice@wonderland").expect("Valid"); - let alice_keys = KeyPair::random(); - let account = - Account::new(alice_id.clone(), alice_keys.public_key().clone()).build(&alice_id); + let (alice_id, alice_keypair) = gen_account_in("wonderland"); + let account = Account::new(alice_id.clone()).build(&alice_id); let domain_id = DomainId::from_str("wonderland").expect("Valid"); let mut domain = Domain::new(domain_id).build(&alice_id); assert!(domain.add_account(account).is_none()); @@ -905,7 +902,7 @@ mod tests { let transaction_limits = &state_block.transaction_executor().transaction_limits; let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([create_asset_definition]) - .sign(&alice_keys); + .sign(&alice_keypair); let tx = AcceptedTransaction::accept(tx, &chain_id, transaction_limits).expect("Valid"); let fail_mint = Mint::asset_numeric( @@ -918,12 +915,12 @@ mod tests { let tx0 = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([fail_mint]) - .sign(&alice_keys); + .sign(&alice_keypair); let tx0 = AcceptedTransaction::accept(tx0, &chain_id, transaction_limits).expect("Valid"); let tx2 = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions([succeed_mint]) - .sign(&alice_keys); + .sign(&alice_keypair); let tx2 = AcceptedTransaction::accept(tx2, &chain_id, transaction_limits).expect("Valid"); // Creating a block of two identical transactions and validating it @@ -931,7 +928,7 @@ mod tests { let topology = Topology::new(UniqueVec::new()); let valid_block = BlockBuilder::new(transactions, topology, Vec::new()) .chain(0, &mut state_block) - .sign(&alice_keys) + .sign(&alice_keypair) .unpack(|_| {}); // The first transaction should fail @@ -958,10 +955,8 @@ mod tests { let chain_id = ChainId::from("0"); // Predefined world state - let alice_id = AccountId::from_str("alice@wonderland").expect("Valid"); - let alice_keys = KeyPair::random(); - let account = - Account::new(alice_id.clone(), alice_keys.public_key().clone()).build(&alice_id); + let (alice_id, alice_keypair) = gen_account_in("wonderland"); + let account = Account::new(alice_id.clone()).build(&alice_id); let domain_id = DomainId::from_str("wonderland").expect("Valid"); let mut domain = Domain::new(domain_id).build(&alice_id); assert!( @@ -987,12 +982,12 @@ mod tests { let instructions_accept: [InstructionBox; 2] = [create_domain.into(), create_asset.into()]; let tx_fail = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions(instructions_fail) - .sign(&alice_keys); + .sign(&alice_keypair); let tx_fail = AcceptedTransaction::accept(tx_fail, &chain_id, transaction_limits).expect("Valid"); let tx_accept = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions(instructions_accept) - .sign(&alice_keys); + .sign(&alice_keypair); let tx_accept = AcceptedTransaction::accept(tx_accept, &chain_id, transaction_limits).expect("Valid"); @@ -1001,7 +996,7 @@ mod tests { let topology = Topology::new(UniqueVec::new()); let valid_block = BlockBuilder::new(transactions, topology, Vec::new()) .chain(0, &mut state_block) - .sign(&alice_keys) + .sign(&alice_keypair) .unpack(|_| {}); // The first transaction should be rejected @@ -1036,13 +1031,19 @@ mod tests { // Predefined world state let genesis_correct_key = KeyPair::random(); let genesis_wrong_key = KeyPair::random(); - let mut genesis_domain = Domain::new(GENESIS_DOMAIN_ID.clone()).build(&GENESIS_ACCOUNT_ID); - let genesis_account = Account::new( - GENESIS_ACCOUNT_ID.clone(), + let genesis_correct_account_id = AccountId::new( + GENESIS_DOMAIN_ID.clone(), + genesis_correct_key.public_key().clone(), + ); + let genesis_wrong_account_id = AccountId::new( + GENESIS_DOMAIN_ID.clone(), genesis_wrong_key.public_key().clone(), - ) - .build(&GENESIS_ACCOUNT_ID); - assert!(genesis_domain.add_account(genesis_account).is_none(),); + ); + let mut genesis_domain = + Domain::new(GENESIS_DOMAIN_ID.clone()).build(&genesis_correct_account_id); + let genesis_wrong_account = + Account::new(genesis_wrong_account_id.clone()).build(&genesis_wrong_account_id); + assert!(genesis_domain.add_account(genesis_wrong_account).is_none(),); let world = World::with([genesis_domain], UniqueVec::new()); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); @@ -1057,7 +1058,7 @@ mod tests { // Create genesis transaction // Sign with `genesis_wrong_key` as peer which has incorrect genesis key pair - let tx = TransactionBuilder::new(chain_id.clone(), GENESIS_ACCOUNT_ID.clone()) + let tx = TransactionBuilder::new(chain_id.clone(), genesis_wrong_account_id.clone()) .with_instructions([isi]) .sign(&genesis_wrong_key); let tx = AcceptedTransaction::accept_genesis( diff --git a/core/src/lib.rs b/core/src/lib.rs index f9b25a0a831..5a3e1bb4be6 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -171,7 +171,8 @@ pub mod prelude { mod tests { use std::cmp::Ordering; - use iroha_data_model::{account::AccountId, role::RoleId}; + use iroha_data_model::role::RoleId; + use test_samples::gen_account_in; use crate::role::RoleIdWithOwner; @@ -179,8 +180,8 @@ mod tests { fn cmp_role_id_with_owner() { let role_id_a: RoleId = "a".parse().expect("failed to parse RoleId"); let role_id_b: RoleId = "b".parse().expect("failed to parse RoleId"); - let account_id_a: AccountId = "a@domain".parse().expect("failed to parse AccountId"); - let account_id_b: AccountId = "b@domain".parse().expect("failed to parse AccountId"); + let (account_id_a, _account_keypair_a) = gen_account_in("domain"); + let (account_id_b, _account_keypair_b) = gen_account_in("domain"); let mut role_ids_with_owner = Vec::new(); for account_id in [&account_id_a, &account_id_b] { diff --git a/core/src/queue.rs b/core/src/queue.rs index 51e3ad38a5b..7029f57ff7f 100644 --- a/core/src/queue.rs +++ b/core/src/queue.rs @@ -22,24 +22,10 @@ use crate::{prelude::*, EventsSender}; impl AcceptedTransaction { // TODO: We should have another type of transaction like `CheckedTransaction` in the type system? - #[must_use] - fn check_signature_condition(&self, state_view: &StateView<'_>) -> bool { + fn is_signatory_consistent(&self) -> bool { let authority = self.as_ref().authority(); - - let transaction_signatories = self - .as_ref() - .signatures() - .iter() - .map(|signature| signature.public_key()) - .cloned() - .collect(); - - state_view - .world - .map_account(authority, |account| { - account.check_signature_check_condition(&transaction_signatories) - }) - .unwrap_or(false) + let signatory = self.as_ref().signature().public_key(); + authority.signatory_matches(signatory) } /// Check if [`self`] is committed or rejected. @@ -91,8 +77,8 @@ pub enum Error { MaximumTransactionsPerUser, /// The transaction is already in the queue IsInQueue, - /// Failure during signature condition execution - SignatureCondition, + /// Signatories in signature and payload mismatch + SignatoryInconsistent, } /// Failure that can pop up when pushing transaction into the queue @@ -181,8 +167,8 @@ impl Queue { Err(Error::Expired) } else if tx.is_in_blockchain(state_view) { Err(Error::InBlockchain) - } else if !tx.check_signature_condition(state_view) { - Err(Error::SignatureCondition) + } else if !tx.is_signatory_consistent() { + Err(Error::SignatoryInconsistent) } else { Ok(()) } @@ -396,6 +382,7 @@ pub mod tests { use iroha_data_model::{prelude::*, transaction::TransactionLimits}; use nonzero_ext::nonzero; use rand::Rng as _; + use test_samples::gen_account_in; use tokio::test; use super::*; @@ -423,24 +410,25 @@ pub mod tests { } } - fn accepted_tx( - account_id: &str, - key: &KeyPair, + fn accepted_tx_by_someone(time_source: &TimeSource) -> AcceptedTransaction { + let (account_id, key_pair) = gen_account_in("wonderland"); + accepted_tx_by(account_id, &key_pair, time_source) + } + + fn accepted_tx_by( + account_id: AccountId, + key_pair: &KeyPair, time_source: &TimeSource, ) -> AcceptedTransaction { let chain_id = ChainId::from("0"); - let message = std::iter::repeat_with(rand::random::) .take(16) .collect(); let instructions = [Fail { message }]; - let tx = TransactionBuilder::new_with_time_source( - chain_id.clone(), - AccountId::from_str(account_id).expect("Valid"), - time_source, - ) - .with_instructions(instructions) - .sign(key); + let tx = + TransactionBuilder::new_with_time_source(chain_id.clone(), account_id, time_source) + .with_instructions(instructions) + .sign(&key_pair); let limits = TransactionLimits { max_instruction_number: 4096, max_wasm_size_bytes: 0, @@ -448,18 +436,11 @@ pub mod tests { AcceptedTransaction::accept(tx, &chain_id, &limits).expect("Failed to accept Transaction.") } - pub fn world_with_test_domains( - signatories: impl IntoIterator, - ) -> World { + pub fn world_with_test_domains() -> World { let domain_id = DomainId::from_str("wonderland").expect("Valid"); - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); + let (account_id, _account_keypair) = gen_account_in("wonderland"); let mut domain = Domain::new(domain_id).build(&account_id); - let mut signatories = signatories.into_iter(); - let mut account = Account::new(account_id.clone(), signatories.next().unwrap()); - for signatory in signatories { - account = account.add_signatory(signatory); - } - let account = account.build(&account_id); + let account = Account::new(account_id.clone()).build(&account_id); assert!(domain.add_account(account).is_none()); World::with([domain], PeersIds::new()) } @@ -474,14 +455,9 @@ pub mod tests { #[test] async fn push_tx() { - let key_pair = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new( - world_with_test_domains([key_pair.public_key().clone()]), - kura, - query_handle, - )); + let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let state_view = state.view(); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -489,10 +465,7 @@ pub mod tests { let queue = Queue::test(config_factory(), &time_source); queue - .push( - accepted_tx("alice@wonderland", &key_pair, &time_source), - &state_view, - ) + .push(accepted_tx_by_someone(&time_source), &state_view) .expect("Failed to push tx into queue"); } @@ -500,14 +473,9 @@ pub mod tests { async fn push_tx_overflow() { let capacity = nonzero!(10_usize); - let key_pair = KeyPair::random(); - let kura = Kura::blank_kura_for_testing(); + let kura: Arc = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new( - world_with_test_domains([key_pair.public_key().clone()]), - kura, - query_handle, - )); + let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let state_view = state.view(); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -523,19 +491,13 @@ pub mod tests { for _ in 0..capacity.get() { queue - .push( - accepted_tx("alice@wonderland", &key_pair, &time_source), - &state_view, - ) + .push(accepted_tx_by_someone(&time_source), &state_view) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(10)); } assert!(matches!( - queue.push( - accepted_tx("alice@wonderland", &key_pair, &time_source), - &state_view - ), + queue.push(accepted_tx_by_someone(&time_source), &state_view), Err(Failure { err: Error::Full, .. @@ -543,84 +505,12 @@ pub mod tests { )); } - #[test] - async fn push_multisignature_tx() { - let chain_id = ChainId::from("0"); - - let key_pairs = [KeyPair::random(), KeyPair::random()]; - let kura = Kura::blank_kura_for_testing(); - let state = { - let domain_id = DomainId::from_str("wonderland").expect("Valid"); - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); - let mut domain = Domain::new(domain_id).build(&account_id); - let mut account = Account::new(account_id.clone(), key_pairs[0].public_key().clone()) - .add_signatory(key_pairs[1].public_key().clone()) - .build(&account_id); - account.signature_check_condition = SignatureCheckCondition::all_account_signatures(); - assert!(domain.add_account(account).is_none()); - let query_handle = LiveQueryStore::test().start(); - Arc::new(State::new( - World::with([domain], PeersIds::new()), - kura, - query_handle, - )) - }; - let state_view = state.view(); - - let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); - - let queue = Queue::test(config_factory(), &time_source); - let instructions: [InstructionBox; 0] = []; - let tx = TransactionBuilder::new_with_time_source( - chain_id.clone(), - "alice@wonderland".parse().expect("Valid"), - &time_source, - ) - .with_instructions(instructions); - let tx_limits = TransactionLimits { - max_instruction_number: 4096, - max_wasm_size_bytes: 0, - }; - let fully_signed_tx: AcceptedTransaction = { - let mut signed_tx = tx.clone().sign(&key_pairs[0]); - for key_pair in &key_pairs[1..] { - signed_tx = signed_tx.sign(key_pair); - } - AcceptedTransaction::accept(signed_tx, &chain_id, &tx_limits) - .expect("Failed to accept Transaction.") - }; - // Check that fully signed transaction passes signature check - assert!(fully_signed_tx.check_signature_condition(&state_view)); - - let get_tx = |key_pair| { - AcceptedTransaction::accept(tx.clone().sign(&key_pair), &chain_id, &tx_limits) - .expect("Failed to accept Transaction.") - }; - for key_pair in key_pairs { - let partially_signed_tx: AcceptedTransaction = get_tx(key_pair); - // Check that none of partially signed txs passes signature check - assert!(!partially_signed_tx.check_signature_condition(&state_view),); - assert!(matches!( - queue - .push(partially_signed_tx, &state_view) - .unwrap_err() - .err, - Error::SignatureCondition - )) - } - } - #[test] async fn get_available_txs() { let max_txs_in_block = 2; - let alice_key = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new( - world_with_test_domains([alice_key.public_key().clone()]), - kura, - query_handle, - )); + let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let state_view = state.view(); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -634,10 +524,7 @@ pub mod tests { ); for _ in 0..5 { queue - .push( - accepted_tx("alice@wonderland", &alice_key, &time_source), - &state_view, - ) + .push(accepted_tx_by_someone(&time_source), &state_view) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(10)); } @@ -648,18 +535,11 @@ pub mod tests { #[test] async fn push_tx_already_in_blockchain() { - let alice_key = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = State::new( - world_with_test_domains([alice_key.public_key().clone()]), - kura, - query_handle, - ); - + let state = State::new(world_with_test_domains(), kura, query_handle); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); - - let tx = accepted_tx("alice@wonderland", &alice_key, &time_source); + let tx = accepted_tx_by_someone(&time_source); let mut state_block = state.block(); state_block.transactions.insert(tx.as_ref().hash(), 1); state_block.commit(); @@ -678,18 +558,11 @@ pub mod tests { #[test] async fn get_tx_drop_if_in_blockchain() { let max_txs_in_block = 2; - let alice_key = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = State::new( - world_with_test_domains([alice_key.public_key().clone()]), - kura, - query_handle, - ); - + let state = State::new(world_with_test_domains(), kura, query_handle); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); - - let tx = accepted_tx("alice@wonderland", &alice_key, &time_source); + let tx = accepted_tx_by_someone(&time_source); let queue = Queue::test(config_factory(), &time_source); queue.push(tx.clone(), &state.view()).unwrap(); let mut state_block = state.block(); @@ -707,14 +580,9 @@ pub mod tests { #[test] async fn get_available_txs_with_timeout() { let max_txs_in_block = 6; - let alice_key = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new( - world_with_test_domains([alice_key.public_key().clone()]), - kura, - query_handle, - )); + let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let state_view = state.view(); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -728,19 +596,13 @@ pub mod tests { ); for _ in 0..(max_txs_in_block - 1) { queue - .push( - accepted_tx("alice@wonderland", &alice_key, &time_source), - &state_view, - ) + .push(accepted_tx_by_someone(&time_source), &state_view) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(100)); } queue - .push( - accepted_tx("alice@wonderland", &alice_key, &time_source), - &state_view, - ) + .push(accepted_tx_by_someone(&time_source), &state_view) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(101)); assert_eq!( @@ -751,10 +613,7 @@ pub mod tests { ); queue - .push( - accepted_tx("alice@wonderland", &alice_key, &time_source), - &state_view, - ) + .push(accepted_tx_by_someone(&time_source), &state_view) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(210)); assert_eq!( @@ -770,24 +629,16 @@ pub mod tests { #[test] async fn transactions_available_after_pop() { let max_txs_in_block = 2; - let alice_key = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new( - world_with_test_domains([alice_key.public_key().clone()]), - kura, - query_handle, - )); + let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let state_view = state.view(); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); let queue = Queue::test(config_factory(), &time_source); queue - .push( - accepted_tx("alice@wonderland", &alice_key, &time_source), - &state_view, - ) + .push(accepted_tx_by_someone(&time_source), &state_view) .expect("Failed to push tx into queue"); let a = queue @@ -811,14 +662,10 @@ pub mod tests { let chain_id = ChainId::from("0"); let max_txs_in_block = 2; - let alice_key = KeyPair::random(); + let (alice_id, alice_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new( - world_with_test_domains([alice_key.public_key().clone()]), - kura, - query_handle, - )); + let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let state_view = state.view(); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -828,14 +675,11 @@ pub mod tests { let instructions = [Fail { message: "expired".to_owned(), }]; - let mut tx = TransactionBuilder::new_with_time_source( - chain_id.clone(), - AccountId::from_str("alice@wonderland").expect("Valid"), - &time_source, - ) - .with_instructions(instructions); + let mut tx = + TransactionBuilder::new_with_time_source(chain_id.clone(), alice_id, &time_source) + .with_instructions(instructions); tx.set_ttl(Duration::from_millis(TTL_MS)); - let tx = tx.sign(&alice_key); + let tx = tx.sign(&alice_keypair); let limits = TransactionLimits { max_instruction_number: 4096, max_wasm_size_bytes: 0, @@ -878,14 +722,9 @@ pub mod tests { #[test] async fn concurrent_stress_test() { let max_txs_in_block = 10; - let alice_key = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new( - world_with_test_domains([alice_key.public_key().clone()]), - kura, - query_handle, - )); + let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -908,7 +747,7 @@ pub mod tests { // Spawn a thread where we push transactions thread::spawn(move || { while start_time.elapsed() < run_for { - let tx = accepted_tx("alice@wonderland", &alice_key, &time_source); + let tx = accepted_tx_by_someone(&time_source); match queue_arc_clone.push(tx, &state.view()) { Ok(()) | Err(Failure { @@ -957,15 +796,9 @@ pub mod tests { async fn push_tx_in_future() { let future_threshold = Duration::from_secs(1); - let alice_id = "alice@wonderland"; - let alice_key = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new( - world_with_test_domains([alice_key.public_key().clone()]), - kura, - query_handle, - )); + let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let state_view = state.view(); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -977,12 +810,12 @@ pub mod tests { &time_source, ); - let tx = accepted_tx(alice_id, &alice_key, &time_source); + let tx = accepted_tx_by_someone(&time_source); assert!(queue.push(tx.clone(), &state_view).is_ok()); // create the same tx but with timestamp in the future time_handle.advance(future_threshold * 2); - let tx = accepted_tx(alice_id, &alice_key, &time_source); + let tx = accepted_tx_by_someone(&time_source); time_handle.rewind(future_threshold * 2); assert!(matches!( @@ -997,22 +830,14 @@ pub mod tests { #[test] async fn queue_throttling() { - let alice_key_pair = KeyPair::random(); - let bob_key_pair = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); + let (alice_id, alice_keypair) = gen_account_in("wonderland"); + let (bob_id, bob_keypair) = gen_account_in("wonderland"); let world = { let domain_id = DomainId::from_str("wonderland").expect("Valid"); - let alice_account_id = AccountId::from_str("alice@wonderland").expect("Valid"); - let bob_account_id = AccountId::from_str("bob@wonderland").expect("Valid"); - let mut domain = Domain::new(domain_id).build(&alice_account_id); - let alice_account = Account::new( - alice_account_id.clone(), - alice_key_pair.public_key().clone(), - ) - .build(&alice_account_id); - let bob_account = - Account::new(bob_account_id.clone(), bob_key_pair.public_key().clone()) - .build(&bob_account_id); + let mut domain = Domain::new(domain_id).build(&alice_id); + let alice_account = Account::new(alice_id.clone()).build(&alice_id); + let bob_account = Account::new(bob_id.clone()).build(&bob_id); assert!(domain.add_account(alice_account).is_none()); assert!(domain.add_account(bob_account).is_none()); World::with([domain], PeersIds::new()) @@ -1035,14 +860,14 @@ pub mod tests { // First push by Alice should be fine queue .push( - accepted_tx("alice@wonderland", &alice_key_pair, &time_source), + accepted_tx_by(alice_id.clone(), &alice_keypair, &time_source), &state.view(), ) .expect("Failed to push tx into queue"); // Second push by Alice excide limit and will be rejected let result = queue.push( - accepted_tx("alice@wonderland", &alice_key_pair, &time_source), + accepted_tx_by(alice_id.clone(), &alice_keypair, &time_source), &state.view(), ); assert!( @@ -1059,7 +884,7 @@ pub mod tests { // First push by Bob should be fine despite previous Alice error queue .push( - accepted_tx("bob@wonderland", &bob_key_pair, &time_source), + accepted_tx_by(bob_id.clone(), &bob_keypair, &time_source), &state.view(), ) .expect("Failed to push tx into queue"); @@ -1081,14 +906,14 @@ pub mod tests { // After cleanup Alice and Bob pushes should work fine queue .push( - accepted_tx("alice@wonderland", &alice_key_pair, &time_source), + accepted_tx_by(alice_id, &alice_keypair, &time_source), &state.view(), ) .expect("Failed to push tx into queue"); queue .push( - accepted_tx("bob@wonderland", &bob_key_pair, &time_source), + accepted_tx_by(bob_id, &bob_keypair, &time_source), &state.view(), ) .expect("Failed to push tx into queue"); diff --git a/core/src/smartcontracts/isi/account.rs b/core/src/smartcontracts/isi/account.rs index 0661f8618e6..15484de7627 100644 --- a/core/src/smartcontracts/isi/account.rs +++ b/core/src/smartcontracts/isi/account.rs @@ -132,95 +132,6 @@ pub mod isi { } } - impl Execute for Mint { - #[metrics(+"mint_account_public_key")] - fn execute( - self, - _authority: &AccountId, - state_transaction: &mut StateTransaction<'_, '_>, - ) -> Result<(), Error> { - let account_id = self.destination_id; - let public_key = self.object; - - state_transaction - .world - .account_mut(&account_id) - .map_err(Error::from) - .and_then(|account| { - if account.contains_signatory(&public_key) { - return Err(RepetitionError { - instruction_type: InstructionType::Mint, - id: account_id.clone().into(), - } - .into()); - } - - account.add_signatory(public_key); - Ok(()) - })?; - - state_transaction - .world - .emit_events(Some(AccountEvent::AuthenticationAdded(account_id.clone()))); - - Ok(()) - } - } - - impl Execute for Burn { - #[metrics(+"burn_account_public_key")] - fn execute( - self, - _authority: &AccountId, - state_transaction: &mut StateTransaction<'_, '_>, - ) -> Result<(), Error> { - let account_id = self.destination_id; - let public_key = self.object; - - state_transaction.world.account_mut(&account_id) - .map_err(Error::from) - .and_then(|account| { - match account.remove_signatory(&public_key) { - None => Err(Error::InvariantViolation(String::from( - "Public keys cannot be burned to nothing, \ - if you want to delete the account, please use an unregister instruction", - ))), - Some(false) => Err(FindError::PublicKey(public_key).into()), - Some(true) => Ok(()) - } - })?; - - state_transaction - .world - .emit_events(Some(AccountEvent::AuthenticationRemoved(account_id))); - - Ok(()) - } - } - - impl Execute for Mint { - #[metrics(+"mint_account_signature_check_condition")] - fn execute( - self, - _authority: &AccountId, - state_transaction: &mut StateTransaction<'_, '_>, - ) -> Result<(), Error> { - let account_id = self.destination_id; - let signature_check_condition = self.object; - - state_transaction - .world - .account_mut(&account_id)? - .signature_check_condition = signature_check_condition; - - state_transaction - .world - .emit_events(Some(AccountEvent::AuthenticationAdded(account_id.clone()))); - - Ok(()) - } - } - impl Execute for Transfer { fn execute( self, @@ -575,12 +486,13 @@ pub mod isi { #[cfg(test)] mod test { use iroha_data_model::{prelude::AssetDefinition, ParseError}; + use test_samples::gen_account_in; use crate::smartcontracts::isi::Registrable as _; #[test] fn cannot_forbid_minting_on_asset_mintable_infinitely() -> Result<(), ParseError> { - let authority = "alice@wonderland".parse()?; + let (authority, _authority_keypair) = gen_account_in("wonderland"); let mut definition = AssetDefinition::numeric("test#hello".parse()?).build(&authority); assert!(super::forbid_minting(&mut definition).is_err()); Ok(()) @@ -658,31 +570,6 @@ pub mod query { } } - impl ValidQuery for FindAccountsByName { - #[metrics(+"find_account_by_name")] - fn execute<'state>( - &self, - state_ro: &'state impl StateReadOnly, - ) -> Result + 'state>, Error> { - let name = self.name.clone(); - iroha_logger::trace!(%name); - Ok(Box::new( - state_ro - .world() - .domains_iter() - .flat_map(move |domain| { - let name = name.clone(); - - domain - .accounts - .values() - .filter(move |account| account.id().name == name) - }) - .cloned(), - )) - } - } - impl ValidQuery for FindAccountsByDomainId { #[metrics(+"find_accounts_by_domain_id")] fn execute<'state>( diff --git a/core/src/smartcontracts/isi/domain.rs b/core/src/smartcontracts/isi/domain.rs index 0ae2a44fde1..b3c2ac376c3 100644 --- a/core/src/smartcontracts/isi/domain.rs +++ b/core/src/smartcontracts/isi/domain.rs @@ -50,14 +50,9 @@ pub mod isi { let account: Account = self.object.build(authority); let account_id = account.id().clone(); - account_id - .name - .validate_len(state_transaction.config.ident_length_limits) - .map_err(Error::from)?; - - if account_id == *iroha_genesis::GENESIS_ACCOUNT_ID { + if *account_id.domain_id() == *iroha_genesis::GENESIS_DOMAIN_ID { return Err(InstructionExecutionError::InvariantViolation( - "Not allowed to register `genesis@genesis` account".to_owned(), + "Not allowed to register account in genesis domain".to_owned(), )); } diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index 4bc587aabee..39cecd6988f 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -107,26 +107,12 @@ impl Execute for MintBox { state_transaction: &mut StateTransaction<'_, '_>, ) -> Result<(), Error> { match self { - Self::Account(isi) => isi.execute(authority, state_transaction), Self::Asset(isi) => isi.execute(authority, state_transaction), Self::TriggerRepetitions(isi) => isi.execute(authority, state_transaction), } } } -impl Execute for AccountMintBox { - fn execute( - self, - authority: &AccountId, - state_transaction: &mut StateTransaction<'_, '_>, - ) -> std::prelude::v1::Result<(), Error> { - match self { - Self::PublicKey(isi) => isi.execute(authority, state_transaction), - Self::SignatureCheckCondition(isi) => isi.execute(authority, state_transaction), - } - } -} - impl Execute for BurnBox { #[iroha_logger::log(name = "burn", skip_all, fields(destination))] fn execute( @@ -135,7 +121,6 @@ impl Execute for BurnBox { state_transaction: &mut StateTransaction<'_, '_>, ) -> Result<(), Error> { match self { - Self::AccountPublicKey(isi) => isi.execute(authority, state_transaction), Self::Asset(isi) => isi.execute(authority, state_transaction), Self::TriggerRepetitions(isi) => isi.execute(authority, state_transaction), } @@ -254,9 +239,10 @@ mod tests { use core::str::FromStr as _; use std::sync::Arc; - use iroha_crypto::KeyPair; use iroha_data_model::metadata::MetadataValueBox; - use iroha_genesis::GENESIS_ACCOUNT_ID; + use test_samples::{ + gen_account_in, ALICE_ID, SAMPLE_GENESIS_ACCOUNT_ID, SAMPLE_GENESIS_ACCOUNT_KEYPAIR, + }; use tokio::test; use super::*; @@ -272,18 +258,15 @@ mod tests { let world = World::with([], PeersIds::new()); let query_handle = LiveQueryStore::test().start(); let state = State::new(world, kura.clone(), query_handle); - let genesis_account_id = AccountId::from_str("genesis@genesis")?; - let account_id = AccountId::from_str("alice@wonderland")?; - let (public_key, _) = KeyPair::random().into_parts(); let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland")?; let mut state_block = state.block(); let mut state_transaction = state_block.transaction(); Register::domain(Domain::new(DomainId::from_str("wonderland")?)) - .execute(&genesis_account_id, &mut state_transaction)?; - Register::account(Account::new(account_id, public_key)) - .execute(&genesis_account_id, &mut state_transaction)?; + .execute(&SAMPLE_GENESIS_ACCOUNT_ID, &mut state_transaction)?; + Register::account(Account::new(ALICE_ID.clone())) + .execute(&SAMPLE_GENESIS_ACCOUNT_ID, &mut state_transaction)?; Register::asset_definition(AssetDefinition::store(asset_definition_id)) - .execute(&genesis_account_id, &mut state_transaction)?; + .execute(&SAMPLE_GENESIS_ACCOUNT_ID, &mut state_transaction)?; state_transaction.apply(); state_block.commit(); Ok(state) @@ -293,9 +276,9 @@ mod tests { async fn asset_store() -> Result<()> { let kura = Kura::blank_kura_for_testing(); let state = state_with_test_domains(&kura)?; - let mut staet_block = state.block(); - let mut state_transaction = staet_block.transaction(); - let account_id = AccountId::from_str("alice@wonderland")?; + let mut state_block = state.block(); + let mut state_transaction = state_block.transaction(); + let account_id = ALICE_ID.clone(); let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland")?; let asset_id = AssetId::new(asset_definition_id, account_id.clone()); SetKeyValue::asset( @@ -326,7 +309,7 @@ mod tests { let state = state_with_test_domains(&kura)?; let mut state_block = state.block(); let mut state_transaction = state_block.transaction(); - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); SetKeyValue::account( account_id.clone(), Name::from_str("Bytes")?, @@ -359,7 +342,7 @@ mod tests { let mut state_block = state.block(); let mut state_transaction = state_block.transaction(); let definition_id = AssetDefinitionId::from_str("rose#wonderland")?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); SetKeyValue::asset_definition( definition_id.clone(), Name::from_str("Bytes")?, @@ -390,7 +373,7 @@ mod tests { let mut state_block = state.block(); let mut state_transaction = state_block.transaction(); let domain_id = DomainId::from_str("wonderland")?; - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); SetKeyValue::domain( domain_id.clone(), Name::from_str("Bytes")?, @@ -420,7 +403,7 @@ mod tests { let state = state_with_test_domains(&kura)?; let mut state_block = state.block(); let mut state_transaction = state_block.transaction(); - let account_id = AccountId::from_str("alice@wonderland")?; + let account_id = ALICE_ID.clone(); let trigger_id = TriggerId::from_str("test_trigger_id")?; assert!(matches!( @@ -439,13 +422,12 @@ mod tests { let state = state_with_test_domains(&kura)?; let mut state_block = state.block(); let mut state_transaction = state_block.transaction(); - let account_id = AccountId::from_str("alice@wonderland")?; - let fake_account_id = AccountId::from_str("fake@wonderland")?; + let account_id = ALICE_ID.clone(); + let (fake_account_id, _fake_account_keypair) = gen_account_in("wonderland"); let trigger_id = TriggerId::from_str("test_trigger_id")?; // register fake account - let (public_key, _) = KeyPair::random().into_parts(); - let register_account = Register::account(Account::new(fake_account_id.clone(), public_key)); + let register_account = Register::account(Account::new(fake_account_id.clone())); register_account.execute(&account_id, &mut state_transaction)?; // register the trigger @@ -481,20 +463,16 @@ mod tests { async fn not_allowed_to_register_genesis_domain_or_account() -> Result<()> { let kura = Kura::blank_kura_for_testing(); let state = state_with_test_domains(&kura)?; - let mut staet_block = state.block(); - let mut state_transaction = staet_block.transaction(); - let account_id = AccountId::from_str("alice@wonderland")?; + let mut state_block = state.block(); + let mut state_transaction = state_block.transaction(); + let account_id = ALICE_ID.clone(); assert!(matches!( Register::domain(Domain::new(DomainId::from_str("genesis")?)) .execute(&account_id, &mut state_transaction) .expect_err("Error expected"), Error::InvariantViolation(_) )); - let (public_key, _) = KeyPair::random().into_parts(); - let register_account = Register::account(Account::new( - AccountId::from_str("genesis@genesis")?, - public_key, - )); + let register_account = Register::account(Account::new(SAMPLE_GENESIS_ACCOUNT_ID.clone())); assert!(matches!( register_account .execute(&account_id, &mut state_transaction) @@ -512,10 +490,9 @@ mod tests { let state_block = state.block(); let instructions: [InstructionBox; 0] = []; - let genesis_keys = KeyPair::random(); - let tx = TransactionBuilder::new(chain_id.clone(), GENESIS_ACCOUNT_ID.clone()) + let tx = TransactionBuilder::new(chain_id.clone(), SAMPLE_GENESIS_ACCOUNT_ID.clone()) .with_instructions(instructions) - .sign(&genesis_keys); + .sign(&SAMPLE_GENESIS_ACCOUNT_KEYPAIR); let tx_limits = &state_block.transaction_executor().transaction_limits; assert!(matches!( AcceptedTransaction::accept(tx, &chain_id, tx_limits), diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index daf7faae917..ba8cc1843a2 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -72,13 +72,10 @@ impl ValidQueryRequest { query: SignedQuery, state_ro: &impl StateReadOnly, ) -> Result { - let account_has_public_key = state_ro - .world() - .map_account(query.authority(), |account| { - account.contains_signatory(query.signature().public_key()) - }) - .map_err(Error::from)?; - if !account_has_public_key { + if !query + .authority() + .signatory_matches(query.signature().public_key()) + { return Err(Error::Signature(String::from( "Signature public key doesn't correspond to the account.", )) @@ -155,7 +152,6 @@ impl ValidQuery for QueryBox { } FindAllAccounts, - FindAccountsByName, FindAccountsByDomainId, FindAccountsWithAsset, FindAllAssets, @@ -186,12 +182,12 @@ impl ValidQuery for QueryBox { mod tests { use std::str::FromStr as _; - use iroha_crypto::{Hash, HashOf, KeyPair}; + use iroha_crypto::{Hash, HashOf}; use iroha_data_model::{ metadata::MetadataValueBox, query::error::FindError, transaction::TransactionLimits, }; use iroha_primitives::unique_vec::UniqueVec; - use once_cell::sync::Lazy; + use test_samples::{gen_account_in, ALICE_ID, ALICE_KEYPAIR}; use tokio::test; use super::*; @@ -206,15 +202,10 @@ mod tests { PeersIds, }; - static ALICE_KEYS: Lazy = Lazy::new(KeyPair::random); - static ALICE_ID: Lazy = - Lazy::new(|| AccountId::from_str("alice@wonderland").expect("Valid")); - fn world_with_test_domains() -> World { let domain_id = DomainId::from_str("wonderland").expect("Valid"); let mut domain = Domain::new(domain_id).build(&ALICE_ID); - let account = - Account::new(ALICE_ID.clone(), ALICE_KEYS.public_key().clone()).build(&ALICE_ID); + let account = Account::new(ALICE_ID.clone()).build(&ALICE_ID); assert!(domain.add_account(account).is_none()); let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland").expect("Valid"); assert!(domain @@ -227,8 +218,7 @@ mod tests { let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland").expect("Valid"); let mut domain = Domain::new(DomainId::from_str("wonderland").expect("Valid")).build(&ALICE_ID); - let mut account = - Account::new(ALICE_ID.clone(), ALICE_KEYS.public_key().clone()).build(&ALICE_ID); + let mut account = Account::new(ALICE_ID.clone()).build(&ALICE_ID); assert!(domain .add_asset_definition( AssetDefinition::numeric(asset_definition_id.clone()).build(&ALICE_ID) @@ -260,7 +250,7 @@ mod tests { )?; let mut domain = Domain::new(DomainId::from_str("wonderland")?).build(&ALICE_ID); - let account = Account::new(ALICE_ID.clone(), ALICE_KEYS.public_key().clone()) + let account = Account::new(ALICE_ID.clone()) .with_metadata(metadata) .build(&ALICE_ID); assert!(domain.add_account(account).is_none()); @@ -298,14 +288,14 @@ mod tests { let instructions: [InstructionBox; 0] = []; let tx = TransactionBuilder::new(chain_id.clone(), ALICE_ID.clone()) .with_instructions(instructions) - .sign(&ALICE_KEYS); + .sign(&ALICE_KEYPAIR); AcceptedTransaction::accept(tx, &chain_id, &limits)? }; let invalid_tx = { let isi = Fail::new("fail".to_owned()); let tx = TransactionBuilder::new(chain_id.clone(), ALICE_ID.clone()) .with_instructions([isi.clone(), isi]) - .sign(&ALICE_KEYS); + .sign(&ALICE_KEYPAIR); AcceptedTransaction::accept(tx, &chain_id, &huge_limits)? }; @@ -315,7 +305,7 @@ mod tests { let topology = Topology::new(UniqueVec::new()); let first_block = BlockBuilder::new(transactions.clone(), topology.clone(), Vec::new()) .chain(0, &mut state_block) - .sign(&ALICE_KEYS) + .sign(&ALICE_KEYPAIR) .unpack(|_| {}) .commit(&topology) .unpack(|_| {}) @@ -327,7 +317,7 @@ mod tests { for _ in 1u64..blocks { let block = BlockBuilder::new(transactions.clone(), topology.clone(), Vec::new()) .chain(0, &mut state_block) - .sign(&ALICE_KEYS) + .sign(&ALICE_KEYPAIR) .unpack(|_| {}) .commit(&topology) .unpack(|_| {}) @@ -461,7 +451,7 @@ mod tests { let instructions: [InstructionBox; 0] = []; let tx = TransactionBuilder::new(chain_id.clone(), ALICE_ID.clone()) .with_instructions(instructions) - .sign(&ALICE_KEYS); + .sign(&ALICE_KEYPAIR); let tx_limits = &state_block.transaction_executor().transaction_limits; let va_tx = AcceptedTransaction::accept(tx, &chain_id, tx_limits)?; @@ -469,7 +459,7 @@ mod tests { let topology = Topology::new(UniqueVec::new()); let vcb = BlockBuilder::new(vec![va_tx.clone()], topology.clone(), Vec::new()) .chain(0, &mut state_block) - .sign(&ALICE_KEYS) + .sign(&ALICE_KEYPAIR) .unpack(|_| {}) .commit(&topology) .unpack(|_| {}) @@ -482,8 +472,8 @@ mod tests { let state_view = state.view(); let unapplied_tx = TransactionBuilder::new(chain_id, ALICE_ID.clone()) - .with_instructions([Unregister::account("account@domain".parse().unwrap())]) - .sign(&ALICE_KEYS); + .with_instructions([Unregister::account(gen_account_in("domain").0)]) + .sign(&ALICE_KEYPAIR); let wrong_hash = unapplied_tx.hash(); let not_found = FindTransactionByHash::new(wrong_hash).execute(&state_view); assert!(matches!( @@ -515,8 +505,7 @@ mod tests { let mut domain = Domain::new(DomainId::from_str("wonderland")?) .with_metadata(metadata) .build(&ALICE_ID); - let account = - Account::new(ALICE_ID.clone(), ALICE_KEYS.public_key().clone()).build(&ALICE_ID); + let account = Account::new(ALICE_ID.clone()).build(&ALICE_ID); assert!(domain.add_account(account).is_none()); let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland")?; assert!(domain diff --git a/core/src/smartcontracts/isi/world.rs b/core/src/smartcontracts/isi/world.rs index 19b56c01dd4..3eba2e10c3a 100644 --- a/core/src/smartcontracts/isi/world.rs +++ b/core/src/smartcontracts/isi/world.rs @@ -90,7 +90,7 @@ pub mod isi { if domain_id == *iroha_genesis::GENESIS_DOMAIN_ID { return Err(InstructionExecutionError::InvariantViolation( - "Not allowed to register `genesis` domain".to_owned(), + "Not allowed to register genesis domain".to_owned(), )); } diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index c10b17a6069..470321a972b 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -74,7 +74,7 @@ mod import { use super::super::*; - pub(crate) trait ExecuteOperations { + pub trait ExecuteOperations { /// Execute `query` on host #[codec::wrap_trait_fn] fn execute_query( @@ -1706,11 +1706,9 @@ impl GetExport for (&wasmtime::Instance, C) { #[cfg(test)] mod tests { - use std::str::FromStr as _; - - use iroha_crypto::KeyPair; use iroha_data_model::query::{sorting::Sorting, Pagination}; use parity_scale_codec::Encode; + use test_samples::gen_account_in; use tokio::test; use super::*; @@ -1721,8 +1719,7 @@ mod tests { fn world_with_test_account(authority: &AccountId) -> World { let domain_id = authority.domain_id.clone(); - let (public_key, _) = KeyPair::random().into_parts(); - let account = Account::new(authority.clone(), public_key).build(authority); + let account = Account::new(authority.clone()).build(authority); let mut domain = Domain::new(domain_id).build(authority); assert!(domain.add_account(account).is_none()); @@ -1775,17 +1772,14 @@ mod tests { #[test] async fn execute_instruction_exported() -> Result<(), Error> { - let authority = AccountId::from_str("alice@wonderland").expect("Valid"); + let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world_with_test_account(&authority), kura, query_handle); let isi_hex = { - let new_authority = AccountId::from_str("mad_hatter@wonderland").expect("Valid"); - let register_isi = Register::account(Account::new( - new_authority, - KeyPair::random().into_parts().0, - )); + let (new_authority, _new_authority_keypair) = gen_account_in("wonderland"); + let register_isi = Register::account(Account::new(new_authority)); encode_hex(InstructionBox::from(register_isi)) }; @@ -1820,7 +1814,7 @@ mod tests { #[test] async fn execute_query_exported() -> Result<(), Error> { - let authority = AccountId::from_str("alice@wonderland").expect("Valid"); + let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world_with_test_account(&authority), kura, query_handle); @@ -1865,18 +1859,15 @@ mod tests { #[test] async fn instruction_limit_reached() -> Result<(), Error> { - let authority = AccountId::from_str("alice@wonderland").expect("Valid"); + let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world_with_test_account(&authority), kura, query_handle); let isi_hex = { - let new_authority = AccountId::from_str("mad_hatter@wonderland").expect("Valid"); - let register_isi = Register::account(Account::new( - new_authority, - KeyPair::random().into_parts().0, - )); + let (new_authority, _new_authority_keypair) = gen_account_in("wonderland"); + let register_isi = Register::account(Account::new(new_authority)); encode_hex(InstructionBox::from(register_isi)) }; @@ -1918,17 +1909,14 @@ mod tests { #[test] async fn instructions_not_allowed() -> Result<(), Error> { - let authority = AccountId::from_str("alice@wonderland").expect("Valid"); + let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world_with_test_account(&authority), kura, query_handle); let isi_hex = { - let new_authority = AccountId::from_str("mad_hatter@wonderland").expect("Valid"); - let register_isi = Register::account(Account::new( - new_authority, - KeyPair::random().into_parts().0, - )); + let (new_authority, _new_authority_keypair) = gen_account_in("wonderland"); + let register_isi = Register::account(Account::new(new_authority)); encode_hex(InstructionBox::from(register_isi)) }; @@ -1970,7 +1958,7 @@ mod tests { #[test] async fn queries_not_allowed() -> Result<(), Error> { - let authority = AccountId::from_str("alice@wonderland").expect("Valid"); + let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world_with_test_account(&authority), kura, query_handle); @@ -2012,7 +2000,7 @@ mod tests { #[test] async fn trigger_related_func_is_not_linked_for_smart_contract() -> Result<(), Error> { - let authority = AccountId::from_str("alice@wonderland").expect("Valid"); + let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world_with_test_account(&authority), kura, query_handle); diff --git a/core/src/snapshot.rs b/core/src/snapshot.rs index c2b5f331be0..e046b49dba5 100644 --- a/core/src/snapshot.rs +++ b/core/src/snapshot.rs @@ -247,7 +247,6 @@ enum TryWriteError { mod tests { use std::{fs::File, io::Write}; - use iroha_crypto::KeyPair; use tempfile::tempdir; use tokio::test; @@ -255,11 +254,10 @@ mod tests { use crate::query::store::LiveQueryStore; fn state_factory() -> State { - let alice_key = KeyPair::random(); let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); State::new( - crate::queue::tests::world_with_test_domains([alice_key.public_key().clone()]), + crate::queue::tests::world_with_test_domains(), kura, query_handle, ) diff --git a/core/src/state.rs b/core/src/state.rs index 81ec0c79dec..d86a1dab212 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -1766,6 +1766,7 @@ pub(crate) mod deserialize { mod tests { use iroha_data_model::block::BlockPayload; use iroha_primitives::unique_vec::UniqueVec; + use test_samples::gen_account_in; use super::*; use crate::{ @@ -1844,14 +1845,14 @@ mod tests { #[test] fn role_account_range() { - let account_id: AccountId = "alice@wonderland".parse().unwrap(); + let (account_id, _account_keypair) = gen_account_in("wonderland"); let roles = [ RoleIdWithOwner::new(account_id.clone(), "1".parse().unwrap()), RoleIdWithOwner::new(account_id.clone(), "2".parse().unwrap()), - RoleIdWithOwner::new("bob@wonderland".parse().unwrap(), "3".parse().unwrap()), - RoleIdWithOwner::new("a@wonderland".parse().unwrap(), "4".parse().unwrap()), - RoleIdWithOwner::new("0@0".parse().unwrap(), "5".parse().unwrap()), - RoleIdWithOwner::new("1@1".parse().unwrap(), "6".parse().unwrap()), + RoleIdWithOwner::new(gen_account_in("wonderland").0, "3".parse().unwrap()), + RoleIdWithOwner::new(gen_account_in("wonderland").0, "4".parse().unwrap()), + RoleIdWithOwner::new(gen_account_in("0").0, "5".parse().unwrap()), + RoleIdWithOwner::new(gen_account_in("1").0, "6".parse().unwrap()), ]; let map = BTreeSet::from(roles); diff --git a/core/src/sumeragi/main_loop.rs b/core/src/sumeragi/main_loop.rs index 49e1c1db8b6..370dcbca0f0 100644 --- a/core/src/sumeragi/main_loop.rs +++ b/core/src/sumeragi/main_loop.rs @@ -1202,6 +1202,7 @@ fn handle_block_sync<'state, F: Fn(PipelineEventBox)>( #[cfg(test)] mod tests { use iroha_primitives::{unique_vec, unique_vec::UniqueVec}; + use test_samples::gen_account_in; use tokio::test; use super::*; @@ -1217,12 +1218,11 @@ mod tests { chain_id: &ChainId, topology: &Topology, leader_key_pair: &KeyPair, - tx_signer_key_pair: &KeyPair, - ) -> (State, Arc, SignedBlock) { + ) -> (State, Arc, SignedBlock, PublicKey) { // Predefined world state - let alice_id: AccountId = "alice@wonderland".parse().expect("Valid"); - let account = Account::new(alice_id.clone(), tx_signer_key_pair.public_key().clone()) - .build(&alice_id); + let (alice_id, alice_keypair) = gen_account_in("wonderland"); + let genesis_public_key = alice_keypair.public_key().clone(); + let account = Account::new(alice_id.clone()).build(&alice_id); let domain_id = "wonderland".parse().expect("Valid"); let mut domain = Domain::new(domain_id).build(&alice_id); assert!(domain.add_account(account).is_none()); @@ -1239,7 +1239,7 @@ mod tests { // Making two transactions that have the same instruction let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([fail_box]) - .sign(tx_signer_key_pair); + .sign(&alice_keypair); let tx = AcceptedTransaction::accept( tx, chain_id, @@ -1273,7 +1273,7 @@ mod tests { let tx1 = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([create_asset_definition1]) - .sign(tx_signer_key_pair); + .sign(&alice_keypair); let tx1 = AcceptedTransaction::accept( tx1, chain_id, @@ -1283,7 +1283,7 @@ mod tests { .expect("Valid"); let tx2 = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions([create_asset_definition2]) - .sign(tx_signer_key_pair); + .sign(&alice_keypair); let tx2 = AcceptedTransaction::accept( tx2, chain_id, @@ -1299,55 +1299,47 @@ mod tests { .unpack(|_| {}) }; - (state, kura, block.into()) + (state, kura, block.into(), genesis_public_key) } #[test] #[allow(clippy::redundant_clone)] async fn block_sync_invalid_block() { let chain_id = ChainId::from("0"); - let tx_signer_key_pair = KeyPair::random(); let leader_key_pair = KeyPair::random(); let topology = Topology::new(unique_vec![PeerId::new( "127.0.0.1:8080".parse().unwrap(), leader_key_pair.public_key().clone(), )]); - let (state, _, mut block) = - create_data_for_test(&chain_id, &topology, &leader_key_pair, &tx_signer_key_pair); + let (state, _, mut block, genesis_public_key) = + create_data_for_test(&chain_id, &topology, &leader_key_pair); // Malform block to make it invalid payload_mut(&mut block).commit_topology.clear(); - let result = handle_block_sync( - &chain_id, - tx_signer_key_pair.public_key(), - block, - &state, - &|_| {}, - ); + let result = handle_block_sync(&chain_id, &genesis_public_key, block, &state, &|_| {}); assert!(matches!(result, Err((_, BlockSyncError::BlockNotValid(_))))) } #[test] async fn block_sync_invalid_soft_fork_block() { let chain_id = ChainId::from("0"); - let tx_signer_key_pair = KeyPair::random(); let leader_key_pair = KeyPair::random(); let topology = Topology::new(unique_vec![PeerId::new( "127.0.0.1:8080".parse().unwrap(), leader_key_pair.public_key().clone(), )]); - let (state, kura, mut block) = - create_data_for_test(&chain_id, &topology, &leader_key_pair, &tx_signer_key_pair); + let (state, kura, mut block, genesis_public_key) = + create_data_for_test(&chain_id, &topology, &leader_key_pair); let mut state_block = state.block(); let committed_block = ValidBlock::validate( block.clone(), &topology, &chain_id, - tx_signer_key_pair.public_key(), + &genesis_public_key, &mut state_block, ) .unpack(|_| {}) @@ -1363,13 +1355,7 @@ mod tests { payload_mut(&mut block).commit_topology.clear(); payload_mut(&mut block).header.view_change_index = 1; - let result = handle_block_sync( - &chain_id, - tx_signer_key_pair.public_key(), - block, - &state, - &|_| {}, - ); + let result = handle_block_sync(&chain_id, &genesis_public_key, block, &state, &|_| {}); assert!(matches!( result, Err((_, BlockSyncError::SoftForkBlockNotValid(_))) @@ -1380,23 +1366,16 @@ mod tests { #[allow(clippy::redundant_clone)] async fn block_sync_not_proper_height() { let chain_id = ChainId::from("0"); - let tx_signer_key_pair = KeyPair::random(); let topology = Topology::new(UniqueVec::new()); let leader_key_pair = KeyPair::random(); - let (state, _, mut block) = - create_data_for_test(&chain_id, &topology, &leader_key_pair, &tx_signer_key_pair); + let (state, _, mut block, genesis_public_key) = + create_data_for_test(&chain_id, &topology, &leader_key_pair); // Change block height payload_mut(&mut block).header.height = 42; - let result = handle_block_sync( - &chain_id, - tx_signer_key_pair.public_key(), - block, - &state, - &|_| {}, - ); + let result = handle_block_sync(&chain_id, &genesis_public_key, block, &state, &|_| {}); assert!(matches!( result, Err(( @@ -1413,44 +1392,36 @@ mod tests { #[allow(clippy::redundant_clone)] async fn block_sync_commit_block() { let chain_id = ChainId::from("0"); - let tx_signer_key_pair = KeyPair::random(); let leader_key_pair = KeyPair::random(); let topology = Topology::new(unique_vec![PeerId::new( "127.0.0.1:8080".parse().unwrap(), leader_key_pair.public_key().clone(), )]); - let (state, _, block) = - create_data_for_test(&chain_id, &topology, &leader_key_pair, &tx_signer_key_pair); - let result = handle_block_sync( - &chain_id, - tx_signer_key_pair.public_key(), - block, - &state, - &|_| {}, - ); + let (state, _, block, genesis_public_key) = + create_data_for_test(&chain_id, &topology, &leader_key_pair); + let result = handle_block_sync(&chain_id, &genesis_public_key, block, &state, &|_| {}); assert!(matches!(result, Ok(BlockSyncOk::CommitBlock(_, _)))) } #[test] async fn block_sync_replace_top_block() { let chain_id = ChainId::from("0"); - let tx_signer_key_pair = KeyPair::random(); let leader_key_pair = KeyPair::random(); let topology = Topology::new(unique_vec![PeerId::new( "127.0.0.1:8080".parse().unwrap(), leader_key_pair.public_key().clone(), )]); - let (state, kura, mut block) = - create_data_for_test(&chain_id, &topology, &leader_key_pair, &tx_signer_key_pair); + let (state, kura, mut block, genesis_public_key) = + create_data_for_test(&chain_id, &topology, &leader_key_pair); let mut state_block = state.block(); let committed_block = ValidBlock::validate( block.clone(), &topology, &chain_id, - tx_signer_key_pair.public_key(), + &genesis_public_key, &mut state_block, ) .unpack(|_| {}) @@ -1467,28 +1438,21 @@ mod tests { // Increase block view change index payload_mut(&mut block).header.view_change_index = 42; - let result = handle_block_sync( - &chain_id, - tx_signer_key_pair.public_key(), - block, - &state, - &|_| {}, - ); + let result = handle_block_sync(&chain_id, &genesis_public_key, block, &state, &|_| {}); assert!(matches!(result, Ok(BlockSyncOk::ReplaceTopBlock(_, _)))) } #[test] async fn block_sync_small_view_change_index() { let chain_id = ChainId::from("0"); - let tx_signer_key_pair = KeyPair::random(); let leader_key_pair = KeyPair::random(); let topology = Topology::new(unique_vec![PeerId::new( "127.0.0.1:8080".parse().unwrap(), leader_key_pair.public_key().clone(), )]); - let (state, kura, mut block) = - create_data_for_test(&chain_id, &topology, &leader_key_pair, &tx_signer_key_pair); + let (state, kura, mut block, genesis_public_key) = + create_data_for_test(&chain_id, &topology, &leader_key_pair); // Increase block view change index payload_mut(&mut block).header.view_change_index = 42; @@ -1498,7 +1462,7 @@ mod tests { block.clone(), &topology, &chain_id, - tx_signer_key_pair.public_key(), + &genesis_public_key, &mut state_block, ) .unpack(|_| {}) @@ -1514,13 +1478,7 @@ mod tests { // Decrease block view change index back payload_mut(&mut block).header.view_change_index = 0; - let result = handle_block_sync( - &chain_id, - tx_signer_key_pair.public_key(), - block, - &state, - &|_| {}, - ); + let result = handle_block_sync(&chain_id, &genesis_public_key, block, &state, &|_| {}); assert!(matches!( result, Err(( @@ -1537,25 +1495,18 @@ mod tests { #[allow(clippy::redundant_clone)] async fn block_sync_genesis_block_do_not_replace() { let chain_id = ChainId::from("0"); - let tx_signer_key_pair = KeyPair::random(); let topology = Topology::new(UniqueVec::new()); let leader_key_pair = KeyPair::random(); - let (state, _, mut block) = - create_data_for_test(&chain_id, &topology, &leader_key_pair, &tx_signer_key_pair); + let (state, _, mut block, genesis_public_key) = + create_data_for_test(&chain_id, &topology, &leader_key_pair); // Change block height and view change index // Soft-fork on genesis block is not possible payload_mut(&mut block).header.view_change_index = 42; payload_mut(&mut block).header.height = 1; - let result = handle_block_sync( - &chain_id, - tx_signer_key_pair.public_key(), - block, - &state, - &|_| {}, - ); + let result = handle_block_sync(&chain_id, &genesis_public_key, block, &state, &|_| {}); assert!(matches!( result, Err(( diff --git a/core/src/tx.rs b/core/src/tx.rs index 070ff3e7d03..ac1e5986ccb 100644 --- a/core/src/tx.rs +++ b/core/src/tx.rs @@ -63,14 +63,13 @@ impl AcceptedTransaction { })); } - for signature in tx.0.signatures() { - if signature.public_key() != genesis_public_key { - return Err(SignatureVerificationFail { - signature: signature.clone().into(), - reason: "Signature doesn't correspond to genesis public key".to_string(), - } - .into()); + let signature = tx.0.signature(); + if signature.public_key() != genesis_public_key { + return Err(SignatureVerificationFail { + signature: signature.clone().into(), + reason: "Signature doesn't correspond to genesis public key".to_string(), } + .into()); } Ok(Self(tx.0)) @@ -95,7 +94,7 @@ impl AcceptedTransaction { })); } - if *iroha_genesis::GENESIS_ACCOUNT_ID == *tx.authority() { + if *iroha_genesis::GENESIS_DOMAIN_ID == *tx.authority().domain_id() { return Err(AcceptTransactionFail::UnexpectedGenesisAccountSignature); } diff --git a/core/test_network/Cargo.toml b/core/test_network/Cargo.toml index 71e24f95f18..06888ac23dd 100644 --- a/core/test_network/Cargo.toml +++ b/core/test_network/Cargo.toml @@ -17,7 +17,7 @@ iroha_data_model = { workspace = true } iroha_primitives = { workspace = true } iroha_logger = { workspace = true } iroha_genesis = { workspace = true } - +test_samples = { workspace = true } eyre = { workspace = true } futures = { workspace = true, features = ["std", "async-await"] } diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index 483332a6a0d..e7de53c116c 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -2,7 +2,7 @@ use core::{fmt::Debug, str::FromStr as _, time::Duration}; #[cfg(debug_assertions)] use std::sync::atomic::AtomicBool; -use std::{collections::BTreeMap, path::Path, sync::Arc, thread}; +use std::{collections::BTreeMap, ops::Deref, path::Path, sync::Arc, thread}; use eyre::Result; use futures::{prelude::*, stream::FuturesUnordered}; @@ -26,6 +26,7 @@ use iroha_primitives::{ use rand::{seq::IteratorRandom, thread_rng}; use serde_json::json; use tempfile::TempDir; +use test_samples::{ALICE_ID, ALICE_KEYPAIR, PEER_KEYPAIR, SAMPLE_GENESIS_ACCOUNT_KEYPAIR}; use tokio::{ runtime::{self, Runtime}, task::{self, JoinHandle}, @@ -48,17 +49,22 @@ pub fn get_chain_id() -> ChainId { ChainId::from("0") } -/// Get a standardised key-pair from the hard-coded literals. -pub fn get_key_pair() -> KeyPair { - KeyPair::new( - iroha_crypto::PublicKey::from_str( - "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0", - ).unwrap(), - iroha_crypto::PrivateKey::from_hex( - iroha_crypto::Algorithm::Ed25519, - "9AC47ABF59B356E0BD7DCBBBB4DEC080E302156A48CA907E47CB6AEA1D32719E7233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" - ).unwrap() - ).unwrap() +/// Get a key pair of a common signatory in the test network +pub fn get_key_pair(signatory: Signatory) -> KeyPair { + match signatory { + Signatory::Peer => &PEER_KEYPAIR, + Signatory::Genesis => &SAMPLE_GENESIS_ACCOUNT_KEYPAIR, + Signatory::Alice => &ALICE_KEYPAIR, + } + .deref() + .clone() +} + +/// A common signatory in the test network +pub enum Signatory { + Peer, + Genesis, + Alice, } /// Trait used to differentiate a test instance of `genesis`. @@ -84,7 +90,6 @@ impl TestGenesis for GenesisNetwork { let rose_definition_id = AssetDefinitionId::from_str("rose#wonderland").expect("valid names"); - let alice_id = AccountId::from_str("alice@wonderland").expect("valid names"); let mint_rose_permission = PermissionToken::new( "CanMintAssetWithDefinition".parse().unwrap(), @@ -117,7 +122,7 @@ impl TestGenesis for GenesisNetwork { upgrade_executor_permission, ] { first_transaction - .append_instruction(Grant::permission(permission, alice_id.clone()).into()); + .append_instruction(Grant::permission(permission, ALICE_ID.clone()).into()); } for isi in extra_isi.into_iter() { @@ -781,7 +786,8 @@ impl TestConfig for Config { let mut layer = iroha::samples::get_user_config( &UniqueVec::new(), Some(get_chain_id()), - Some(get_key_pair()), + Some(get_key_pair(Signatory::Peer)), + Some(get_key_pair(Signatory::Genesis)), ) .merge(RootPartial::from_env(&StdEnv).expect("test env variables should parse properly")); @@ -811,7 +817,7 @@ impl TestClientConfig for ClientConfig { fn test(api_address: &SocketAddr) -> Self { iroha_client::samples::get_client_config( get_chain_id(), - get_key_pair().clone(), + get_key_pair(Signatory::Alice), format!("http://{api_address}") .parse() .expect("should be valid url"), diff --git a/data_model/derive/tests/ui_fail/transparent_api_private_field.rs b/data_model/derive/tests/ui_fail/transparent_api_private_field.rs index bdf02982028..72d0692dc6d 100644 --- a/data_model/derive/tests/ui_fail/transparent_api_private_field.rs +++ b/data_model/derive/tests/ui_fail/transparent_api_private_field.rs @@ -1,6 +1,6 @@ use iroha_data_model::account::AccountId; fn main() { - let account_id: AccountId = "alice@wonderland".parse().expect("Valid account id"); - println!("ID: {}", account_id.name); + let account_id: AccountId = "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland".parse().unwrap(); + println!("ID: {}", account_id.signatory); } diff --git a/data_model/derive/tests/ui_fail/transparent_api_private_field.stderr b/data_model/derive/tests/ui_fail/transparent_api_private_field.stderr index 884d5e959b1..16b358917e2 100644 --- a/data_model/derive/tests/ui_fail/transparent_api_private_field.stderr +++ b/data_model/derive/tests/ui_fail/transparent_api_private_field.stderr @@ -1,10 +1,10 @@ -error[E0616]: field `name` of struct `iroha_data_model::account::AccountId` is private +error[E0616]: field `signatory` of struct `iroha_data_model::account::AccountId` is private --> tests/ui_fail/transparent_api_private_field.rs:5:35 | -5 | println!("ID: {}", account_id.name); - | ^^^^ private field +5 | println!("ID: {}", account_id.signatory); + | ^^^^^^^^^ private field | -help: a method `name` also exists, call it with parentheses +help: a method `signatory` also exists, call it with parentheses | -5 | println!("ID: {}", account_id.name()); - | ++ +5 | println!("ID: {}", account_id.signatory()); + | ++ diff --git a/data_model/src/account.rs b/data_model/src/account.rs index fa0cd7fdcd4..9f83150cee5 100644 --- a/data_model/src/account.rs +++ b/data_model/src/account.rs @@ -1,19 +1,13 @@ //! Structures, traits and impls related to `Account`s. #[cfg(not(feature = "std"))] -use alloc::{ - collections::{btree_map, btree_set}, - format, - string::String, - vec::Vec, -}; +use alloc::{collections::btree_map, format, string::String, vec::Vec}; use core::str::FromStr; #[cfg(feature = "std")] -use std::collections::{btree_map, btree_set}; +use std::collections::btree_map; use derive_more::{Constructor, DebugCustom, Display}; use getset::Getters; use iroha_data_model_derive::{model, IdEqOrdHash}; -use iroha_primitives::const_vec::ConstVec; use iroha_schema::IntoSchema; use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; @@ -27,27 +21,28 @@ use crate::{ }, domain::prelude::*, metadata::Metadata, - name::Name, HasMetadata, Identifiable, ParseError, PublicKey, Registered, }; /// API to work with collections of [`Id`] : [`Account`] mappings. pub type AccountsMap = btree_map::BTreeMap; -type Signatories = btree_set::BTreeSet; - #[model] mod model { use super::*; - /// Identification of an [`Account`]. Consists of Account name and Domain name. + /// Identification of [`Account`] by the combination of the [`PublicKey`] as its sole signatory and the [`Domain`](crate::domain::Domain) it belongs to. + /// TODO #4373 include multi-signatory use. /// /// # Examples /// /// ```rust /// use iroha_data_model::account::AccountId; /// - /// let id = "user@company".parse::().expect("Valid"); + /// let id: AccountId = + /// "ed0120BDF918243253B1E731FA096194C8928DA37C4D3226F97EEBD18CF5523D758D6C@domain" + /// .parse() + /// .expect("multihash@domain should be valid format"); /// ``` #[derive( DebugCustom, @@ -66,140 +61,63 @@ mod model { SerializeDisplay, IntoSchema, )] - #[display(fmt = "{name}@{domain_id}")] - #[debug(fmt = "{name}@{domain_id}")] + #[display(fmt = "{signatory}@{domain_id}")] + #[debug(fmt = "{signatory}@{domain_id}")] #[getset(get = "pub")] #[ffi_type] pub struct AccountId { - /// [`Account`]'s [`Domain`](`crate::domain::Domain`) id. + /// [`Domain`](crate::domain::Domain) that the [`Account`] belongs to. pub domain_id: DomainId, - /// [`Account`]'s name. - pub name: Name, + /// Sole signatory of the [`Account`]. + pub signatory: PublicKey, } /// Account entity is an authority which is used to execute `Iroha Special Instructions`. #[derive( - Debug, Display, Clone, IdEqOrdHash, Getters, Encode, Deserialize, Serialize, IntoSchema, + Debug, + Display, + Clone, + IdEqOrdHash, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, )] #[allow(clippy::multiple_inherent_impl)] #[display(fmt = "({id})")] // TODO: Add more? #[ffi_type] - #[serde(try_from = "candidate::Account")] pub struct Account { - /// An Identification of the [`Account`]. + /// Identification of the [`Account`]. pub id: AccountId, /// Assets in this [`Account`]. pub assets: AssetsMap, - /// [`Account`]'s signatories. - pub(super) signatories: Signatories, - /// Condition which checks if the account has the right signatures. - #[getset(get = "pub")] - pub signature_check_condition: SignatureCheckCondition, /// Metadata of this account as a key-value store. pub metadata: Metadata, } /// Builder which should be submitted in a transaction to create a new [`Account`] #[derive( - DebugCustom, Display, Clone, IdEqOrdHash, Encode, Serialize, Deserialize, IntoSchema, + DebugCustom, Display, Clone, IdEqOrdHash, Decode, Encode, Serialize, Deserialize, IntoSchema, )] #[display(fmt = "[{id}]")] - #[debug(fmt = "[{id:?}] {{ signatories: {signatories:?}, metadata: {metadata} }}")] + #[debug(fmt = "[{id:?}] {{ metadata: {metadata} }}")] #[ffi_type] - #[serde(try_from = "candidate::NewAccount")] pub struct NewAccount { /// Identification pub id: AccountId, - /// Signatories, i.e. signatures attached to this message. - /// Cannot be empty, guaranteed by constructors. - pub(super) signatories: Signatories, /// Metadata that should be submitted with the builder pub metadata: Metadata, } - - /// Condition which checks if the account has the right signatures. - #[derive( - Debug, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[ffi_type(opaque)] - #[allow(clippy::enum_variant_names)] - pub enum SignatureCheckCondition { - #[display(fmt = "AnyAccountSignatureOr({_0:?})")] - AnyAccountSignatureOr(ConstVec), - #[display(fmt = "AllAccountSignaturesAnd({_0:?})")] - AllAccountSignaturesAnd(ConstVec), - } } -mod candidate { - //! Contains structs for deserialization checks - - use super::*; - - #[derive(Decode, Deserialize)] - /// [`Account`] candidate used for deserialization checks - pub struct Account { - id: AccountId, - assets: AssetsMap, - signatories: Signatories, - signature_check_condition: SignatureCheckCondition, - metadata: Metadata, - } - - impl TryFrom for super::Account { - type Error = &'static str; - - fn try_from(candidate: Account) -> Result { - check_signatories(&candidate.signatories)?; - - Ok(Self { - id: candidate.id, - assets: candidate.assets, - signatories: candidate.signatories, - signature_check_condition: candidate.signature_check_condition, - metadata: candidate.metadata, - }) - } - } - - /// [`NewAccount`] candidate used for deserialization checks - #[derive(Decode, Deserialize)] - pub struct NewAccount { - id: AccountId, - signatories: Signatories, - metadata: Metadata, - } - - impl TryFrom for super::NewAccount { - type Error = &'static str; - - fn try_from(candidate: NewAccount) -> Result { - check_signatories(&candidate.signatories)?; - - Ok(Self { - id: candidate.id, - signatories: candidate.signatories, - metadata: candidate.metadata, - }) - } - } - - fn check_signatories(signatories: &Signatories) -> Result<(), &'static str> { - if signatories.is_empty() { - return Err("Signatories cannot be empty"); - } - Ok(()) +impl AccountId { + /// Return `true` if the account signatory matches the given `public_key`. + #[inline] + #[cfg(feature = "transparent_api")] + pub fn signatory_matches(&self, public_key: &PublicKey) -> bool { + self.signatory() == public_key } } @@ -207,14 +125,14 @@ impl Account { /// Construct builder for [`Account`] identifiable by [`Id`] containing the given signatory. #[inline] #[must_use] - pub fn new(id: AccountId, signatory: PublicKey) -> ::With { - ::With::new(id, signatory) + pub fn new(id: AccountId) -> ::With { + ::With::new(id) } - /// Get an iterator over [`signatories`](PublicKey) of the `Account` + /// Return a reference to the `Account` signatory. #[inline] - pub fn signatories(&self) -> impl ExactSizeIterator { - self.signatories.iter() + pub fn signatory(&self) -> &PublicKey { + &self.id.signatory } /// Return a reference to the [`Asset`] corresponding to the asset id. @@ -228,12 +146,6 @@ impl Account { pub fn assets(&self) -> impl ExactSizeIterator { self.assets.values() } - - /// Return `true` if the `Account` contains the given signatory - #[inline] - pub fn contains_signatory(&self, signatory: &PublicKey) -> bool { - self.signatories.contains(signatory) - } } #[cfg(feature = "transparent_api")] @@ -249,67 +161,16 @@ impl Account { pub fn remove_asset(&mut self, asset_id: &AssetId) -> Option { self.assets.remove(asset_id) } - - /// Add [`signatory`](PublicKey) into the [`Account`]. - /// - /// If [`Account`] did not have this signatory present, `true` is returned. - /// If [`Account`] did have this signatory present, `false` is returned. - #[inline] - pub fn add_signatory(&mut self, signatory: PublicKey) -> bool { - self.signatories.insert(signatory) - } - - /// Remove a signatory from the [`Account`]. - /// - /// Does nothing and returns [`None`] if only one signature is left. - /// Otherwise returns whether the signatory was presented in the Account. - #[inline] - pub fn remove_signatory(&mut self, signatory: &PublicKey) -> Option { - if self.signatories.len() < 2 { - return None; - } - - Some(self.signatories.remove(signatory)) - } - - /// Checks whether the transaction contains all the signatures required by the - /// [`SignatureCheckCondition`] stored in this account. - #[must_use] - pub fn check_signature_check_condition( - &self, - transaction_signatories: &btree_set::BTreeSet, - ) -> bool { - self.signature_check_condition - .check(&self.signatories, transaction_signatories) - } -} - -impl Decode for Account { - fn decode( - input: &mut I, - ) -> Result { - let candidate = candidate::Account::decode(input)?; - Self::try_from(candidate).map_err(Into::into) - } } impl NewAccount { - fn new(id: AccountId, signatory: PublicKey) -> Self { + fn new(id: AccountId) -> Self { Self { id, - signatories: Signatories::from([signatory]), metadata: Metadata::default(), } } - /// Add signatory to account. - #[inline] - #[must_use] - pub fn add_signatory(mut self, signatory: PublicKey) -> Self { - self.signatories.insert(signatory); - self - } - /// Add [`Metadata`] to the account replacing any previously defined metadata #[inline] #[must_use] @@ -325,9 +186,7 @@ impl NewAccount { pub fn into_account(self) -> Account { Account { id: self.id, - signatories: self.signatories, assets: AssetsMap::default(), - signature_check_condition: SignatureCheckCondition::default(), metadata: self.metadata, } } @@ -339,15 +198,6 @@ impl HasMetadata for NewAccount { } } -impl Decode for NewAccount { - fn decode( - input: &mut I, - ) -> Result { - let candidate = candidate::NewAccount::decode(input)?; - Self::try_from(candidate).map_err(Into::into) - } -} - impl HasMetadata for Account { fn metadata(&self) -> &Metadata { &self.metadata @@ -358,207 +208,57 @@ impl Registered for Account { type With = NewAccount; } -/// Account Identification is represented by `name@domain_name` string. impl FromStr for AccountId { type Err = ParseError; - fn from_str(string: &str) -> Result { - let split = string.rsplit_once('@'); - match split { - Some(("", _)) => Err(ParseError { - reason: "`AccountId` cannot be empty", + fn from_str(s: &str) -> Result { + match s.rsplit_once('@') { + None => Err(ParseError { + reason: "Account ID should have format `signatory@domain`", }), - Some((name, domain_id)) if !name.is_empty() && !domain_id.is_empty() => Ok(AccountId { - name: name.parse()?, - domain_id: domain_id.parse()?, + Some(("", _)) => Err(ParseError { + reason: "Empty `signatory` part in `signatory@domain`", }), - _ => Err(ParseError { - reason: "`AccountId` should have format `name@domain_name`", + Some((_, "")) => Err(ParseError { + reason: "Empty `domain` part in `signatory@domain`", }), - } - } -} - -impl Default for SignatureCheckCondition { - fn default() -> Self { - Self::AnyAccountSignatureOr(ConstVec::new_empty()) - } -} - -impl SignatureCheckCondition { - /// Shorthand to create a [`SignatureCheckCondition::AnyAccountSignatureOr`] variant without additional allowed signatures. - #[inline] - pub fn any_account_signature() -> Self { - Self::AnyAccountSignatureOr(ConstVec::new_empty()) - } - - /// Shorthand to create a [`SignatureCheckCondition::AllAccountSignaturesAnd`] variant without additional required signatures. - #[inline] - pub fn all_account_signatures() -> Self { - Self::AllAccountSignaturesAnd(ConstVec::new_empty()) - } - - #[must_use] - #[cfg(feature = "transparent_api")] - fn check( - &self, - account_signatories: &btree_set::BTreeSet, - transaction_signatories: &btree_set::BTreeSet, - ) -> bool { - let result = match &self { - SignatureCheckCondition::AnyAccountSignatureOr(additional_allowed_signatures) => { - account_signatories - .iter() - .chain(additional_allowed_signatures.as_ref()) - .any(|allowed| transaction_signatories.contains(allowed)) - } - SignatureCheckCondition::AllAccountSignaturesAnd(additional_required_signatures) => { - account_signatories - .iter() - .chain(additional_required_signatures.as_ref()) - .all(|required_signature| transaction_signatories.contains(required_signature)) + Some((signatory_candidate, domain_id_candidate)) => { + let signatory = signatory_candidate.parse().map_err(|_| ParseError { + reason: r#"Failed to parse `signatory` part in `signatory@domain`. `signatory` should have multihash format e.g. "ed0120...""#, + })?; + let domain_id = domain_id_candidate.parse().map_err(|_| ParseError { + reason: "Failed to parse `domain` part in `signatory@domain`", + })?; + Ok(Self::new(domain_id, signatory)) } - }; - - result + } } } /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { - pub use super::{Account, AccountId, SignatureCheckCondition}; + pub use super::{Account, AccountId}; } #[cfg(test)] mod tests { - #[cfg(not(feature = "std"))] - use alloc::{vec, vec::Vec}; - use core::cmp::Ordering; - - use iroha_crypto::{KeyPair, PublicKey}; - - use super::{AccountId, SignatureCheckCondition}; - use crate::{domain::DomainId, name::Name}; - - fn make_key() -> PublicKey { - KeyPair::random().public_key().clone() - } - - fn check_signature_check_condition( - condition: &SignatureCheckCondition, - account_signatories: &[&PublicKey], - tx_signatories: &[&PublicKey], - result: bool, - ) { - let account_signatories = account_signatories.iter().copied().cloned().collect(); - let tx_signatories = tx_signatories.iter().copied().cloned().collect(); - - assert_eq!( - condition.check(&account_signatories, &tx_signatories,), - result - ); - } - - #[test] - fn signature_check_condition_default() { - let key1 = make_key(); - let key2 = make_key(); - let key3 = make_key(); - let condition = SignatureCheckCondition::default(); - - check_signature_check_condition(&condition, &[], &[], false); - check_signature_check_condition(&condition, &[&key1], &[], false); - check_signature_check_condition(&condition, &[], &[&key1], false); - check_signature_check_condition(&condition, &[&key1], &[&key1], true); - check_signature_check_condition(&condition, &[&key1], &[&key2], false); - check_signature_check_condition(&condition, &[&key1, &key2, &key3], &[&key1], true); - check_signature_check_condition(&condition, &[&key1, &key2, &key3], &[&key2], true); - check_signature_check_condition(&condition, &[&key1, &key2, &key3], &[&key3], true); - } - - #[test] - fn signature_check_condition_all() { - let key1 = make_key(); - let key2 = make_key(); - let key3 = make_key(); - let condition = SignatureCheckCondition::all_account_signatures(); - - // technically, `\forall x \in \emptyset, check(x)` is true for any `check`, so this evaluate to true - // maybe not the logic we want? - check_signature_check_condition(&condition, &[], &[], true); - check_signature_check_condition(&condition, &[], &[&key1], true); - - check_signature_check_condition(&condition, &[&key1], &[], false); - check_signature_check_condition(&condition, &[&key1], &[&key1], true); - check_signature_check_condition(&condition, &[&key1], &[&key2], false); - check_signature_check_condition(&condition, &[&key1, &key2, &key3], &[&key1], false); - check_signature_check_condition(&condition, &[&key1, &key2, &key3], &[&key2], false); - check_signature_check_condition(&condition, &[&key1, &key2, &key3], &[&key3], false); - check_signature_check_condition(&condition, &[&key1, &key2], &[&key1, &key2, &key3], true); - check_signature_check_condition(&condition, &[&key1, &key2], &[&key1, &key2], true); - check_signature_check_condition(&condition, &[&key1, &key2], &[&key2, &key3], false); - } - - #[test] - fn signature_check_condition_any_or() { - let key1 = make_key(); - let key2 = make_key(); - let key3 = make_key(); - let condition = SignatureCheckCondition::AnyAccountSignatureOr(vec![key3.clone()].into()); - - check_signature_check_condition(&condition, &[], &[], false); - check_signature_check_condition(&condition, &[], &[&key3], true); - check_signature_check_condition(&condition, &[], &[&key2], false); - check_signature_check_condition(&condition, &[], &[&key1, &key2], false); - check_signature_check_condition(&condition, &[&key2], &[&key2], true); - check_signature_check_condition(&condition, &[&key2, &key3], &[&key2], true); - check_signature_check_condition(&condition, &[&key1, &key2], &[&key2], true); - } - - #[test] - fn signature_check_condition_all_and() { - let key1 = make_key(); - let key2 = make_key(); - let key3 = make_key(); - let condition = SignatureCheckCondition::AllAccountSignaturesAnd(vec![key3.clone()].into()); - - check_signature_check_condition(&condition, &[], &[], false); - check_signature_check_condition(&condition, &[], &[&key3], true); - check_signature_check_condition(&condition, &[&key1], &[&key3], false); - check_signature_check_condition(&condition, &[&key1], &[&key1, &key3], true); - check_signature_check_condition(&condition, &[&key2], &[&key1, &key3], false); - check_signature_check_condition(&condition, &[&key2], &[&key1, &key2, &key3], true); - } + use super::*; #[test] - fn cmp_account_id() { - let domain_id_a: DomainId = "a".parse().expect("failed to parse DomainId"); - let domain_id_b: DomainId = "b".parse().expect("failed to parse DomainId"); - let name_a: Name = "a".parse().expect("failed to parse Name"); - let name_b: Name = "b".parse().expect("failed to parse Name"); - - 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(domain_id.clone(), name.clone())); - } - } - - for account_id_1 in &account_ids { - for account_id_2 in &account_ids { - match ( - account_id_1.domain_id.cmp(&account_id_2.domain_id), - account_id_1.name.cmp(&account_id_2.name), - ) { - // `DomainId` take precedence in comparison - // if `DomainId`s are equal than comparison based on `Name`s - (Ordering::Equal, ordering) | (ordering, _) => assert_eq!( - account_id_1.cmp(account_id_2), - ordering, - "{account_id_1:?} and {account_id_2:?} are expected to be {ordering:?}" - ), - } - } - } + fn parse_account_id() { + const SIGNATORY: &str = + "ed0120EDF6D7B52C7032D03AEC696F2068BD53101528F3C7B6081BFF05A1662D7FC245"; + let _ok = format!("{SIGNATORY}@domain") + .parse::() + .expect("should be valid"); + let _err_empty_signatory = "@domain" + .parse::() + .expect_err("@domain should not be valid"); + let _err_empty_domain = format!("{SIGNATORY}@") + .parse::() + .expect_err("signatory@ should not be valid"); + let _err_violates_format = format!("{SIGNATORY}#domain") + .parse::() + .expect_err("signatory#domain should not be valid"); } } diff --git a/data_model/src/asset.rs b/data_model/src/asset.rs index 36e589a02ec..53fa815730e 100644 --- a/data_model/src/asset.rs +++ b/data_model/src/asset.rs @@ -382,19 +382,26 @@ impl> From for AssetValue { impl FromStr for AssetDefinitionId { type Err = ParseError; - fn from_str(string: &str) -> Result { - let mut split = string.split('#'); - match (split.next(), split.next(), split.next()) { - (Some(""), _, _) => Err(ParseError { - reason: "Asset Definition ID cannot be empty", + fn from_str(s: &str) -> Result { + match s.rsplit_once('#') { + None => Err(ParseError { + reason: "Asset Definition ID should have format `name#domain`", }), - (Some(name), Some(domain_id), None) if !domain_id.is_empty() => Ok(Self { - name: name.parse()?, - domain_id: domain_id.parse()?, + Some(("", _)) => Err(ParseError { + reason: "Empty `name` part in `name#domain`", }), - _ => Err(ParseError { - reason: "Asset Definition ID should have format `asset#domain`", + Some((_, "")) => Err(ParseError { + reason: "Empty `domain` part in `name#domain`", }), + Some((name_candidate, domain_id_candidate)) => { + let name = name_candidate.parse().map_err(|_| ParseError { + reason: "Failed to parse `name` part in `name#domain`", + })?; + let domain_id = domain_id_candidate.parse().map_err(|_| ParseError { + reason: "Failed to parse `domain` part in `name#domain`", + })?; + Ok(Self::new(domain_id, name)) + } } } } @@ -415,42 +422,26 @@ impl fmt::Debug for AssetId { } } -/// Asset Identification, represented by -/// `name#asset_domain#account_name@account_domain`. If the domains of -/// the asset and account match, the name can be shortened to -/// `asset##account@domain`. impl FromStr for AssetId { type Err = ParseError; - fn from_str(string: &str) -> Result { - if let Some((asset_definition_candidate, account_id_candidate)) = string.rsplit_once('#') { - let account_id: AccountId = account_id_candidate.parse() - .map_err(|_err| ParseError { - reason: "Failed to parse the `account_id` part of the `asset_id`. Please ensure that it has the form `account@domain`" - })?; - let definition_id = { - if let Ok(def_id) = asset_definition_candidate.parse() { - def_id - } else if let Some((name, "")) = asset_definition_candidate.rsplit_once('#') { - 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" }); - } - }; - Ok(Self { - definition_id, - account_id, - }) + fn from_str(s: &str) -> Result { + let (definition_id_candidate, account_id_candidate) = + s.rsplit_once('#').ok_or(ParseError { + reason: "Asset ID should have format `asset#domain#account@domain`, or `asset##account@domain` for the same domains", + })?; + let account_id = account_id_candidate.parse::().map_err(|_| ParseError { + reason: "Failed to parse `account@domain` part in `asset#domain#account@domain`. `account` should have multihash format e.g. `ed0120...`" + })?; + let domain_complement = if definition_id_candidate.ends_with('#') { + account_id.domain_id.name.as_ref() } else { - Err(ParseError { - reason: "The `AssetId` did not contain the `#` character. ", - }) - } + "" + }; + let definition_id = format!("{definition_id_candidate}{domain_complement}").parse().map_err(|_| ParseError { + reason: "Failed to parse `asset#domain` (or `asset#`) part in `asset#domain#account@domain` (or `asset##account@domain`)", + })?; + Ok(Self::new(definition_id, account_id)) } } @@ -494,9 +485,38 @@ pub mod prelude { #[cfg(test)] mod tests { use super::*; + + #[test] + fn parse_definition_id() { + let _ok = "asset#domain" + .parse::() + .expect("should be valid"); + let _err_empty_asset = "#domain" + .parse::() + .expect_err("#domain should not be valid"); + let _err_empty_domain = "asset#" + .parse::() + .expect_err("asset# should not be valid"); + let _err_violates_format = "asset@domain" + .parse::() + .expect_err("asset@domain should not be valid"); + } + #[test] - fn test_error_for_asset_id() { - let _invalid_asset_id = AssetId::from_str("store#alice@wonderland") - .expect_err("store#alice@wonderland should not be a valid AssetId"); + fn parse_asset_id() { + const SIGNATORY: &str = + "ed0120EDF6D7B52C7032D03AEC696F2068BD53101528F3C7B6081BFF05A1662D7FC245"; + let _account_id = format!("{SIGNATORY}@domain") + .parse::() + .expect("should be valid"); + let _ok = format!("asset#domain#{SIGNATORY}@domain") + .parse::() + .expect("should be valid"); + let _ok_short = format!("asset##{SIGNATORY}@domain") + .parse::() + .expect("should be valid"); + let _err = format!("asset#{SIGNATORY}@domain") + .parse::() + .expect_err("asset#signatory@domain should not be valid"); } } diff --git a/data_model/src/block.rs b/data_model/src/block.rs index b0f861757b9..91aca3ac52f 100644 --- a/data_model/src/block.rs +++ b/data_model/src/block.rs @@ -9,8 +9,6 @@ use alloc::{boxed::Box, format, string::String, vec::Vec}; use core::{fmt::Display, time::Duration}; use derive_more::Display; -#[cfg(all(feature = "std", feature = "transparent_api"))] -use iroha_crypto::KeyPair; use iroha_crypto::{HashOf, MerkleTree, SignaturesOf}; use iroha_data_model_derive::model; use iroha_macro::FromVariant; @@ -166,6 +164,7 @@ impl SignedBlock { /// Signatures of peers which approved this block. #[inline] + #[allow(private_interfaces)] pub fn signatures(&self) -> &SignaturesOf { let SignedBlock::V1(block) = self; &block.signatures @@ -188,8 +187,8 @@ impl SignedBlock { /// Add additional signatures to this block #[must_use] - #[cfg(feature = "transparent_api")] - pub fn sign(mut self, key_pair: &KeyPair) -> Self { + #[cfg(all(feature = "std", feature = "transparent_api"))] + pub fn sign(mut self, key_pair: &iroha_crypto::KeyPair) -> Self { let SignedBlock::V1(block) = &mut self; let signature = iroha_crypto::SignatureOf::new(key_pair, &block.payload); block.signatures.insert(signature); diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 4ef246bf076..4fb6aee691e 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -740,10 +740,11 @@ pub mod prelude { TriggerEventFilter, }; } - #[cfg(test)] #[cfg(feature = "transparent_api")] mod tests { + use iroha_crypto::KeyPair; + use super::*; use crate::{ account::AccountsMap, @@ -753,12 +754,11 @@ mod tests { #[test] #[cfg(feature = "transparent_api")] fn entity_scope() { - let domain_name = "wonderland".parse().expect("Valid"); - let account_name = "alice".parse().expect("Valid"); - let asset_name = "rose".parse().expect("Valid"); - let domain_owner_id = "genesis@genesis".parse().expect("Valid"); + let domain_id: DomainId = "wonderland".parse().unwrap(); + let account_id = AccountId::new(domain_id.clone(), KeyPair::random().into_parts().0); + let asset_id: AssetId = format!("rose##{account_id}").parse().unwrap(); + let domain_owner_id = AccountId::new(domain_id.clone(), KeyPair::random().into_parts().0); - let domain_id = DomainId::new(domain_name); let domain = Domain { id: domain_id.clone(), accounts: AccountsMap::default(), @@ -768,16 +768,7 @@ mod tests { metadata: Metadata::default(), owned_by: domain_owner_id, }; - let account_id = AccountId::new(domain_id.clone(), account_name); - let account = Account::new( - account_id.clone(), - iroha_crypto::KeyPair::random().into_parts().0, - ) - .into_account(); - let asset_id = AssetId::new( - AssetDefinitionId::new(domain_id.clone(), asset_name), - account_id.clone(), - ); + let account = Account::new(account_id.clone()).into_account(); let asset = Asset::new(asset_id.clone(), 0_u32); // Create three events with three levels of nesting diff --git a/data_model/src/isi.rs b/data_model/src/isi.rs index 31aceca6dd6..d7c03236ba4 100644 --- a/data_model/src/isi.rs +++ b/data_model/src/isi.rs @@ -157,11 +157,8 @@ impl_instruction! { Unregister, Unregister, Unregister, - Mint, - Mint, Mint, Mint, - Burn, Burn, Burn, Transfer, @@ -646,29 +643,6 @@ mod transparent { } } - impl Mint { - /// Constructs a new [`Mint`] for a [`PublicKey`] for [`Account`]. - pub fn account_public_key(public_key: PublicKey, account_id: AccountId) -> Self { - Self { - object: public_key, - destination_id: account_id, - } - } - } - - impl Mint { - /// Constructs a new [`Mint`] for a [`SignatureCheckCondition`] for [`Account`]. - pub fn account_signature_check_condition( - signature_check_condition: SignatureCheckCondition, - account_id: AccountId, - ) -> Self { - Self { - object: signature_check_condition, - destination_id: account_id, - } - } - } - impl Mint { /// Constructs a new [`Mint`] for an [`Asset`] of [`Numeric`] type. pub fn asset_numeric(object: impl Into, asset_id: AssetId) -> Self { @@ -702,15 +676,6 @@ mod transparent { } impl_into_box! { - Mint | - Mint - => AccountMintBox => MintBox[Account], - => AccountMintBoxRef<'a> => MintBoxRef<'a>[Account] - } - - impl_into_box! { - Mint | - Mint | Mint | Mint => MintBox => InstructionBox[Mint], @@ -728,16 +693,6 @@ mod transparent { } } - impl Burn { - /// Constructs a new [`Burn`] for a [`PublicKey`] for [`Account`]. - pub fn account_public_key(public_key: PublicKey, account_id: AccountId) -> Self { - Self { - object: public_key, - destination_id: account_id, - } - } - } - impl Burn { /// Constructs a new [`Burn`] for an [`Asset`] of [`Numeric`] type. pub fn asset_numeric(object: impl Into, asset_id: AssetId) -> Self { @@ -771,7 +726,6 @@ mod transparent { } impl_into_box! { - Burn | Burn | Burn => BurnBox => InstructionBox[Burn], @@ -1172,9 +1126,6 @@ isi_box! { )] /// Enum with all supported [`Mint`] instructions. pub enum MintBox { - /// Mint for [`Account`]. - #[enum_ref(transparent)] - Account(AccountMintBox), /// Mint for [`Asset`]. Asset(Mint), /// Mint [`Trigger`] repetitions. @@ -1182,21 +1133,6 @@ isi_box! { } } -isi_box! { - #[strum_discriminants( - vis(pub(crate)), - name(AccountMintType), - derive(Encode), - )] - /// Enum with all supported [`Mint`] instructions related to [`Account`]. - pub enum AccountMintBox { - /// Mint [`PublicKey`]. - PublicKey(Mint), - /// Mint [`SignatureCheckCondition`]. - SignatureCheckCondition(Mint), - } -} - isi_box! { #[strum_discriminants( vis(pub(crate)), @@ -1205,8 +1141,6 @@ isi_box! { )] /// Enum with all supported [`Burn`] instructions. pub enum BurnBox { - /// Burn [`PublicKey`] for [`Account`]. - AccountPublicKey(Burn), /// Burn [`Asset`]. Asset(Burn), /// Burn [`Trigger`] repetitions. @@ -1584,9 +1518,9 @@ pub mod error { /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{ - AccountMintBox, AssetTransferBox, Burn, BurnBox, ExecuteTrigger, Fail, Grant, GrantBox, - InstructionBox, Log, Mint, MintBox, NewParameter, Register, RegisterBox, RemoveKeyValue, - RemoveKeyValueBox, Revoke, RevokeBox, SetKeyValue, SetKeyValueBox, SetParameter, Transfer, - TransferBox, Unregister, UnregisterBox, Upgrade, + AssetTransferBox, Burn, BurnBox, ExecuteTrigger, Fail, Grant, GrantBox, InstructionBox, + Log, Mint, MintBox, NewParameter, Register, RegisterBox, RemoveKeyValue, RemoveKeyValueBox, + Revoke, RevokeBox, SetKeyValue, SetKeyValueBox, SetParameter, Transfer, TransferBox, + Unregister, UnregisterBox, Upgrade, }; } diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index a4be42ece8a..31b4c974b8b 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -97,12 +97,9 @@ mod seal { Unregister, Unregister, - Mint, - Mint, Mint, Mint, - Burn, Burn, Burn, @@ -131,7 +128,6 @@ mod seal { FindAllAccounts, FindAccountById, FindAccountKeyValueByIdAndKey, - FindAccountsByName, FindAccountsByDomainId, FindAccountsWithAsset, FindAllAssets, @@ -619,6 +615,7 @@ pub mod parameter { } #[model] +#[allow(clippy::redundant_pub_crate)] mod model { use super::*; diff --git a/data_model/src/name.rs b/data_model/src/name.rs index e9b5f86221e..518ae2a230c 100644 --- a/data_model/src/name.rs +++ b/data_model/src/name.rs @@ -71,7 +71,7 @@ impl Name { if candidate.is_empty() { return Err(ParseError { - reason: "`Name` cannot be empty", + reason: "Empty `Name`", }); } if candidate.chars().any(char::is_whitespace) { diff --git a/data_model/src/query/mod.rs b/data_model/src/query/mod.rs index 9837f00905d..bd84908848d 100644 --- a/data_model/src/query/mod.rs +++ b/data_model/src/query/mod.rs @@ -152,7 +152,6 @@ mod model { FindAllAccounts(FindAllAccounts), FindAccountById(FindAccountById), FindAccountKeyValueByIdAndKey(FindAccountKeyValueByIdAndKey), - FindAccountsByName(FindAccountsByName), FindAccountsByDomainId(FindAccountsByDomainId), FindAccountsWithAsset(FindAccountsWithAsset), FindAllAssets(FindAllAssets), @@ -339,7 +338,6 @@ impl_query! { FindAllAccounts => Vec, FindAccountById => crate::account::Account, FindAccountKeyValueByIdAndKey => MetadataValueBox, - FindAccountsByName => Vec, FindAccountsByDomainId => Vec, FindAccountsWithAsset => Vec, FindAllAssets => Vec, @@ -668,19 +666,6 @@ pub mod account { pub key: Name, } - /// [`FindAccountsByName`] Iroha Query gets [`Account`]s name as input and - /// finds all [`Account`]s with this name. - #[derive(Display)] - #[display(fmt = "Find accounts with `{name}` name")] - #[repr(transparent)] - // SAFETY: `FindAccountsByName` has no trap representation in `EvaluatesTo` - #[ffi_type(unsafe {robust})] - pub struct FindAccountsByName { - /// `name` of accounts to find. - pub name: Name, - } - - /// [`FindAccountsByDomainId`] Iroha Query gets [`Domain`]s id as input and /// finds all [`Account`]s under this [`Domain`]. #[derive(Display)] @@ -710,7 +695,7 @@ pub mod account { pub mod prelude { pub use super::{ FindAccountById, FindAccountKeyValueByIdAndKey, FindAccountsByDomainId, - FindAccountsByName, FindAccountsWithAsset, FindAllAccounts, + FindAccountsWithAsset, FindAllAccounts, }; } } diff --git a/data_model/src/query/predicate.rs b/data_model/src/query/predicate.rs index 6b6ab4c3682..aee03ed9d89 100644 --- a/data_model/src/query/predicate.rs +++ b/data_model/src/query/predicate.rs @@ -614,6 +614,8 @@ pub mod string { use super::*; mod id_box { + use iroha_crypto::KeyPair; + use super::*; use crate::peer::PeerId; @@ -689,34 +691,32 @@ pub mod string { #[test] fn account_id() { - let id = IdBox::AccountId("alice@wonderland".parse().expect("Valid")); - assert!(StringPredicate::starts_with("alice@").applies(&id)); + let alice: PublicKey = KeyPair::random().into_parts().0; + let id = IdBox::AccountId(format!("{alice}@wonderland").parse().expect("Valid")); + assert!(StringPredicate::starts_with(&*format!("{alice}@")).applies(&id)); assert!(StringPredicate::ends_with("@wonderland").applies(&id)); - assert!(StringPredicate::is("alice@wonderland").applies(&id)); + assert!(StringPredicate::is(&*format!("{alice}@wonderland")).applies(&id)); // Should we also include a check into string // predicates? If the internal predicate starts with // whitespace, it can't possibly match any Id, but // there's no way to enforce this at both type level // and run-time. - assert!(!StringPredicate::starts_with(" alice@").applies(&id)); + assert!(!StringPredicate::starts_with(&*format!(" {alice}@")).applies(&id)); assert!(!StringPredicate::ends_with("@wonderland ").applies(&id)); - assert!(!StringPredicate::is("alice@@wonderland ").applies(&id)); + assert!(!StringPredicate::is(&*format!("{alice}@@wonderland ")).applies(&id)); assert!(!StringPredicate::contains("#").applies(&id)); - assert!(!StringPredicate::is("alice#wonderland").applies(&id)); + assert!(!StringPredicate::is(&*format!("{alice}#wonderland")).applies(&id)); } #[test] fn asset_id() { - let definition_id = "rose#wonderland".parse().expect("Valid"); - let account_id = "alice@wonderland".parse().expect("Valid"); - let id = IdBox::AssetId(crate::asset::AssetId { - definition_id, - account_id, - }); + let alice: PublicKey = KeyPair::random().into_parts().0; + let id = + IdBox::AssetId(format!("rose##{alice}@wonderland").parse().expect("Valid")); assert!(StringPredicate::starts_with("rose##").applies(&id)); - assert!(StringPredicate::ends_with("#alice@wonderland").applies(&id)); - assert!(StringPredicate::is("rose##alice@wonderland").applies(&id)); - assert!(StringPredicate::contains("#alice@").applies(&id)); + assert!(StringPredicate::ends_with(&*format!("#{alice}@wonderland")).applies(&id)); + assert!(StringPredicate::is(&*format!("rose##{alice}@wonderland")).applies(&id)); + assert!(StringPredicate::contains(&*format!("#{alice}@")).applies(&id)); } #[test] @@ -1237,98 +1237,95 @@ pub mod value { #[test] fn typing() { + let alice: PublicKey = KeyPair::random().into_parts().0; + let alice_id: AccountId = format!("{alice}@wonderland").parse().expect("Valid"); { let pred = QueryOutputPredicate::Identifiable(string::StringPredicate::is( - "alice@wonderland", + &*alice_id.to_string(), )); println!("{pred:?}"); - assert!(pred.applies(&QueryOutputBox::Id(IdBox::AccountId( - "alice@wonderland".parse().expect("Valid") - )))); + assert!(pred.applies(&QueryOutputBox::Id(IdBox::AccountId(alice_id.clone())))); assert!( pred.applies(&QueryOutputBox::Identifiable(IdentifiableBox::NewAccount( - Account::new( - "alice@wonderland".parse().expect("Valid"), - KeyPair::random().into_parts().0 - ) + Account::new(alice_id.clone()) ))) ); - assert!(!pred.applies( - &MetadataValueBox::from("alice".parse::().expect("Valid")).into() - )); + assert!(!pred.applies(&MetadataValueBox::from(alice_id.to_string()).into())); assert!(!pred.applies(&QueryOutputBox::Vec(Vec::new()))); } { let pred = QueryOutputPredicate::Pass; println!("{pred:?}"); - assert!(pred.applies(&MetadataValueBox::from("alice@wonderland".to_owned()).into())); + assert!(pred.applies(&MetadataValueBox::from(alice_id.to_string()).into())); } { let pred = QueryOutputPredicate::TimeStamp(numerical::SemiInterval::starting(0)); println!("{pred:?}"); - assert!( - !pred.applies(&MetadataValueBox::from("alice@wonderland".to_owned()).into()) - ); + assert!(!pred.applies(&MetadataValueBox::from(alice_id.to_string()).into())); } { - let key_pair = iroha_crypto::KeyPair::random(); - let (public_key, _) = key_pair.into_parts(); - let pred = - QueryOutputPredicate::Display(string::StringPredicate::is("alice@wonderland")); + let pred = QueryOutputPredicate::Display(string::StringPredicate::is( + &*alice_id.to_string(), + )); println!("{pred:?}"); assert!( !pred.applies(&QueryOutputBox::Identifiable(IdentifiableBox::Peer(Peer { - id: PeerId::new(socket_addr!(127.0.0.1:123), public_key) + id: PeerId::new( + socket_addr!(127.0.0.1:123), + KeyPair::random().into_parts().0 + ) }))) ); } let pred = QueryOutputPredicate::Numerical(numerical::SemiRange::Numeric( (numeric!(0), numeric!(42)).into(), )); - assert!(!pred.applies(&MetadataValueBox::from("alice".to_owned()).into())); + assert!(!pred.applies(&MetadataValueBox::from(alice_id.to_string()).into())); assert!(pred.applies(&numeric!(41).into())); } #[test] fn container_vec() { + let wonderland: DomainId = "wonderland".parse().expect("Valid"); + let alice: PublicKey = KeyPair::random().into_parts().0; + let alice_id = AccountId::new(wonderland.clone(), alice.clone()); let list = QueryOutputBox::Vec(vec![ - QueryOutputBox::Identifiable( - Domain::new("alice".parse::().unwrap()).into(), - ), - QueryOutputBox::Id("alice@wonderland".parse::().unwrap().into()), - QueryOutputBox::Id("aliceee!".parse::().unwrap().into()), + QueryOutputBox::Identifiable(Domain::new(wonderland.clone()).into()), + QueryOutputBox::Id(alice_id.into()), + QueryOutputBox::Id(wonderland.clone().into()), ]); - let alice_pred = - QueryOutputPredicate::Display(string::StringPredicate::contains("alice")); + let wonderland_pred = + QueryOutputPredicate::Display(string::StringPredicate::contains("wonderland")); { - let pred = QueryOutputPredicate::any(alice_pred.clone()); + let pred = QueryOutputPredicate::any(wonderland_pred.clone()); println!("{pred:?}"); assert!(pred.applies(&list)); assert!(!pred.applies(&QueryOutputBox::Vec(Vec::new()))); } { - let pred = QueryOutputPredicate::all(alice_pred.clone()); + let pred = QueryOutputPredicate::all(wonderland_pred.clone()); println!("{pred:?}"); assert!(pred.applies(&list)); assert!(pred.applies(&QueryOutputBox::Vec(Vec::new()))); } { - let alice_id_pred = - QueryOutputPredicate::Identifiable(string::StringPredicate::contains("alice")); - let pred = QueryOutputPredicate::all(alice_id_pred); + let wonderland_id_pred = QueryOutputPredicate::Identifiable( + string::StringPredicate::contains("wonderland"), + ); + let pred = QueryOutputPredicate::all(wonderland_id_pred); println!("{pred:?}"); assert!(pred.applies(&list)); assert!(pred.applies(&QueryOutputBox::Vec(Vec::new()))); } - assert!(QueryOutputPredicate::at_index(0, alice_pred.clone()).applies(&list)); + assert!(QueryOutputPredicate::at_index(0, wonderland_pred.clone()).applies(&list)); - let idx_pred = QueryOutputPredicate::at_index(3, alice_pred); // Should be out of bounds. + let idx_pred = QueryOutputPredicate::at_index(3, wonderland_pred); // Should be out of bounds. println!("{idx_pred:?}"); assert!(!idx_pred.applies(&list)); } diff --git a/data_model/src/transaction.rs b/data_model/src/transaction.rs index 0a541f70d04..c1dbe0e1686 100644 --- a/data_model/src/transaction.rs +++ b/data_model/src/transaction.rs @@ -9,7 +9,7 @@ use core::{ }; use derive_more::{DebugCustom, Display}; -use iroha_crypto::SignaturesOf; +use iroha_crypto::SignatureOf; use iroha_data_model_derive::model; use iroha_macro::FromVariant; use iroha_schema::IntoSchema; @@ -100,6 +100,7 @@ mod model { /// Unique id of the blockchain. Used for simple replay attack protection. pub chain_id: ChainId, /// Account ID of transaction creator. + /// TODO dedup public keys in transaction #4410 pub authority: AccountId, /// Creation timestamp (unix time in milliseconds). pub creation_time_ms: u64, @@ -140,12 +141,12 @@ mod model { pub max_wasm_size_bytes: u64, } - /// Transaction that contains at least one signature + /// Transaction that contains a signature /// /// `Iroha` and its clients use [`Self`] to send transactions over the network. /// After a transaction is signed and before it can be processed any further, /// the transaction must be accepted by the `Iroha` peer. - /// The peer verifies the signatures and checks the limits. + /// The peer verifies the signature and checks the limits. #[version(version = 1, versioned_alias = "SignedTransaction")] #[derive( Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Serialize, IntoSchema, @@ -154,9 +155,9 @@ mod model { #[cfg_attr(feature = "std", display(fmt = "{}", "self.hash()"))] #[ffi_type] pub struct SignedTransactionV1 { - /// [`iroha_crypto::SignatureOf`]<[`TransactionPayload`]>. - pub(super) signatures: SignaturesOf, - /// [`Transaction`] payload. + /// Signature of [`Self::payload`]. + pub(super) signature: SignatureOf, + /// Payload of the transaction. pub(super) payload: TransactionPayload, } @@ -290,11 +291,12 @@ impl SignedTransaction { &tx.payload.chain_id } - /// Return transaction signatures + /// Return the transaction signature #[inline] - pub fn signatures(&self) -> &SignaturesOf { + #[allow(private_interfaces)] + pub fn signature(&self) -> &SignatureOf { let SignedTransaction::V1(tx) = self; - &tx.signatures + &tx.signature } /// Calculate transaction [`Hash`](`iroha_crypto::HashOf`). @@ -308,11 +310,11 @@ impl SignedTransaction { pub fn sign(self, key_pair: &iroha_crypto::KeyPair) -> SignedTransaction { let SignedTransaction::V1(mut tx) = self; let signature = iroha_crypto::SignatureOf::new(key_pair, &tx.payload); - tx.signatures.insert(signature); + tx.signature = signature; SignedTransactionV1 { payload: tx.payload, - signatures: tx.signatures, + signature: tx.signature, } .into() } @@ -346,13 +348,13 @@ mod candidate { #[derive(Decode, Deserialize)] struct SignedTransactionCandidate { - signatures: SignaturesOf, + signature: SignatureOf, payload: TransactionPayload, } impl SignedTransactionCandidate { fn validate(self) -> Result { - self.validate_signatures()?; + self.validate_signature()?; self.validate_instructions() } @@ -365,12 +367,12 @@ mod candidate { Ok(SignedTransactionV1 { payload: self.payload, - signatures: self.signatures, + signature: self.signature, }) } - fn validate_signatures(&self) -> Result<(), &'static str> { - self.signatures + fn validate_signature(&self) -> Result<(), &'static str> { + self.signature .verify(&self.payload) .map_err(|_| "Transaction contains invalid signatures") } @@ -741,11 +743,11 @@ mod http { /// Sign transaction with provided key pair. #[must_use] pub fn sign(self, key_pair: &iroha_crypto::KeyPair) -> SignedTransaction { - let signatures = SignaturesOf::new(key_pair, &self.payload); + let signature = SignatureOf::new(key_pair, &self.payload); SignedTransactionV1 { payload: self.payload, - signatures, + signature, } .into() } diff --git a/data_model/src/trigger.rs b/data_model/src/trigger.rs index b7af77ef05e..b32b9573bb7 100644 --- a/data_model/src/trigger.rs +++ b/data_model/src/trigger.rs @@ -106,7 +106,7 @@ impl FromStr for TriggerId { let mut split = s.split('$'); match (split.next(), split.next(), split.next()) { (Some(""), _, _) => Err(ParseError { - reason: "Trigger ID cannot be empty", + reason: "Empty `name` part in `name` or `name$domain_id`", }), (Some(name), None, _) => Ok(Self { name: Name::from_str(name)?, diff --git a/data_model/src/visit.rs b/data_model/src/visit.rs index f25fc3dc9e0..d216a8ee845 100644 --- a/data_model/src/visit.rs +++ b/data_model/src/visit.rs @@ -1,7 +1,6 @@ //! Visitor that visits every node in Iroha syntax tree #![allow(missing_docs, clippy::missing_errors_doc)] -use iroha_crypto::PublicKey; use iroha_primitives::numeric::Numeric; use crate::{isi::Log, prelude::*}; @@ -49,7 +48,6 @@ pub trait Visit { visit_find_account_by_id(&FindAccountById), visit_find_account_key_value_by_id_and_key(&FindAccountKeyValueByIdAndKey), visit_find_accounts_by_domain_id(&FindAccountsByDomainId), - visit_find_accounts_by_name(&FindAccountsByName), visit_find_accounts_with_asset(&FindAccountsWithAsset), visit_find_all_accounts(&FindAllAccounts), visit_find_all_active_trigger_ids(&FindAllActiveTriggerIds), @@ -108,12 +106,9 @@ pub trait Visit { // Visit MintBox visit_mint_asset_numeric(&Mint), - visit_mint_account_public_key(&Mint), - visit_mint_account_signature_check_condition(&Mint), visit_mint_trigger_repetitions(&Mint), // Visit BurnBox - visit_burn_account_public_key(&Burn), visit_burn_asset_numeric(&Burn), visit_burn_trigger_repetitions(&Burn), @@ -178,7 +173,6 @@ pub fn visit_query(visitor: &mut V, authority: &AccountId, qu visit_find_account_by_id(FindAccountById), visit_find_account_key_value_by_id_and_key(FindAccountKeyValueByIdAndKey), visit_find_accounts_by_domain_id(FindAccountsByDomainId), - visit_find_accounts_by_name(FindAccountsByName), visit_find_accounts_with_asset(FindAccountsWithAsset), visit_find_all_accounts(FindAllAccounts), visit_find_all_active_trigger_ids(FindAllActiveTriggerIds), @@ -304,12 +298,6 @@ pub fn visit_unregister( pub fn visit_mint(visitor: &mut V, authority: &AccountId, isi: &MintBox) { match isi { - MintBox::Account(mint_account) => match mint_account { - AccountMintBox::PublicKey(obj) => visitor.visit_mint_account_public_key(authority, obj), - AccountMintBox::SignatureCheckCondition(obj) => { - visitor.visit_mint_account_signature_check_condition(authority, obj) - } - }, MintBox::Asset(obj) => visitor.visit_mint_asset_numeric(authority, obj), MintBox::TriggerRepetitions(obj) => visitor.visit_mint_trigger_repetitions(authority, obj), } @@ -317,7 +305,6 @@ pub fn visit_mint(visitor: &mut V, authority: &AccountId, isi pub fn visit_burn(visitor: &mut V, authority: &AccountId, isi: &BurnBox) { match isi { - BurnBox::AccountPublicKey(obj) => visitor.visit_burn_account_public_key(authority, obj), BurnBox::Asset(obj) => visitor.visit_burn_asset_numeric(authority, obj), BurnBox::TriggerRepetitions(obj) => visitor.visit_burn_trigger_repetitions(authority, obj), } @@ -400,9 +387,6 @@ leaf_visitors! { // Instruction visitors visit_register_account(&Register), visit_unregister_account(&Unregister), - visit_mint_account_public_key(&Mint), - visit_burn_account_public_key(&Burn), - visit_mint_account_signature_check_condition(&Mint), visit_set_account_key_value(&SetKeyValue), visit_remove_account_key_value(&RemoveKeyValue), visit_register_asset(&Register), @@ -450,7 +434,6 @@ leaf_visitors! { visit_find_account_by_id(&FindAccountById), visit_find_account_key_value_by_id_and_key(&FindAccountKeyValueByIdAndKey), visit_find_accounts_by_domain_id(&FindAccountsByDomainId), - visit_find_accounts_by_name(&FindAccountsByName), visit_find_accounts_with_asset(&FindAccountsWithAsset), visit_find_all_accounts(&FindAllAccounts), visit_find_all_active_trigger_ids(&FindAllActiveTriggerIds), diff --git a/data_model/tests/data_model.rs b/data_model/tests/data_model.rs index 4e8a0a7a207..85963718589 100644 --- a/data_model/tests/data_model.rs +++ b/data_model/tests/data_model.rs @@ -1,25 +1,15 @@ -use iroha_data_model::{prelude::*, ParseError}; +use iroha_crypto::KeyPair; +use iroha_data_model::prelude::*; #[test] fn transfer_isi_should_be_valid() { let _instruction = Transfer::asset_numeric( - "btc##seller@crypto".parse().expect("Valid"), + format!("btc##{}@crypto", KeyPair::random().public_key()) + .parse() + .unwrap(), 12u32, - "buyer@crypto".parse().expect("Valid"), + format!("{}@crypto", KeyPair::random().public_key()) + .parse() + .unwrap(), ); } - -#[test] -fn account_id_parsing() -> Result<(), ParseError> { - // `AccountId` should have format `name@domain_name` - let account_normal: AccountId = "test@hello".parse()?; - assert_eq!(account_normal.name().as_ref(), "test"); - assert_eq!(account_normal.domain_id().name().as_ref(), "hello"); - - let account_empty: Result = "@hello".parse(); - assert!(account_empty.is_err()); - - let account_invalid: Result = "@".parse(); - assert!(account_invalid.is_err()); - Ok(()) -} diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index e9196b814df..6610b7a8f29 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -9,14 +9,6 @@ "name": "assets", "type": "SortedMap" }, - { - "name": "signatories", - "type": "SortedVec" - }, - { - "name": "signature_check_condition", - "type": "SignatureCheckCondition" - }, { "name": "metadata", "type": "Metadata" @@ -152,22 +144,8 @@ "type": "DomainId" }, { - "name": "name", - "type": "Name" - } - ] - }, - "AccountMintBox": { - "Enum": [ - { - "tag": "PublicKey", - "discriminant": 0, - "type": "Mint" - }, - { - "tag": "SignatureCheckCondition", - "discriminant": 1, - "type": "Mint" + "name": "signatory", + "type": "PublicKey" } ] }, @@ -713,18 +691,6 @@ } ] }, - "Burn": { - "Struct": [ - { - "name": "object", - "type": "PublicKey" - }, - { - "name": "destination_id", - "type": "AccountId" - } - ] - }, "Burn": { "Struct": [ { @@ -739,19 +705,14 @@ }, "BurnBox": { "Enum": [ - { - "tag": "AccountPublicKey", - "discriminant": 0, - "type": "Burn" - }, { "tag": "Asset", - "discriminant": 1, + "discriminant": 0, "type": "Burn" }, { "tag": "TriggerRepetitions", - "discriminant": 2, + "discriminant": 1, "type": "Burn" } ] @@ -1262,14 +1223,6 @@ } ] }, - "FindAccountsByName": { - "Struct": [ - { - "name": "name", - "type": "Name" - } - ] - }, "FindAccountsWithAsset": { "Struct": [ { @@ -2270,30 +2223,6 @@ } ] }, - "Mint": { - "Struct": [ - { - "name": "object", - "type": "PublicKey" - }, - { - "name": "destination_id", - "type": "AccountId" - } - ] - }, - "Mint": { - "Struct": [ - { - "name": "object", - "type": "SignatureCheckCondition" - }, - { - "name": "destination_id", - "type": "AccountId" - } - ] - }, "Mint": { "Struct": [ { @@ -2308,19 +2237,14 @@ }, "MintBox": { "Enum": [ - { - "tag": "Account", - "discriminant": 0, - "type": "AccountMintBox" - }, { "tag": "Asset", - "discriminant": 1, + "discriminant": 0, "type": "Mint" }, { "tag": "TriggerRepetitions", - "discriminant": 2, + "discriminant": 1, "type": "Mint" } ] @@ -2372,10 +2296,6 @@ "name": "id", "type": "AccountId" }, - { - "name": "signatories", - "type": "SortedVec" - }, { "name": "metadata", "type": "Metadata" @@ -2731,189 +2651,184 @@ "discriminant": 2, "type": "FindAccountKeyValueByIdAndKey" }, - { - "tag": "FindAccountsByName", - "discriminant": 3, - "type": "FindAccountsByName" - }, { "tag": "FindAccountsByDomainId", - "discriminant": 4, + "discriminant": 3, "type": "FindAccountsByDomainId" }, { "tag": "FindAccountsWithAsset", - "discriminant": 5, + "discriminant": 4, "type": "FindAccountsWithAsset" }, { "tag": "FindAllAssets", - "discriminant": 6, + "discriminant": 5, "type": "FindAllAssets" }, { "tag": "FindAllAssetsDefinitions", - "discriminant": 7, + "discriminant": 6, "type": "FindAllAssetsDefinitions" }, { "tag": "FindAssetById", - "discriminant": 8, + "discriminant": 7, "type": "FindAssetById" }, { "tag": "FindAssetDefinitionById", - "discriminant": 9, + "discriminant": 8, "type": "FindAssetDefinitionById" }, { "tag": "FindAssetsByName", - "discriminant": 10, + "discriminant": 9, "type": "FindAssetsByName" }, { "tag": "FindAssetsByAccountId", - "discriminant": 11, + "discriminant": 10, "type": "FindAssetsByAccountId" }, { "tag": "FindAssetsByAssetDefinitionId", - "discriminant": 12, + "discriminant": 11, "type": "FindAssetsByAssetDefinitionId" }, { "tag": "FindAssetsByDomainId", - "discriminant": 13, + "discriminant": 12, "type": "FindAssetsByDomainId" }, { "tag": "FindAssetsByDomainIdAndAssetDefinitionId", - "discriminant": 14, + "discriminant": 13, "type": "FindAssetsByDomainIdAndAssetDefinitionId" }, { "tag": "FindAssetQuantityById", - "discriminant": 15, + "discriminant": 14, "type": "FindAssetQuantityById" }, { "tag": "FindTotalAssetQuantityByAssetDefinitionId", - "discriminant": 16, + "discriminant": 15, "type": "FindTotalAssetQuantityByAssetDefinitionId" }, { "tag": "FindAssetKeyValueByIdAndKey", - "discriminant": 17, + "discriminant": 16, "type": "FindAssetKeyValueByIdAndKey" }, { "tag": "FindAssetDefinitionKeyValueByIdAndKey", - "discriminant": 18, + "discriminant": 17, "type": "FindAssetDefinitionKeyValueByIdAndKey" }, { "tag": "FindAllDomains", - "discriminant": 19, + "discriminant": 18, "type": "FindAllDomains" }, { "tag": "FindDomainById", - "discriminant": 20, + "discriminant": 19, "type": "FindDomainById" }, { "tag": "FindDomainKeyValueByIdAndKey", - "discriminant": 21, + "discriminant": 20, "type": "FindDomainKeyValueByIdAndKey" }, { "tag": "FindAllPeers", - "discriminant": 22, + "discriminant": 21, "type": "FindAllPeers" }, { "tag": "FindAllBlocks", - "discriminant": 23, + "discriminant": 22, "type": "FindAllBlocks" }, { "tag": "FindAllBlockHeaders", - "discriminant": 24, + "discriminant": 23, "type": "FindAllBlockHeaders" }, { "tag": "FindBlockHeaderByHash", - "discriminant": 25, + "discriminant": 24, "type": "FindBlockHeaderByHash" }, { "tag": "FindAllTransactions", - "discriminant": 26, + "discriminant": 25, "type": "FindAllTransactions" }, { "tag": "FindTransactionsByAccountId", - "discriminant": 27, + "discriminant": 26, "type": "FindTransactionsByAccountId" }, { "tag": "FindTransactionByHash", - "discriminant": 28, + "discriminant": 27, "type": "FindTransactionByHash" }, { "tag": "FindPermissionTokensByAccountId", - "discriminant": 29, + "discriminant": 28, "type": "FindPermissionTokensByAccountId" }, { "tag": "FindPermissionTokenSchema", - "discriminant": 30, + "discriminant": 29, "type": "FindPermissionTokenSchema" }, { "tag": "FindAllActiveTriggerIds", - "discriminant": 31, + "discriminant": 30, "type": "FindAllActiveTriggerIds" }, { "tag": "FindTriggerById", - "discriminant": 32, + "discriminant": 31, "type": "FindTriggerById" }, { "tag": "FindTriggerKeyValueByIdAndKey", - "discriminant": 33, + "discriminant": 32, "type": "FindTriggerKeyValueByIdAndKey" }, { "tag": "FindTriggersByDomainId", - "discriminant": 34, + "discriminant": 33, "type": "FindTriggersByDomainId" }, { "tag": "FindAllRoles", - "discriminant": 35, + "discriminant": 34, "type": "FindAllRoles" }, { "tag": "FindAllRoleIds", - "discriminant": 36, + "discriminant": 35, "type": "FindAllRoleIds" }, { "tag": "FindRoleByRoleId", - "discriminant": 37, + "discriminant": 36, "type": "FindRoleByRoleId" }, { "tag": "FindRolesByAccountId", - "discriminant": 38, + "discriminant": 37, "type": "FindRolesByAccountId" }, { "tag": "FindAllParameters", - "discriminant": 39, + "discriminant": 38, "type": "FindAllParameters" } ] @@ -3577,20 +3492,6 @@ } ] }, - "SignatureCheckCondition": { - "Enum": [ - { - "tag": "AnyAccountSignatureOr", - "discriminant": 0, - "type": "Vec" - }, - { - "tag": "AllAccountSignaturesAnd", - "discriminant": 1, - "type": "Vec" - } - ] - }, "SignatureOf": "Signature", "SignatureOf": "Signature", "SignatureOf": "Signature", @@ -3602,14 +3503,6 @@ } ] }, - "SignaturesOf": { - "Struct": [ - { - "name": "signatures", - "type": "SortedVec>" - } - ] - }, "SignedBlock": { "Enum": [ { @@ -3664,8 +3557,8 @@ "SignedTransactionV1": { "Struct": [ { - "name": "signatures", - "type": "SignaturesOf" + "name": "signature", + "type": "SignatureOf" }, { "name": "payload", @@ -3773,15 +3666,9 @@ "SortedVec": { "Vec": "PermissionToken" }, - "SortedVec": { - "Vec": "PublicKey" - }, "SortedVec>": { "Vec": "SignatureOf" }, - "SortedVec>": { - "Vec": "SignatureOf" - }, "String": "String", "StringPredicate": { "Enum": [ @@ -4429,9 +4316,6 @@ "Vec": { "Vec": "PeerId" }, - "Vec": { - "Vec": "PublicKey" - }, "Vec": { "Vec": "QueryOutputBox" }, diff --git a/genesis/Cargo.toml b/genesis/Cargo.toml index 75b8186cc7e..604c98045e6 100644 --- a/genesis/Cargo.toml +++ b/genesis/Cargo.toml @@ -24,3 +24,4 @@ eyre = { workspace = true } [dev-dependencies] iroha_crypto = { workspace = true, features = ["rand"] } +test_samples = { workspace = true } diff --git a/genesis/src/lib.rs b/genesis/src/lib.rs index 1fe4cfe92ab..0bbdae09468 100644 --- a/genesis/src/lib.rs +++ b/genesis/src/lib.rs @@ -20,12 +20,8 @@ use iroha_data_model::{ use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -/// [`DomainId`] of the genesis account. -pub static GENESIS_DOMAIN_ID: Lazy = Lazy::new(|| "genesis".parse().expect("Valid")); - -/// [`AccountId`] of the genesis account. -pub static GENESIS_ACCOUNT_ID: Lazy = - Lazy::new(|| AccountId::new(GENESIS_DOMAIN_ID.clone(), "genesis".parse().expect("Valid"))); +/// [`DomainId`](iroha_data_model::domain::DomainId) of the genesis account. +pub static GENESIS_DOMAIN_ID: Lazy = Lazy::new(|| "genesis".parse().unwrap()); /// Genesis transaction #[derive(Debug, Clone)] @@ -168,7 +164,11 @@ impl GenesisTransactionBuilder { /// Convert [`GenesisTransactionBuilder`] into [`SignedTransaction`] with signature. #[must_use] fn sign(self, chain_id: ChainId, genesis_key_pair: &KeyPair) -> SignedTransaction { - TransactionBuilder::new(chain_id, GENESIS_ACCOUNT_ID.clone()) + let genesis_account_id = AccountId::new( + GENESIS_DOMAIN_ID.clone(), + genesis_key_pair.public_key().clone(), + ); + TransactionBuilder::new(chain_id, genesis_account_id) .with_instructions(self.isi) .sign(genesis_key_pair) } @@ -310,31 +310,15 @@ impl RawGenesisDomainBuilder { } } - /// Add an account to this domain with random public key. - #[cfg(test)] - fn account_with_random_public_key(mut self, account_name: Name) -> Self { - let account_id = AccountId::new(self.domain_id.clone(), account_name); - self.transaction.isi.push( - Register::account(Account::new(account_id, KeyPair::random().into_parts().0)).into(), - ); - self - } - /// Add an account to this domain - pub fn account(self, account_name: Name, public_key: PublicKey) -> Self { - self.account_with_metadata(account_name, public_key, Metadata::default()) + pub fn account(self, signatory: PublicKey) -> Self { + self.account_with_metadata(signatory, Metadata::default()) } /// Add an account (having provided `metadata`) to this domain. - pub fn account_with_metadata( - mut self, - account_name: Name, - public_key: PublicKey, - metadata: Metadata, - ) -> Self { - let account_id = AccountId::new(self.domain_id.clone(), account_name); - let register = - Register::account(Account::new(account_id, public_key).with_metadata(metadata)); + pub fn account_with_metadata(mut self, signatory: PublicKey, metadata: Metadata) -> Self { + let account_id = AccountId::new(self.domain_id.clone(), signatory); + let register = Register::account(Account::new(account_id).with_metadata(metadata)); self.transaction.isi.push(register.into()); self } @@ -352,6 +336,8 @@ impl RawGenesisDomainBuilder { #[cfg(test)] mod tests { + use test_samples::{ALICE_KEYPAIR, BOB_KEYPAIR}; + use super::*; fn dummy_executor() -> Executor { @@ -367,7 +353,7 @@ mod tests { let _genesis_block = GenesisNetwork::new( RawGenesisBlockBuilder::default() .domain("wonderland".parse()?) - .account("alice".parse()?, alice_public_key) + .account(alice_public_key) .finish_domain() .executor_blob(dummy_executor()) .build(), @@ -379,19 +365,26 @@ mod tests { #[test] fn genesis_block_builder_example() { - let public_key = "ed0120204E9593C3FFAF4464A6189233811C297DD4CE73ABA167867E4FBD4F8C450ACB"; + let public_key: std::collections::HashMap<&'static str, PublicKey> = [ + ("alice", ALICE_KEYPAIR.public_key().clone()), + ("bob", BOB_KEYPAIR.public_key().clone()), + ("cheshire_cat", KeyPair::random().into_parts().0), + ("mad_hatter", KeyPair::random().into_parts().0), + ] + .into_iter() + .collect(); let mut genesis_builder = RawGenesisBlockBuilder::default(); genesis_builder = genesis_builder .domain("wonderland".parse().unwrap()) - .account_with_random_public_key("alice".parse().unwrap()) - .account_with_random_public_key("bob".parse().unwrap()) + .account(public_key["alice"].clone()) + .account(public_key["bob"].clone()) .finish_domain() .domain("tulgey_wood".parse().unwrap()) - .account_with_random_public_key("Cheshire_Cat".parse().unwrap()) + .account(public_key["cheshire_cat"].clone()) .finish_domain() .domain("meadow".parse().unwrap()) - .account("Mad_Hatter".parse().unwrap(), public_key.parse().unwrap()) + .account(public_key["mad_hatter"].clone()) .asset( "hats".parse().unwrap(), AssetValueType::Numeric(NumericSpec::default()), @@ -408,18 +401,18 @@ mod tests { ); assert_eq!( finished_genesis_block.transactions[0].isi[1], - Register::account(Account::new( - AccountId::new(domain_id.clone(), "alice".parse().unwrap()), - KeyPair::random().into_parts().0, - )) + Register::account(Account::new(AccountId::new( + domain_id.clone(), + public_key["alice"].clone() + ),)) .into() ); assert_eq!( finished_genesis_block.transactions[0].isi[2], - Register::account(Account::new( - AccountId::new(domain_id, "bob".parse().unwrap()), - KeyPair::random().into_parts().0, - )) + Register::account(Account::new(AccountId::new( + domain_id, + public_key["bob"].clone() + ),)) .into() ); } @@ -431,10 +424,10 @@ mod tests { ); assert_eq!( finished_genesis_block.transactions[0].isi[4], - Register::account(Account::new( - AccountId::new(domain_id, "Cheshire_Cat".parse().unwrap()), - KeyPair::random().into_parts().0, - )) + Register::account(Account::new(AccountId::new( + domain_id, + public_key["cheshire_cat"].clone() + ),)) .into() ); } @@ -446,10 +439,10 @@ mod tests { ); assert_eq!( finished_genesis_block.transactions[0].isi[6], - Register::account(Account::new( - AccountId::new(domain_id, "Mad_Hatter".parse().unwrap()), - public_key.parse().unwrap(), - )) + Register::account(Account::new(AccountId::new( + domain_id, + public_key["mad_hatter"].clone() + ),)) .into() ); assert_eq!( diff --git a/hooks/pre-commit.sample b/hooks/pre-commit.sample index 72addb9c6b5..d77824f2d1f 100755 --- a/hooks/pre-commit.sample +++ b/hooks/pre-commit.sample @@ -1,7 +1,25 @@ #!/bin/sh +# rustup default nightly-2024-04-18 set -e -cargo +nightly fmt --all -- --check -cargo +nightly lints clippy --workspace --benches --tests --examples --all-features -cargo run --bin kagami -- genesis >configs/peer/genesis.json -cargo run --bin kagami -- schema >docs/source/references/schema.json -git add configs/peer/genesis.json docs/source/references/schema.json +# format checks +cargo fmt --all -- --check +cd ./default_executor +cargo fmt --all -- --check +cd - +cd ./client/tests/integration/smartcontracts +cargo fmt --all -- --check +cd - +# update the default executor +cargo run --release --bin iroha_wasm_builder_cli -- build ./default_executor --optimize --outfile ./configs/swarm/executor.wasm +# update the default genesis, assuming the transaction authority is `test_samples::SAMPLE_GENESIS_ACCOUNT_ID` +GENESIS_PUBLIC_KEY=ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 cargo run --release --bin kagami -- genesis --executor-path-in-genesis ./executor.wasm > ./configs/swarm/genesis.json +# update schema +cargo run --release --bin kagami -- schema > ./docs/source/references/schema.json +# update docker compose files +cargo run --release --bin iroha_swarm -- -p 1 -s Iroha --force --config-dir ./configs/swarm --health-check --build . --outfile ./configs/swarm/docker-compose.single.yml +cargo run --release --bin iroha_swarm -- -p 4 -s Iroha --force --config-dir ./configs/swarm --health-check --build . --outfile ./configs/swarm/docker-compose.local.yml +cargo run --release --bin iroha_swarm -- -p 4 -s Iroha --force --config-dir ./configs/swarm --health-check --image hyperledger/iroha2:dev --outfile ./configs/swarm/docker-compose.yml +# lints +cargo lints clippy --workspace --benches --tests --examples --all-features +# stage updates +git add ./configs/swarm/executor.wasm ./configs/swarm/genesis.json ./docs/source/references/schema.json ./configs/swarm/docker-compose.single.yml ./configs/swarm/docker-compose.local.yml ./configs/swarm/docker-compose.yml diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index e3c56afd90c..0a95dd31b40 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -63,7 +63,6 @@ types!( AccountEventFilter, AccountEventSet, AccountId, - AccountMintBox, AccountPermissionChanged, AccountRoleChanged, Action, @@ -91,9 +90,7 @@ types!( BTreeMap, BTreeMap, BTreeSet, - BTreeSet, BTreeSet>, - BTreeSet>, BatchedResponse, BatchedResponseV1, BlockEvent, @@ -109,14 +106,12 @@ types!( Box, Burn, Burn, - Burn, BurnBox, ChainId, ConfigurationEvent, ConfigurationEventFilter, ConfigurationEventSet, ConstString, - ConstVec, ConstVec, Container, DataEvent, @@ -145,7 +140,6 @@ types!( FindAccountById, FindAccountKeyValueByIdAndKey, FindAccountsByDomainId, - FindAccountsByName, FindAccountsWithAsset, FindAllAccounts, FindAllActiveTriggerIds, @@ -219,8 +213,6 @@ types!( MetadataValueBox, Mint, Mint, - Mint, - Mint, MintBox, MintabilityError, Mintable, @@ -317,14 +309,11 @@ types!( SetKeyValueBox, SetParameter, Signature, - SignatureCheckCondition, SignatureOf, SignatureOf, SignatureOf, SignatureWrapperOf, - SignatureWrapperOf, SignaturesOf, - SignaturesOf, SignedBlock, SignedBlockV1, SignedQuery, diff --git a/scripts/tests/consistency.sh b/scripts/tests/consistency.sh index ba3a34531f5..c55cbbfda10 100755 --- a/scripts/tests/consistency.sh +++ b/scripts/tests/consistency.sh @@ -3,8 +3,9 @@ set -e case $1 in "genesis") - cargo run --release --bin kagami -- genesis --executor-path-in-genesis ./executor.wasm | diff - configs/swarm/genesis.json || { - echo 'Please re-generate the genesis with `cargo run --release --bin kagami -- genesis --executor-path-in-genesis ./executor.wasm > configs/swarm/genesis.json`' + GENESIS_PUBLIC_KEY=ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 cargo run --release --bin kagami -- genesis --executor-path-in-genesis ./executor.wasm | diff - configs/swarm/genesis.json || { + echo 'Please re-generate the default genesis with `GENESIS_PUBLIC_KEY=ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 cargo run --release --bin kagami -- genesis --executor-path-in-genesis ./executor.wasm > configs/swarm/genesis.json`' + echo 'The assumption here is that the authority of the default genesis transaction is `test_samples::SAMPLE_GENESIS_ACCOUNT_ID`' exit 1 };; "schema") diff --git a/smart_contract/executor/derive/src/default.rs b/smart_contract/executor/derive/src/default.rs index cb2778b85e5..9723b534c20 100644 --- a/smart_contract/executor/derive/src/default.rs +++ b/smart_contract/executor/derive/src/default.rs @@ -125,9 +125,6 @@ pub fn impl_derive_visit(emitter: &mut Emitter, input: &syn::DeriveInput) -> Tok "fn visit_remove_domain_key_value(operation: &RemoveKeyValue)", "fn visit_register_account(operation: &Register)", "fn visit_unregister_account(operation: &Unregister)", - "fn visit_mint_account_public_key(operation: &Mint)", - "fn visit_burn_account_public_key(operation: &Burn)", - "fn visit_mint_account_signature_check_condition(operation: &Mint)", "fn visit_set_account_key_value(operation: &SetKeyValue)", "fn visit_remove_account_key_value(operation: &RemoveKeyValue)", "fn visit_register_asset(operation: &Register)", diff --git a/smart_contract/executor/derive/src/lib.rs b/smart_contract/executor/derive/src/lib.rs index 713e099e810..7e605a9adb0 100644 --- a/smart_contract/executor/derive/src/lib.rs +++ b/smart_contract/executor/derive/src/lib.rs @@ -88,7 +88,7 @@ pub fn entrypoint(attr: TokenStream, item: TokenStream) -> TokenStream { /// /// CanDoSomethingWithAsset { /// some_data: "some data".to_owned(), -/// asset_id: parse!("rose#wonderland" as AssetId), +/// asset_id: parse!(AssetId, "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland"), /// }.is_owned_by(&authority) /// } /// ``` diff --git a/smart_contract/executor/src/default.rs b/smart_contract/executor/src/default.rs index 79eff62ad71..584a9048253 100644 --- a/smart_contract/executor/src/default.rs +++ b/smart_contract/executor/src/default.rs @@ -6,9 +6,8 @@ pub mod tokens; use alloc::format; pub use account::{ - visit_burn_account_public_key, visit_mint_account_public_key, - visit_mint_account_signature_check_condition, visit_register_account, - visit_remove_account_key_value, visit_set_account_key_value, visit_unregister_account, + visit_register_account, visit_remove_account_key_value, visit_set_account_key_value, + visit_unregister_account, }; pub use asset::{ visit_burn_asset_numeric, visit_mint_asset_numeric, visit_register_asset, @@ -498,85 +497,6 @@ pub mod account { deny!(executor, "Can't unregister another account"); } - pub fn visit_mint_account_public_key( - executor: &mut V, - authority: &AccountId, - isi: &Mint, - ) { - let account_id = isi.destination_id(); - - if is_genesis(executor) { - execute!(executor, isi); - } - match is_account_owner(account_id, authority) { - Err(err) => deny!(executor, err), - Ok(true) => execute!(executor, isi), - Ok(false) => {} - } - let can_mint_user_public_keys = tokens::account::CanMintUserPublicKeys { - account_id: account_id.clone(), - }; - if can_mint_user_public_keys.is_owned_by(authority) { - execute!(executor, isi); - } - - deny!(executor, "Can't mint public keys of another account"); - } - - pub fn visit_burn_account_public_key( - executor: &mut V, - authority: &AccountId, - isi: &Burn, - ) { - let account_id = isi.destination_id(); - - if is_genesis(executor) { - execute!(executor, isi); - } - match is_account_owner(account_id, authority) { - Err(err) => deny!(executor, err), - Ok(true) => execute!(executor, isi), - Ok(false) => {} - } - let can_burn_user_public_keys = tokens::account::CanBurnUserPublicKeys { - account_id: account_id.clone(), - }; - if can_burn_user_public_keys.is_owned_by(authority) { - execute!(executor, isi); - } - - deny!(executor, "Can't burn public keys of another account"); - } - - pub fn visit_mint_account_signature_check_condition( - executor: &mut V, - authority: &AccountId, - isi: &Mint, - ) { - let account_id = isi.destination_id(); - - if is_genesis(executor) { - execute!(executor, isi); - } - match is_account_owner(account_id, authority) { - Err(err) => deny!(executor, err), - Ok(true) => execute!(executor, isi), - Ok(false) => {} - } - let can_mint_user_signature_check_conditions_token = - tokens::account::CanMintUserSignatureCheckConditions { - account_id: account_id.clone(), - }; - if can_mint_user_signature_check_conditions_token.is_owned_by(authority) { - execute!(executor, isi); - } - - deny!( - executor, - "Can't mint signature check conditions of another account" - ); - } - pub fn visit_set_account_key_value( executor: &mut V, authority: &AccountId, @@ -794,7 +714,7 @@ pub mod asset_definition { isi: &Transfer, ) { let source_id = isi.source_id(); - let destination_id = isi.object(); + let asset_definition_id = isi.object(); if is_genesis(executor) { execute!(executor, isi); @@ -804,7 +724,7 @@ pub mod asset_definition { Ok(true) => execute!(executor, isi), Ok(false) => {} } - match is_asset_definition_owner(destination_id, authority) { + match is_asset_definition_owner(asset_definition_id, authority) { Err(err) => deny!(executor, err), Ok(true) => execute!(executor, isi), Ok(false) => {} diff --git a/smart_contract/src/lib.rs b/smart_contract/src/lib.rs index b97c3800336..19cf0744920 100644 --- a/smart_contract/src/lib.rs +++ b/smart_contract/src/lib.rs @@ -74,27 +74,37 @@ pub fn stub_getrandom(_dest: &mut [u8]) -> Result<(), getrandom::Error> { unimplemented!("{ERROR_MESSAGE}") } -/// Macro to parse literal as a type. Panics if failed. +/// Returns the annotated type of value parsed from the given expression, or fails with [`dbg_expect`](debug::DebugExpectExt::dbg_expect) message. +/// Panics if the internal parsing fails. /// -/// # Example +/// # Examples /// -/// ```ignore -/// use iroha_smart_contract::{prelude::*, parse}; +/// ``` +/// use iroha_smart_contract::{parse, prelude::*}; /// -/// let account_id = parse!("alice@wonderland" as AccountId); +/// let from_literal = parse!(DomainId, "wonderland"); +/// let expr = "wonderland"; +/// // Although "expr" would be less informative in debug message +/// let from_expr = parse!(DomainId, expr); /// ``` #[macro_export] macro_rules! parse { - ($l:literal as _) => { + (_, $e:expr) => { compile_error!( "Don't use `_` as a type in this macro, \ otherwise panic message would be less informative" ) }; - ($l:literal as $t:ty) => { + ($t:ty, $e:expr) => { $crate::debug::DebugExpectExt::dbg_expect( - $l.parse::<$t>(), - concat!("Failed to parse `", $l, "` as `", stringify!($t), "`"), + $e.parse::<$t>(), + concat!( + "Failed to parse `", + stringify!($e), + "` as `", + stringify!($t), + "`" + ), ) }; } @@ -489,14 +499,12 @@ mod tests { const ISI_RESULT: Result<(), ValidationFail> = Ok(()); fn get_test_instruction() -> InstructionBox { - let new_asset_id = "tulip##alice@wonderland".parse().unwrap(); - let register_isi = Register::asset(Asset::new(new_asset_id, 1_u32)); - - register_isi.into() + let new_asset_id: AssetId = "tulip##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland".parse().unwrap(); + Register::asset(Asset::new(new_asset_id, 1_u32)).into() } fn get_test_query() -> QueryBox { - let asset_id: AssetId = "rose##alice@wonderland".parse().expect("Valid"); + let asset_id: AssetId = "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland".parse().unwrap(); FindAssetQuantityById::new(asset_id).into() } diff --git a/test_samples/Cargo.toml b/test_samples/Cargo.toml new file mode 100644 index 00000000000..276af31906f --- /dev/null +++ b/test_samples/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "test_samples" +edition.workspace = true +version.workspace = true +authors.workspace = true +description.workspace = true +repository.workspace = true +documentation.workspace = true +homepage.workspace = true +license.workspace = true +keywords.workspace = true +categories.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +iroha_crypto = { workspace = true } +iroha_data_model = { workspace = true } + +once_cell = { workspace = true } +serde = { workspace = true, features = ["derive"] } +toml = { workspace = true } + +[lints] +workspace = true + +[features] +default = ["rand"] +rand = ["iroha_crypto/rand"] diff --git a/test_samples/src/lib.rs b/test_samples/src/lib.rs new file mode 100644 index 00000000000..668fb4d7116 --- /dev/null +++ b/test_samples/src/lib.rs @@ -0,0 +1,56 @@ +//! Utility crate for standardized and random signatories. + +use iroha_crypto::KeyPair; +use iroha_data_model::prelude::AccountId; +use once_cell::sync::Lazy; + +/// Generate [`AccountId`](iroha_data_model::account::AccountId) in the given `domain`. +/// +/// # Panics +/// +/// Panics if the given `domain` is invalid as [`Name`](iroha_data_model::name::Name). +#[cfg(feature = "rand")] +pub fn gen_account_in(domain: impl core::fmt::Display) -> (AccountId, KeyPair) { + let key_pair = KeyPair::random(); + let account_id = format!("{}@{}", key_pair.public_key(), domain) + .parse() + .expect("domain name should be valid"); + (account_id, key_pair) +} + +macro_rules! declare_keypair { + ( $key_pair:ident, $public_key:expr, $private_key:expr ) => { + /// A standardized [`KeyPair`](iroha_crypto::KeyPair). + pub static $key_pair: Lazy = Lazy::new(|| { + KeyPair::new( + $public_key + .parse() + .expect(r#"public_key should be valid multihash e.g. "ed0120...""#), + $private_key + .parse() + .expect(r#"private_key should be valid multihash e.g. "802640...""#), + ) + .expect("public_key and private_key should be valid as a pair") + }); + }; +} + +macro_rules! declare_account_with_keypair { + ( $account_id:ident, $domain:literal, $key_pair:ident, $public_key:literal, $private_key:literal ) => { + /// A standardized [`AccountId`](iroha_data_model::account::AccountId). + pub static $account_id: Lazy = Lazy::new(|| { + format!("{}@{}", $key_pair.public_key(), $domain) + .parse() + .expect("domain and public_key should be valid as name and multihash, respectively") + }); + + declare_keypair!($key_pair, $public_key, $private_key); + }; +} + +declare_keypair!(PEER_KEYPAIR, "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0", "8026409AC47ABF59B356E0BD7DCBBBB4DEC080E302156A48CA907E47CB6AEA1D32719E7233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"); + +declare_account_with_keypair!(ALICE_ID, "wonderland", ALICE_KEYPAIR, "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03", "802640CCF31D85E3B32A4BEA59987CE0C78E3B8E2DB93881468AB2435FE45D5C9DCD53CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03"); +declare_account_with_keypair!(BOB_ID, "wonderland", BOB_KEYPAIR, "ed012004FF5B81046DDCCF19E2E451C45DFB6F53759D4EB30FA2EFA807284D1CC33016", "802640AF3F96DEEF44348FEB516C057558972CEC4C75C4DB9C5B3AAC843668854BF82804FF5B81046DDCCF19E2E451C45DFB6F53759D4EB30FA2EFA807284D1CC33016"); +declare_account_with_keypair!(CARPENTER_ID, "garden_of_live_flowers", CARPENTER_KEYPAIR, "ed0120E9F632D3034BAB6BB26D92AC8FD93EF878D9C5E69E01B61B4C47101884EE2F99", "802640B5DD003D106B273F3628A29E6087C31CE12C9F32223BE26DD1ADB85CEBB48E1DE9F632D3034BAB6BB26D92AC8FD93EF878D9C5E69E01B61B4C47101884EE2F99"); +declare_account_with_keypair!(SAMPLE_GENESIS_ACCOUNT_ID, "genesis", SAMPLE_GENESIS_ACCOUNT_KEYPAIR, "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4", "80264082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD4164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4"); diff --git a/tools/kagami/Cargo.toml b/tools/kagami/Cargo.toml index 7a4d4145ecf..1f076c54b85 100644 --- a/tools/kagami/Cargo.toml +++ b/tools/kagami/Cargo.toml @@ -19,6 +19,7 @@ iroha_data_model = { workspace = true } iroha_schema_gen = { workspace = true } iroha_primitives = { workspace = true } iroha_genesis = { workspace = true } +test_samples = { workspace = true } color-eyre = { workspace = true } clap = { workspace = true, features = ["derive"] } diff --git a/tools/kagami/src/genesis.rs b/tools/kagami/src/genesis.rs index 1a7292df8b8..db0db26b668 100644 --- a/tools/kagami/src/genesis.rs +++ b/tools/kagami/src/genesis.rs @@ -12,8 +12,11 @@ use iroha_data_model::{ parameter::{default::*, ParametersBuilder}, prelude::AssetId, }; -use iroha_genesis::{executor_state, RawGenesisBlockBuilder, RawGenesisBlockFile}; +use iroha_genesis::{ + executor_state, RawGenesisBlockBuilder, RawGenesisBlockFile, GENESIS_DOMAIN_ID, +}; use serde_json::json; +use test_samples::{gen_account_in, ALICE_ID, BOB_ID, CARPENTER_ID}; use super::*; @@ -76,24 +79,28 @@ impl RunArgs for Args { pub fn generate_default( builder: RawGenesisBlockBuilder, ) -> color_eyre::Result { + let genesis_account_id: AccountId = { + let multihash = + std::env::var("GENESIS_PUBLIC_KEY").wrap_err("GENESIS_PUBLIC_KEY should be set")?; + let domain = &*GENESIS_DOMAIN_ID; + format!("{multihash}@{domain}") + .parse() + .wrap_err("GENESIS_PUBLIC_KEY should be valid multihash")? + }; let mut meta = Metadata::new(); meta.insert_with_limits("key".parse()?, "value".to_owned(), Limits::new(1024, 1024))?; let mut genesis = builder .domain_with_metadata("wonderland".parse()?, meta.clone()) - .account_with_metadata( - "alice".parse()?, - crate::DEFAULT_PUBLIC_KEY.parse()?, - meta.clone(), - ) - .account_with_metadata("bob".parse()?, crate::DEFAULT_PUBLIC_KEY.parse()?, meta) + .account_with_metadata(ALICE_ID.signatory().clone(), meta.clone()) + .account_with_metadata(BOB_ID.signatory().clone(), meta) .asset( "rose".parse()?, AssetValueType::Numeric(NumericSpec::default()), ) .finish_domain() .domain("garden_of_live_flowers".parse()?) - .account("carpenter".parse()?, crate::DEFAULT_PUBLIC_KEY.parse()?) + .account(CARPENTER_ID.signatory().clone()) .asset( "cabbage".parse()?, AssetValueType::Numeric(NumericSpec::default()), @@ -101,33 +108,37 @@ pub fn generate_default( .finish_domain() .build(); - let alice_id = AccountId::from_str("alice@wonderland")?; let mint = Mint::asset_numeric( 13u32, - AssetId::new("rose#wonderland".parse()?, alice_id.clone()), + AssetId::new("rose#wonderland".parse()?, ALICE_ID.clone()), ); let mint_cabbage = Mint::asset_numeric( 44u32, - AssetId::new("cabbage#garden_of_live_flowers".parse()?, alice_id.clone()), + AssetId::new("cabbage#garden_of_live_flowers".parse()?, ALICE_ID.clone()), ); let grant_permission_to_set_parameters = Grant::permission( PermissionToken::new("CanSetParameters".parse()?, &json!(null)), - alice_id.clone(), + ALICE_ID.clone(), + ); + let transfer_rose_ownership = Transfer::asset_definition( + genesis_account_id.clone(), + "rose#wonderland".parse()?, + ALICE_ID.clone(), ); - let transfer_domain_ownerhip = Transfer::domain( - "genesis@genesis".parse()?, + let transfer_wonderland_ownership = Transfer::domain( + genesis_account_id.clone(), "wonderland".parse()?, - alice_id.clone(), + ALICE_ID.clone(), ); let register_user_metadata_access = Register::role( Role::new("ALICE_METADATA_ACCESS".parse()?) .add_permission(PermissionToken::new( "CanSetKeyValueInAccount".parse()?, - &json!({ "account_id": alice_id }), + &json!({ "account_id": ALICE_ID.clone() }), )) .add_permission(PermissionToken::new( "CanRemoveKeyValueInAccount".parse()?, - &json!({ "account_id": alice_id }), + &json!({ "account_id": ALICE_ID.clone() }), )), ) .into(); @@ -176,7 +187,8 @@ pub fn generate_default( for isi in [ mint.into(), mint_cabbage.into(), - transfer_domain_ownerhip.into(), + transfer_rose_ownership.into(), + transfer_wonderland_ownership.into(), grant_permission_to_set_parameters.into(), ] .into_iter() @@ -207,12 +219,10 @@ fn generate_synthetic( first_transaction .append_instruction(Register::domain(Domain::new(domain_id.clone())).into()); - for account in 0..accounts_per_domain { - let (public_key, _) = iroha_crypto::KeyPair::random().into_parts(); - let account_id: AccountId = format!("account_{account}@{domain_id}").parse()?; - first_transaction.append_instruction( - Register::account(Account::new(account_id.clone(), public_key)).into(), - ); + for _ in 0..accounts_per_domain { + let (account_id, _account_keypair) = gen_account_in(&domain_id); + first_transaction + .append_instruction(Register::account(Account::new(account_id.clone())).into()); } for asset in 0..assets_per_domain { diff --git a/tools/kagami/src/main.rs b/tools/kagami/src/main.rs index 16228701582..270e140994e 100644 --- a/tools/kagami/src/main.rs +++ b/tools/kagami/src/main.rs @@ -1,10 +1,7 @@ //! CLI for generating iroha sample configuration, genesis and //! cryptographic key pairs. To be used with all compliant Iroha //! installations. -use std::{ - io::{stdout, BufWriter, Write}, - str::FromStr as _, -}; +use std::io::{stdout, BufWriter, Write}; use clap::{Args as ClapArgs, Parser}; use color_eyre::eyre::WrapErr as _; @@ -17,12 +14,6 @@ mod schema; /// Outcome shorthand used throughout this crate pub(crate) type Outcome = color_eyre::Result<()>; -// The reason for hard-coding this default is to ensure that the -// algorithm is matched to the public key in Ed25519 format. If -// you need to change either, you should definitely change both. -const DEFAULT_PUBLIC_KEY: &str = - "ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"; - fn main() -> Outcome { color_eyre::install()?; let args = Args::parse(); diff --git a/tools/parity_scale_cli/Cargo.toml b/tools/parity_scale_cli/Cargo.toml index 2b797c55a8f..aa8bf8d2c29 100644 --- a/tools/parity_scale_cli/Cargo.toml +++ b/tools/parity_scale_cli/Cargo.toml @@ -38,3 +38,6 @@ parity-scale-codec = { workspace = true } serde_json = { workspace = true, features = ["std"]} serde = { workspace = true } eyre = { workspace = true } + +[dev-dependencies] +test_samples = { workspace = true } diff --git a/tools/parity_scale_cli/README.md b/tools/parity_scale_cli/README.md index 824bfbac4a2..4ca6aedee2e 100644 --- a/tools/parity_scale_cli/README.md +++ b/tools/parity_scale_cli/README.md @@ -63,6 +63,7 @@ Algorithm ## `scale-to-json` and `json-to-scale` + Both commands by default read data from `stdin` and print result to `stdout`. There are flags `--input` and `--output` which can be used to read/write from files instead. @@ -85,7 +86,7 @@ These commands require `--type` argument. If data type is not known, [`scale-to- * Encode the `NewAccount` data type from the `samples/account.json`: ```bash - ./target/debug/parity_scale_cli json-to-scale --input tools/parity_scale_cli/samples/domain.bin --output result.bin --type NewAccount + ./target/debug/parity_scale_cli json-to-scale --input tools/parity_scale_cli/samples/account.json --output result.bin --type NewAccount ``` ## `scale-to-rust` diff --git a/tools/parity_scale_cli/samples/account.bin b/tools/parity_scale_cli/samples/account.bin index c0ac2716337..b9ece2bea12 100644 Binary files a/tools/parity_scale_cli/samples/account.bin and b/tools/parity_scale_cli/samples/account.bin differ diff --git a/tools/parity_scale_cli/samples/account.json b/tools/parity_scale_cli/samples/account.json index 7bb4321521b..c749623fb95 100644 --- a/tools/parity_scale_cli/samples/account.json +++ b/tools/parity_scale_cli/samples/account.json @@ -1,8 +1,5 @@ { - "id": "alice@wonderland", - "signatories": [ - "ed0120EDF6D7B52C7032D03AEC696F2068BD53101528F3C7B6081BFF05A1662D7FC245" - ], + "id": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland", "metadata": { "hat": { "Name": "white" diff --git a/tools/parity_scale_cli/samples/trigger.bin b/tools/parity_scale_cli/samples/trigger.bin index bf1bf3f4b9e..35d40540b8b 100644 Binary files a/tools/parity_scale_cli/samples/trigger.bin and b/tools/parity_scale_cli/samples/trigger.bin differ diff --git a/tools/parity_scale_cli/samples/trigger.json b/tools/parity_scale_cli/samples/trigger.json index bcc84114c88..6c74b0f5a53 100644 --- a/tools/parity_scale_cli/samples/trigger.json +++ b/tools/parity_scale_cli/samples/trigger.json @@ -7,14 +7,14 @@ "Mint": { "Asset": { "object": "1", - "destination_id": "rose##alice@wonderland" + "destination_id": "rose##ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland" } } } ] }, "repeats": "Indefinitely", - "authority": "alice@wonderland", + "authority": "ed0120CE7FA46C9DCE7EA4B125E2E36BDB63EA33073E7590AC92816AE1E861B7048B03@wonderland", "filter": { "Data": { "Domain": { diff --git a/tools/parity_scale_cli/src/main.rs b/tools/parity_scale_cli/src/main.rs index 3f14c549f84..331bacb6b8e 100644 --- a/tools/parity_scale_cli/src/main.rs +++ b/tools/parity_scale_cli/src/main.rs @@ -321,6 +321,7 @@ mod tests { use std::str::FromStr as _; use iroha_data_model::{ipfs::IpfsPath, prelude::*}; + use test_samples::ALICE_ID; use super::*; @@ -335,12 +336,7 @@ mod tests { limits, ) .expect("Valid"); - let signature = PublicKey::from_str( - "ed0120EDF6D7B52C7032D03AEC696F2068BD53101528F3C7B6081BFF05A1662D7FC245", - ) - .unwrap(); - let account = - Account::new("alice@wonderland".parse().unwrap(), signature).with_metadata(metadata); + let account = Account::new(ALICE_ID.clone()).with_metadata(metadata); decode_sample("account.bin", String::from("NewAccount"), &account); } @@ -364,17 +360,16 @@ mod tests { #[test] fn decode_trigger_sample() { - let account_id = AccountId::from_str("alice@wonderland").expect("Valid"); let rose_definition_id = AssetDefinitionId::new( "wonderland".parse().expect("Valid"), "rose".parse().expect("Valid"), ); - let rose_id = AssetId::new(rose_definition_id, account_id.clone()); + let rose_id = AssetId::new(rose_definition_id, ALICE_ID.clone()); let trigger_id = "mint_rose".parse().expect("Valid"); let action = Action::new( vec![Mint::asset_numeric(1u32, rose_id)], Repeats::Indefinitely, - account_id, + ALICE_ID.clone(), DomainEventFilter::new().for_events(DomainEventSet::AnyAccount), ); let trigger = Trigger::new(trigger_id, action); diff --git a/torii/src/lib.rs b/torii/src/lib.rs index 94d3b11ad79..c2445065125 100644 --- a/torii/src/lib.rs +++ b/torii/src/lib.rs @@ -341,7 +341,7 @@ impl Error { Config(_) | StatusSegmentNotFound(_) => StatusCode::NOT_FOUND, PushIntoQueue(err) => match **err { queue::Error::Full => StatusCode::INTERNAL_SERVER_ERROR, - queue::Error::SignatureCondition => StatusCode::UNAUTHORIZED, + queue::Error::SignatoryInconsistent => StatusCode::UNAUTHORIZED, _ => StatusCode::BAD_REQUEST, }, #[cfg(feature = "telemetry")] diff --git a/torii/src/routing.rs b/torii/src/routing.rs index edff834fed4..2d2aa7fcdd7 100644 --- a/torii/src/routing.rs +++ b/torii/src/routing.rs @@ -360,6 +360,7 @@ pub mod profiling { use super::*; /// Query params used to configure profile gathering + #[allow(clippy::unsafe_derive_deserialize)] #[derive(Serialize, Deserialize, Clone, Copy)] pub struct ProfileParams { /// How often to sample iroha