Skip to content

Commit

Permalink
test: integrations for updating the contract code and config (#807)
Browse files Browse the repository at this point in the history
* Added test for update contract

* Added proposing config

* Fmt
  • Loading branch information
ChaoticTempest authored Aug 8, 2024
1 parent eef0d1b commit d1bfb5f
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
39 changes: 39 additions & 0 deletions integration-tests/chain-signatures/tests/cases/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use crypto_shared::{self, derive_epsilon, derive_key, x_coordinate, ScalarExt};
use integration_tests_chain_signatures::containers::{self, DockerClient};
use integration_tests_chain_signatures::MultichainConfig;
use k256::elliptic_curve::point::AffineCoordinates;
use mpc_contract::config::Config;
use mpc_contract::update::ProposeUpdateArgs;
use mpc_node::kdf::into_eth_sig;
use mpc_node::test_utils;
use mpc_node::types::LatestBlockHeight;
Expand Down Expand Up @@ -353,3 +355,40 @@ async fn test_multichain_reshare_with_lake_congestion() -> anyhow::Result<()> {
})
.await
}

#[test(tokio::test)]
async fn test_multichain_update_contract() -> anyhow::Result<()> {
let config = MultichainConfig::default();
with_multichain_nodes(config.clone(), |ctx| {
Box::pin(async move {
// Get into running state and produce a singular signature.
let state = wait_for::running_mpc(&ctx, Some(0)).await?;
wait_for::has_at_least_mine_triples(&ctx, 2).await?;
wait_for::has_at_least_mine_presignatures(&ctx, 1).await?;
actions::single_payload_signature_production(&ctx, &state).await?;

// Perform update to the contract and see that the nodes are still properly running and picking
// up the new contract by first upgrading the contract, then trying to generate a new signature.
let id = ctx.propose_update_contract_default().await;
ctx.vote_update(id).await;
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
wait_for::has_at_least_mine_presignatures(&ctx, 1).await?;
actions::single_payload_signature_production(&ctx, &state).await?;

// Now do a config update and see if that also updates the same:
let id = ctx
.propose_update(ProposeUpdateArgs {
code: None,
config: Some(Config::default()),
})
.await;
ctx.vote_update(id).await;
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
wait_for::has_at_least_mine_presignatures(&ctx, 1).await?;
actions::single_payload_signature_production(&ctx, &state).await?;

Ok(())
})
})
.await
}
58 changes: 56 additions & 2 deletions integration-tests/chain-signatures/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@ mod actions;
mod cases;

use crate::actions::wait_for;
use mpc_contract::update::{ProposeUpdateArgs, UpdateId};

use anyhow::anyhow;
use futures::future::BoxFuture;
use integration_tests_chain_signatures::containers::DockerClient;
use integration_tests_chain_signatures::utils::{vote_join, vote_leave};
use integration_tests_chain_signatures::{run, utils, MultichainConfig, Nodes};
use near_jsonrpc_client::JsonRpcClient;

use near_workspaces::types::SecretKey;
use near_jsonrpc_client::JsonRpcClient;
use near_workspaces::types::{NearToken, SecretKey};
use near_workspaces::{Account, AccountId};

use integration_tests_chain_signatures::local::NodeConfig;
use std::str::FromStr;

const CURRENT_CONTRACT_DEPLOY_DEPOSIT: NearToken = NearToken::from_millinear(9000);
const CURRENT_CONTRACT_FILE_PATH: &str =
"../../target/wasm32-unknown-unknown/release/mpc_contract.wasm";

pub struct MultichainTestContext<'a> {
nodes: Nodes<'a>,
rpc_client: near_fetch::Client,
Expand Down Expand Up @@ -144,6 +149,55 @@ impl MultichainTestContext<'_> {

Ok(self.nodes.kill_node(leaving_account_id).await.unwrap())
}

pub async fn propose_update(&self, args: ProposeUpdateArgs) -> mpc_contract::update::UpdateId {
let accounts = self.nodes.near_accounts();
accounts[0]
.call(self.nodes.ctx().mpc_contract.id(), "propose_update")
.args_borsh((args,))
.max_gas()
.deposit(CURRENT_CONTRACT_DEPLOY_DEPOSIT)
.transact()
.await
.unwrap()
.json()
.unwrap()
}

pub async fn propose_update_contract_default(&self) -> UpdateId {
let same_contract_bytes = std::fs::read(CURRENT_CONTRACT_FILE_PATH).unwrap();
self.propose_update(ProposeUpdateArgs {
code: Some(same_contract_bytes),
config: None,
})
.await
}

pub async fn vote_update(&self, id: UpdateId) {
let participants = self.participant_accounts().await.unwrap();

let mut success = 0;
for account in participants.iter() {
let execution = account
.call(self.nodes.ctx().mpc_contract.id(), "vote_update")
.args_json((id,))
.max_gas()
.transact()
.await
.unwrap()
.into_result();

match execution {
Ok(_) => success += 1,
Err(e) => tracing::warn!(?id, ?e, "Failed to vote for update"),
}
}

assert!(
success >= self.cfg.threshold,
"did not successfully vote for update"
);
}
}

pub async fn with_multichain_nodes<F>(cfg: MultichainConfig, f: F) -> anyhow::Result<()>
Expand Down

0 comments on commit d1bfb5f

Please sign in to comment.