diff --git a/Cargo.lock b/Cargo.lock index 2a08743cb..3abdf14f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3212,8 +3212,8 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -3817,7 +3817,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.7", + "regex-automata 0.4.8", "same-file", "walkdir", "winapi-util", @@ -3964,6 +3964,7 @@ dependencies = [ "minotari_node_grpc_client", "minotari_wallet", "rand", + "regex", "reqwest", "serde", "serde_json", @@ -4249,7 +4250,7 @@ dependencies = [ "petgraph", "pico-args", "regex", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "string_cache", "term", "tiny-keccak", @@ -4263,7 +4264,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" dependencies = [ - "regex-automata 0.4.7", + "regex-automata 0.4.8", ] [[package]] @@ -7311,14 +7312,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -7332,13 +7333,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -7355,9 +7356,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "region" diff --git a/dan_layer/state_store_sqlite/src/store.rs b/dan_layer/state_store_sqlite/src/store.rs index b0fdcbdf7..394d524d9 100644 --- a/dan_layer/state_store_sqlite/src/store.rs +++ b/dan_layer/state_store_sqlite/src/store.rs @@ -71,8 +71,12 @@ impl fmt::Debug for SqliteStateStore { impl StateStore for SqliteStateStore { type Addr = TAddr; - type ReadTransaction<'a> = SqliteStateStoreReadTransaction<'a, Self::Addr> where TAddr: 'a; - type WriteTransaction<'a> = SqliteStateStoreWriteTransaction<'a, Self::Addr> where TAddr: 'a; + type ReadTransaction<'a> + = SqliteStateStoreReadTransaction<'a, Self::Addr> + where TAddr: 'a; + type WriteTransaction<'a> + = SqliteStateStoreWriteTransaction<'a, Self::Addr> + where TAddr: 'a; fn create_read_tx(&self) -> Result, StorageError> { let tx = SqliteTransaction::begin(self.connection.lock().unwrap())?; diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 007d575c6..0c8ee9f2f 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -61,6 +61,7 @@ serde_json = { workspace = true } time = { workspace = true } tokio = { workspace = true, features = ["default", "macros", "time", "sync", "rt-multi-thread", "signal"] } tonic = { workspace = true } +regex = "1.11.0" [[test]] name = "cucumber" # this should be the same as the filename of your test target diff --git a/integration_tests/src/wallet_daemon_cli.rs b/integration_tests/src/wallet_daemon_cli.rs index 0724ae929..1afa00d20 100644 --- a/integration_tests/src/wallet_daemon_cli.rs +++ b/integration_tests/src/wallet_daemon_cli.rs @@ -22,7 +22,7 @@ use std::{collections::HashMap, str::FromStr, time::Duration}; -use anyhow::bail; +use anyhow::{anyhow, bail}; use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; use serde_json::json; use tari_crypto::{ @@ -35,7 +35,7 @@ use tari_dan_wallet_sdk::{ apis::confidential_transfer::ConfidentialTransferInputSelection, models::{Account, NonFungibleToken}, }; -use tari_engine_types::instruction::Instruction; +use tari_engine_types::{instruction::Instruction, substate::SubstateId}; use tari_template_lib::{ args, constants::CONFIDENTIAL_TARI_RESOURCE_ADDRESS, @@ -70,7 +70,7 @@ use tari_wallet_daemon_client::{ ComponentAddressOrName, WalletDaemonClient, }; -use tokio::time::timeout; +use tokio::{task::JoinSet, time::timeout}; use crate::{helpers::get_address_from_output, validator_node_cli::add_substate_ids, TariWorld}; @@ -692,18 +692,41 @@ pub async fn create_component( ); } +pub fn find_output_version( + world: &mut TariWorld, + output_ref: &str, + output_component_substate_id: SubstateId, +) -> anyhow::Result> { + let outputs_name = output_ref.split('/').next().ok_or(anyhow!("Output must have a name"))?; + Ok(world + .outputs + .entry(outputs_name.to_string()) + .or_default() + .iter() + .filter(|(_, requirement)| requirement.substate_id == output_component_substate_id) + .map(|(_, requirement)| requirement.version) + .last() + .unwrap_or_default()) +} + pub async fn call_component( world: &mut TariWorld, account_name: String, output_ref: String, wallet_daemon_name: String, function_call: String, + new_outputs_name: Option, ) -> anyhow::Result { let mut client = get_auth_wallet_daemon_client(world, &wallet_daemon_name).await; let source_component_address = get_address_from_output(world, output_ref.clone()) .as_component_address() .expect("Failed to get component address from output"); + let source_component_name = output_ref + .split('/') + .next() + .ok_or(anyhow!("Output must have a name"))? + .to_string(); let account = get_account_from_name(&mut client, account_name).await; let account_component_address = account @@ -714,16 +737,30 @@ pub async fn call_component( let tx = Transaction::builder() .fee_transaction_pay_from_component(account_component_address, Amount(1000)) .call_method(source_component_address, &function_call, vec![]) + .with_inputs(vec![ + SubstateRequirement::new( + account_component_address.into(), + find_output_version(world, output_ref.as_str(), account_component_address.into())?, + ), + SubstateRequirement::new( + source_component_address.into(), + find_output_version(world, output_ref.as_str(), source_component_address.into())?, + ), + ]) .build_unsigned_transaction(); - let resp = submit_unsigned_tx_and_wait_for_response(client, tx, account).await; + let resp = submit_unsigned_tx_and_wait_for_response(client, tx, account).await?; + + let final_outputs_name = if let Some(name) = new_outputs_name { + name + } else { + source_component_name + }; add_substate_ids( world, - output_ref, + final_outputs_name, &resp - .as_ref() - .unwrap() .clone() .result .expect("Call component transaction has timed out") @@ -731,7 +768,7 @@ pub async fn call_component( .expect("Call component transaction has failed"), ); - resp + Ok(resp) } pub async fn concurrent_call_component( @@ -754,34 +791,38 @@ pub async fn concurrent_call_component( .as_component_address() .expect("Failed to get account component address"); - let mut handles = Vec::new(); + let mut join_set = JoinSet::new(); for _ in 0..times { let acc = account.clone(); let clt = client.clone(); let tx = Transaction::builder() - .fee_transaction_pay_from_component(account_component_address, Amount(2000)) + .fee_transaction_pay_from_component(account_component_address, Amount(1000)) .call_method(source_component_address, &function_call, vec![]) .build_unsigned_transaction(); - let handle = tokio::spawn(submit_unsigned_tx_and_wait_for_response(clt, tx, acc)); - handles.push(handle); + join_set.spawn(submit_unsigned_tx_and_wait_for_response(clt, tx, acc)); } - let mut last_resp = None; - for handle in handles { - let result = handle.await.map_err(|e| e.to_string()); - if result.is_err() { - bail!("{}", result.as_ref().unwrap_err()); - } + while let Some(result) = join_set.join_next().await { + let result = result.map_err(|e| e.to_string()); match result { - Ok(response) => last_resp = Some(response), + Ok(response) => match response { + Ok(resp) => { + add_substate_ids( + world, + output_ref.clone(), + &resp + .result + .expect("no finalize result") + .result + .expect("no transaction result"), + ); + }, + Err(error) => bail!("Failed to submit transaction: {error:?}"), + }, Err(e) => bail!("Failed to get response from handler: {}", e), } } - if last_resp.is_none() { - bail!("No responses from any of the wallet daemon concurrent calls"); - } - Ok(()) } diff --git a/integration_tests/tests/cucumber.rs b/integration_tests/tests/cucumber.rs index 2a48a6e61..49a3f80f8 100644 --- a/integration_tests/tests/cucumber.rs +++ b/integration_tests/tests/cucumber.rs @@ -23,7 +23,8 @@ mod steps; use std::{fs, future, io, panic, str::FromStr, time::Duration}; -use cucumber::{gherkin::Step, given, then, when, writer, writer::Verbosity, World, WriterExt}; +use anyhow::bail; +use cucumber::{gherkin::Step, given, then, when, writer, writer::Verbosity, ScenarioType, World, WriterExt}; use integration_tests::{ http_server::{spawn_template_http_server, MockHttpServer}, logging::{create_log_config_file, get_base_dir}, @@ -41,6 +42,7 @@ use libp2p::{ }, Multiaddr, }; +use regex::Regex; use tari_common::initialize_logging; use tari_dan_engine::abi::Type; use tari_dan_storage::consensus_models::QuorumDecision; @@ -61,7 +63,7 @@ async fn main() { let file = fs::File::create("cucumber-output-junit.xml").unwrap(); let cucumber_fut = TariWorld::cucumber() - .max_concurrent_scenarios(1) + .max_concurrent_scenarios(5) .with_writer(writer::Tee::new( writer::JUnit::new(file, Verbosity::ShowWorldAndDocString).normalized(), // following config needed to use eprint statements in the tests @@ -89,6 +91,30 @@ async fn main() { Box::pin(future::ready(())) }) .fail_on_skipped() + .which_scenario(|feature, _, scenario| { + let feature_has_concurrent_tag = feature.tags.iter().any(|tag| tag == "concurrent"); + let feature_has_serial_tag = feature.tags.iter().any(|tag| tag == "serial"); + let scenario_has_concurrent_tag = scenario.tags.iter().any(|tag| tag == "concurrent"); + let scenario_has_serial_tag = scenario.tags.iter().any(|tag| tag == "serial"); + + if scenario_has_serial_tag { + return ScenarioType::Serial; + } + + if scenario_has_concurrent_tag { + return ScenarioType::Concurrent; + } + + if feature_has_serial_tag { + return ScenarioType::Serial; + } + + if feature_has_concurrent_tag { + return ScenarioType::Concurrent; + } + + ScenarioType::Serial + }) .filter_run("tests/features/", |_, _, sc| !sc.tags.iter().any(|t| t == "ignore")); let ctrl_c = tokio::signal::ctrl_c(); @@ -173,6 +199,34 @@ async fn call_template_constructor_via_wallet_daemon_no_args( ) .await; } + +#[when( + expr = r#"I call function "{word}" on template "{word}" with args {string} using account {word} to pay fees via wallet daemon {word} named "{word}""# +)] +async fn call_template_constructor_via_wallet_daemon_with_args( + world: &mut TariWorld, + function_call: String, + template_name: String, + args_raw: String, + account_name: String, + wallet_daemon_name: String, + outputs_name: String, +) { + let args: Vec = args_raw.split(',').map(|str| str.trim().to_string()).collect(); + wallet_daemon_cli::create_component( + world, + outputs_name, + template_name, + account_name, + wallet_daemon_name, + function_call, + args, + None, + None, + ) + .await; +} + #[when(expr = r#"I call function "{word}" on template "{word}" on {word} with args "{word}" named "{word}""#)] async fn call_template_constructor( world: &mut TariWorld, @@ -332,7 +386,8 @@ async fn call_wallet_daemon_method_and_check_result( expected_result: String, ) -> anyhow::Result<()> { let resp = - wallet_daemon_cli::call_component(world, account_name, output_ref, wallet_daemon_name, method_call).await?; + wallet_daemon_cli::call_component(world, account_name, output_ref, wallet_daemon_name, method_call, None) + .await?; let finalize_result = resp .result @@ -361,7 +416,69 @@ async fn call_wallet_daemon_method( output_ref: String, method_call: String, ) -> anyhow::Result<()> { - wallet_daemon_cli::call_component(world, account_name, output_ref, wallet_daemon_name, method_call).await?; + wallet_daemon_cli::call_component(world, account_name, output_ref, wallet_daemon_name, method_call, None).await?; + + Ok(()) +} + +#[when( + expr = r#"I invoke on wallet daemon {word} on account {word} on component {word} the method call "{word}" named "{word}""# +)] +async fn call_wallet_daemon_method_with_output_name( + world: &mut TariWorld, + wallet_daemon_name: String, + account_name: String, + output_ref: String, + method_call: String, + new_output_name: String, +) -> anyhow::Result<()> { + wallet_daemon_cli::call_component( + world, + account_name, + output_ref, + wallet_daemon_name, + method_call, + Some(new_output_name), + ) + .await?; + + Ok(()) +} + +#[when( + expr = r#"I invoke on wallet daemon {word} on account {word} on component {word} the method call "{word}" named "{word}", I expect it to fail with {string}"# +)] +async fn call_wallet_daemon_method_with_output_name_error_result( + world: &mut TariWorld, + wallet_daemon_name: String, + account_name: String, + output_ref: String, + method_call: String, + new_output_name: String, + error_message: String, +) -> anyhow::Result<()> { + if let Err(error) = wallet_daemon_cli::call_component( + world, + account_name, + output_ref, + wallet_daemon_name, + method_call, + Some(new_output_name), + ) + .await + { + let error_str = error.to_string(); + let re = Regex::new(error_message.as_str()).expect("invalid regex for error message"); + if re.find(error_str.as_str()).is_none() { + bail!( + "Error mismatch: \"{}\" does not contain \"{}\"", + error_str, + error_message.as_str() + ); + } + } else { + bail!("Error expected, but none was happening!"); + } Ok(()) } diff --git a/integration_tests/tests/features/claim_burn.feature b/integration_tests/tests/features/claim_burn.feature index 483810971..e4e6fa377 100644 --- a/integration_tests/tests/features/claim_burn.feature +++ b/integration_tests/tests/features/claim_burn.feature @@ -3,7 +3,9 @@ @claim_burn Feature: Claim Burn - @serial @fixed + @concurrent +# @serial + @fixed Scenario: Claim base layer burn funds with wallet daemon # Initialize a base node, wallet, miner and VN Given a base node BASE @@ -41,7 +43,8 @@ Feature: Claim Burn When I claim burn COMMITMENT with PROOF, RANGEPROOF and CLAIM_PUBKEY and spend it into account ACC via the wallet daemon WALLET_D # Then account ACC has one confidential bucket in it - @serial +# @serial + @concurrent Scenario: Double Claim base layer burn funds with wallet daemon. should fail # Initialize a base node, wallet, miner and VN Given a base node BASE diff --git a/integration_tests/tests/features/committee.feature b/integration_tests/tests/features/committee.feature index 3da1f24c3..bd2fac12f 100644 --- a/integration_tests/tests/features/committee.feature +++ b/integration_tests/tests/features/committee.feature @@ -1,9 +1,11 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause + +@concurrent @committee Feature: Committee scenarios - @serial @fixed + @fixed Scenario: Template registration and invocation in a 2-VN committee # Initialize a base node, wallet and miner Given a base node BASE diff --git a/integration_tests/tests/features/concurrency.feature.ignore b/integration_tests/tests/features/concurrency.feature similarity index 97% rename from integration_tests/tests/features/concurrency.feature.ignore rename to integration_tests/tests/features/concurrency.feature index 5a094f0b0..5b6eddc4b 100644 --- a/integration_tests/tests/features/concurrency.feature.ignore +++ b/integration_tests/tests/features/concurrency.feature @@ -1,15 +1,15 @@ # Copyright 2024 The Tari Project # SPDX-License-Identifier: BSD-3-Clause -@concurrency @doit +@concurrency +@doit Feature: Concurrency - @serial + @ignore Scenario: Concurrent calls to the Counter template ##### Setup # Initialize a base node, wallet, miner and VN - Given fees are disabled Given a base node BASE Given a wallet WALLET connected to base node BASE Given a miner MINER connected to base node BASE and wallet WALLET @@ -39,7 +39,7 @@ Feature: Concurrency ##### Scenario # The initial value of the counter must be 0 When I call function "new" on template "counter" using account ACC to pay fees via wallet daemon WALLET_D named "COUNTER" - When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "value" the result is "0" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "value" the result is "0" # Send multiple concurrent transactions to increase the counter # Currently there is a lock bug where the subsequent transactions executed are being rejected, should be tested later after engine changes: diff --git a/integration_tests/tests/features/counter.feature b/integration_tests/tests/features/counter.feature index 925ed2329..2b899a42e 100644 --- a/integration_tests/tests/features/counter.feature +++ b/integration_tests/tests/features/counter.feature @@ -1,11 +1,11 @@ # Copyright 2024 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@concurrent @counter Feature: Counter template - @serial - Scenario: Counter template registration and invocation + Scenario: Counter template registration and invocation once # Initialize a base node, wallet, miner and VN Given a base node BASE @@ -44,6 +44,44 @@ Feature: Counter template # Check that the counter has been increased When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "value" the result is "1" -# Uncomment the following lines to stop execution for manual inspection of the nodes -# When I print the cucumber world -# When I wait 5000 seconds + + Scenario: Counter template registration and invocation multiple times + + # Initialize a base node, wallet, miner and VN + Given a base node BASE + Given a wallet WALLET connected to base node BASE + Given a miner MINER connected to base node BASE and wallet WALLET + + # Initialize a validator node + Given a validator node VN connected to base node BASE and wallet daemon WALLET_D + + # Fund wallet to send VN registration tx + When miner MINER mines 10 new blocks + When wallet WALLET has at least 2000 T + When validator node VN sends a registration transaction to base wallet WALLET + When miner MINER mines 16 new blocks + Then the validator node VN is listed as registered + + # Initialize indexer and connect wallet daemon + Given an indexer IDX connected to base node BASE + Given a wallet daemon WALLET_D connected to indexer IDX + + # Register the "counter" template + When base wallet WALLET registers the template "counter" + When miner MINER mines 20 new blocks + Then VN has scanned to height 43 + + # Create the sender account + When I create an account ACC via the wallet daemon WALLET_D with 10000 free coins + + # The initial value of the counter must be 0 + When I call function "new" on template "counter" using account ACC to pay fees via wallet daemon WALLET_D named "COUNTER" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "value" the result is "0" + + # Increase and check the counter + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "increase" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "value" the result is "1" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "increase" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "value" the result is "2" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "increase" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER/components/Counter the method call "value" the result is "3" diff --git a/integration_tests/tests/features/epoch_change.feature b/integration_tests/tests/features/epoch_change.feature new file mode 100644 index 000000000..05d3ab420 --- /dev/null +++ b/integration_tests/tests/features/epoch_change.feature @@ -0,0 +1,132 @@ +# Copyright 2022 The Tari Project +# SPDX-License-Identifier: BSD-3-Clause + +@concurrent +@epoch_change +Feature: Epoch change + + Scenario: EndEpoch command is used on epoch change + # Initialize a base node, wallet, miner and VN + Given a base node BASE + Given a wallet WALLET connected to base node BASE + Given a miner MINER connected to base node BASE and wallet WALLET + + # Initialize two validator nodes + Given a validator node VAL connected to base node BASE and wallet daemon WALLET_D + Given validator VAL nodes connect to all other validators + + # The wallet must have some funds before the VN sends transactions + When miner MINER mines 6 new blocks + When wallet WALLET has at least 20000 T + + # VN registration + When validator node VAL sends a registration transaction to base wallet WALLET + When base wallet WALLET registers the template "faucet" + + # Mine them into registered epoch + When miner MINER mines 16 new blocks + Then VAL has scanned to height 19 + Then the validator node VAL is listed as registered + Then the template "faucet" is listed as registered by the validator node VAL + + # Initialize indexer and connect wallet daemon + Given an indexer IDX connected to base node BASE + Given a wallet daemon WALLET_D connected to indexer IDX + + # Create account + When I create an account ACC via the wallet daemon WALLET_D with 10000 free coins + + # Push a transaction through to get blocks +# When I call function "mint" on template "faucet" on VAL with args "amount_10000" named "FAUCET" + When I call function "mint" on template "faucet" with args "amount_10000" using account ACC to pay fees via wallet daemon WALLET_D named "FAUCET" + + When Block count on VN VAL is at least 6 + When miner MINER mines 5 new blocks + Then VAL has scanned to height 24 + Then the validator node VAL switches to epoch 2 + +# @serial +# Scenario: Committee is split into two during epoch change +# # Initialize a base node, wallet, miner and VN +# Given a base node BASE +# Given a wallet WALLET connected to base node BASE +# Given a miner MINER connected to base node BASE and wallet WALLET +# +# # Initialize validator nodes +# Given a validator node VAL_1 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_2 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_3 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_4 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_5 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_6 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_7 connected to base node BASE and wallet daemon WALLET_D +# Given validator VAL_1 nodes connect to all other validators +# Given validator VAL_2 nodes connect to all other validators +# Given validator VAL_3 nodes connect to all other validators +# Given validator VAL_4 nodes connect to all other validators +# Given validator VAL_5 nodes connect to all other validators +# Given validator VAL_6 nodes connect to all other validators +# Given validator VAL_7 nodes connect to all other validators +# +# # The wallet must have some funds before the VN sends transactions +# When miner MINER mines 14 new blocks +# When wallet WALLET has at least 120000 T +# +# # VN registration +# When validator node VAL_1 sends a registration transaction to base wallet WALLET +# When validator node VAL_2 sends a registration transaction to base wallet WALLET +# When validator node VAL_3 sends a registration transaction to base wallet WALLET +# When validator node VAL_4 sends a registration transaction to base wallet WALLET +# When validator node VAL_5 sends a registration transaction to base wallet WALLET +# When validator node VAL_6 sends a registration transaction to base wallet WALLET +# When validator node VAL_7 sends a registration transaction to base wallet WALLET +# +# # Mine them into registered epoch +# When miner MINER mines 10 new blocks +# Then VAL_1 has scanned to height 21 +# Then the validator node VAL_1 is listed as registered +# Then the validator node VAL_2 is listed as registered +# Then the validator node VAL_3 is listed as registered +# Then the validator node VAL_4 is listed as registered +# Then the validator node VAL_5 is listed as registered +# Then the validator node VAL_6 is listed as registered +# Then the validator node VAL_7 is listed as registered +# +# +# When Block count on VN VAL_1 is at least 5 +# +# Given a validator node VAL_8 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_9 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_10 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_11 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_12 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_13 connected to base node BASE and wallet daemon WALLET_D +# Given a validator node VAL_14 connected to base node BASE and wallet daemon WALLET_D +# Given validator VAL_8 nodes connect to all other validators +# Given validator VAL_9 nodes connect to all other validators +# Given validator VAL_10 nodes connect to all other validators +# Given validator VAL_11 nodes connect to all other validators +# Given validator VAL_12 nodes connect to all other validators +# Given validator VAL_13 nodes connect to all other validators +# Given validator VAL_14 nodes connect to all other validators +# +# When validator node VAL_8 sends a registration transaction to base wallet WALLET +# When validator node VAL_9 sends a registration transaction to base wallet WALLET +# When validator node VAL_10 sends a registration transaction to base wallet WALLET +# When validator node VAL_11 sends a registration transaction to base wallet WALLET +# When validator node VAL_12 sends a registration transaction to base wallet WALLET +# When validator node VAL_13 sends a registration transaction to base wallet WALLET +# When validator node VAL_14 sends a registration transaction to base wallet WALLET +# +# When miner MINER mines 10 new blocks +# +# Then the validator node VAL_8 is listed as registered +# Then the validator node VAL_9 is listed as registered +# Then the validator node VAL_10 is listed as registered +# Then the validator node VAL_11 is listed as registered +# Then the validator node VAL_12 is listed as registered +# Then the validator node VAL_13 is listed as registered +# Then the validator node VAL_14 is listed as registered +# +# Then the validator node VAL_1 switches to epoch 3 +# Then the validator node VAL_8 switches to epoch 3 diff --git a/integration_tests/tests/features/epoch_change.feature.ignore b/integration_tests/tests/features/epoch_change.feature.ignore deleted file mode 100644 index 5080b04ef..000000000 --- a/integration_tests/tests/features/epoch_change.feature.ignore +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright 2022 The Tari Project -# SPDX-License-Identifier: BSD-3-Clause - -@epoch_change -Feature: Epoch change - - @serial @current - Scenario: EndEpoch command is used on epoch change - Given fees are disabled - # Initialize a base node, wallet, miner and VN - Given a base node BASE - Given a wallet WALLET connected to base node BASE - Given a miner MINER connected to base node BASE and wallet WALLET - - # Initialize two validator nodes - Given a validator node VAL connected to base node BASE and wallet daemon WALLET_D - Given validator VAL nodes connect to all other validators - - # The wallet must have some funds before the VN sends transactions - When miner MINER mines 6 new blocks - When wallet WALLET has at least 20000 T - - # Create a key for transactions - When I use an account key named K1 - - # VN registration - When validator node VAL sends a registration transaction to base wallet WALLET - When base wallet WALLET registers the template "faucet" - - # Mine them into registered epoch - When miner MINER mines 16 new blocks - Then VAL has scanned to height 19 - Then the validator node VAL is listed as registered - Then the template "faucet" is listed as registered by the validator node VAL - - # Push a transaction through to get blocks - When I call function "mint" on template "faucet" on VAL with args "amount_10000" named "FAUCET" - - When Block count on VN VAL is at least 6 - When miner MINER mines 5 new blocks - Then VAL has scanned to height 24 - Then the validator node VAL switches to epoch 2 - -# @serial -# Scenario: Committee is split into two during epoch change -# Given fees are disabled -# # Initialize a base node, wallet, miner and VN -# Given a base node BASE -# Given a wallet WALLET connected to base node BASE -# Given a miner MINER connected to base node BASE and wallet WALLET - -# # Initialize two validator nodes -# Given a validator node VAL_1 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_2 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_3 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_4 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_5 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_6 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_7 connected to base node BASE and wallet daemon WALLET_D -# Given validator VAL_1 nodes connect to all other validators -# Given validator VAL_2 nodes connect to all other validators -# Given validator VAL_3 nodes connect to all other validators -# Given validator VAL_4 nodes connect to all other validators -# Given validator VAL_5 nodes connect to all other validators -# Given validator VAL_6 nodes connect to all other validators -# Given validator VAL_7 nodes connect to all other validators - -# # The wallet must have some funds before the VN sends transactions -# When miner MINER mines 14 new blocks -# When wallet WALLET has at least 120000 T - -# # VN registration -# When validator node VAL_1 sends a registration transaction to base wallet WALLET -# When validator node VAL_2 sends a registration transaction to base wallet WALLET -# When validator node VAL_3 sends a registration transaction to base wallet WALLET -# When validator node VAL_4 sends a registration transaction to base wallet WALLET -# When validator node VAL_5 sends a registration transaction to base wallet WALLET -# When validator node VAL_6 sends a registration transaction to base wallet WALLET -# When validator node VAL_7 sends a registration transaction to base wallet WALLET - -# # Mine them into registered epoch -# When miner MINER mines 10 new blocks -# Then VAL_1 has scanned to height 21 -# Then the validator node VAL_1 is listed as registered -# Then the validator node VAL_2 is listed as registered -# Then the validator node VAL_3 is listed as registered -# Then the validator node VAL_4 is listed as registered -# Then the validator node VAL_5 is listed as registered -# Then the validator node VAL_6 is listed as registered -# Then the validator node VAL_7 is listed as registered - - -# When Block count on VN VAL_1 is at least 5 - -# Given a validator node VAL_8 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_9 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_10 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_11 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_12 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_13 connected to base node BASE and wallet daemon WALLET_D -# Given a validator node VAL_14 connected to base node BASE and wallet daemon WALLET_D -# Given validator VAL_8 nodes connect to all other validators -# Given validator VAL_9 nodes connect to all other validators -# Given validator VAL_10 nodes connect to all other validators -# Given validator VAL_11 nodes connect to all other validators -# Given validator VAL_12 nodes connect to all other validators -# Given validator VAL_13 nodes connect to all other validators -# Given validator VAL_14 nodes connect to all other validators - -# When validator node VAL_8 sends a registration transaction to base wallet WALLET -# When validator node VAL_9 sends a registration transaction to base wallet WALLET -# When validator node VAL_10 sends a registration transaction to base wallet WALLET -# When validator node VAL_11 sends a registration transaction to base wallet WALLET -# When validator node VAL_12 sends a registration transaction to base wallet WALLET -# When validator node VAL_13 sends a registration transaction to base wallet WALLET -# When validator node VAL_14 sends a registration transaction to base wallet WALLET - -# When miner MINER mines 10 new blocks - -# Then the validator node VAL_8 is listed as registered -# Then the validator node VAL_9 is listed as registered -# Then the validator node VAL_10 is listed as registered -# Then the validator node VAL_11 is listed as registered -# Then the validator node VAL_12 is listed as registered -# Then the validator node VAL_13 is listed as registered -# Then the validator node VAL_14 is listed as registered - -# Then the validator node VAL_1 switches to epoch 3 -# Then the validator node VAL_8 switches to epoch 3 diff --git a/integration_tests/tests/features/fungible.feature b/integration_tests/tests/features/fungible.feature index dd88e432d..67d3dff67 100644 --- a/integration_tests/tests/features/fungible.feature +++ b/integration_tests/tests/features/fungible.feature @@ -1,10 +1,10 @@ # Copyright 2024 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@concurrent @fungible Feature: Fungible tokens - - @serial + Scenario: Mint fungible tokens ##### Setup diff --git a/integration_tests/tests/features/indexer.feature b/integration_tests/tests/features/indexer.feature index d4360f16f..e40a4bccd 100644 --- a/integration_tests/tests/features/indexer.feature +++ b/integration_tests/tests/features/indexer.feature @@ -1,10 +1,10 @@ # Copyright 2024 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@concurrent @indexer Feature: Indexer node - @serial Scenario: Wallet daemon is able to connect to indexer ##### Setup @@ -88,7 +88,6 @@ Feature: Indexer node # Scan the network for the event emitted on ACC creation When indexer IDX scans the network events for account ACC with topics component-created,pay_fee,pay_fee,pay_fee,pay_fee,pay_fee,deposit,component-created,pay_fee,pay_fee,deposit,deposit,deposit,deposit,deposit,deposit - @serial Scenario: Indexer GraphQL requests work # Initialize a base node, wallet, miner and VN Given a base node BASE @@ -99,7 +98,6 @@ Feature: Indexer node # Check GraphQL request Given IDX indexer GraphQL request works - @serial Scenario: Indexer GraphQL requests events over network substate indexing ##### Setup @@ -132,7 +130,6 @@ Feature: Indexer node # Scan the network for the event emitted on ACC_2 creation When indexer IDX scans the network events for account ACC_2 with topics component-created,pay_fee,component-created,pay_fee - @serial Scenario: Indexer GraphQL filtering and pagination of events ##### Setup diff --git a/integration_tests/tests/features/nft.feature b/integration_tests/tests/features/nft.feature index 3aeacbaf5..1fbe8bf36 100644 --- a/integration_tests/tests/features/nft.feature +++ b/integration_tests/tests/features/nft.feature @@ -1,10 +1,10 @@ # Copyright 2024 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@concurrent @nft Feature: NFTs - @serial Scenario: Mint, mutate and burn non fungible tokens ###### Setup @@ -78,7 +78,6 @@ Feature: NFTs sparkle_nft.burn(acc_bucket); ``` - @serial Scenario: Create resource and mint in one transaction ##### Setup diff --git a/integration_tests/tests/features/state_sync.feature b/integration_tests/tests/features/state_sync.feature index 0deb37d03..9c704deb8 100644 --- a/integration_tests/tests/features/state_sync.feature +++ b/integration_tests/tests/features/state_sync.feature @@ -1,9 +1,11 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause + +@concurrent @state_sync Feature: State Sync - @serial @fixed + @fixed Scenario: New validator node registers and syncs # Initialize a base node, wallet, miner and VN Given a base node BASE diff --git a/integration_tests/tests/features/substates.feature.ignore b/integration_tests/tests/features/substates.feature similarity index 54% rename from integration_tests/tests/features/substates.feature.ignore rename to integration_tests/tests/features/substates.feature index f5fa1f4a5..2c9601b15 100644 --- a/integration_tests/tests/features/substates.feature.ignore +++ b/integration_tests/tests/features/substates.feature @@ -1,13 +1,11 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause - # TODO: Ignored, no inputs - replace with wallet daemon calls +@concurrent @substates Feature: Substates - @serial Scenario: Transactions with DOWN local substates are rejected - Given fees are disabled # Initialize a base node, wallet, miner and VN Given a base node BASE Given a wallet WALLET connected to base node BASE @@ -30,21 +28,26 @@ Feature: Substates Then the validator node VAL_1 is listed as registered Then the template "counter" is listed as registered by the validator node VAL_1 - # A file-base CLI account must be created to sign future calls - When I use an account key named K1 + # Initialize indexer and connect wallet daemon + Given an indexer IDX connected to base node BASE + Given a wallet daemon WALLET_D connected to indexer IDX + + # Create account + When I create an account ACC via the wallet daemon WALLET_D with 10000 free coins # Create a new Counter component - When I create a component COUNTER_1 of template "counter" on VAL_1 using "new" + When I call function "new" on template "counter" using account ACC to pay fees via wallet daemon WALLET_D named "COUNTER_1" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER_1/components/Counter the method call "value" the result is "0" - # Increase the counter an check the value - When I invoke on VAL_1 on component COUNTER_1/components/Counter the method call "increase" named "TX1" - When I invoke on VAL_1 on component TX1/components/Counter the method call "value" the result is "1" + # Increase the counter and check the value + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER_1/components/Counter the method call "increase" named "TX1" + When I invoke on wallet daemon WALLET_D on account ACC on component TX1/components/Counter the method call "value" the result is "1" # We should get an error if we se as inputs the same component version thas has already been downed from previous transactions # We can achieve this by reusing inputs from COUNTER_1 instead of the most recent TX1 - When I invoke on VAL_1 on component COUNTER_1/components/Counter the method call "increase" named "TX2" the result is error "Shard was rejected" + When I invoke on wallet daemon WALLET_D on account ACC on component COUNTER_1/components/Counter the method call "increase" named "TX2", I expect it to fail with "Substate .*? is DOWN" # Check that the counter has NOT been increased by the previous erroneous transaction - When I invoke on VAL_1 on component TX1/components/Counter the method call "value" the result is "1" + When I invoke on wallet daemon WALLET_D on account ACC on component TX1/components/Counter the method call "value" the result is "1" diff --git a/integration_tests/tests/features/transfer.feature b/integration_tests/tests/features/transfer.feature index e76a923b6..e24da39c8 100644 --- a/integration_tests/tests/features/transfer.feature +++ b/integration_tests/tests/features/transfer.feature @@ -1,10 +1,10 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@concurrent @transfer Feature: Account transfers - @serial Scenario: Transfer tokens to unexisting account # Initialize a base node, wallet, miner and VN Given a base node BASE @@ -82,7 +82,6 @@ Feature: Account transfers ``` When I print the cucumber world - @serial Scenario: Transfer tokens to existing account # Initialize a base node, wallet, miner and VN Given a base node BASE @@ -158,7 +157,6 @@ Feature: Account transfers ``` When I print the cucumber world - @serial Scenario: Confidential transfer to unexisting account # Initialize a base node, wallet, miner and VN Given a base node BASE diff --git a/integration_tests/tests/features/wallet_daemon.feature b/integration_tests/tests/features/wallet_daemon.feature index dc44d4f5d..cc08fe4d8 100644 --- a/integration_tests/tests/features/wallet_daemon.feature +++ b/integration_tests/tests/features/wallet_daemon.feature @@ -1,10 +1,10 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@concurrent @wallet_daemon Feature: Wallet Daemon - @serial Scenario: Create account and transfer faucets via wallet daemon # Initialize a base node, wallet, miner and VN Given a base node BASE @@ -85,7 +85,6 @@ Feature: Wallet Daemon # TODO: Figure out why this is taking more than 10 seconds to update # When I wait for ACC_2 on wallet daemon WALLET_D to have balance eq 50 - @serial Scenario: Claim and transfer confidential assets via wallet daemon # Initialize a base node, wallet, miner and VN Given a base node BASE @@ -127,8 +126,7 @@ Feature: Wallet Daemon When I check the confidential balance of ACCOUNT_1 on wallet daemon WALLET_D the amount is at least 10000 # When account ACCOUNT_1 reveals 100 burned tokens via wallet daemon WALLET_D Then I make a confidential transfer with amount 5 from ACCOUNT_1 to ACCOUNT_2 creating output OUTPUT_TX1 via the wallet_daemon WALLET_D - - @serial + Scenario: Create and mint account NFT # Initialize a base node, wallet, miner and VN Given a network with registered validator VAL_1 and wallet daemon WALLET_D