Skip to content

Commit

Permalink
Merge pull request #655 from near/test-chainsig-main
Browse files Browse the repository at this point in the history
binary to spin up chain signature local cluster
  • Loading branch information
ailisp authored Jun 28, 2024
2 parents e5c91e2 + 87d9432 commit af44bf5
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 29 deletions.
11 changes: 10 additions & 1 deletion integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,24 @@ Now, you can inspect each container's logs according to your needs using `docker

We have a CLI tool that can instantiate a short-lived development environment that has everything except for the leader node set up. You can then seamlessly plug in your own leader node instance that you have set up manually (the tool gives you a CLI command to use as a starting point, but you can attach debugger, enable extra logs etc). Try it out now (sets up 3 signer nodes):

For fastauth:

```bash
$ export RUST_LOG=info
$ cd integration-tests/fastauth
$ cargo run -- setup-env 3
```

For chain signatures:
```bash
$ export RUST_LOG=info
$ cd integration-tests/chain-signatures
$ cargo run -- setup-env --nodes 3 --threshold 2
```

### I'm getting "Error: error trying to connect: No such file or directory (os error 2)"

It's a known issue on MacOS. Try executiong the following command:
It's a known issue on MacOS. Try executing the following command:

```bash
sudo ln -s $HOME/.docker/run/docker.sock /var/run/docker.sock
Expand Down
1 change: 1 addition & 0 deletions integration-tests/chain-signatures/Cargo.lock

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

1 change: 1 addition & 0 deletions integration-tests/chain-signatures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ crypto-shared = { path = "../../chain-signatures/crypto-shared" }
mpc-contract = { path = "../../chain-signatures/contract" }
mpc-keys = { path = "../../chain-signatures/keys" }
mpc-recovery-node = { path = "../../chain-signatures/node" }
clap = { version = "4.5.4", features = ["derive"] }
lazy_static = "1.4.0"

[dev-dependencies]
Expand Down
29 changes: 24 additions & 5 deletions integration-tests/chain-signatures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use testcontainers::{Container, GenericImage};

const NETWORK: &str = "mpc_it_network";

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct MultichainConfig {
pub nodes: usize,
pub threshold: usize,
Expand Down Expand Up @@ -109,10 +109,29 @@ impl Nodes<'_> {
}

pub fn near_accounts(&self) -> Vec<Account> {
self.near_acc_sk()
.iter()
.map(|(account_id, account_sk)| {
Account::from_secret_key(account_id.clone(), account_sk.clone(), &self.ctx().worker)
let acc_sk = self.near_acc_sk();
let mut account_ids = Vec::new();
match self {
Nodes::Local { nodes, .. } => {
for node in nodes {
account_ids.push(node.account_id.clone());
}
}
Nodes::Docker { nodes, .. } => {
for node in nodes {
account_ids.push(node.account_id.clone());
}
}
};

account_ids
.into_iter()
.map(|account_id| {
Account::from_secret_key(
account_id.clone(),
acc_sk.get(&account_id).unwrap().clone(),
&self.ctx().worker,
)
})
.collect()
}
Expand Down
79 changes: 79 additions & 0 deletions integration-tests/chain-signatures/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use clap::Parser;
use integration_tests_chain_signatures::containers::DockerClient;
use integration_tests_chain_signatures::{run, setup, utils, MultichainConfig};
use tokio::signal;
use tracing_subscriber::EnvFilter;

#[derive(Parser, Debug)]
enum Cli {
/// Spin up dependent services and mpc nodes
SetupEnv {
#[arg(short, long, default_value_t = 3)]
nodes: usize,
#[arg(short, long, default_value_t = 2)]
threshold: usize,
},
/// Spin up dependent services but not mpc nodes
DepServices,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let subscriber = tracing_subscriber::fmt()
.with_thread_ids(true)
.with_env_filter(EnvFilter::from_default_env());
subscriber.init();
let docker_client = DockerClient::default();

match Cli::parse() {
Cli::SetupEnv { nodes, threshold } => {
println!(
"Setting up an environment with {} nodes, {} threshold ...",
nodes, threshold
);
let config = MultichainConfig {
nodes,
threshold,
..Default::default()
};
println!("Full config: {:?}", config);
let nodes = run(config.clone(), &docker_client).await?;
let ctx = nodes.ctx();
let urls: Vec<_> = (0..config.nodes).map(|i| nodes.url(i)).collect();
let near_acc_sks = nodes.near_acc_sk();
let near_accounts = nodes.near_accounts();
let sk_local_path = nodes.ctx().storage_options.sk_share_local_path.clone();

println!("\nEnvironment is ready:");
println!(" docker-network: {}", ctx.docker_network);
println!(" release: {}", ctx.release);

println!("\nExternal services:");
println!(" datastore: {}", ctx.datastore.local_address);
println!(" lake_indexer: {}", ctx.lake_indexer.rpc_host_address);

println!("\nNodes:");
for i in 0..urls.len() {
println!(" Node {}", i);
println!(" Url: {}", urls[i]);
let account_id = near_accounts[i].id();
println!(" Account: {}", account_id);
let sk = near_acc_sks.get(account_id).unwrap();
println!(" Secret Key: {}", sk);
let pk = sk.public_key();
println!(" Public Key: {}", pk);
}

signal::ctrl_c().await.expect("Failed to listen for event");
println!("Received Ctrl-C");
utils::clear_local_sk_shares(sk_local_path).await?;
println!("Clean up finished");
}
Cli::DepServices => {
println!("Settting up dependency services");
let _ctx = setup(&docker_client).await?;
}
}

Ok(())
}
20 changes: 20 additions & 0 deletions integration-tests/chain-signatures/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use anyhow::Context;
use hyper::{Body, Client, Method, Request, StatusCode, Uri};
use near_workspaces::result::ExecutionFinalResult;
use near_workspaces::{Account, AccountId};
use std::fs;

pub async fn vote_join(
accounts: Vec<Account>,
Expand Down Expand Up @@ -99,3 +100,22 @@ pub async fn ping_until_ok(addr: &str, timeout: u64) -> anyhow::Result<()> {
.await?;
Ok(())
}

pub async fn clear_local_sk_shares(sk_local_path: Option<String>) -> anyhow::Result<()> {
if let Some(sk_share_local_path) = sk_local_path {
let pattern = format!("{sk_share_local_path}*");
for entry in glob::glob(&pattern).expect("Failed to read glob pattern") {
match entry {
Ok(path) => {
if path.is_file() {
if let Err(e) = fs::remove_file(&path) {
eprintln!("Failed to delete file {:?}: {}", path.display(), e);
}
}
}
Err(e) => eprintln!("{:?}", e),
}
}
}
Ok(())
}
25 changes: 2 additions & 23 deletions integration-tests/chain-signatures/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ use crate::actions::wait_for;

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

use near_workspaces::{Account, AccountId};

use std::fs;
use std::str::FromStr;

pub struct MultichainTestContext<'a> {
Expand Down Expand Up @@ -150,26 +148,7 @@ where
cfg,
})
.await;
clear_local_sk_shares(sk_local_path).await?;
utils::clear_local_sk_shares(sk_local_path).await?;

result
}

pub async fn clear_local_sk_shares(sk_local_path: Option<String>) -> anyhow::Result<()> {
if let Some(sk_share_local_path) = sk_local_path {
let pattern = format!("{sk_share_local_path}*");
for entry in glob(&pattern).expect("Failed to read glob pattern") {
match entry {
Ok(path) => {
if path.is_file() {
if let Err(e) = fs::remove_file(&path) {
eprintln!("Failed to delete file {:?}: {}", path.display(), e);
}
}
}
Err(e) => eprintln!("{:?}", e),
}
}
}
Ok(())
}

0 comments on commit af44bf5

Please sign in to comment.