diff --git a/.github/workflows/iroha2-dev-pr.yml b/.github/workflows/iroha2-dev-pr.yml index 005fab2c68d..32436a5b0ed 100644 --- a/.github/workflows/iroha2-dev-pr.yml +++ b/.github/workflows/iroha2-dev-pr.yml @@ -19,6 +19,7 @@ env: CARGO_TERM_COLOR: always IROHA_CLI_DIR: "/__w/${{ github.event.repository.name }}/${{ github.event.repository.name }}/test" DOCKER_COMPOSE_PATH: defaults + WASM_SAMPLES_TARGET_DIR: wasm_samples/target/prebuilt jobs: consistency: @@ -60,16 +61,22 @@ jobs: name: report-clippy path: clippy.json - build_executor: + build_wasm_samples: runs-on: ubuntu-latest container: image: hyperledger/iroha2-ci:nightly-2024-09-09 timeout-minutes: 30 steps: - uses: actions/checkout@v4 - - name: Build iroha executor - run: mold --run cargo run --bin iroha_wasm_builder -- build ./wasm_samples/default_executor --optimize --out-file ${{ env.DOCKER_COMPOSE_PATH }}/executor.wasm - - name: Upload executor to reuse in other jobs + - name: Build + run: ./scripts/build_wasm_samples.sh + - name: Upload all built WASMs + uses: actions/upload-artifact@v4 + with: + name: wasm_samples + path: ${{ env.WASM_SAMPLES_TARGET_DIR }} + retention-days: 1 + - name: Upload executor.wasm specifically uses: actions/upload-artifact@v4 with: name: executor.wasm @@ -80,7 +87,7 @@ jobs: runs-on: [self-hosted, Linux, iroha2] container: image: hyperledger/iroha2-ci:nightly-2024-09-09 - needs: build_executor + needs: build_wasm_samples env: LLVM_PROFILE_FILE_NAME: "iroha-%p-%m.profraw" steps: @@ -122,7 +129,7 @@ jobs: runs-on: [self-hosted, Linux, iroha2] container: image: hyperledger/iroha2-ci:nightly-2024-09-09 - needs: build_executor + needs: build_wasm_samples timeout-minutes: 30 steps: - uses: actions/checkout@v4 @@ -131,6 +138,11 @@ jobs: with: name: executor.wasm path: ${{ env.DOCKER_COMPOSE_PATH }} + - name: Download the rest of WASM samples + uses: actions/download-artifact@v4 + with: + name: wasm_samples + path: ${{ env.WASM_SAMPLES_TARGET_DIR }} - uses: taiki-e/install-action@nextest - name: Run integration tests, with all features run: > @@ -145,7 +157,7 @@ jobs: runs-on: [self-hosted, Linux, iroha2] container: image: hyperledger/iroha2-ci:nightly-2024-09-09 - needs: build_executor + needs: build_wasm_samples timeout-minutes: 60 steps: - uses: actions/checkout@v4 @@ -154,6 +166,11 @@ jobs: with: name: executor.wasm path: ${{ env.DOCKER_COMPOSE_PATH }} + - name: Download the rest of WASM samples + uses: actions/download-artifact@v4 + with: + name: wasm_samples + path: ${{ env.WASM_SAMPLES_TARGET_DIR }} - uses: taiki-e/install-action@nextest - name: Run integration tests, with all features run: > @@ -198,7 +215,7 @@ jobs: context: . docker-compose-and-pytests: - needs: build_executor + needs: build_wasm_samples runs-on: [self-hosted, Linux, iroha2] timeout-minutes: 60 env: diff --git a/.gitignore b/.gitignore index 4fc48324b89..f4baa3a1eac 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,5 @@ result /test/ /iroha-java/ /lcov.info -**/test-smartcontracts/ test_docker **/*.wasm diff --git a/Cargo.lock b/Cargo.lock index 8769064b75a..e1bf320f267 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2906,7 +2906,6 @@ dependencies = [ "iroha_test_samples", "iroha_torii_const", "iroha_version", - "iroha_wasm_builder", "irohad", "nonzero_ext", "parity-scale-codec", diff --git a/crates/iroha/Cargo.toml b/crates/iroha/Cargo.toml index c3d8adcc10b..6270392be37 100644 --- a/crates/iroha/Cargo.toml +++ b/crates/iroha/Cargo.toml @@ -88,7 +88,6 @@ nonzero_ext = { workspace = true } # Hopefully, once the integration tests migration is finished these can be removed irohad = { workspace = true } -iroha_wasm_builder = { workspace = true } iroha_genesis = { workspace = true } iroha_test_network = { workspace = true } executor_custom_data_model = { version = "=2.0.0-rc.1.0", path = "../../wasm_samples/executor_custom_data_model" } diff --git a/crates/iroha/benches/torii.rs b/crates/iroha/benches/torii.rs index a9e5ded3523..68b285ad0b4 100644 --- a/crates/iroha/benches/torii.rs +++ b/crates/iroha/benches/torii.rs @@ -9,10 +9,8 @@ use iroha::{ }; use iroha_genesis::GenesisBuilder; use iroha_primitives::unique_vec; -use iroha_test_network::{ - construct_executor, get_chain_id, get_key_pair, Peer as TestPeer, PeerBuilder, TestRuntime, -}; -use iroha_test_samples::gen_account_in; +use iroha_test_network::{get_chain_id, get_key_pair, Peer as TestPeer, PeerBuilder, TestRuntime}; +use iroha_test_samples::{gen_account_in, load_sample_wasm}; use irohad::samples::get_config; use tokio::runtime::Runtime; @@ -31,8 +29,7 @@ fn query_requests(criterion: &mut Criterion) { ); let rt = Runtime::test(); - let executor = construct_executor("../../wasm_samples/default_executor") - .expect("Failed to construct executor"); + let executor = Executor::new(load_sample_wasm("default_executor")); let topology = vec![peer.id.clone()]; let genesis = GenesisBuilder::default() .domain("wonderland".parse().expect("Valid")) @@ -133,8 +130,7 @@ fn instruction_submits(criterion: &mut Criterion) { get_key_pair(iroha_test_network::Signatory::Peer), genesis_key_pair.public_key(), ); - let executor = construct_executor("../../wasm_samples/default_executor") - .expect("Failed to construct executor"); + let executor = Executor::new(load_sample_wasm("default_executor")); let genesis = GenesisBuilder::default() .domain("wonderland".parse().expect("Valid")) .account(configuration.common.key_pair.public_key().clone()) diff --git a/crates/iroha/examples/million_accounts_genesis.rs b/crates/iroha/examples/million_accounts_genesis.rs index 6fe2e5e5b63..aa50d6ab98a 100644 --- a/crates/iroha/examples/million_accounts_genesis.rs +++ b/crates/iroha/examples/million_accounts_genesis.rs @@ -8,9 +8,10 @@ use iroha::{ use iroha_genesis::{GenesisBlock, GenesisBuilder}; use iroha_primitives::unique_vec; use iroha_test_network::{ - construct_executor, get_chain_id, get_key_pair, wait_for_genesis_committed, Peer as TestPeer, - PeerBuilder, TestRuntime, + get_chain_id, get_key_pair, wait_for_genesis_committed, Peer as TestPeer, PeerBuilder, + TestRuntime, }; +use iroha_test_samples::load_sample_wasm; use irohad::samples::get_config; use tokio::runtime::Runtime; @@ -36,8 +37,7 @@ fn generate_genesis( .finish_domain(); } - let executor = construct_executor("../../wasm_samples/default_executor") - .expect("Failed to construct executor"); + let executor = Executor::new(load_sample_wasm("default_executor")); builder.build_and_sign(chain_id, executor, topology, genesis_key_pair) } diff --git a/crates/iroha/examples/register_1000_triggers.rs b/crates/iroha/examples/register_1000_triggers.rs index c54a9df41c8..63954526fc1 100644 --- a/crates/iroha/examples/register_1000_triggers.rs +++ b/crates/iroha/examples/register_1000_triggers.rs @@ -12,10 +12,10 @@ use iroha_data_model::parameter::{Parameter, SmartContractParameter}; use iroha_genesis::{GenesisBlock, GenesisBuilder}; use iroha_primitives::unique_vec; use iroha_test_network::{ - construct_executor, get_chain_id, get_key_pair, 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 iroha_test_samples::gen_account_in; +use iroha_test_samples::{gen_account_in, load_sample_wasm}; use irohad::samples::get_config; use tokio::runtime::Runtime; @@ -33,19 +33,13 @@ fn generate_genesis( SmartContractParameter::Memory(NonZeroU64::MAX), ))); - let wasm = iroha_wasm_builder::Builder::new("wasm_samples/mint_rose_trigger") - .show_output() - .build()? - .optimize()? - .into_bytes()?; - let wasm = WasmSmartContract::from_compiled(wasm); let (account_id, _account_keypair) = gen_account_in("wonderland"); let build_trigger = |trigger_id: TriggerId| { Trigger::new( trigger_id.clone(), Action::new( - wasm.clone(), + load_sample_wasm("mint_rose_trigger"), Repeats::Indefinitely, account_id.clone(), ExecuteTriggerEventFilter::new() @@ -63,8 +57,7 @@ fn generate_genesis( }) .fold(builder, GenesisBuilder::append_instruction); - let executor = construct_executor("../../wasm_samples/default_executor") - .expect("Failed to construct executor"); + let executor = Executor::new(load_sample_wasm("default_executor")); Ok(builder.build_and_sign(chain_id, executor, topology, genesis_key_pair)) } diff --git a/crates/iroha/tests/integration/multisig.rs b/crates/iroha/tests/integration/multisig.rs index 55e61bbec36..1a531107dc2 100644 --- a/crates/iroha/tests/integration/multisig.rs +++ b/crates/iroha/tests/integration/multisig.rs @@ -9,13 +9,13 @@ use iroha::{ parameter::SmartContractParameter, prelude::*, query::{builder::SingleQueryError, trigger::FindTriggers}, - transaction::{TransactionBuilder, WasmSmartContract}, + transaction::TransactionBuilder, }, }; use iroha_data_model::asset::{AssetDefinition, AssetDefinitionId}; use iroha_executor_data_model::permission::asset_definition::CanRegisterAssetDefinition; use iroha_test_network::*; -use iroha_test_samples::{gen_account_in, ALICE_ID}; +use iroha_test_samples::{gen_account_in, load_sample_wasm, ALICE_ID}; use nonzero_ext::nonzero; #[test] @@ -36,17 +36,10 @@ fn mutlisig() -> Result<()> { let account_id = ALICE_ID.clone(); let multisig_register_trigger_id = "multisig_register".parse::()?; - let wasm = iroha_wasm_builder::Builder::new("../../wasm_samples/multisig_register") - .show_output() - .build()? - .optimize()? - .into_bytes()?; - let wasm = WasmSmartContract::from_compiled(wasm); - let trigger = Trigger::new( multisig_register_trigger_id.clone(), Action::new( - wasm, + load_sample_wasm("multisig_register"), Repeats::Indefinitely, account_id.clone(), ExecuteTriggerEventFilter::new().for_trigger(multisig_register_trigger_id.clone()), diff --git a/crates/iroha/tests/integration/queries/smart_contract.rs b/crates/iroha/tests/integration/queries/smart_contract.rs index a00001a9142..f3435977f3a 100644 --- a/crates/iroha/tests/integration/queries/smart_contract.rs +++ b/crates/iroha/tests/integration/queries/smart_contract.rs @@ -4,20 +4,17 @@ use iroha::{ data_model::{prelude::*, query::error::QueryExecutionFail}, }; use iroha_test_network::*; +use iroha_test_samples::load_sample_wasm; #[test] fn live_query_is_dropped_after_smart_contract_end() -> Result<()> { let (_rt, _peer, client) = ::new().with_port(11_140).start_with_runtime(); wait_for_genesis_committed(&[client.clone()], 0); - let wasm = iroha_wasm_builder::Builder::new("../../wasm_samples/query_assets_and_save_cursor") - .show_output() - .build()? - .optimize()? - .into_bytes()?; - - let transaction = - client.build_transaction(WasmSmartContract::from_compiled(wasm), Metadata::default()); + let transaction = client.build_transaction( + load_sample_wasm("query_assets_and_save_cursor"), + Metadata::default(), + ); client.submit_transaction_blocking(&transaction)?; let metadata_value: JsonString = client.query_single(FindAccountMetadata::new( @@ -44,15 +41,10 @@ fn smart_contract_can_filter_queries() -> Result<()> { let (_rt, _peer, client) = ::new().with_port(11_260).start_with_runtime(); wait_for_genesis_committed(&[client.clone()], 0); - let wasm = - iroha_wasm_builder::Builder::new("../../wasm_samples/smart_contract_can_filter_queries") - .show_output() - .build()? - .optimize()? - .into_bytes()?; - - let transaction = - client.build_transaction(WasmSmartContract::from_compiled(wasm), Metadata::default()); + let transaction = client.build_transaction( + load_sample_wasm("smart_contract_can_filter_queries"), + Metadata::default(), + ); client.submit_transaction_blocking(&transaction)?; Ok(()) diff --git a/crates/iroha/tests/integration/triggers/by_call_trigger.rs b/crates/iroha/tests/integration/triggers/by_call_trigger.rs index 063a96e05eb..a2a9c38376b 100644 --- a/crates/iroha/tests/integration/triggers/by_call_trigger.rs +++ b/crates/iroha/tests/integration/triggers/by_call_trigger.rs @@ -5,18 +5,14 @@ use eyre::{eyre, Result, WrapErr}; use iroha::{ client::{self, Client}, crypto::KeyPair, - data_model::{ - prelude::*, - query::error::FindError, - transaction::{Executable, WasmSmartContract}, - }, + data_model::{prelude::*, query::error::FindError, transaction::Executable}, }; use iroha_data_model::query::{builder::SingleQueryError, trigger::FindTriggers}; use iroha_executor_data_model::permission::trigger::CanRegisterTrigger; use iroha_genesis::GenesisBlock; use iroha_logger::info; use iroha_test_network::{Peer as TestPeer, *}; -use iroha_test_samples::ALICE_ID; +use iroha_test_samples::{load_sample_wasm, ALICE_ID}; use tokio::runtime::Runtime; const TRIGGER_NAME: &str = "mint_rose"; @@ -409,41 +405,16 @@ fn unregister_trigger() -> Result<()> { Ok(()) } -/// Register wasm-trigger in genesis and execute it. -/// -/// Not very representable from end-user point of view. -/// It's the problem of all ours *"integration"* tests that they are not really -/// integration. -/// Here it's easier to use the approach with `GenesisNetwork::test()` function -/// and extra isi insertion instead of a hardcoded genesis config. -/// This allows to not to update the hardcoded genesis every time -/// instructions/genesis API is changing. -/// -/// Despite this simplification this test should really check -/// if we have the ability to pass a base64-encoded WASM trigger in the genesis. #[test] -fn trigger_in_genesis_using_base64() -> Result<()> { - // Building wasm trigger - - info!("Building trigger"); - let wasm = iroha_wasm_builder::Builder::new("../../wasm_samples/mint_rose_trigger") - .show_output() - .build()? - .optimize()? - .into_bytes()?; - - info!("WASM size is {} bytes", wasm.len()); - - let engine = base64::engine::general_purpose::STANDARD; - let wasm_base64 = serde_json::json!(base64::engine::Engine::encode(&engine, wasm)).to_string(); +fn trigger_in_genesis() -> Result<()> { + let wasm = load_sample_wasm("mint_rose_trigger"); let account_id = ALICE_ID.clone(); let trigger_id = "genesis_trigger".parse::()?; let trigger = Trigger::new( trigger_id.clone(), Action::new( - serde_json::from_str::(&wasm_base64) - .wrap_err("Can't deserialize wasm using base64")?, + wasm, Repeats::Indefinitely, account_id.clone(), ExecuteTriggerEventFilter::new() @@ -591,18 +562,11 @@ fn unregistering_one_of_two_triggers_with_identical_wasm_should_not_cause_origin let first_trigger_id = "mint_rose_1".parse::()?; let second_trigger_id = "mint_rose_2".parse::()?; - let wasm = iroha_wasm_builder::Builder::new("../../wasm_samples/mint_rose_trigger") - .show_output() - .build()? - .optimize()? - .into_bytes()?; - let wasm = WasmSmartContract::from_compiled(wasm); - let build_trigger = |trigger_id: TriggerId| { Trigger::new( trigger_id.clone(), Action::new( - wasm.clone(), + load_sample_wasm("mint_rose_trigger"), Repeats::Indefinitely, account_id.clone(), ExecuteTriggerEventFilter::new() @@ -675,16 +639,10 @@ fn call_execute_trigger_with_args() -> Result<()> { let prev_value = get_asset_value(&mut test_client, asset_id.clone()); let trigger_id = TRIGGER_NAME.parse::()?; - let wasm = iroha_wasm_builder::Builder::new("../../wasm_samples/mint_rose_trigger_args") - .show_output() - .build()? - .optimize()? - .into_bytes()?; - let wasm = WasmSmartContract::from_compiled(wasm); let trigger = Trigger::new( trigger_id.clone(), Action::new( - wasm, + load_sample_wasm("mint_rose_trigger_args"), Repeats::Indefinitely, account_id.clone(), ExecuteTriggerEventFilter::new() diff --git a/crates/iroha/tests/integration/triggers/time_trigger.rs b/crates/iroha/tests/integration/triggers/time_trigger.rs index d42fafb926a..6a952098dd6 100644 --- a/crates/iroha/tests/integration/triggers/time_trigger.rs +++ b/crates/iroha/tests/integration/triggers/time_trigger.rs @@ -8,13 +8,11 @@ use iroha::{ events::pipeline::{BlockEventFilter, BlockStatus}, parameter::SumeragiParameters, prelude::*, - transaction::WasmSmartContract, Level, }, }; -use iroha_logger::info; use iroha_test_network::*; -use iroha_test_samples::{gen_account_in, ALICE_ID}; +use iroha_test_samples::{gen_account_in, load_sample_wasm, ALICE_ID}; /// Default estimation of consensus duration. pub fn default_consensus_estimation() -> Duration { @@ -219,16 +217,6 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { const TRIGGER_PERIOD: Duration = Duration::from_millis(1000); const EXPECTED_COUNT: u64 = 4; - info!("Building trigger"); - let wasm = - iroha_wasm_builder::Builder::new("../../wasm_samples/create_nft_for_every_user_trigger") - .show_output() - .build()? - .optimize()? - .into_bytes()?; - - info!("WASM size is {} bytes", wasm.len()); - let (_rt, _peer, mut test_client) = ::new().with_port(10_780).start_with_runtime(); wait_for_genesis_committed(&vec![test_client.clone()], 0); @@ -264,7 +252,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { let register_trigger = Register::trigger(Trigger::new( "mint_nft_for_all".parse()?, Action::new( - WasmSmartContract::from_compiled(wasm), + load_sample_wasm("create_nft_for_every_user_trigger"), Repeats::Indefinitely, alice_id.clone(), filter, diff --git a/crates/iroha/tests/integration/upgrade.rs b/crates/iroha/tests/integration/upgrade.rs index 76d32c9bcb3..7a2a4c81ad6 100644 --- a/crates/iroha/tests/integration/upgrade.rs +++ b/crates/iroha/tests/integration/upgrade.rs @@ -1,5 +1,3 @@ -use std::path::Path; - use executor_custom_data_model::permissions::CanControlDomainLives; use eyre::Result; use futures_util::TryStreamExt as _; @@ -11,9 +9,8 @@ use iroha::{ }, }; use iroha_executor_data_model::permission::{domain::CanUnregisterDomain, Permission as _}; -use iroha_logger::info; use iroha_test_network::*; -use iroha_test_samples::{ALICE_ID, BOB_ID}; +use iroha_test_samples::{load_sample_wasm, ALICE_ID, BOB_ID}; use nonzero_ext::nonzero; const ADMIN_PUBLIC_KEY_MULTIHASH: &str = @@ -55,7 +52,7 @@ fn executor_upgrade_should_work() -> Result<()> { .submit_transaction_blocking(&transfer_rose_tx) .expect_err("Should fail"); - upgrade_executor(&client, "../../wasm_samples/executor_with_admin")?; + upgrade_executor(&client, "executor_with_admin")?; // Check that admin can transfer alice's rose now // Creating new transaction instead of cloning, because we need to update it's creation time @@ -95,10 +92,7 @@ fn executor_upgrade_should_run_migration() -> Result<()> { .is_ok_and(|permission| permission == can_unregister_domain) })); - upgrade_executor( - &client, - "../../wasm_samples/executor_with_custom_permission", - )?; + upgrade_executor(&client, "executor_with_custom_permission")?; // Check that `CanUnregisterDomain` doesn't exist let data_model = client.query_single(FindExecutorDataModel)?; @@ -172,7 +166,7 @@ fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { .is_ok_and(|permission| permission == can_unregister_domain) })); - upgrade_executor(&client, "../../wasm_samples/executor_remove_permission")?; + upgrade_executor(&client, "executor_remove_permission")?; // Check that permission doesn't exist assert!(!client @@ -214,10 +208,7 @@ fn executor_custom_instructions_simple() -> Result<()> { let (_rt, _peer, client) = ::new().with_port(11_270).start_with_runtime(); wait_for_genesis_committed(&vec![client.clone()], 0); - upgrade_executor( - &client, - "../../wasm_samples/executor_custom_instructions_simple", - )?; + upgrade_executor(&client, "executor_custom_instructions_simple")?; let asset_definition_id: AssetDefinitionId = "rose#wonderland".parse().unwrap(); @@ -260,10 +251,7 @@ fn executor_custom_instructions_complex() -> Result<()> { nonzero!(1_000_000_000_u64), ))); client.submit_blocking(executor_fuel_limit)?; - upgrade_executor( - &client, - "../../wasm_samples/executor_custom_instructions_complex", - )?; + upgrade_executor(&client, "executor_custom_instructions_complex")?; // Give 6 roses to bob let asset_definition_id: AssetDefinitionId = "rose#wonderland".parse().unwrap(); @@ -333,7 +321,7 @@ fn migration_fail_should_not_cause_any_effects() { "failed_migration_test_domain".parse().expect("Valid"); assert_domain_does_not_exist(&client, &domain_registered_in_migration); - let _err = upgrade_executor(&client, "../../wasm_samples/executor_with_migration_fail") + let _report = upgrade_executor(&client, "executor_with_migration_fail") .expect_err("Upgrade should fail due to migration failure"); // Checking that things registered in migration does not exist after failed migration @@ -365,11 +353,7 @@ fn migration_should_cause_upgrade_event() { } }); - upgrade_executor( - &client, - "../../wasm_samples/executor_with_custom_permission", - ) - .unwrap(); + upgrade_executor(&client, "executor_with_custom_permission").unwrap(); rt.block_on(async { tokio::time::timeout(core::time::Duration::from_secs(60), task) @@ -390,7 +374,7 @@ fn define_custom_parameter() -> Result<()> { let create_domain = Register::domain(Domain::new(long_domain_name)); client.submit_blocking(create_domain)?; - upgrade_executor(&client, "../../wasm_samples/executor_with_custom_parameter").unwrap(); + upgrade_executor(&client, "executor_with_custom_parameter").unwrap(); let too_long_domain_name = "1".repeat(2_usize.pow(5)).parse::()?; let create_domain = Register::domain(Domain::new(too_long_domain_name)); @@ -406,18 +390,8 @@ fn define_custom_parameter() -> Result<()> { Ok(()) } -fn upgrade_executor(client: &Client, executor: impl AsRef) -> Result<()> { - info!("Building executor"); - - let wasm = iroha_wasm_builder::Builder::new(executor.as_ref()) - .show_output() - .build()? - .optimize()? - .into_bytes()?; - - info!("WASM size is {} bytes", wasm.len()); - - let upgrade_executor = Upgrade::new(Executor::new(WasmSmartContract::from_compiled(wasm))); +fn upgrade_executor(client: &Client, executor: impl AsRef) -> Result<()> { + let upgrade_executor = Upgrade::new(Executor::new(load_sample_wasm(executor))); client.submit_blocking(upgrade_executor)?; Ok(()) diff --git a/crates/iroha_test_network/src/lib.rs b/crates/iroha_test_network/src/lib.rs index 7f144779343..5e4c6780243 100644 --- a/crates/iroha_test_network/src/lib.rs +++ b/crates/iroha_test_network/src/lib.rs @@ -850,24 +850,3 @@ impl TestClient for Client { self.poll_with_period(Config::pipeline_time() / 2, 10, f) } } - -/// Construct executor from path. -/// -/// `relative_path` should be relative to `CARGO_MANIFEST_DIR`. -/// -/// # Errors -/// -/// - Failed to create temp dir for executor output -/// - Failed to build executor -/// - Failed to optimize executor -pub fn construct_executor

(relative_path: &P) -> eyre::Result -where - P: AsRef + ?Sized, -{ - let wasm_blob = iroha_wasm_builder::Builder::new(relative_path) - .build()? - .optimize()? - .into_bytes()?; - - Ok(Executor::new(WasmSmartContract::from_compiled(wasm_blob))) -} diff --git a/crates/iroha_test_samples/src/lib.rs b/crates/iroha_test_samples/src/lib.rs index 7a0ea083576..3e2dd3ea1b4 100644 --- a/crates/iroha_test_samples/src/lib.rs +++ b/crates/iroha_test_samples/src/lib.rs @@ -1,8 +1,13 @@ //! Utility crate for standardized and random signatories. -use std::sync::LazyLock; + +use std::{ + io::Read, + path::{Path, PathBuf}, + sync::LazyLock, +}; use iroha_crypto::KeyPair; -use iroha_data_model::prelude::AccountId; +use iroha_data_model::prelude::{AccountId, WasmSmartContract}; /// Generate [`AccountId`](iroha_data_model::account::AccountId) in the given `domain`. /// @@ -83,3 +88,43 @@ declare_account_with_keypair!( "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4", "80262082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD" ); + +fn read_file(path: impl AsRef) -> std::io::Result> { + let mut blob = vec![]; + std::fs::File::open(path.as_ref())?.read_to_end(&mut blob)?; + Ok(blob) +} + +const WASM_SAMPLES_PREBUILT_DIR: &str = "wasm_samples/target/prebuilt"; + +/// Load WASM smart contract from `wasm_samples` by the name of smart contract, +/// e.g. `default_executor`. +/// +/// WASMs must be pre-built with the `build_wasm_samples.sh` script +pub fn load_sample_wasm(name: impl AsRef) -> WasmSmartContract { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../") + .canonicalize() + .expect("invoking from crates/iroha_test_samples, should be fine") + .join(WASM_SAMPLES_PREBUILT_DIR) + .join(name.as_ref()) + .with_extension("wasm"); + + let blob = match read_file(&path) { + Err(err) => { + eprintln!( + "ERROR: Could not load sample WASM `{}` from `{}`: {err}\n \ + There are two possible reasons why:\n \ + 1. You haven't pre-built WASM samples before running tests. Make sure to run `build_wasm_samples.sh` first.\n \ + 2. `{}` is not a valid name. Check the `wasm_samples` directory and make sure you haven't made a mistake.", + name.as_ref(), + path.display(), + name.as_ref() + ); + panic!("could not build WASM, see the message above"); + } + Ok(blob) => blob, + }; + + WasmSmartContract::from_compiled(blob) +} diff --git a/crates/iroha_wasm_builder/src/lib.rs b/crates/iroha_wasm_builder/src/lib.rs index a39bf65336e..0311a05b95a 100644 --- a/crates/iroha_wasm_builder/src/lib.rs +++ b/crates/iroha_wasm_builder/src/lib.rs @@ -158,7 +158,7 @@ impl<'path, 'out_dir> Builder<'path, 'out_dir> { mod internal { //! Internal implementation of [`Builder`](super::Builder). - use std::borrow::Cow; + use std::{borrow::Cow, process::Stdio}; use super::*; @@ -208,6 +208,7 @@ mod internal { let mut command = cargo_command(); command .current_dir(&self.absolute_path) + .stderr(Stdio::inherit()) .arg(cmd) .args(Self::build_options()); @@ -361,17 +362,20 @@ impl Output { // TODO: Remove cargo invocation (#2152) fn cargo_command() -> Command { + const INSTRUMENT_COVERAGE_FLAG: &str = "instrument-coverage"; + for var in ["RUSTFLAGS", "CARGO_ENCODED_RUSTFLAGS"] { + if let Some(value) = env::var(var).ok() { + if value.contains(INSTRUMENT_COVERAGE_FLAG) { + eprintln!("WARNING: found `{INSTRUMENT_COVERAGE_FLAG}` rustc flag in `{var}` environment variable\n \ + This directly interferes with `-Z build-std` flag set by `iroha_wasm_builder`\n \ + See https://github.com/rust-lang/wg-cargo-std-aware/issues/68\n \ + Further execution of `cargo` will most probably fail with `could not find profiler-builtins` error"); + } + } + } + let mut cargo = Command::new("cargo"); - cargo - // Removing environment variable to avoid - // `error: infinite recursion detected` when running `cargo lints` - .env_remove("RUST_RECURSION_COUNT") - // Removing environment variable to avoid - // `error: `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`` - // when running with `-C instrument-coverage` - // TODO: Check if there are no problems with that - .env_remove("CARGO_ENCODED_RUSTFLAGS") - .args([TOOLCHAIN]); + cargo.arg(TOOLCHAIN); cargo } diff --git a/scripts/build_wasm_samples.sh b/scripts/build_wasm_samples.sh new file mode 100755 index 00000000000..18d1d5117c8 --- /dev/null +++ b/scripts/build_wasm_samples.sh @@ -0,0 +1,15 @@ +#!/bin/sh +set -e; +SAMPLES_DIR="wasm_samples" +TARGET_DIR="$SAMPLES_DIR/target/prebuilt" +mkdir -p "$TARGET_DIR" +for dir in $( + cargo metadata --no-deps --manifest-path ./wasm_samples/Cargo.toml --format-version=1 | + jq '.packages | map(select(.targets[].kind | contains(["cdylib"]))) | map(.manifest_path | split("/") | .[-2]) | .[]' -r +); do + out_file="$TARGET_DIR/$dir.wasm" + cargo run --bin iroha_wasm_builder -- build "$SAMPLES_DIR/$dir" --optimize --out-file "$out_file" +done +echo "info: WASM samples build complete" +cp "$TARGET_DIR/default_executor.wasm" ./defaults/executor.wasm +echo "info: copied default executor to ./defaults/executor.wasm" diff --git a/scripts/generate_wasm.sh b/scripts/generate_wasm.sh deleted file mode 100755 index b7fcd2a0a22..00000000000 --- a/scripts/generate_wasm.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# Default source directory -DEFAULT_SOURCE_DIR="wasm_samples" - -# If no arguments are provided, use the default source directory -if [ "$#" -eq 0 ]; then - SOURCE_DIR="$DEFAULT_SOURCE_DIR" -else - SOURCE_DIR="$1" -fi - -TARGET_DIR="test-smartcontracts" - -mkdir -p "$TARGET_DIR" - -for folder in "$SOURCE_DIR"/*; do - if [ -d "$folder" ] && [ "$(basename "$folder")" != ".cargo" ]; then - - folder_name=$(basename "$folder") - target_wasm_file_path="${TARGET_DIR}/${folder_name}.wasm" - # Build the smart contracts - cargo run --bin iroha_wasm_builder -- build "$folder" --optimize --out-file "$target_wasm_file_path" - - fi -done - -echo "Smart contracts build complete." diff --git a/wasm_samples/multisig/Cargo.toml b/wasm_samples/multisig/Cargo.toml index c84fa2d037f..4c53ff63ae7 100644 --- a/wasm_samples/multisig/Cargo.toml +++ b/wasm_samples/multisig/Cargo.toml @@ -20,6 +20,3 @@ getrandom.workspace = true serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true, default-features = false } - -[build-dependencies] -iroha_wasm_builder = { version = "=2.0.0-rc.1.0", path = "../../crates/iroha_wasm_builder" }