mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 13:39:25 +00:00
Compare commits
5 Commits
6a7d803fe7
...
cca9e8cf16
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cca9e8cf16 | ||
|
|
97ef70fbd7 | ||
|
|
92275988dd | ||
|
|
c8f690e2f8 | ||
|
|
70add5b270 |
@@ -196,10 +196,10 @@ impl Serai {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn active_network_validators(&self, network: NetworkId) -> Result<Vec<Public>, SeraiError> {
|
async fn active_network_validators(&self, network: NetworkId) -> Result<Vec<Public>, SeraiError> {
|
||||||
let hash: String = self
|
let validators: String = self
|
||||||
.call("state_call", ["SeraiRuntimeApi_validators".to_string(), hex::encode(network.encode())])
|
.call("state_call", ["SeraiRuntimeApi_validators".to_string(), hex::encode(network.encode())])
|
||||||
.await?;
|
.await?;
|
||||||
let bytes = Self::hex_decode(hash)?;
|
let bytes = Self::hex_decode(validators)?;
|
||||||
let r = Vec::<Public>::decode(&mut bytes.as_slice())
|
let r = Vec::<Public>::decode(&mut bytes.as_slice())
|
||||||
.map_err(|e| SeraiError::ErrorInResponse(e.to_string()))?;
|
.map_err(|e| SeraiError::ErrorInResponse(e.to_string()))?;
|
||||||
Ok(r)
|
Ok(r)
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ use serai_client::{
|
|||||||
mod common;
|
mod common;
|
||||||
use common::validator_sets::{set_keys, allocate_stake, deallocate_stake};
|
use common::validator_sets::{set_keys, allocate_stake, deallocate_stake};
|
||||||
|
|
||||||
// TODO: get rid of this is constant and retrive the epoch numbers from sthe node directly
|
|
||||||
// since epochs doesn't always change at the exact intervals.
|
|
||||||
const EPOCH_INTERVAL: u64 = 300;
|
|
||||||
|
|
||||||
serai_test!(
|
serai_test!(
|
||||||
set_keys_test: (|serai: Serai| async move {
|
set_keys_test: (|serai: Serai| async move {
|
||||||
let network = NetworkId::Bitcoin;
|
let network = NetworkId::Bitcoin;
|
||||||
@@ -225,20 +221,38 @@ async fn validator_set_rotation() {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn epoch_for_block(serai: &Serai, block: [u8; 32]) -> u64 {
|
||||||
|
let epoch: String = serai
|
||||||
|
.call("state_call", ["BabeApi_current_epoch".to_string(), String::new(), hex::encode(block)])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
<u64 as scale::Decode>::decode(
|
||||||
|
&mut hex::decode(epoch.strip_prefix("0x").unwrap()).unwrap().as_slice(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
async fn verify_session_and_active_validators(
|
async fn verify_session_and_active_validators(
|
||||||
serai: &Serai,
|
serai: &Serai,
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
session: u64,
|
session: u64,
|
||||||
participants: &[Public],
|
participants: &[Public],
|
||||||
) {
|
) {
|
||||||
// wait untill the epoch block finalized
|
// wait untill the epoch block finalizes
|
||||||
let epoch_block = (session * EPOCH_INTERVAL) + 1;
|
let block = loop {
|
||||||
while serai.finalized_block_by_number(epoch_block).await.unwrap().is_none() {
|
let mut block = serai.latest_finalized_block_hash().await.unwrap();
|
||||||
// sleep 1 block
|
if epoch_for_block(serai, block).await < session {
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(6)).await;
|
// Sleep a block
|
||||||
}
|
tokio::time::sleep(tokio::time::Duration::from_secs(6)).await;
|
||||||
let serai_for_block =
|
continue;
|
||||||
serai.as_of(serai.finalized_block_by_number(epoch_block).await.unwrap().unwrap().hash());
|
}
|
||||||
|
while epoch_for_block(serai, block).await > session {
|
||||||
|
block = serai.block(block).await.unwrap().unwrap().header.parent_hash.0;
|
||||||
|
}
|
||||||
|
assert_eq!(epoch_for_block(serai, block).await, session);
|
||||||
|
break block;
|
||||||
|
};
|
||||||
|
let serai_for_block = serai.as_of(block);
|
||||||
|
|
||||||
// verify session
|
// verify session
|
||||||
let s = serai_for_block.validator_sets().session(network).await.unwrap().unwrap();
|
let s = serai_for_block.validator_sets().session(network).await.unwrap().unwrap();
|
||||||
@@ -251,9 +265,10 @@ async fn verify_session_and_active_validators(
|
|||||||
assert_eq!(validators, participants);
|
assert_eq!(validators, participants);
|
||||||
|
|
||||||
// make sure finalization continues as usual after the changes
|
// make sure finalization continues as usual after the changes
|
||||||
|
let current_finalized_block = serai.latest_finalized_block().await.unwrap().header.number;
|
||||||
tokio::time::timeout(tokio::time::Duration::from_secs(60), async move {
|
tokio::time::timeout(tokio::time::Duration::from_secs(60), async move {
|
||||||
let mut finalized_block = serai.latest_finalized_block().await.unwrap().header.number;
|
let mut finalized_block = serai.latest_finalized_block().await.unwrap().header.number;
|
||||||
while finalized_block <= epoch_block + 2 {
|
while finalized_block <= current_finalized_block + 2 {
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(6)).await;
|
tokio::time::sleep(tokio::time::Duration::from_secs(6)).await;
|
||||||
finalized_block = serai.latest_finalized_block().await.unwrap().header.number;
|
finalized_block = serai.latest_finalized_block().await.unwrap().header.number;
|
||||||
}
|
}
|
||||||
@@ -265,8 +280,7 @@ async fn verify_session_and_active_validators(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn get_active_session(serai: &Serai, network: NetworkId, hash: [u8; 32]) -> u64 {
|
async fn get_active_session(serai: &Serai, network: NetworkId, hash: [u8; 32]) -> u64 {
|
||||||
let block_number = serai.block(hash).await.unwrap().unwrap().header.number;
|
let epoch = epoch_for_block(serai, hash).await;
|
||||||
let epoch = block_number / EPOCH_INTERVAL;
|
|
||||||
|
|
||||||
// changes should be active in the next session
|
// changes should be active in the next session
|
||||||
if network == NetworkId::Serai {
|
if network == NetworkId::Serai {
|
||||||
|
|||||||
@@ -350,7 +350,7 @@ impl Processor {
|
|||||||
|
|
||||||
/// Receive a message from the coordinator as a processor.
|
/// Receive a message from the coordinator as a processor.
|
||||||
pub async fn recv_message(&mut self) -> CoordinatorMessage {
|
pub async fn recv_message(&mut self) -> CoordinatorMessage {
|
||||||
// Set a timeout of 30 minutes to allow effectively any protocol to occur without a fear of
|
// Set a timeout of 20 minutes to allow effectively any protocol to occur without a fear of
|
||||||
// an arbitrary timeout cutting it short
|
// an arbitrary timeout cutting it short
|
||||||
tokio::time::timeout(Duration::from_secs(20 * 60), self.msgs.recv()).await.unwrap().unwrap()
|
tokio::time::timeout(Duration::from_secs(20 * 60), self.msgs.recv()).await.unwrap().unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ pub async fn batch(
|
|||||||
async fn batch_test() {
|
async fn batch_test() {
|
||||||
new_test(
|
new_test(
|
||||||
|mut processors: Vec<Processor>| async move {
|
|mut processors: Vec<Processor>| async move {
|
||||||
// pop the last participant since genesis keygen has only 4 participant.
|
// pop the last participant since genesis keygen has only 4 participants
|
||||||
processors.pop().unwrap();
|
processors.pop().unwrap();
|
||||||
assert_eq!(processors.len(), COORDINATORS);
|
assert_eq!(processors.len(), COORDINATORS);
|
||||||
|
|
||||||
|
|||||||
@@ -32,16 +32,20 @@ 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() {
|
||||||
let mut found = false;
|
loop {
|
||||||
while !found {
|
|
||||||
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 {
|
||||||
|
id: this_id,
|
||||||
params,
|
params,
|
||||||
..
|
shares,
|
||||||
}) => {
|
}) => {
|
||||||
|
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());
|
participant_is.push(params.i());
|
||||||
found = true;
|
break;
|
||||||
}
|
}
|
||||||
CoordinatorMessage::Substrate(
|
CoordinatorMessage::Substrate(
|
||||||
messages::substrate::CoordinatorMessage::ConfirmKeyPair { .. },
|
messages::substrate::CoordinatorMessage::ConfirmKeyPair { .. },
|
||||||
@@ -50,20 +54,6 @@ pub async fn key_gen<C: Ciphersuite>(
|
|||||||
}
|
}
|
||||||
_ => 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
|
||||||
@@ -193,14 +183,14 @@ pub async fn key_gen<C: Ciphersuite>(
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.as_secs()
|
.as_secs()
|
||||||
.abs_diff(context.serai_time) <
|
.abs_diff(context.serai_time) <
|
||||||
(60 * 60 * 3) // 3hrs
|
(60 * 60 * 3) // 3 hours, which should exceed the length of any test we run
|
||||||
);
|
);
|
||||||
assert_eq!(context.network_latest_finalized_block.0, [0; 32]);
|
assert_eq!(context.network_latest_finalized_block.0, [0; 32]);
|
||||||
assert_eq!(set.session, session);
|
assert_eq!(set.session, session);
|
||||||
assert_eq!(key_pair.0 .0, substrate_key);
|
assert_eq!(key_pair.0 .0, substrate_key);
|
||||||
assert_eq!(&key_pair.1, &network_key);
|
assert_eq!(&key_pair.1, &network_key);
|
||||||
}
|
}
|
||||||
_ => panic!("coordinator didn't respond with ConfirmKeyPair msg: {msg:?}"),
|
_ => panic!("coordinator didn't respond with ConfirmKeyPair. msg: {msg:?}"),
|
||||||
}
|
}
|
||||||
message = Some(msg);
|
message = Some(msg);
|
||||||
} else {
|
} else {
|
||||||
@@ -233,7 +223,7 @@ pub async fn key_gen<C: Ciphersuite>(
|
|||||||
async fn key_gen_test() {
|
async fn key_gen_test() {
|
||||||
new_test(
|
new_test(
|
||||||
|mut processors: Vec<Processor>| async move {
|
|mut processors: Vec<Processor>| async move {
|
||||||
// pop the last participant since genesis keygen has only 4 participant.
|
// pop the last participant since genesis keygen has only 4 participants
|
||||||
processors.pop().unwrap();
|
processors.pop().unwrap();
|
||||||
assert_eq!(processors.len(), COORDINATORS);
|
assert_eq!(processors.len(), COORDINATORS);
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ pub(crate) async fn new_test(test_body: impl TestBody, fast_epoch: bool) {
|
|||||||
let mut coordinators = vec![];
|
let mut coordinators = vec![];
|
||||||
let mut test = DockerTest::new().with_network(dockertest::Network::Isolated);
|
let mut test = DockerTest::new().with_network(dockertest::Network::Isolated);
|
||||||
let mut coordinator_compositions = vec![];
|
let mut coordinator_compositions = vec![];
|
||||||
for i in 0 .. 5 {
|
// Spawn one extra coordinator which isn't in-set
|
||||||
|
#[allow(clippy::range_plus_one)]
|
||||||
|
for i in 0 .. (COORDINATORS + 1) {
|
||||||
let name = match i {
|
let name = match i {
|
||||||
0 => "Alice",
|
0 => "Alice",
|
||||||
1 => "Bob",
|
1 => "Bob",
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ use serai_client::{
|
|||||||
},
|
},
|
||||||
Amount, Pair, Transaction,
|
Amount, Pair, Transaction,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{*, tests::*};
|
use crate::{*, tests::*};
|
||||||
|
|
||||||
|
// TODO: This is duplicated with serai-client's tests
|
||||||
async fn publish_tx(serai: &Serai, tx: &Transaction) -> [u8; 32] {
|
async fn publish_tx(serai: &Serai, tx: &Transaction) -> [u8; 32] {
|
||||||
let mut latest = serai
|
let mut latest = serai
|
||||||
.block(serai.latest_finalized_block_hash().await.unwrap())
|
.block(serai.latest_finalized_block_hash().await.unwrap())
|
||||||
|
|||||||
Reference in New Issue
Block a user