diff --git a/.github/workflows/multichain-nightly.yml b/.github/workflows/multichain-nightly.yml new file mode 100644 index 000000000..5830206c3 --- /dev/null +++ b/.github/workflows/multichain-nightly.yml @@ -0,0 +1,111 @@ +name: Nightly Chain Signature Tests + +# The right schedule +on: + schedule: + - cron: "0 3 * * *" # Run once per day at 3:00 am + +jobs: + # Check the date and see if latest commit is within a day. + commited_recently: + runs-on: ubuntu-20.04 + name: Check latest commit + outputs: + should_run: ${{ steps.should_run.outputs.should_run }} + steps: + - uses: actions/checkout@v4 + - name: print latest_commit + run: echo ${{ github.sha }} + - id: should_run + continue-on-error: true + name: Check if the latest commit is within a day + if: ${{ github.event_name == 'schedule' }} + run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false" + + nightly: + strategy: + matrix: + # FIXME: macos-latest-xl is disabled since colima is erroring out right now + os: [warp-ubuntu-latest-x64-4x] + + needs: commited_recently + if: ${{ needs.commited_recently.outputs.should_run != 'false' }} + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + + - name: Install Docker + if: ${{ matrix.os == 'macos-latest-xl' }} + run: | + brew install docker + colima start + # Colima does not expose the Docker socket by default, we have to symlink it + # https://github.com/abiosoft/colima/blob/main/docs/FAQ.md#cannot-connect-to-the-docker-daemon-at-unixvarrundockersock-is-the-docker-daemon-running + sudo ln -sf $HOME/.colima/default/docker.sock /var/run/docker.sock + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Pull Relayer & Sandbox Docker Images + run: | + docker pull ghcr.io/near/os-relayer:12ba6e35690df3979fce0b36a41d0ca0db9c0ab4 + docker pull ghcr.io/near/near-lake-indexer:node-1.40.0 + docker pull localstack/localstack:3.5.0 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + target: wasm32-unknown-unknown + + - uses: WarpBuilds/cache@v1 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: "${{ runner.os }}-cargo-${{ hashFiles('chain-signatures/Cargo.lock') }}" + restore-keys: ${{ runner.os }}-cargo- + + - name: Install Protoc + uses: arduino/setup-protoc@v1.1.2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install toxiproxy-server + run: | + wget -O toxiproxy-2.9.0_linux_amd64.deb https://github.com/Shopify/toxiproxy/releases/download/v2.9.0/toxiproxy_2.9.0_linux_amd64.deb + sudo dpkg -i toxiproxy-2.9.0_linux_amd64.deb + + - name: Configure AWS + run: | + # Fake AWS configuration for LocalStack + aws configure set region us-east-1 + aws --profile default configure set aws_access_key_id "123" + aws --profile default configure set aws_secret_access_key "456" + + - name: Build Chain-Signatures Contract + working-directory: ./chain-signatures + run: cargo build -p mpc-contract --target wasm32-unknown-unknown --release + + - name: Build Chain-Signatures Node + working-directory: ./chain-signatures + run: cargo build -p mpc-recovery-node --release + + - name: Build Chain-Signatures Integration Tests + working-directory: ./integration-tests/chain-signatures + run: cargo build --tests + + - name: Run Nightly + working-directory: ./integration-tests/chain-signatures + run: cargo test --package integration-tests-chain-signatures --test lib -- cases::nightly --show-output --ignored + env: + RUST_LOG: info,workspaces=warn + RUST_BACKTRACE: 1 diff --git a/integration-tests/chain-signatures/tests/cases/mod.rs b/integration-tests/chain-signatures/tests/cases/mod.rs index d3a46a1f1..67b597de1 100644 --- a/integration-tests/chain-signatures/tests/cases/mod.rs +++ b/integration-tests/chain-signatures/tests/cases/mod.rs @@ -8,13 +8,13 @@ use integration_tests_chain_signatures::containers::{self, DockerClient}; use integration_tests_chain_signatures::MultichainConfig; use k256::elliptic_curve::point::AffineCoordinates; use mpc_recovery_node::kdf::into_eth_sig; -use mpc_recovery_node::protocol::presignature::PresignatureConfig; -use mpc_recovery_node::protocol::triple::TripleConfig; use mpc_recovery_node::test_utils; use mpc_recovery_node::types::LatestBlockHeight; use mpc_recovery_node::util::NearPublicKeyExt; use test_log::test; +pub mod nightly; + #[test(tokio::test)] async fn test_multichain_reshare() -> anyhow::Result<()> { let config = MultichainConfig::default(); @@ -103,55 +103,6 @@ async fn test_signature_offline_node() -> anyhow::Result<()> { .await } -#[test(tokio::test)] -#[ignore = "This test is too slow to run in CI"] -async fn test_signature_large_stockpile() -> anyhow::Result<()> { - const SIGNATURE_AMOUNT: usize = 10; - const NODES: usize = 8; - const THRESHOLD: usize = 4; - const MIN_TRIPLES: usize = 10; - const MAX_TRIPLES: usize = 2 * NODES * MIN_TRIPLES; - - let triple_cfg = TripleConfig { - // This is the min triples required by each node. - min_triples: MIN_TRIPLES, - // This is the total amount of triples that will be generated by all nodes. - max_triples: MAX_TRIPLES, - // This is the amount each node can introduce a triple generation protocol into the system. - max_concurrent_introduction: 4, - // This is the maximum amount of triples that can be generated concurrently by the whole system. - max_concurrent_generation: 24, - }; - let presig_cfg = PresignatureConfig { - // this is the min presignatures required by each node - min_presignatures: 10, - // This is the total amount of presignatures that will be generated by all nodes. - max_presignatures: 1000, - }; - - let config = MultichainConfig { - triple_cfg, - presig_cfg, - nodes: NODES, - threshold: THRESHOLD, - }; - - with_multichain_nodes(config, |ctx| { - Box::pin(async move { - let state_0 = wait_for::running_mpc(&ctx, Some(0)).await?; - assert_eq!(state_0.participants.len(), NODES); - wait_for::has_at_least_triples(&ctx, triple_cfg.min_triples).await?; - wait_for::has_at_least_presignatures(&ctx, SIGNATURE_AMOUNT).await?; - - for _ in 0..SIGNATURE_AMOUNT { - actions::single_signature_production(&ctx, &state_0).await?; - } - Ok(()) - }) - }) - .await -} - #[test(tokio::test)] async fn test_key_derivation() -> anyhow::Result<()> { with_multichain_nodes(MultichainConfig::default(), |ctx| { diff --git a/integration-tests/chain-signatures/tests/cases/nightly.rs b/integration-tests/chain-signatures/tests/cases/nightly.rs new file mode 100644 index 000000000..568f0239c --- /dev/null +++ b/integration-tests/chain-signatures/tests/cases/nightly.rs @@ -0,0 +1,68 @@ +use integration_tests_chain_signatures::MultichainConfig; +use mpc_recovery_node::protocol::presignature::PresignatureConfig; +use mpc_recovery_node::protocol::triple::TripleConfig; +use test_log::test; + +use crate::actions::{self, wait_for}; +use crate::with_multichain_nodes; + +#[test(tokio::test)] +#[ignore = "This is triggered by the nightly Github Actions pipeline"] +async fn test_nightly_signature_production() -> anyhow::Result<()> { + const SIGNATURE_AMOUNT: usize = 1000; + const NODES: usize = 8; + const THRESHOLD: usize = 4; + const MIN_TRIPLES: usize = 10; + const MAX_TRIPLES: usize = 2 * NODES * MIN_TRIPLES; + + let triple_cfg = TripleConfig { + // This is the min triples required by each node. + min_triples: MIN_TRIPLES, + // This is the total amount of triples that will be generated by all nodes. + max_triples: MAX_TRIPLES, + // This is the amount each node can introduce a triple generation protocol into the system. + max_concurrent_introduction: 4, + // This is the maximum amount of triples that can be generated concurrently by the whole system. + max_concurrent_generation: 24, + }; + let presig_cfg = PresignatureConfig { + // this is the min presignatures required by each node + min_presignatures: 10, + // This is the total amount of presignatures that will be generated by all nodes. + max_presignatures: 1000, + }; + + let config = MultichainConfig { + triple_cfg, + presig_cfg, + nodes: NODES, + threshold: THRESHOLD, + }; + + with_multichain_nodes(config, |ctx| { + Box::pin(async move { + let state_0 = wait_for::running_mpc(&ctx, Some(0)).await?; + assert_eq!(state_0.participants.len(), NODES); + + for i in 0..SIGNATURE_AMOUNT { + if let Err(err) = wait_for::has_at_least_mine_triples(&ctx, 4).await { + tracing::error!(?err, "Failed to wait for triples"); + continue; + } + + if let Err(err) = wait_for::has_at_least_mine_presignatures(&ctx, 2).await { + tracing::error!(?err, "Failed to wait for presignatures"); + continue; + } + + tracing::info!(at_signature = i, "Producing signature..."); + if let Err(err) = actions::single_signature_production(&ctx, &state_0).await { + tracing::error!(?err, "Failed to produce signature"); + } + } + + Ok(()) + }) + }) + .await +}