From 9dac61d8da58d8ce4d31805b1f2afbcb40b37b1c Mon Sep 17 00:00:00 2001 From: JesseAbram <33698952+JesseAbram@users.noreply.github.com> Date: Thu, 8 Aug 2024 13:03:52 -0400 Subject: [PATCH] Test reshare now takes 2 Ts with signer and 3 Ns (#989) * working * clean tests * add test * clean * clean --- crates/client/entropy_metadata.scale | Bin 206543 -> 207236 bytes .../src/validator/api.rs | 53 +++++++++++++----- .../src/validator/tests.rs | 24 +++++++- node/cli/src/chain_spec/integration_tests.rs | 11 +++- node/cli/src/chain_spec/mod.rs | 1 - node/cli/src/endowed_accounts.rs | 1 + 6 files changed, 68 insertions(+), 22 deletions(-) diff --git a/crates/client/entropy_metadata.scale b/crates/client/entropy_metadata.scale index 6c00606437c2037d28a9c2ec0693713a072ae971..e4a096a429421bbd780f43e25175f76a859c1cc9 100644 GIT binary patch delta 611 zcmZXRL2FY%5Xavn0W0)k+kl4#hT_3O38LbmC)*??RnTfYR21T7-z0Cz%kFb`UdlVg zLq)&A!;2q6l=msbgLv~GcoEITZ{WVvs@Ti2JM*8J|8Mrg`{m=0%g^4zg)U&R(uK#> z)wZRPa!j^wbYDh7>81SMH@K32=|X4YTH;5OGYry?sVqjBmsIH5?X)-{Co2 zd~hqBBs~_E?-*{GN#d(03|8{bKcI1QHHh~0RKzOWRmruhZL(@ASQ&jFI11K+WD(wx z(xjUIX7_}OeUo~S|9l7=FB)?w8uQAq4(r7+RO>Kn-~SCk;a%M-Ap)pX-odA(TCjE= za7UwJnjl*t$4ZaT(;!ELsUz#~6pBJLdJ*qvwkF9?6CW8nZU*~+9!N>@X~7H4NtN~f zXTHj@V8YOlLv0vCN=Pr-37ugt9XLPR3&aT<4#?Yh3jd7W!a>UDMG;vP*q{34471Yg zn6myB9z{w797PxyiCoJzoQh|J3)V* q`tl^ZiltE+jm1uBhSJGqGj5e%LUzyCGrNZT&DYBH;#H-3j8xU9%xQ)Qe|gpb97~L zX>Mmma&K)=VRB_|bW3G<01^O~L5=|;hav3&w;}BUW)%Sxw}=7*6#=(S1p_uD`3D|< diff --git a/crates/threshold-signature-server/src/validator/api.rs b/crates/threshold-signature-server/src/validator/api.rs index 8332de2e0..7632ed87e 100644 --- a/crates/threshold-signature-server/src/validator/api.rs +++ b/crates/threshold-signature-server/src/validator/api.rs @@ -66,15 +66,12 @@ pub async fn new_reshare( let api = get_api(&app_state.configuration.endpoint).await?; let rpc = get_rpc(&app_state.configuration.endpoint).await?; validate_new_reshare(&api, &rpc, &data, &app_state.kv_store).await?; - let signers_query = entropy::storage().staking_extension().signers(); - let signers = query_chain(&api, &rpc, signers_query, None) - .await? - .ok_or_else(|| ValidatorErr::ChainFetch("Error getting signers"))?; - let next_signers_query = entropy::storage().staking_extension().signers(); + let next_signers_query = entropy::storage().staking_extension().next_signers(); let next_signers = query_chain(&api, &rpc, next_signers_query, None) .await? - .ok_or_else(|| ValidatorErr::ChainFetch("Error getting next signers"))?; + .ok_or_else(|| ValidatorErr::ChainFetch("Error getting next signers"))? + .next_signers; let validators_info = get_validators_info(&api, &rpc, next_signers) .await @@ -85,9 +82,11 @@ pub async fn new_reshare( .map_err(|e| ValidatorErr::UserError(e.to_string()))?; let verifying_key_query = entropy::storage().staking_extension().jump_start_progress(); - let verifying_key = query_chain(&api, &rpc, verifying_key_query, None) + let parent_key_details = query_chain(&api, &rpc, verifying_key_query, None) .await? - .ok_or_else(|| ValidatorErr::ChainFetch("Parent verifying key error"))? + .ok_or_else(|| ValidatorErr::ChainFetch("Parent verifying key error"))?; + + let verifying_key = parent_key_details .verifying_key .ok_or_else(|| ValidatorErr::OptionUnwrapError("Failed to get verifying key".to_string()))? .0; @@ -107,10 +106,11 @@ pub async fn new_reshare( if !is_proper_signer { return Ok(StatusCode::MISDIRECTED_REQUEST); } - // get old key if have it + let my_stash_address = get_stash_address(&api, &rpc, signer.account_id()) .await .map_err(|e| ValidatorErr::UserError(e.to_string()))?; + let old_holder: Option> = if data.new_signer == my_stash_address.encode() { None @@ -121,19 +121,19 @@ pub async fn new_reshare( .ok_or_else(|| ValidatorErr::KvDeserialize("Failed to load KeyShare".into()))?; Some(OldHolder { key_share: key_share.0 }) }; + let party_ids: BTreeSet = validators_info.iter().cloned().map(|x| PartyId::new(x.tss_account)).collect(); - let old_holders_info = get_validators_info(&api, &rpc, signers) - .await - .map_err(|e| ValidatorErr::UserError(e.to_string()))?; + let pruned_old_holders = + prune_old_holders(&api, &rpc, data.new_signer, validators_info.clone()).await?; + let old_holders: BTreeSet = - old_holders_info.iter().cloned().map(|x| PartyId::new(x.tss_account)).collect(); + pruned_old_holders.into_iter().map(|x| PartyId::new(x.tss_account)).collect(); let new_holder = NewHolder { verifying_key: decoded_verifying_key, - // TODO: get from chain see #941 - old_threshold: party_ids.len(), + old_threshold: parent_key_details.parent_key_threshold as usize, old_holders, }; let key_info_query = entropy::storage().parameters().signers_info(); @@ -337,3 +337,26 @@ pub fn check_forbidden_key(key: &str) -> Result<(), ValidatorErr> { } Ok(()) } + +/// Filters out new signer from next signers to get old holders +pub async fn prune_old_holders( + api: &OnlineClient, + rpc: &LegacyRpcMethods, + new_signer: Vec, + validators_info: Vec, +) -> Result, ValidatorErr> { + Ok(if !new_signer.is_empty() { + let address_slice: &[u8; 32] = &new_signer.clone().try_into().unwrap(); + let new_signer_address = AccountId32(*address_slice); + let new_signer_info = &get_validators_info(api, rpc, vec![new_signer_address]) + .await + .map_err(|e| ValidatorErr::UserError(e.to_string()))?[0]; + validators_info + .iter() + .filter(|x| x.tss_account != new_signer_info.tss_account) + .cloned() + .collect() + } else { + validators_info.clone() + }) +} diff --git a/crates/threshold-signature-server/src/validator/tests.rs b/crates/threshold-signature-server/src/validator/tests.rs index 35885d769..23b64fc25 100644 --- a/crates/threshold-signature-server/src/validator/tests.rs +++ b/crates/threshold-signature-server/src/validator/tests.rs @@ -29,7 +29,10 @@ use crate::{ }, validator::get_signer_and_x25519_secret_from_mnemonic, }, - validator::{api::validate_new_reshare, errors::ValidatorErr}, + validator::{ + api::{prune_old_holders, validate_new_reshare}, + errors::ValidatorErr, + }, }; use entropy_kvdb::{ clean_tests, @@ -59,7 +62,7 @@ async fn test_reshare() { initialize_test_logger().await; clean_tests(); - let alice = AccountKeyring::Alice; + let alice = AccountKeyring::AliceStash; let cxt = test_node_process_testing_state(true).await; let (_validator_ips, _validator_ids) = spawn_testing_validators(true).await; @@ -177,6 +180,21 @@ async fn test_reshare_validation_fail_not_in_reshare() { clean_tests(); } +#[tokio::test] +#[serial] +async fn test_empty_next_signer() { + initialize_test_logger().await; + clean_tests(); + + let cxt = test_context_stationary().await; + let api = get_api(&cxt.node_proc.ws_url).await.unwrap(); + let rpc = get_rpc(&cxt.node_proc.ws_url).await.unwrap(); + + assert!(prune_old_holders(&api, &rpc, vec![], vec![]).await.is_ok()); + + clean_tests(); +} + async fn setup_for_reshare( api: &OnlineClient, rpc: &LegacyRpcMethods, @@ -187,7 +205,7 @@ async fn setup_for_reshare( let jump_start_request = entropy::tx().registry().jump_start_network(); let _result = submit_transaction(api, rpc, &signer, &jump_start_request, None).await.unwrap(); - let validators_names = vec![ValidatorName::Alice, ValidatorName::Bob, ValidatorName::Charlie]; + let validators_names = vec![ValidatorName::Bob, ValidatorName::Charlie, ValidatorName::Dave]; for validator_name in validators_names { let mnemonic = development_mnemonic(&Some(validator_name)); let (tss_signer, _static_secret) = diff --git a/node/cli/src/chain_spec/integration_tests.rs b/node/cli/src/chain_spec/integration_tests.rs index cad55b3d9..bd901dc72 100644 --- a/node/cli/src/chain_spec/integration_tests.rs +++ b/node/cli/src/chain_spec/integration_tests.rs @@ -53,9 +53,15 @@ pub fn integration_tests_config() -> ChainSpec { crate::chain_spec::authority_keys_from_seed("Alice"), crate::chain_spec::authority_keys_from_seed("Bob"), crate::chain_spec::authority_keys_from_seed("Charlie"), + crate::chain_spec::authority_keys_from_seed("Dave"), ], vec![], get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + ], )) .build() } @@ -72,6 +78,7 @@ pub fn integration_tests_genesis_config( )>, initial_nominators: Vec, root_key: AccountId, + mock_signer_rotate_data: Vec, ) -> serde_json::Value { // Note that any endowed_accounts added here will be included in the `elections` and // `technical_committee` genesis configs. If you don't want that, don't push those accounts to @@ -208,9 +215,7 @@ pub fn integration_tests_genesis_config( ], vec![EVE_VERIFYING_KEY.to_vec(), DAVE_VERIFYING_KEY.to_vec()], ), - mock_signer_rotate: (true, initial_authorities.iter().map(|auth| { - auth.0.clone() - }).collect::>(), vec![get_account_id_from_seed::("Alice")],), + mock_signer_rotate: (true, mock_signer_rotate_data, vec![get_account_id_from_seed::("Alice//stash")],), }, "elections": ElectionsConfig { members: endowed_accounts diff --git a/node/cli/src/chain_spec/mod.rs b/node/cli/src/chain_spec/mod.rs index fa45d78cd..79485d720 100644 --- a/node/cli/src/chain_spec/mod.rs +++ b/node/cli/src/chain_spec/mod.rs @@ -97,7 +97,6 @@ pub mod tss_x25519_public_key { 8, 22, 19, 230, 107, 217, 249, 190, 14, 142, 155, 252, 156, 229, 120, 11, 180, 35, 83, 245, 222, 11, 153, 201, 162, 29, 153, 13, 123, 126, 128, 32, ]; - /// The `DEFAULT_BOB_MNEMONIC` is used to derive the public key. /// Mnemonic: "where sight patient orphan general short empower hope party hurt month voice" pub const BOB: [u8; 32] = [ diff --git a/node/cli/src/endowed_accounts.rs b/node/cli/src/endowed_accounts.rs index ebd58528f..34726dbcc 100644 --- a/node/cli/src/endowed_accounts.rs +++ b/node/cli/src/endowed_accounts.rs @@ -75,5 +75,6 @@ pub fn endowed_accounts_dev() -> Vec { crate::chain_spec::tss_account_id::ALICE.clone(), crate::chain_spec::tss_account_id::BOB.clone(), crate::chain_spec::tss_account_id::CHARLIE.clone(), + crate::chain_spec::tss_account_id::DAVE.clone(), ] }