-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix reshare timing issue #1211
Fix reshare timing issue #1211
Changes from 8 commits
b98ff72
5337ea4
0a6da75
4ab4c52
40997da
246351d
346d664
7657f86
81e3ab3
989c7b7
a4132d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -295,7 +295,7 @@ pub async fn validate_new_reshare( | |
.await? | ||
.ok_or_else(|| ValidatorErr::ChainFetch("Not Currently in a reshare"))?; | ||
|
||
if chain_data.block_number != reshare_data.block_number.saturating_sub(1) | ||
if chain_data.block_number != reshare_data.block_number | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The sub was removed as now it matches the running testnet |
||
|| chain_data.new_signers != reshare_data.new_signers | ||
{ | ||
return Err(ValidatorErr::InvalidData); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,8 +17,8 @@ use crate::{ | |
helpers::{ | ||
launch::{FORBIDDEN_KEYS, LATEST_BLOCK_NUMBER_RESHARE}, | ||
tests::{ | ||
get_port, initialize_test_logger, run_to_block, setup_client, spawn_testing_validators, | ||
unsafe_get, | ||
call_set_storage, get_port, initialize_test_logger, run_to_block, setup_client, | ||
spawn_testing_validators, unsafe_get, | ||
}, | ||
}, | ||
validator::{ | ||
|
@@ -29,8 +29,13 @@ use crate::{ | |
use entropy_client::{self as test_client}; | ||
use entropy_client::{ | ||
chain_api::{ | ||
entropy, entropy::runtime_types::bounded_collections::bounded_vec::BoundedVec, | ||
entropy::runtime_types::pallet_registry::pallet::ProgramInstance, get_api, get_rpc, | ||
entropy, | ||
entropy::runtime_types::bounded_collections::bounded_vec::BoundedVec, | ||
entropy::runtime_types::entropy_runtime::RuntimeCall, | ||
entropy::runtime_types::frame_system::pallet::Call as SystemsCall, | ||
entropy::runtime_types::pallet_registry::pallet::ProgramInstance, | ||
entropy::runtime_types::pallet_staking_extension::pallet::{NextSignerInfo, ReshareInfo}, | ||
get_api, get_rpc, | ||
}, | ||
substrate::query_chain, | ||
Hasher, | ||
|
@@ -69,7 +74,8 @@ async fn test_reshare_basic() { | |
.await; | ||
let api = get_api(&context[0].ws_url).await.unwrap(); | ||
let rpc = get_rpc(&context[0].ws_url).await.unwrap(); | ||
|
||
let alice_stash = AccountKeyring::AliceStash; | ||
let dave_stash = AccountKeyring::DaveStash; | ||
let client = reqwest::Client::new(); | ||
|
||
// Get current signers | ||
|
@@ -78,7 +84,9 @@ async fn test_reshare_basic() { | |
let old_signer_ids: HashSet<[u8; 32]> = | ||
HashSet::from_iter(signer_stash_accounts.clone().into_iter().map(|id| id.0)); | ||
let mut signers = Vec::new(); | ||
let mut next_signers = vec![]; | ||
for signer in signer_stash_accounts.iter() { | ||
next_signers.push(signer); | ||
let query = entropy::storage().staking_extension().threshold_servers(signer); | ||
let server_info = query_chain(&api, &rpc, query, None).await.unwrap().unwrap(); | ||
signers.push(server_info); | ||
|
@@ -89,6 +97,29 @@ async fn test_reshare_basic() { | |
let key_share = unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), port).await; | ||
assert!(!key_share.is_empty()); | ||
} | ||
next_signers.remove(0); | ||
let binding = dave_stash.to_account_id().into(); | ||
next_signers.push(&binding); | ||
let block_number = rpc.chain_get_header(None).await.unwrap().unwrap().number + 1; | ||
let storage_address_next_signers = entropy::storage().staking_extension().next_signers(); | ||
let value_next_signers = | ||
NextSignerInfo { confirmations: vec![], next_signers: next_signers.clone() }; | ||
// Add reshare | ||
let call = RuntimeCall::System(SystemsCall::set_storage { | ||
items: vec![(storage_address_next_signers.to_root_bytes(), value_next_signers.encode())], | ||
}); | ||
call_set_storage(&api, &rpc, call).await; | ||
|
||
let storage_address_reshare_data = entropy::storage().staking_extension().reshare_data(); | ||
let value_reshare_info = | ||
ReshareInfo { block_number, new_signers: vec![dave_stash.public().encode()] }; | ||
// Add reshare | ||
let call = RuntimeCall::System(SystemsCall::set_storage { | ||
items: vec![(storage_address_reshare_data.to_root_bytes(), value_reshare_info.encode())], | ||
}); | ||
call_set_storage(&api, &rpc, call).await; | ||
|
||
let key_share_before = unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), 3002).await; | ||
|
||
let mut i = 0; | ||
// Wait up to 2min for reshare to complete: check once every second if we have a new set of signers. | ||
|
@@ -101,14 +132,19 @@ async fn test_reshare_basic() { | |
if new_signer_ids != old_signer_ids { | ||
break Ok(new_signer_ids); | ||
} | ||
if i > 120 { | ||
if i > 240 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. Was this needed to get the tests to pass? Disappointingly we are still often getting this timeout error, and i kinda thought it could not be that the reshare takes more than two minutes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably not, I changed it when I was doing to reshares so it took more time, but I mean doesn't hurt |
||
break Err("Timed out waiting for reshare"); | ||
} | ||
i += 1; | ||
tokio::time::sleep(std::time::Duration::from_secs(1)).await; | ||
} | ||
.unwrap(); | ||
|
||
// wait for roatate keyshare | ||
tokio::time::sleep(std::time::Duration::from_secs(10)).await; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah now i see what you mean about rotate keyshare happening after signers have changed. Yeah totally makes sense that you have to wait here a block before checking the keyshare has changed. |
||
|
||
let key_share_after = unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), 3002).await; | ||
assert_ne!(key_share_before, key_share_after); | ||
// At this point the signing set has changed on-chain, but the keyshares haven't been rotated | ||
// but by the time we have stored a program and registered, the rotation should have happened | ||
|
||
|
@@ -173,6 +209,36 @@ async fn test_reshare_basic() { | |
let key_share = unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), port).await; | ||
assert!(!key_share.is_empty()); | ||
} | ||
let block_number = rpc.chain_get_header(None).await.unwrap().unwrap().number + 1; | ||
let key_share_before_2 = unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), 3003).await; | ||
|
||
next_signers.remove(0); | ||
let binding = alice_stash.to_account_id().into(); | ||
next_signers.push(&binding); | ||
|
||
let storage_address_next_signers = entropy::storage().staking_extension().next_signers(); | ||
let value_next_signers = NextSignerInfo { confirmations: vec![], next_signers }; | ||
// Add another reshare | ||
let call = RuntimeCall::System(SystemsCall::set_storage { | ||
items: vec![(storage_address_next_signers.to_root_bytes(), value_next_signers.encode())], | ||
}); | ||
call_set_storage(&api, &rpc, call).await; | ||
|
||
let storage_address_reshare_data = entropy::storage().staking_extension().reshare_data(); | ||
let value_reshare_info = | ||
ReshareInfo { block_number, new_signers: vec![alice_stash.public().encode()] }; | ||
// Add another reshare | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment made me think you are doing a third reshare here - but this is part of the second reshare right? We need to modify There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yup, I can try to find better comments |
||
let call = RuntimeCall::System(SystemsCall::set_storage { | ||
items: vec![(storage_address_reshare_data.to_root_bytes(), value_reshare_info.encode())], | ||
}); | ||
call_set_storage(&api, &rpc, call).await; | ||
|
||
// wait for roatate keyshare | ||
tokio::time::sleep(std::time::Duration::from_secs(60)).await; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems a bit brittle - how come one minute here but above we have 4 mins plus 10 seconds for the key rotation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes on the second I am just checking that the rotate key share happend, got to 60 seconds from trial and error, the above one exists if finished early so I didn't try to make it shorter |
||
|
||
let key_share_after_2 = unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), 3003).await; | ||
assert_ne!(key_share_before_2, key_share_after_2); | ||
|
||
clean_tests(); | ||
} | ||
|
||
|
@@ -225,9 +291,17 @@ async fn test_reshare_validation_fail() { | |
validate_new_reshare(&api, &rpc, &ocw_message, &kv).await.map_err(|e| e.to_string()); | ||
assert_eq!(err_stale_data, Err("Data is stale".to_string())); | ||
|
||
let block_number = rpc.chain_get_header(None).await.unwrap().unwrap().number + 1; | ||
let block_number = rpc.chain_get_header(None).await.unwrap().unwrap().number; | ||
let storage_address_reshare_data = entropy::storage().staking_extension().reshare_data(); | ||
let value_reshare_info = | ||
ReshareInfo { block_number: block_number + 1, new_signers: vec![dave.public().encode()] }; | ||
// Add reshare | ||
let call = RuntimeCall::System(SystemsCall::set_storage { | ||
items: vec![(storage_address_reshare_data.to_root_bytes(), value_reshare_info.encode())], | ||
}); | ||
|
||
ocw_message.block_number = block_number; | ||
run_to_block(&rpc, block_number + 1).await; | ||
call_set_storage(&api, &rpc, call).await; | ||
|
||
let err_incorrect_data = | ||
validate_new_reshare(&api, &rpc, &ocw_message, &kv).await.map_err(|e| e.to_string()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -160,11 +160,11 @@ pub mod pallet { | |
/// Submits a request to do a key refresh on the signers parent key. | ||
pub fn post_reshare(block_number: BlockNumberFor<T>) -> Result<(), http::Error> { | ||
let reshare_data = pallet_staking_extension::Pallet::<T>::reshare_data(); | ||
if reshare_data.block_number != block_number { | ||
if reshare_data.block_number + sp_runtime::traits::One::one() != block_number { | ||
return Ok(()); | ||
} | ||
|
||
let deadline = sp_io::offchain::timestamp().add(Duration::from_millis(2_000)); | ||
let deadline = sp_io::offchain::timestamp().add(Duration::from_millis(10_000)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No harm in leaving this here i guess, but in theory it should not be needed outside of the hot fix because resharing happens in a separate task There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true, gonna leave it tho cuz why not |
||
let kind = sp_core::offchain::StorageKind::PERSISTENT; | ||
let from_local = sp_io::offchain::local_storage_get(kind, b"reshare_validators") | ||
.unwrap_or_else(|| b"http://localhost:3001/validator/reshare".to_vec()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,7 +61,7 @@ use sp_staking::SessionIndex; | |
pub mod pallet { | ||
use entropy_shared::{ | ||
QuoteContext, ValidatorInfo, X25519PublicKey, MAX_SIGNERS, | ||
PREGENERATED_NETWORK_VERIFYING_KEY, TEST_RESHARE_BLOCK_NUMBER, VERIFICATION_KEY_LENGTH, | ||
PREGENERATED_NETWORK_VERIFYING_KEY, VERIFICATION_KEY_LENGTH, | ||
}; | ||
use frame_support::{ | ||
dispatch::{DispatchResult, DispatchResultWithPostInfo}, | ||
|
@@ -262,8 +262,6 @@ pub mod pallet { | |
pub threshold_servers: Vec<ThresholdServersConfig<T>>, | ||
/// validator info and accounts to take part in proactive refresh | ||
pub proactive_refresh_data: (Vec<ValidatorInfo>, Vec<Vec<u8>>), | ||
/// validator info and account new signer to take part in a reshare | ||
pub mock_signer_rotate: (bool, Vec<T::ValidatorId>, Vec<T::ValidatorId>), | ||
/// Whether to begin in an already jumpstarted state in order to be able to test signing | ||
/// using pre-generated keyshares | ||
pub jump_started_signers: Option<Vec<T::ValidatorId>>, | ||
|
@@ -295,22 +293,6 @@ pub mod pallet { | |
proactive_refresh_keys: self.proactive_refresh_data.1.clone(), | ||
}; | ||
ProactiveRefresh::<T>::put(refresh_info); | ||
// mocks a signer rotation for tss new_reshare tests | ||
if self.mock_signer_rotate.0 { | ||
let next_signers = &mut self.mock_signer_rotate.1.clone(); | ||
let mut new_signers = vec![]; | ||
for new_signer in self.mock_signer_rotate.2.clone() { | ||
next_signers.push(new_signer.clone()); | ||
new_signers.push(new_signer.encode()) | ||
} | ||
let next_signers = next_signers.to_vec(); | ||
NextSigners::<T>::put(NextSignerInfo { next_signers, confirmations: vec![] }); | ||
ReshareData::<T>::put(ReshareInfo { | ||
// To give enough time for test_reshare setup | ||
block_number: TEST_RESHARE_BLOCK_NUMBER.into(), | ||
new_signers, | ||
}) | ||
} | ||
|
||
if let Some(jump_started_signers) = &self.jump_started_signers { | ||
Signers::<T>::put(jump_started_signers.clone()); | ||
|
@@ -876,7 +858,7 @@ pub mod pallet { | |
// trigger reshare at next block | ||
let current_block_number = <frame_system::Pallet<T>>::block_number(); | ||
let reshare_info = ReshareInfo { | ||
block_number: current_block_number + sp_runtime::traits::One::one(), | ||
block_number: current_block_number - sp_runtime::traits::One::one(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems kinda weird that we subtract one here and then add one again in the propagation pallet. But since it works, definitely don't touch it. |
||
new_signers, | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh i am happy to say goodbye to this one