Skip to content

Commit

Permalink
Add test environment with four TS servers (#1029)
Browse files Browse the repository at this point in the history
* Add 4 node setup to integration test chainspec

* Add helper to create 4 node test setup

* Reshare test spawns 4 TS servers

* Add daves constants

* Fix initial chain state for mock reshare

* Fix reshare test

* Specify chainspec type when spawning TSS nodes

* Rm debug logging

* Typo

* Fix proactive reshare test

* Rm comment

* Add test helper fn

* Doccomments

* Refer to client fns as test_client:: in test

* Update test following merge

* Update test following merge

* Fix test
  • Loading branch information
ameba23 authored Sep 2, 2024
1 parent 38b73d5 commit 4c99706
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 63 deletions.
9 changes: 9 additions & 0 deletions crates/testing-utils/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ lazy_static! {
hex!["2cbc68e8bf0fbc1c28c282d1263fc9d29267dc12a1044fb730e8b65abc37524c"].into(),
// Charlie - from DEFAULT_CHARLIE_MNEMONIC in entropy_tss::helpers::launch
hex!["946140d3d5ddb980c74ffa1bb64353b5523d2d77cdf3dc617fd63de9d3b66338"].into(),
// Dave - from DEFAULT_DAVE_MNEMONIC in entropy_tss::helpers::launch
hex!["0a9054ef6b6b8ad0dd2c89895b2515583f2fbf1edced68e7328ae456d86b9402"].into(),
];

// See entropy_tss::helpers::validator::get_signer_and_x25519_secret for how these are derived
Expand All @@ -57,6 +59,13 @@ lazy_static! {
]
.try_into()
.unwrap(),
// Dave - from DEFAULT_DAVE_MNEMONIC in entropy_tss::helpers::launch
vec![
165, 202, 97, 104, 222, 190, 168, 183, 231, 63, 209, 233, 19, 185, 187, 200, 10, 29, 102,
240, 39, 50, 140, 15, 124, 112, 94, 121, 44, 182, 40, 71
]
.try_into()
.unwrap()
];
}

Expand Down
54 changes: 54 additions & 0 deletions crates/testing-utils/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (C) 2023 Entropy Cryptography Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::{
chain_api::{get_api, get_rpc, EntropyConfig},
spawn_testing_validators,
substrate_context::{test_context_stationary, test_node_process_testing_state},
ChainSpecType,
};
use entropy_protocol::PartyId;
use subxt::{backend::legacy::LegacyRpcMethods, OnlineClient};

/// A helper for setting up tests which starts both a set of TS servers and a chain node and returns
/// the chain API as well as IP addresses and PartyId of the started validators
pub async fn spawn_tss_nodes_and_start_chain(
add_parent_key: bool,
chain_spec_type: ChainSpecType,
) -> (OnlineClient<EntropyConfig>, LegacyRpcMethods<EntropyConfig>, Vec<String>, Vec<PartyId>) {
let (validator_ips, validator_ids) =
spawn_testing_validators(add_parent_key, chain_spec_type.clone()).await;

let (api, rpc) = match chain_spec_type {
ChainSpecType::Development => {
let substrate_context = test_context_stationary().await;
(
get_api(&substrate_context.node_proc.ws_url).await.unwrap(),
get_rpc(&substrate_context.node_proc.ws_url).await.unwrap(),
)
},
ChainSpecType::Integration => {
// Here we need to use `--chain=integration-tests` and force authoring otherwise we won't be
// able to get our chain in the right state to be jump started.
let force_authoring = true;
let substrate_context = test_node_process_testing_state(force_authoring).await;
(
get_api(&substrate_context.ws_url).await.unwrap(),
get_rpc(&substrate_context.ws_url).await.unwrap(),
)
},
};
(api, rpc, validator_ips, validator_ids)
}
3 changes: 2 additions & 1 deletion crates/testing-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ extern crate lazy_static;
pub use entropy_tss::chain_api;
pub mod constants;
pub mod create_test_keyshares;
pub mod helpers;
mod node_proc;
pub mod substrate_context;
pub use entropy_tss::helpers::tests::{
jump_start_network_with_signer as jump_start_network, spawn_testing_validators,
jump_start_network_with_signer as jump_start_network, spawn_testing_validators, ChainSpecType,
};
pub use node_proc::TestNodeProcess;
pub use substrate_context::*;
6 changes: 4 additions & 2 deletions crates/threshold-signature-server/src/attestation/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
chain_api::{entropy, get_api, get_rpc},
helpers::{
substrate::query_chain,
tests::{initialize_test_logger, run_to_block, spawn_testing_validators},
tests::{initialize_test_logger, run_to_block, spawn_testing_validators, ChainSpecType},
},
};
use entropy_kvdb::clean_tests;
Expand All @@ -32,7 +32,9 @@ async fn test_attest() {
clean_tests();

let cxt = test_node_process_stationary().await;
let (_validator_ips, _validator_ids) = spawn_testing_validators(false).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(false, ChainSpecType::Integration).await;

let api = get_api(&cxt.ws_url).await.unwrap();
let rpc = get_rpc(&cxt.ws_url).await.unwrap();

Expand Down
46 changes: 41 additions & 5 deletions crates/threshold-signature-server/src/helpers/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ use entropy_kvdb::{encrypted_sled::PasswordMethod, get_db_path, kv_manager::KvMa
use entropy_protocol::PartyId;
use entropy_shared::{DAVE_VERIFYING_KEY, EVE_VERIFYING_KEY, NETWORK_PARENT_KEY};
use std::time::Duration;

use subxt::{
backend::legacy::LegacyRpcMethods, ext::sp_core::sr25519, tx::PairSigner,
utils::AccountId32 as SubxtAccountId32, Config, OnlineClient,
Expand Down Expand Up @@ -119,10 +118,29 @@ pub async fn create_clients(
(app, kv_store)
}

/// Spawn 3 TSS nodes with pre-stored keyshares
pub async fn spawn_testing_validators(add_parent_key: bool) -> (Vec<String>, Vec<PartyId>) {
/// A way to specify which chainspec to use in testing
#[derive(Clone, PartialEq)]
pub enum ChainSpecType {
/// The development chainspec, which has 3 TSS nodes
Development,
/// The integration test chainspec, which has 4 TSS nodes
Integration,
}

/// Spawn either 3 or 4 TSS nodes depending on chain configuration, adding pre-stored keyshares if
/// desired
pub async fn spawn_testing_validators(
add_parent_key: bool,
chain_spec_type: ChainSpecType,
) -> (Vec<String>, Vec<PartyId>) {
let add_fourth_server = chain_spec_type == ChainSpecType::Integration;

// spawn threshold servers
let ports = [3001i64, 3002, 3003];
let mut ports = vec![3001i64, 3002, 3003];

if add_fourth_server {
ports.push(3004);
}

let (alice_axum, alice_kv) =
create_clients("validator1".to_string(), vec![], vec![], &Some(ValidatorName::Alice)).await;
Expand All @@ -143,11 +161,12 @@ pub async fn spawn_testing_validators(add_parent_key: bool) -> (Vec<String>, Vec
*get_signer(&charlie_kv).await.unwrap().account_id().clone().as_ref(),
));

let ids = vec![alice_id, bob_id, charlie_id];
let mut ids = vec![alice_id, bob_id, charlie_id];

put_keyshares_in_db("alice", alice_kv, add_parent_key).await;
put_keyshares_in_db("bob", bob_kv, add_parent_key).await;
put_keyshares_in_db("charlie", charlie_kv, add_parent_key).await;
// Don't give dave keyshares as dave is not initially in the signing committee

let listener_alice = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", ports[0]))
.await
Expand All @@ -170,6 +189,23 @@ pub async fn spawn_testing_validators(add_parent_key: bool) -> (Vec<String>, Vec
axum::serve(listener_charlie, charlie_axum).await.unwrap();
});

if add_fourth_server {
let (dave_axum, dave_kv) =
create_clients("validator4".to_string(), vec![], vec![], &Some(ValidatorName::Dave))
.await;

let listener_dave = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", ports[3]))
.await
.expect("Unable to bind to given server address.");
tokio::spawn(async move {
axum::serve(listener_dave, dave_axum).await.unwrap();
});
let dave_id = PartyId::new(SubxtAccountId32(
*get_signer(&dave_kv).await.unwrap().account_id().clone().as_ref(),
));
ids.push(dave_id);
}

tokio::time::sleep(Duration::from_secs(1)).await;

let ips = ports.iter().map(|port| format!("127.0.0.1:{port}")).collect();
Expand Down
11 changes: 6 additions & 5 deletions crates/threshold-signature-server/src/signing_client/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
launch::LATEST_BLOCK_NUMBER_PROACTIVE_REFRESH,
tests::{
initialize_test_logger, run_to_block, setup_client, spawn_testing_validators,
unsafe_get,
unsafe_get, ChainSpecType,
},
},
};
Expand All @@ -45,7 +45,8 @@ async fn test_proactive_refresh() {
clean_tests();
let _cxt = test_node_process_testing_state(false).await;

let (validator_ips, _ids) = spawn_testing_validators(false).await;
let (validator_ips, _ids) = spawn_testing_validators(false, ChainSpecType::Integration).await;
let signing_committee_ips = &validator_ips[..3].to_vec();

let client = reqwest::Client::new();

Expand Down Expand Up @@ -78,14 +79,14 @@ async fn test_proactive_refresh() {
};

let test_fail_incorrect_data =
submit_transaction_requests(validator_ips.clone(), ocw_message.clone()).await;
submit_transaction_requests(signing_committee_ips.clone(), ocw_message.clone()).await;

for res in test_fail_incorrect_data {
assert_eq!(res.unwrap().text().await.unwrap(), "Proactive Refresh data incorrect");
}
ocw_message.validators_info[0].x25519_public_key = X25519_PUBLIC_KEYS[0];
let test_user_res =
submit_transaction_requests(validator_ips.clone(), ocw_message.clone()).await;
submit_transaction_requests(signing_committee_ips.clone(), ocw_message.clone()).await;

for res in test_user_res {
assert_eq!(res.unwrap().text().await.unwrap(), "");
Expand All @@ -104,7 +105,7 @@ async fn test_proactive_refresh() {
ocw_message.validators_info[2].tss_account = alice.public().encode();

let test_user_res_not_in_group =
submit_transaction_requests(validator_ips.clone(), ocw_message.clone()).await;
submit_transaction_requests(signing_committee_ips.clone(), ocw_message.clone()).await;
for res in test_user_res_not_in_group {
assert_eq!(
res.unwrap().text().await.unwrap(),
Expand Down
35 changes: 23 additions & 12 deletions crates/threshold-signature-server/src/user/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ use crate::{
substrate::{get_oracle_data, query_chain, submit_transaction},
tests::{
create_clients, initialize_test_logger, jump_start_network_with_signer, remove_program,
run_to_block, setup_client, spawn_testing_validators, unsafe_get,
run_to_block, setup_client, spawn_testing_validators, unsafe_get, ChainSpecType,
},
user::compute_hash,
validator::get_signer_and_x25519_secret_from_mnemonic,
Expand Down Expand Up @@ -169,7 +169,8 @@ async fn test_signature_requests_fail_on_different_conditions() {
let two = AccountKeyring::Two;

let add_parent_key_to_kvdb = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key_to_kvdb).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key_to_kvdb, ChainSpecType::Integration).await;

// Here we need to use `--chain=integration-tests` and force authoring otherwise we won't be
// able to get our chain in the right state to be jump started.
Expand Down Expand Up @@ -326,7 +327,8 @@ async fn signature_request_with_derived_account_works() {
let charlie = AccountKeyring::Charlie;

let add_parent_key_to_kvdb = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key_to_kvdb).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key_to_kvdb, ChainSpecType::Integration).await;

// Here we need to use `--chain=integration-tests` and force authoring otherwise we won't be
// able to get our chain in the right state to be jump started.
Expand Down Expand Up @@ -396,7 +398,8 @@ async fn test_signing_fails_if_wrong_participants_are_used() {
let one = AccountKeyring::Dave;

let add_parent_key = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key, ChainSpecType::Integration).await;

let force_authoring = true;
let substrate_context = test_node_process_testing_state(force_authoring).await;
Expand Down Expand Up @@ -470,7 +473,8 @@ async fn test_request_limit_are_updated_during_signing() {
let two = AccountKeyring::Two;

let add_parent_key = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key, ChainSpecType::Integration).await;

let force_authoring = true;
let substrate_context = test_node_process_testing_state(force_authoring).await;
Expand Down Expand Up @@ -592,7 +596,8 @@ async fn test_fails_to_sign_if_non_signing_group_participants_are_used() {
let two = AccountKeyring::Two;

let add_parent_key = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key, ChainSpecType::Integration).await;

let force_authoring = true;
let substrate_context = test_node_process_testing_state(force_authoring).await;
Expand Down Expand Up @@ -703,7 +708,8 @@ async fn test_program_with_config() {
let two = AccountKeyring::Two;

let add_parent_key = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key, ChainSpecType::Integration).await;

let force_authoring = true;
let substrate_context = test_node_process_testing_state(force_authoring).await;
Expand Down Expand Up @@ -790,7 +796,8 @@ async fn test_jumpstart_network() {
let alice = AccountKeyring::Alice;

let cxt = test_context_stationary().await;
let (_validator_ips, _validator_ids) = spawn_testing_validators(false).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(false, ChainSpecType::Development).await;
let api = get_api(&cxt.node_proc.ws_url).await.unwrap();
let rpc = get_rpc(&cxt.node_proc.ws_url).await.unwrap();

Expand Down Expand Up @@ -1002,7 +1009,8 @@ async fn test_fail_infinite_program() {
let two = AccountKeyring::Two;

let add_parent_key = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key, ChainSpecType::Integration).await;

let force_authoring = true;
let substrate_context = test_node_process_testing_state(force_authoring).await;
Expand Down Expand Up @@ -1085,7 +1093,8 @@ async fn test_device_key_proxy() {
let two = AccountKeyring::Two;

let add_parent_key_to_kvdb = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key_to_kvdb).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key_to_kvdb, ChainSpecType::Integration).await;

// Here we need to use `--chain=integration-tests` and force authoring otherwise we won't be
// able to get our chain in the right state to be jump started.
Expand Down Expand Up @@ -1223,7 +1232,8 @@ async fn test_faucet() {
let two = AccountKeyring::Eve;
let alice = AccountKeyring::Alice;

let (validator_ips, _validator_ids) = spawn_testing_validators(false).await;
let (validator_ips, _validator_ids) =
spawn_testing_validators(false, ChainSpecType::Development).await;
let substrate_context = test_node_process_testing_state(true).await;
let entropy_api = get_api(&substrate_context.ws_url).await.unwrap();
let rpc = get_rpc(&substrate_context.ws_url).await.unwrap();
Expand Down Expand Up @@ -1395,7 +1405,8 @@ async fn test_new_registration_flow() {
let charlie = AccountKeyring::Charlie;

let add_parent_key_to_kvdb = true;
let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key_to_kvdb).await;
let (_validator_ips, _validator_ids) =
spawn_testing_validators(add_parent_key_to_kvdb, ChainSpecType::Integration).await;

// Here we need to use `--chain=integration-tests` and force authoring otherwise we won't be
// able to get our chain in the right state to be jump started.
Expand Down
Loading

0 comments on commit 4c99706

Please sign in to comment.