From 2a0381789368235d81177628aeab2f1694afc7c1 Mon Sep 17 00:00:00 2001 From: Clara van Staden Date: Wed, 9 Oct 2024 15:34:30 +0200 Subject: [PATCH] Daily Smoketests (#1287) * test smoketests * remove dir * check dirs * fix * fix * fix * fix * check * create dir * test * remove dir * cleanup * remove polkadot-sdk checkout * run start-services * add rust-src * test on Snowfork branch * complete e2e services test * remove extra sh * change to stable branch * bump * see whats cookin * adds dir * test * run tests * print out env * whoops * check var * see whats up * add things back * remove 0x from contract address * fix test * cleanup * remove comment * fix penpal * fix printed messages * revert cron time and switch to main branch --- .github/workflows/smoke-tests.yml | 80 +++++++++++++++++ scripts/init-smoketests.sh | 37 ++++++++ smoketest/Cargo.lock | 1 + smoketest/Cargo.toml | 2 +- smoketest/src/constants.rs | 4 +- smoketest/tests/send_token_to_penpal.rs | 115 ++++++++++++++++++++++-- 6 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/smoke-tests.yml create mode 100755 scripts/init-smoketests.sh diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml new file mode 100644 index 0000000000..0634950438 --- /dev/null +++ b/.github/workflows/smoke-tests.yml @@ -0,0 +1,80 @@ +name: bridge + +on: + push: + branches: + - main + workflow_dispatch: + schedule: + # Runs at 8:00 AM every day + - cron: '0 8 * * *' + +jobs: + smoketests: + runs-on: snowbridge-runner + env: + CARGO_INCREMENTAL: 0 + RUST_BACKTRACE: 1 + RUSTFLAGS: -C debuginfo=1 + outputs: + success: ${{ steps.run_e2e_stack.outcome == 'success' }} + steps: + - uses: actions/checkout@v2 + with: + repository: snowfork/snowbridge + ref: main + - run: rm -rf polkadot-sdk + - uses: actions/checkout@v2 + with: + repository: paritytech/polkadot-sdk + ref: stable2409 + path: ./polkadot-sdk + - uses: arduino/setup-protoc@v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Set build directory environment variable + run: echo "OUTPUT_DIR=${GITHUB_WORKSPACE}/tmp" >> $GITHUB_ENV + - name: Set log directory environment variable + run: echo "LOG_DIR=${GITHUB_WORKSPACE}/log-tmp" >> $GITHUB_ENV + - name: polkadot-sdk dir + run: echo "POLKADOT_SDK_DIR=./polkadot-sdk" >> $GITHUB_ENV + - name: Create directories + run: mkdir -p $OUTPUT_DIR && mkdir -p $LOG_DIR + - uses: actions/cache@v1 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + - uses: cachix/install-nix-action@v22 + with: + github_access_token: ${{ secrets.GITHUB_TOKEN }} + - name: run E2E stack + id: run_e2e_stack + run: | + nix develop -c sh -c ' + ./scripts/init-smoketests.sh && + cd web/packages/test && + (./scripts/start-services.sh > "${{ env.LOG_DIR }}/start-services.log" 2>&1 &) && + sleep 10 && + ./scripts/check-relayer.sh && + ./scripts/run-smoketests.sh' + continue-on-error: true + - name: Save start-services log file + uses: actions/upload-artifact@v3 + with: + name: start-services.log + path: "${{ env.LOG_DIR }}/start-services.log" + - name: Save beacon-relay log file + uses: actions/upload-artifact@v3 + with: + name: beacon-relay.log + path: "${{ env.OUTPUT_DIR }}/beacon-relay.log" + - run: ls + - name: check E2E test outcome + if: ${{ steps.run_e2e_stack.outcome != 'success' }} + run: | + echo "E2E tests failed" + exit 1 diff --git a/scripts/init-smoketests.sh b/scripts/init-smoketests.sh new file mode 100755 index 0000000000..c3f2c6514c --- /dev/null +++ b/scripts/init-smoketests.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -eux + +echo "Checkout lodestar" +pushd .. + if [ ! -d "lodestar" ]; then + git clone https://github.com/ChainSafe/lodestar + fi + if [ ! -L "snowbridge/lodestar" ]; then + (cd snowbridge && ln -sf ../lodestar lodestar) + fi + pushd lodestar + git fetch && git checkout $LODESTAR_VERSION + popd +popd + +echo "Setting up git hooks" +git config --local core.hooksPath hooks/ + +echo "Installing Rust nightly toolchain" +rustup default stable +rustup target add wasm32-unknown-unknown +rustup component add rust-src +rustup install --profile minimal $RUST_NIGHTLY_VERSION +rustup component add --toolchain $RUST_NIGHTLY_VERSION rustfmt +rustup show + +echo "Installing sszgen" +go install github.com/ferranbt/fastssz/sszgen@v0.1.3 + +echo "Installing cargo fuzz" +cargo install cargo-fuzz + +echo "Installing web packages" +(cd web && pnpm install) + diff --git a/smoketest/Cargo.lock b/smoketest/Cargo.lock index 6223b9ff8a..94325032e6 100644 --- a/smoketest/Cargo.lock +++ b/smoketest/Cargo.lock @@ -5039,6 +5039,7 @@ dependencies = [ "lazy_static", "parity-scale-codec", "serde", + "sp-crypto-hashing", "subxt", "subxt-codegen", "subxt-macro", diff --git a/smoketest/Cargo.toml b/smoketest/Cargo.toml index 965d732068..34d87e4842 100644 --- a/smoketest/Cargo.toml +++ b/smoketest/Cargo.toml @@ -19,4 +19,4 @@ subxt-codegen = { version = "0.37.0" } subxt-signer = { version = "0.37.0" } ethers = { git = "https://github.com/gakonst/ethers-rs", default-features = false, features = ["abigen", "ws", "rustls"] } lazy_static = "1.4.0" - +sp-crypto-hashing = "0.1.0" diff --git a/smoketest/src/constants.rs b/smoketest/src/constants.rs index c65b7228f5..ccd251270b 100644 --- a/smoketest/src/constants.rs +++ b/smoketest/src/constants.rs @@ -53,6 +53,8 @@ pub const PENPAL_SOVEREIGN: [u8; 32] = lazy_static! { // SS58: 5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL + pub static ref ALICE: Pair = Pair::from_string("//Alice", None) + .expect("cannot create keypair"); pub static ref FERDIE: Pair = Pair::from_string("//Ferdie", None) .expect("cannot create keypair"); pub static ref FERDIE_PUBLIC: [u8; 32] = (*FERDIE).public().into(); @@ -139,7 +141,7 @@ lazy_static! { }; pub static ref GATEWAY_PROXY_CONTRACT: [u8; 20] = { if let Ok(val) = env::var("GATEWAY_PROXY_CONTRACT") { - <[u8; 20]>::from_hex(val).unwrap() + <[u8; 20]>::from_hex(val.strip_prefix("0x").unwrap_or(&val)).unwrap() } else { DEFAULT_GATEWAY_PROXY_CONTRACT diff --git a/smoketest/tests/send_token_to_penpal.rs b/smoketest/tests/send_token_to_penpal.rs index d278cb56df..418831d3b5 100644 --- a/smoketest/tests/send_token_to_penpal.rs +++ b/smoketest/tests/send_token_to_penpal.rs @@ -15,7 +15,7 @@ use snowbridge_smoketest::{ Junction::{AccountKey20, GlobalConsensus}, NetworkId, }, - junctions::Junctions::X2, + junctions::Junctions::{Here, X2}, location::Location, }, }, @@ -29,6 +29,11 @@ use subxt::{ utils::{AccountId32, MultiAddress}, OnlineClient, }; +use sp_crypto_hashing::twox_128; +use penpal::{api::runtime_types as penpalTypes}; +use penpalTypes::{ + penpal_runtime::RuntimeCall as PenpalRuntimeCall, +}; #[tokio::test] async fn send_token_to_penpal() { @@ -50,7 +55,9 @@ async fn send_token_to_penpal() { let receipt = weth.deposit().value(value).send().await.unwrap().await.unwrap().unwrap(); assert_eq!(receipt.status.unwrap().as_u64(), 1u64); + set_reserve_asset_storage(&mut penpal_client.clone()).await; ensure_penpal_asset_exists(&mut penpal_client.clone()).await; + ensure_dot_asset_exists(&mut penpal_client.clone()).await; // Approve token spend weth.approve(gateway_addr, value.into()) @@ -99,6 +106,10 @@ async fn send_token_to_penpal() { .expect("block subscription") .take(wait_for_blocks); + let expected_dot_id = Location { + parents: 1, + interior: Here, + }; let expected_asset_id = Location { parents: 2, interior: X2([ @@ -137,23 +148,33 @@ async fn send_token_to_penpal() { let penpal_expected_owner: AccountId32 = (*FERDIE_PUBLIC).into(); issued_event_found = false; + let mut issued_fee_event_found = false; while let Some(Ok(block)) = penpal_blocks.next().await { println!("Polling penpal block {} for issued event.", block.number()); let events = block.events().await.unwrap(); for issued in events.find::() { - println!("Created event found in penpal block {}.", block.number()); let issued = issued.unwrap(); - assert_eq!(issued.asset_id.encode(), expected_asset_id.encode()); - assert_eq!(issued.owner, penpal_expected_owner); - assert_eq!(issued.amount, amount); - issued_event_found = true; + // DOT fee deposited + if issued.asset_id.encode() == expected_dot_id.encode() { + println!("Issued DOT event found in penpal block {}.", block.number()); + assert_eq!(issued.owner, penpal_expected_owner); + issued_fee_event_found = true + } + // Weth deposited + if issued.asset_id.encode() == expected_asset_id.encode() { + println!("Issued Weth event found in penpal block {}.", block.number()); + assert_eq!(issued.owner, penpal_expected_owner); + assert_eq!(issued.amount, amount); + issued_event_found = true; + } } - if issued_event_found { + if issued_event_found && issued_fee_event_found { break } } assert!(issued_event_found); + assert!(issued_fee_event_found); } async fn ensure_penpal_asset_exists(penpal_client: &mut OnlineClient) { @@ -202,3 +223,83 @@ async fn ensure_penpal_asset_exists(penpal_client: &mut OnlineClient) { + use penpal::api::runtime_types::staging_xcm::v4::{ + junctions::Junctions::Here, + location::Location, + }; + let dot_asset_id = Location { + parents: 1, + interior: Here, + }; + + let dot_asset_address = penpal::api::storage().foreign_assets().asset(&dot_asset_id); + let result = penpal_client + .storage() + .at_latest() + .await + .unwrap() + .fetch(&dot_asset_address) + .await + .unwrap(); + + if result.is_some() { + println!("DOT asset exists on penpal."); + return + } + + println!("creating DOT on penpal."); + let admin = MultiAddress::Id(ASSET_HUB_SOVEREIGN.into()); + let signer: PairSigner = PairSigner::new((*FERDIE).clone()); + + let create_asset_call = penpal::api::tx().foreign_assets().create(dot_asset_id, admin, 1); + penpal_client + .tx() + .sign_and_submit_then_watch_default(&create_asset_call, &signer) + .await + .unwrap() + .wait_for_finalized_success() + .await + .expect("asset created"); +} +async fn set_reserve_asset_storage(penpal_client: &mut OnlineClient) { + use penpal::api::runtime_types::staging_xcm::v4::{ + junction::{ + Junction::GlobalConsensus, + NetworkId, + }, + junctions::Junctions::X1, + location::Location, + }; + let storage_key: Vec = twox_128(b":CustomizableAssetFromSystemAssetHub:").to_vec(); + let reserve_location: Vec = Location { + parents: 2, + interior: X1([ + GlobalConsensus(NetworkId::Ethereum { chain_id: ETHEREUM_CHAIN_ID }), + ]), + }.encode(); + + println!("setting CustomizableAssetFromSystemAssetHub storage on penpal."); + let signer: PairSigner = PairSigner::new((*ALICE).clone()); + + let items = vec![( + storage_key, + reserve_location, + )]; + + let sudo_call = penpal::api::sudo::calls::TransactionApi::sudo( + &penpal::api::sudo::calls::TransactionApi, + PenpalRuntimeCall::System(crate::penpalTypes::frame_system::pallet::Call::set_storage { + items + }), + ); + penpal_client + .tx() + .sign_and_submit_then_watch_default(&sudo_call, &signer) + .await + .unwrap() + .wait_for_finalized_success() + .await + .expect("reserve location set"); +}