mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 13:39:25 +00:00
Compare commits
2 Commits
cca9e8cf16
...
44d0eeeb18
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44d0eeeb18 | ||
|
|
5a9ebc8cdc |
@@ -643,8 +643,9 @@ pub mod pallet {
|
|||||||
// Checks if this session has completed the handover from the prior session.
|
// Checks if this session has completed the handover from the prior session.
|
||||||
fn handover_completed(network: NetworkId, session: Session) -> bool {
|
fn handover_completed(network: NetworkId, session: Session) -> bool {
|
||||||
let Some(current_session) = Self::session(network) else { return false };
|
let Some(current_session) = Self::session(network) else { return false };
|
||||||
// No handover occurs on genesis
|
|
||||||
if current_session.0 == 0 {
|
// If the session we've been queried about is old, it must have completed its handover
|
||||||
|
if current_session.0 > session.0 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// If the session we've been queried about has yet to start, it can't have completed its
|
// If the session we've been queried about has yet to start, it can't have completed its
|
||||||
@@ -652,19 +653,21 @@ pub mod pallet {
|
|||||||
if current_session.0 < session.0 {
|
if current_session.0 < session.0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if current_session.0 == session.0 {
|
|
||||||
// Handover is automatically complete for Serai as it doesn't have a handover protocol
|
// Handover is automatically complete for Serai as it doesn't have a handover protocol
|
||||||
// If not Serai, check the prior session had its keys cleared, which happens once its
|
if network == NetworkId::Serai {
|
||||||
// retired
|
return true;
|
||||||
return (network == NetworkId::Serai) ||
|
|
||||||
(!Keys::<T>::contains_key(ValidatorSet {
|
|
||||||
network,
|
|
||||||
session: Session(current_session.0 - 1),
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
// We're currently in a future session, meaning this session definitely performed itself
|
|
||||||
// handover
|
// The current session must have set keys for its handover to be completed
|
||||||
true
|
if !Keys::<T>::contains_key(ValidatorSet { network, session }) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must be the first session (which has set keys) OR the prior session must have been
|
||||||
|
// retired (signified by its keys no longer being present)
|
||||||
|
(session.0 == 0) ||
|
||||||
|
(!Keys::<T>::contains_key(ValidatorSet { network, session: Session(session.0 - 1) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_session() {
|
fn new_session() {
|
||||||
@@ -682,6 +685,8 @@ pub mod pallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This is called retire_set, yet just starts retiring the set
|
||||||
|
// Update the nomenclature within this function
|
||||||
pub fn retire_set(set: ValidatorSet) {
|
pub fn retire_set(set: ValidatorSet) {
|
||||||
// If the prior prior set didn't report, emit they're retired now
|
// If the prior prior set didn't report, emit they're retired now
|
||||||
if PendingSlashReport::<T>::get(set.network).is_some() {
|
if PendingSlashReport::<T>::get(set.network).is_some() {
|
||||||
|
|||||||
@@ -32,30 +32,31 @@ pub async fn key_gen<C: Ciphersuite>(
|
|||||||
let id = KeyGenId { session: set.session, attempt: 0 };
|
let id = KeyGenId { session: set.session, attempt: 0 };
|
||||||
|
|
||||||
for (i, processor) in processors.iter_mut().enumerate() {
|
for (i, processor) in processors.iter_mut().enumerate() {
|
||||||
loop {
|
let msg = processor.recv_message().await;
|
||||||
let msg = processor.recv_message().await;
|
match &msg {
|
||||||
match &msg {
|
CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::GenerateKey {
|
||||||
CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::GenerateKey {
|
params,
|
||||||
id: this_id,
|
..
|
||||||
params,
|
}) => {
|
||||||
shares,
|
participant_is.push(params.i());
|
||||||
}) => {
|
|
||||||
assert_eq!(id, *this_id);
|
|
||||||
assert_eq!(params.t(), u16::try_from(((coordinators * 2) / 3) + 1).unwrap(),);
|
|
||||||
assert_eq!(params.n(), u16::try_from(coordinators).unwrap(),);
|
|
||||||
assert_eq!(*shares, 1);
|
|
||||||
participant_is.push(params.i());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CoordinatorMessage::Substrate(
|
|
||||||
messages::substrate::CoordinatorMessage::ConfirmKeyPair { .. },
|
|
||||||
) => {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_ => panic!("unexpected message: {msg:?}"),
|
|
||||||
}
|
}
|
||||||
|
_ => panic!("unexpected message: {msg:?}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
msg,
|
||||||
|
CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::GenerateKey {
|
||||||
|
id,
|
||||||
|
params: ThresholdParams::new(
|
||||||
|
u16::try_from(((coordinators * 2) / 3) + 1).unwrap(),
|
||||||
|
u16::try_from(coordinators).unwrap(),
|
||||||
|
participant_is[i],
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
shares: 1,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
processor
|
processor
|
||||||
.send_message(messages::key_gen::ProcessorMessage::Commitments {
|
.send_message(messages::key_gen::ProcessorMessage::Commitments {
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -83,46 +83,45 @@ async fn deallocate_stake(
|
|||||||
publish_tx(serai, &tx).await
|
publish_tx(serai, &tx).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn wait_till_next_epoch(serai: &Serai, current_epoch: u32) -> Session {
|
async fn get_session(serai: &Serai, network: NetworkId) -> Session {
|
||||||
let mut session = Session(current_epoch);
|
serai
|
||||||
while session.0 < current_epoch + 1 {
|
.as_of_latest_finalized_block()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.validator_sets()
|
||||||
|
.session(network)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn wait_till_next_epoch(serai: &Serai) -> Session {
|
||||||
|
let starting_session = get_session(serai, NetworkId::Serai).await;
|
||||||
|
|
||||||
|
let mut session = starting_session;
|
||||||
|
while session == starting_session {
|
||||||
sleep(Duration::from_secs(6)).await;
|
sleep(Duration::from_secs(6)).await;
|
||||||
session = serai
|
session = get_session(serai, NetworkId::Serai).await;
|
||||||
.as_of_latest_finalized_block()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.validator_sets()
|
|
||||||
.session(NetworkId::Serai)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
session
|
session
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_session(serai: &Serai, block: [u8; 32], network: NetworkId) -> Session {
|
async fn most_recent_new_set_event(serai: &Serai, network: NetworkId) -> ValidatorSetsEvent {
|
||||||
serai.as_of(block).validator_sets().session(network).await.unwrap().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn new_set_events(
|
|
||||||
serai: &Serai,
|
|
||||||
session: Session,
|
|
||||||
network: NetworkId,
|
|
||||||
) -> Vec<ValidatorSetsEvent> {
|
|
||||||
let mut current_block = serai.latest_finalized_block().await.unwrap();
|
let mut current_block = serai.latest_finalized_block().await.unwrap();
|
||||||
let mut current_session = get_session(serai, current_block.hash(), network).await;
|
loop {
|
||||||
|
|
||||||
while current_session == session {
|
|
||||||
let events = serai.as_of(current_block.hash()).validator_sets().new_set_events().await.unwrap();
|
let events = serai.as_of(current_block.hash()).validator_sets().new_set_events().await.unwrap();
|
||||||
if !events.is_empty() {
|
for event in events {
|
||||||
return events;
|
match event {
|
||||||
|
ValidatorSetsEvent::NewSet { set } => {
|
||||||
|
if set.network == network {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("new_set_events gave non-NewSet event: {event:?}"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_block = serai.block(current_block.header.parent_hash.0).await.unwrap().unwrap();
|
current_block = serai.block(current_block.header.parent_hash.0).await.unwrap().unwrap();
|
||||||
current_session = get_session(serai, current_block.hash(), network).await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("can't find the new set events for session: {} ", session.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@@ -130,33 +129,39 @@ async fn set_rotation_test() {
|
|||||||
new_test(
|
new_test(
|
||||||
|mut processors: Vec<Processor>| async move {
|
|mut processors: Vec<Processor>| async move {
|
||||||
// exclude the last processor from keygen since we will add him later
|
// exclude the last processor from keygen since we will add him later
|
||||||
let excluded = processors.pop().unwrap();
|
let mut excluded = processors.pop().unwrap();
|
||||||
assert_eq!(processors.len(), COORDINATORS);
|
assert_eq!(processors.len(), COORDINATORS);
|
||||||
|
|
||||||
// genesis keygen
|
|
||||||
let _ = key_gen::<Secp256k1>(&mut processors, Session(0)).await;
|
|
||||||
|
|
||||||
let pair5 = insecure_pair_from_name("Eve");
|
let pair5 = insecure_pair_from_name("Eve");
|
||||||
let network = NetworkId::Bitcoin;
|
let network = NetworkId::Bitcoin;
|
||||||
let amount = Amount(1_000_000 * 10_u64.pow(8));
|
let amount = Amount(1_000_000 * 10_u64.pow(8));
|
||||||
let serai = processors[0].serai().await;
|
let serai = processors[0].serai().await;
|
||||||
|
|
||||||
// add the last participant into validator set for btc network
|
// add the last participant into validator set for btc network
|
||||||
let block = allocate_stake(&serai, network, amount, &pair5, 0).await;
|
allocate_stake(&serai, network, amount, &pair5, 0).await;
|
||||||
|
|
||||||
|
// genesis keygen
|
||||||
|
let _ = key_gen::<Secp256k1>(&mut processors, Session(0)).await;
|
||||||
|
// Even the excluded processor should receive the key pair confirmation
|
||||||
|
match excluded.recv_message().await {
|
||||||
|
CoordinatorMessage::Substrate(
|
||||||
|
messages::substrate::CoordinatorMessage::ConfirmKeyPair { session, .. },
|
||||||
|
) => assert_eq!(session, Session(0)),
|
||||||
|
_ => panic!("excluded got message other than ConfirmKeyPair"),
|
||||||
|
}
|
||||||
|
|
||||||
// wait until next session to see the effect on coordinator
|
// wait until next session to see the effect on coordinator
|
||||||
let current_epoch = get_session(&serai, block, NetworkId::Serai).await;
|
wait_till_next_epoch(&serai).await;
|
||||||
let session = wait_till_next_epoch(&serai, current_epoch.0).await;
|
|
||||||
|
|
||||||
// verfiy that coordinator received new_set
|
// verfiy that coordinator received new_set
|
||||||
let events = new_set_events(&serai, session, network).await;
|
assert_eq!(
|
||||||
assert!(
|
most_recent_new_set_event(&serai, network).await,
|
||||||
events.contains(&ValidatorSetsEvent::NewSet { set: ValidatorSet { session, network } })
|
ValidatorSetsEvent::NewSet { set: ValidatorSet { session: Session(1), network } },
|
||||||
);
|
);
|
||||||
|
|
||||||
// add the last participant & do the keygen
|
// add the last participant & do the keygen
|
||||||
processors.push(excluded);
|
processors.push(excluded);
|
||||||
let _ = key_gen::<Secp256k1>(&mut processors, session).await;
|
let _ = key_gen::<Secp256k1>(&mut processors, Session(1)).await;
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user