From 5175183d2ec2eb6c0bf99b65d4d2cfe39f7c9deb Mon Sep 17 00:00:00 2001 From: Jesse Abramowitz Date: Thu, 22 Aug 2024 14:08:17 -0400 Subject: [PATCH] add validate rotate keyshare --- crates/client/entropy_metadata.scale | Bin 209102 -> 209508 bytes .../src/validator/api.rs | 24 +++++++++ .../src/validator/tests.rs | 50 ++++++++++++++++++ pallets/propagation/src/lib.rs | 5 +- pallets/propagation/src/tests.rs | 2 +- pallets/staking/src/lib.rs | 6 ++- 6 files changed, 81 insertions(+), 6 deletions(-) diff --git a/crates/client/entropy_metadata.scale b/crates/client/entropy_metadata.scale index c0c5982a0fe6dd2d75315561d406a7d993720319..dd28d7ff493e0fabf6c9ae55e13a4bfc3667fc3a 100644 GIT binary patch delta 522 zcmZ`$JxeP=6y1$eSolOl8{xq%`~j9CBKV2np{R+4pv7e8#vQVm8)s(yz(U35HG&cg z!Q}D4N-M!4{sb%kfuNxH6KuV11Z|vdF6W$k?m72QUC+;5*O%vE-_6zeYdEm_2X~gp zOOI|2os;XhAe}=cg8BjV{}P=I20$B8myO@`&SrP-L_$$zKCPC}&X64~j;$S@G+QUl z@Ns2NoGzy15h6+x1%^D75Ngu0CXj_qw7RTO6_*We*D&&^#yu}*2bxR}io0)Lz-@1} zaXJE*ma3Y83btZ2nXbi+l!>Tj^Clu|SuAh%YN?-+UIsaFH!EGt1Z{W*iie;GUB<0S zAH^&sJ#0zGd)iip=c(YCH6F2j<1%uw@s6Y$J!5h?b9A z$(u3-LNtEl6${`pC>tx2_&;qeSqB!AOx6?l7(sr8!s#Um`qs-^czYZUw*LLiJ&2Lf pb|>79i={;u20c9iKd}!*OcE&Qb%U(SdN%79Dxc8S?oqCA@ebbU#5({0 delta 119 zcmV--0EqwO07yx0V{dYD zWn*+nZg6#UL}7Gc00ICwPH$6mVRL9fV`Fc1Zgcfi2~gOw-Jv5Q=|ULEg=8^ diff --git a/crates/threshold-signature-server/src/validator/api.rs b/crates/threshold-signature-server/src/validator/api.rs index e0586affb..8a4d3cee5 100644 --- a/crates/threshold-signature-server/src/validator/api.rs +++ b/crates/threshold-signature-server/src/validator/api.rs @@ -200,6 +200,7 @@ pub async fn rotate_network_key( // validate from chain let api = get_api(&app_state.configuration.endpoint).await?; let rpc = get_rpc(&app_state.configuration.endpoint).await?; + validate_rotate_network_key(&api, &rpc).await?; let (signer, _) = get_signer_and_x25519_secret(&app_state.kv_store) .await @@ -284,6 +285,29 @@ pub async fn validate_new_reshare( Ok(()) } +/// Validates rotate_network_key +/// Checks the chain that the reshare was completed +pub async fn validate_rotate_network_key( + api: &OnlineClient, + rpc: &LegacyRpcMethods, +) -> Result<(), ValidatorErr> { + let latest_block_number = rpc + .chain_get_header(None) + .await? + .ok_or_else(|| ValidatorErr::OptionUnwrapError("Failed to get block number".to_string()))? + .number; + + let rotate_keyshares_info_query = entropy::storage().staking_extension().rotate_keyshares(); + let rotate_keyshare_block = query_chain(api, rpc, rotate_keyshares_info_query, None) + .await? + .ok_or_else(|| ValidatorErr::ChainFetch("Rotate Keyshare not in progress"))?; + + if latest_block_number > rotate_keyshare_block { + return Err(ValidatorErr::StaleData); + } + + Ok(()) +} /// Confirms that a validator has succefully reshared. pub async fn confirm_key_reshare( api: &OnlineClient, diff --git a/crates/threshold-signature-server/src/validator/tests.rs b/crates/threshold-signature-server/src/validator/tests.rs index 9b6b9909a..e98821d6a 100644 --- a/crates/threshold-signature-server/src/validator/tests.rs +++ b/crates/threshold-signature-server/src/validator/tests.rs @@ -127,11 +127,61 @@ async fn test_reshare() { serialize(&aux_info_before).unwrap(), serialize(&aux_info_after_rotate).unwrap() ); + + // calling twice doesn't do anything + let response = client + .post(format!("http://127.0.0.1:{}/validator/rotate_network_key", validator_ports[i])) + .send() + .await + .unwrap(); + + assert_eq!(response.text().await.unwrap(), "Kv error: Recv Error: channel closed"); + let key_share_and_aux_data_after_rotate_twice = + unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), validator_ports[i]).await; + let (key_share_after_rotate_twice, aux_info_after_rotate_twice): KeyShareWithAuxInfo = + deserialize(&key_share_and_aux_data_after_rotate_twice).unwrap(); + + // Check key share has not changed + assert_eq!( + serialize(&key_share_after_rotate_twice).unwrap(), + serialize(&key_share_after_rotate).unwrap() + ); + // Check aux info has not changed + assert_eq!( + serialize(&aux_info_after_rotate_twice).unwrap(), + serialize(&aux_info_after_rotate).unwrap() + ); } // TODO #981 - test signing a message with the new keyshare set clean_tests(); } +#[tokio::test] +#[serial] +async fn test_reshare_none_called() { + initialize_test_logger().await; + clean_tests(); + + let _cxt = test_node_process_testing_state(true).await; + + let add_parent_key_to_kvdb = true; + let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key_to_kvdb).await; + + let validator_ports = vec![3001, 3002, 3003]; + + let client = reqwest::Client::new(); + + for i in 0..validator_ports.len() { + let response = client + .post(format!("http://127.0.0.1:{}/validator/rotate_network_key", validator_ports[i])) + .send() + .await + .unwrap(); + + assert_eq!(response.text().await.unwrap(), "Chain Fetch: Rotate Keyshare not in progress"); + } +} + #[tokio::test] #[serial] async fn test_reshare_validation_fail() { diff --git a/pallets/propagation/src/lib.rs b/pallets/propagation/src/lib.rs index 21f0306b0..7d110665a 100644 --- a/pallets/propagation/src/lib.rs +++ b/pallets/propagation/src/lib.rs @@ -72,13 +72,12 @@ pub mod pallet { let _ = Self::post_user_registration(block_number); let _ = Self::post_attestation_request(block_number); let _ = Self::post_proactive_refresh(block_number); - let _ = Self::post_rotate_keyshare + let _ = Self::post_rotate_keyshare(block_number); } fn on_initialize(block_number: BlockNumberFor) -> Weight { pallet_registry::Dkg::::remove(block_number.saturating_sub(2u32.into())); pallet_staking_extension::ProactiveRefresh::::take(); - // delete rotate keyshare trigger ::WeightInfo::on_initialize() } } @@ -328,7 +327,7 @@ pub mod pallet { /// Submits a request to rotate parent network key the threshold servers. pub fn post_rotate_keyshare(block_number: BlockNumberFor) -> Result<(), http::Error> { let rotate_keyshares = pallet_staking_extension::Pallet::::rotate_keyshares(); - if !rotate_keyshares { + if rotate_keyshares != block_number { return Ok(()); } diff --git a/pallets/propagation/src/tests.rs b/pallets/propagation/src/tests.rs index 857f2b705..eae4e59a3 100644 --- a/pallets/propagation/src/tests.rs +++ b/pallets/propagation/src/tests.rs @@ -146,7 +146,7 @@ fn knows_how_to_mock_several_http_calls() { // now triggers Propagation::post_reshare(7).unwrap(); - pallet_staking_extension::RotateKeyshares::::put(true); + pallet_staking_extension::RotateKeyshares::::put(10); Propagation::post_rotate_keyshare(10).unwrap(); }) } diff --git a/pallets/staking/src/lib.rs b/pallets/staking/src/lib.rs index c67308f74..b94707d02 100644 --- a/pallets/staking/src/lib.rs +++ b/pallets/staking/src/lib.rs @@ -233,7 +233,7 @@ pub mod pallet { /// Tell Signers to rotate keyshare #[pallet::storage] #[pallet::getter(fn rotate_keyshares)] - pub type RotateKeyshares = StorageValue<_, bool, ValueQuery>; + pub type RotateKeyshares = StorageValue<_, BlockNumberFor, ValueQuery>; /// A type used to simplify the genesis configuration definition. pub type ThresholdServersConfig = ( @@ -510,7 +510,9 @@ pub mod pallet { let current_signer_length = signers_info.next_signers.len(); if signers_info.confirmations.len() == (current_signer_length - 1) { Signers::::put(signers_info.next_signers.clone()); - RotateKeyshares::::put(true); + RotateKeyshares::::put( + >::block_number() + sp_runtime::traits::One::one(), + ); Self::deposit_event(Event::SignersRotation(signers_info.next_signers)); Ok(Pays::No.into()) } else {