Skip to content
Draft
6 changes: 4 additions & 2 deletions .github/workflows/iroha2-dev-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,16 @@ jobs:
run: |
mv ${{ env.WASM_TARGET_DIR }}/libs ${{ env.DEFAULTS_DIR }}/libs
mv ${{ env.DEFAULTS_DIR }}/libs/default_executor.wasm ${{ env.DEFAULTS_DIR }}/executor.wasm
- name: Install irohad
run: which irohad || cargo install --path crates/irohad --locked
- name: Install irohad with no default features
run: cargo install --path crates/irohad --locked --no-default-features
- name: Test with no default features
id: test_no_features
run: >
mold --run cargo llvm-cov nextest
--no-default-features
--branch --no-report
- name: Install irohad with all features
run: cargo install --path crates/irohad --locked --all-features
- name: Test with all features
id: test_all_features
run: >
Expand Down
23 changes: 23 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ iroha_executor_data_model = { version = "=2.0.0-rc.1.0", path = "crates/iroha_ex

iroha_test_network = { version = "=2.0.0-rc.1.0", path = "crates/iroha_test_network" }
iroha_test_samples = { version = "=2.0.0-rc.1.0", path = "crates/iroha_test_samples" }
iroha_tree = { version = "=2.0.0-rc.1.0", path = "crates/iroha_tree" }
iroha_authorizer = { version = "=2.0.0-rc.1.0", path = "crates/iroha_authorizer" }

proc-macro2 = "1.0.86"
syn = { version = "2.0.72", default-features = false }
Expand Down
9 changes: 9 additions & 0 deletions crates/iroha/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ tls-rustls-webpki-roots = [
"tungstenite/rustls-tls-webpki-roots",
]

# Abstract instructions, events, and event filters into a generic structure to simulate possible execution paths.
prediction = []

[dependencies]
iroha_config = { workspace = true }
iroha_config_base = { workspace = true }
Expand Down Expand Up @@ -97,3 +100,9 @@ hex = { workspace = true }
assertables = { workspace = true }
trybuild = { workspace = true }
assert_matches = "1.5.0"
criterion = { workspace = true }

[[bench]]
name = "one_block"
harness = false
path = "benches/one_block.rs"
156 changes: 156 additions & 0 deletions crates/iroha/benches/one_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#![expect(missing_docs)]

use criterion::{criterion_group, criterion_main, Criterion};
use iroha::{
client::Client,
data_model::{parameter::BlockParameter, prelude::*},
};
use iroha_test_network::*;
use iroha_test_samples::{load_sample_wasm, ALICE_ID, BOB_ID};
use nonzero_ext::nonzero;

const N_TRANSACTIONS_PER_BLOCK: u64 = 1;

fn bench(c: &mut Criterion) {
let mut group = c.benchmark_group("one_block");
group.sample_size(10);
group.bench_function("trigger_executable_builtin", |b| {
b.iter_batched(setup_builtin, routine, criterion::BatchSize::SmallInput);
});
group.bench_function("trigger_executable_wasm", |b| {
b.iter_batched(setup_wasm, routine, criterion::BatchSize::SmallInput);
});
group.finish();
}

fn setup_builtin() -> Input {
let rose: AssetDefinitionId = "rose#wonderland".parse().unwrap();
let rose_alice: AssetId = format!("{rose}#{}", ALICE_ID.clone()).parse().unwrap();
let transfer_rose_alice_bob = Transfer::asset_numeric(rose_alice.clone(), 1u32, BOB_ID.clone());
setup(vec![transfer_rose_alice_bob])
}

fn setup_wasm() -> Input {
setup(load_sample_wasm("trigger_transfer_one"))
}

/// Given a test network equipped with a trigger
fn setup(trigger_executable: impl Into<Executable>) -> Input {
let rose: AssetDefinitionId = "rose#wonderland".parse().unwrap();
let rose_alice: AssetId = format!("{rose}#{}", ALICE_ID.clone()).parse().unwrap();
let rose_bob: AssetId = format!("{rose}#{}", BOB_ID.clone()).parse().unwrap();
let register_trigger = Register::trigger(Trigger::new(
"transfer_one_to_bob_on_mint_roses_at_alice"
.parse()
.unwrap(),
Action::new(
trigger_executable,
Repeats::Indefinitely,
ALICE_ID.clone(),
AssetEventFilter::new()
.for_asset(rose_alice.clone())
.for_events(AssetEventSet::Created),
),
));
let (network, rt) = NetworkBuilder::new()
.with_genesis_instruction(register_trigger)
.with_genesis_instruction(SetParameter::new(Parameter::Block(
BlockParameter::MaxTransactions(nonzero!(N_TRANSACTIONS_PER_BLOCK)),
)))
.start_blocking()
.unwrap();
let mut test_client = network.client();
test_client.add_transaction_nonce = true;
let n0_rose_alice = get_asset_value(&test_client, rose_alice.clone());
let n0_rose_bob = get_asset_value(&test_client, rose_bob.clone());
let mint_rose_alice = Mint::asset_numeric(1u32, rose_alice.clone());

Input {
network,
rt,
test_client,
rose_alice,
rose_bob,
n0_rose_alice,
n0_rose_bob,
mint_rose_alice,
}
}

struct Input {
network: Network,
rt: tokio::runtime::Runtime,
test_client: Client,
rose_alice: AssetId,
rose_bob: AssetId,
n0_rose_alice: Numeric,
n0_rose_bob: Numeric,
mint_rose_alice: Mint<Numeric, Asset>,
}

/// # Scenario
///
/// 0. Transaction: [mint a rose for Alice, mint another rose for Alice]
/// 0. Trigger execution: asset created (some roses for Alice) -> transfer a rose from Alice to Bob
fn routine(
Input {
network: _network,
rt: _rt,
test_client,
rose_alice,
rose_bob,
n0_rose_alice,
n0_rose_bob,
mint_rose_alice,
}: Input,
) {
let mint_twice = [mint_rose_alice.clone(), mint_rose_alice];
#[allow(clippy::reversed_empty_ranges)]
for _ in 1..N_TRANSACTIONS_PER_BLOCK {
// Transaction nonce is enabled in setup, otherwise hashes may collide
test_client
.submit_all(mint_twice.clone())
.expect("transaction should be submitted");
}
test_client
.submit_all_blocking(mint_twice)
.expect("transaction should be committed");
// TODO peer.once_block(2)
assert_eq!(
test_client.get_status().unwrap().blocks,
2,
"Extra blocks created"
);

let n1_rose_alice = get_asset_value(&test_client, rose_alice);
let n1_rose_bob = get_asset_value(&test_client, rose_bob);

// FIXME
// assert_eq!(
// n1_rose_alice,
// n0_rose_alice.checked_add(N_TRANSACTIONS_PER_BLOCK.into()).unwrap()
// );
// assert_eq!(n1_rose_bob, n0_rose_bob.checked_add(N_TRANSACTIONS_PER_BLOCK.into()).unwrap());
assert_eq!(
n1_rose_alice,
n0_rose_alice
.checked_add(Numeric::from(2 * N_TRANSACTIONS_PER_BLOCK))
.unwrap()
);
assert_eq!(n1_rose_bob, n0_rose_bob);
}

fn get_asset_value(client: &Client, asset_id: AssetId) -> Numeric {
let Ok(asset) = client
.query(FindAssets::new())
.filter_with(|asset| asset.id.eq(asset_id))
.execute_single()
else {
return Numeric::ZERO;
};

*asset.value()
}

criterion_group!(benches, bench);
criterion_main!(benches);
2 changes: 2 additions & 0 deletions crates/iroha/tests/events/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use iroha_test_samples::ALICE_ID;
use tokio::{task::spawn_blocking, time::timeout};

#[tokio::test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
async fn trigger_completion_success_should_produce_event() -> Result<()> {
let network = NetworkBuilder::new().start().await?;

Expand Down Expand Up @@ -48,6 +49,7 @@ async fn trigger_completion_success_should_produce_event() -> Result<()> {
}

#[tokio::test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
async fn trigger_completion_failure_should_produce_event() -> Result<()> {
let network = NetworkBuilder::new().start().await?;

Expand Down
1 change: 1 addition & 0 deletions crates/iroha/tests/transfer_domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ fn domain_owner_nft_permissions() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn domain_owner_trigger_permissions() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down
18 changes: 14 additions & 4 deletions crates/iroha/tests/triggers/by_call_trigger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,19 @@ use eyre::{eyre, Result, WrapErr};
use iroha::{
crypto::KeyPair,
data_model::{
prelude::*,
query::{builder::SingleQueryError, error::FindError, trigger::FindTriggers},
transaction::Executable,
},
};
use iroha_executor_data_model::permission::trigger::CanRegisterTrigger;
use iroha_test_network::*;
use iroha_test_samples::{load_sample_wasm, ALICE_ID};
use mint_rose_trigger_data_model::MintRoseArgs;

use crate::triggers::get_asset_value;
use super::*;

const TRIGGER_NAME: &str = "mint_rose";

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn call_execute_trigger() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand All @@ -43,6 +41,7 @@ fn call_execute_trigger() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn execute_trigger_should_produce_event() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -79,6 +78,7 @@ fn execute_trigger_should_produce_event() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn infinite_recursion_should_produce_one_call_per_block() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -109,6 +109,7 @@ fn infinite_recursion_should_produce_one_call_per_block() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -169,6 +170,7 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -234,6 +236,7 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -281,6 +284,7 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn only_account_with_permission_can_register_trigger() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -353,6 +357,7 @@ fn only_account_with_permission_can_register_trigger() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn unregister_trigger() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -412,6 +417,7 @@ fn unregister_trigger() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn trigger_in_genesis() -> Result<()> {
let wasm = load_sample_wasm("mint_rose_trigger");
let account_id = ALICE_ID.clone();
Expand Down Expand Up @@ -457,6 +463,7 @@ fn trigger_in_genesis() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -517,6 +524,7 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn trigger_burn_repetitions() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down Expand Up @@ -552,6 +560,7 @@ fn trigger_burn_repetitions() -> Result<()> {
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn unregistering_one_of_two_triggers_with_identical_wasm_should_not_cause_original_wasm_loss(
) -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
Expand Down Expand Up @@ -614,6 +623,7 @@ fn build_register_trigger_isi(
}

#[test]
#[cfg_attr(feature = "prediction", ignore = "depends on deprecated event types")]
fn call_execute_trigger_with_args() -> Result<()> {
let (network, _rt) = NetworkBuilder::new().start_blocking()?;
let test_client = network.client();
Expand Down
Loading
Loading