-
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
Reshare confirmation #965
Reshare confirmation #965
Changes from all commits
24de588
25f2ba1
f8e462d
3ee6614
ca6968b
b137a55
87e2390
9e6db22
eba2a82
bff3238
7ff8ba9
9d23d85
c3fa564
f11f95c
6957598
3827de0
41508bf
40751f9
60da524
0412852
cae97fc
17f8418
003a452
1ebc3a0
0e41d56
4e30876
2e2cfeb
b059027
a3c6dc8
91176a2
f1631d2
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 |
---|---|---|
|
@@ -57,9 +57,9 @@ use sp_staking::SessionIndex; | |
|
||
#[frame_support::pallet] | ||
pub mod pallet { | ||
use entropy_shared::{ValidatorInfo, X25519PublicKey}; | ||
use entropy_shared::{ValidatorInfo, X25519PublicKey, SIGNING_PARTY_SIZE}; | ||
use frame_support::{ | ||
dispatch::DispatchResult, | ||
dispatch::{DispatchResult, DispatchResultWithPostInfo}, | ||
pallet_prelude::*, | ||
traits::{Currency, Randomness}, | ||
DefaultNoBound, | ||
|
@@ -71,6 +71,7 @@ pub mod pallet { | |
}; | ||
use sp_runtime::traits::TrailingZeroInput; | ||
use sp_staking::StakingAccount; | ||
use sp_std::vec; | ||
use sp_std::vec::Vec; | ||
|
||
use super::*; | ||
|
@@ -119,6 +120,12 @@ pub mod pallet { | |
pub new_signer: Vec<u8>, | ||
pub block_number: BlockNumber, | ||
} | ||
|
||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)] | ||
pub struct NextSignerInfo<ValidatorId> { | ||
pub next_signers: Vec<ValidatorId>, | ||
pub confirmations: Vec<ValidatorId>, | ||
} | ||
#[pallet::pallet] | ||
#[pallet::without_storage_info] | ||
pub struct Pallet<T>(_); | ||
|
@@ -173,7 +180,7 @@ pub mod pallet { | |
/// The next signers ready to take the Signers place when a reshare is done | ||
#[pallet::storage] | ||
#[pallet::getter(fn next_signers)] | ||
pub type NextSigners<T: Config> = StorageValue<_, Vec<T::ValidatorId>, ValueQuery>; | ||
pub type NextSigners<T: Config> = StorageValue<_, NextSignerInfo<T::ValidatorId>, OptionQuery>; | ||
|
||
/// The next time a reshare should happen | ||
#[pallet::storage] | ||
|
@@ -193,6 +200,8 @@ pub mod pallet { | |
pub inital_signers: Vec<T::ValidatorId>, | ||
/// validator info and accounts to take part in proactive refresh | ||
pub proactive_refresh_data: (Vec<ValidatorInfo>, Vec<Vec<u8>>), | ||
/// validator info and account to take part in a reshare | ||
pub mock_signer_rotate: bool, | ||
} | ||
|
||
#[pallet::genesis_build] | ||
|
@@ -222,6 +231,13 @@ pub mod pallet { | |
proactive_refresh_keys: self.proactive_refresh_data.1.clone(), | ||
}; | ||
ProactiveRefresh::<T>::put(refresh_info); | ||
|
||
if self.mock_signer_rotate { | ||
NextSigners::<T>::put(NextSignerInfo { | ||
next_signers: self.inital_signers.clone(), | ||
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. is 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. pretty much if next signers do not exist then the chain isn't in a rotating state and when the nodes call confirm done they will get rejected |
||
confirmations: vec![], | ||
}); | ||
} | ||
} | ||
} | ||
// Errors inform users that something went wrong. | ||
|
@@ -234,6 +250,9 @@ pub mod pallet { | |
InvalidValidatorId, | ||
SigningGroupError, | ||
TssAccountAlreadyExists, | ||
NotNextSigner, | ||
ReshareNotInProgress, | ||
AlreadyConfirmed, | ||
} | ||
|
||
#[pallet::event] | ||
|
@@ -257,6 +276,10 @@ pub mod pallet { | |
Vec<Vec<<T as pallet_session::Config>::ValidatorId>>, | ||
Vec<Vec<<T as pallet_session::Config>::ValidatorId>>, | ||
), | ||
/// Validators in new signer group [new_signers] | ||
SignerConfirmed(<T as pallet_session::Config>::ValidatorId), | ||
/// Validators subgroups rotated [old, new] | ||
SignersRotation(Vec<<T as pallet_session::Config>::ValidatorId>), | ||
} | ||
|
||
#[pallet::call] | ||
|
@@ -403,6 +426,43 @@ pub mod pallet { | |
Self::deposit_event(Event::ValidatorSyncStatus(stash, synced)); | ||
Ok(()) | ||
} | ||
|
||
#[pallet::call_index(5)] | ||
#[pallet::weight(({ | ||
<T as Config>::WeightInfo::confirm_key_reshare_confirmed(SIGNING_PARTY_SIZE as u32) | ||
.max(<T as Config>::WeightInfo::confirm_key_reshare_completed()) | ||
}, DispatchClass::Operational))] | ||
pub fn confirm_key_reshare(origin: OriginFor<T>) -> DispatchResultWithPostInfo { | ||
let ts_server_account = ensure_signed(origin)?; | ||
let validator_stash = | ||
Self::threshold_to_stash(&ts_server_account).ok_or(Error::<T>::NoThresholdKey)?; | ||
|
||
let mut signers_info = | ||
NextSigners::<T>::take().ok_or(Error::<T>::ReshareNotInProgress)?; | ||
ensure!( | ||
signers_info.next_signers.contains(&validator_stash), | ||
Error::<T>::NotNextSigner | ||
); | ||
|
||
ensure!( | ||
!signers_info.confirmations.contains(&validator_stash), | ||
Error::<T>::AlreadyConfirmed | ||
); | ||
|
||
// TODO (#927): Add another check, such as a signature or a verifying key comparison, to | ||
// ensure that rotation was indeed successful. | ||
let current_signer_length = signers_info.next_signers.len(); | ||
if signers_info.confirmations.len() == (current_signer_length - 1) { | ||
Signers::<T>::put(signers_info.next_signers.clone()); | ||
Self::deposit_event(Event::SignersRotation(signers_info.next_signers)); | ||
Ok(Pays::No.into()) | ||
} else { | ||
signers_info.confirmations.push(validator_stash.clone()); | ||
NextSigners::<T>::put(signers_info); | ||
Self::deposit_event(Event::SignerConfirmed(validator_stash)); | ||
Ok(Pays::No.into()) | ||
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 makes it a free transaction, right? 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. free may not be the right term, refunded, as in they pay up front then if they don't hit any errors they get their fees back |
||
} | ||
} | ||
} | ||
|
||
impl<T: Config> Pallet<T> { | ||
|
@@ -446,7 +506,10 @@ pub mod pallet { | |
// removes first signer and pushes new signer to back | ||
current_signers.remove(0); | ||
current_signers.push(next_signer_up.clone()); | ||
NextSigners::<T>::put(current_signers); | ||
NextSigners::<T>::put(NextSignerInfo { | ||
next_signers: current_signers, | ||
confirmations: vec![], | ||
}); | ||
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. Not directly related to this PR, but is it possible to test this with our 3 node integration test / docker-compose setup? I guess we need 4 nodes before the check above which checks that the validator size is greater than the number of current signers will pass. 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 we would need an extra node added |
||
// trigger reshare at next block | ||
let current_block_number = <frame_system::Pallet<T>>::block_number(); | ||
let reshare_info = ReshareInfo { | ||
|
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.
Im guessing this will be removed when this is all finished and we always rotate 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 no, this is for rotating on spin up, it is the only way I can get the tests in the TSS in the right state to actually test it (like the proactive refresh data above)