mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-15 07:29:25 +00:00
fix part of tests
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -8176,6 +8176,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"pallet-babe",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
"serai-coins-pallet",
|
||||
|
||||
@@ -7,6 +7,7 @@ use blake2::{
|
||||
|
||||
use scale::Encode;
|
||||
|
||||
use serai_abi::primitives::insecure_pair_from_name;
|
||||
use serai_client::{
|
||||
primitives::{Amount, NetworkId, Coin, Balance, BlockHash, SeraiAddress},
|
||||
in_instructions::{
|
||||
@@ -45,7 +46,7 @@ serai_test!(
|
||||
}],
|
||||
};
|
||||
|
||||
let block = provide_batch(&serai, batch.clone()).await;
|
||||
let block = provide_batch(&serai, &[insecure_pair_from_name("Alice")], batch.clone()).await;
|
||||
|
||||
let serai = serai.as_of(block);
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@ serai_test!(
|
||||
}],
|
||||
};
|
||||
|
||||
let block = provide_batch(&serai, batch.clone()).await;
|
||||
let block = provide_batch(&serai, &[insecure_pair_from_name("Alice")], batch.clone()).await;
|
||||
|
||||
let instruction = {
|
||||
let serai = serai.as_of(block);
|
||||
|
||||
@@ -1,31 +1,29 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use rand_core::{RngCore, OsRng};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use ciphersuite::{Ciphersuite, Ristretto};
|
||||
use frost::dkg::musig::musig;
|
||||
use schnorrkel::Schnorrkel;
|
||||
|
||||
use sp_core::{sr25519::Signature, Pair as PairTrait};
|
||||
use sp_core::sr25519::Pair;
|
||||
|
||||
use serai_abi::{
|
||||
genesis_liquidity::primitives::{oraclize_values_message, Values},
|
||||
validator_sets::primitives::{musig_context, Session, ValidatorSet},
|
||||
validator_sets::primitives::{Session, ValidatorSet},
|
||||
in_instructions::primitives::{InInstruction, InInstructionWithBalance, Batch},
|
||||
primitives::{
|
||||
Amount, NetworkId, Coin, Balance, BlockHash, SeraiAddress, insecure_pair_from_name,
|
||||
},
|
||||
primitives::{Amount, NetworkId, Coin, Balance, BlockHash, SeraiAddress},
|
||||
};
|
||||
|
||||
use serai_client::{Serai, SeraiGenesisLiquidity};
|
||||
|
||||
use crate::common::{in_instructions::provide_batch, tx::publish_tx};
|
||||
use crate::common::{
|
||||
in_instructions::provide_batch,
|
||||
tx::{get_musig_of_pairs, publish_tx},
|
||||
validator_sets::get_ordered_keys,
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn set_up_genesis(
|
||||
serai: &Serai,
|
||||
coins: &[Coin],
|
||||
pairs: &[Pair],
|
||||
values: &HashMap<Coin, u64>,
|
||||
) -> (HashMap<Coin, Vec<(SeraiAddress, Amount)>>, HashMap<NetworkId, u32>) {
|
||||
// make accounts with amounts
|
||||
@@ -67,7 +65,7 @@ pub async fn set_up_genesis(
|
||||
|
||||
let batch =
|
||||
Batch { network: coin.network(), id: batch_ids[&coin.network()], block, instructions };
|
||||
provide_batch(serai, batch).await;
|
||||
provide_batch(serai, &get_ordered_keys(serai, coin.network(), pairs).await, batch).await;
|
||||
}
|
||||
|
||||
// set values relative to each other. We can do that without checking for genesis period blocks
|
||||
@@ -75,41 +73,19 @@ pub async fn set_up_genesis(
|
||||
// TODO: Random values here
|
||||
let values =
|
||||
Values { monero: values[&Coin::Monero], ether: values[&Coin::Ether], dai: values[&Coin::Dai] };
|
||||
set_values(serai, &values).await;
|
||||
set_values(serai, &get_ordered_keys(serai, NetworkId::Serai, pairs).await, &values).await;
|
||||
|
||||
(accounts, batch_ids)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
async fn set_values(serai: &Serai, values: &Values) {
|
||||
// prepare a Musig tx to oraclize the relative values
|
||||
let pair = insecure_pair_from_name("Alice");
|
||||
let public = pair.public();
|
||||
pub async fn set_values(serai: &Serai, pairs: &[Pair], values: &Values) {
|
||||
// we publish the tx in set 1
|
||||
let set = ValidatorSet { session: Session(1), network: NetworkId::Serai };
|
||||
|
||||
let public_key = <Ristretto as Ciphersuite>::read_G::<&[u8]>(&mut public.0.as_ref()).unwrap();
|
||||
let secret_key = <Ristretto as Ciphersuite>::read_F::<&[u8]>(
|
||||
&mut pair.as_ref().secret.to_bytes()[.. 32].as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Ristretto::generator() * secret_key, public_key);
|
||||
let threshold_keys =
|
||||
musig::<Ristretto>(&musig_context(set), &Zeroizing::new(secret_key), &[public_key]).unwrap();
|
||||
|
||||
let sig = frost::tests::sign_without_caching(
|
||||
&mut OsRng,
|
||||
frost::tests::algorithm_machines(
|
||||
&mut OsRng,
|
||||
&Schnorrkel::new(b"substrate"),
|
||||
&HashMap::from([(threshold_keys.params().i(), threshold_keys.into())]),
|
||||
),
|
||||
&oraclize_values_message(&set, values),
|
||||
);
|
||||
// prepare a Musig tx to oraclize the relative values
|
||||
let sig = get_musig_of_pairs(pairs, set, &oraclize_values_message(&set, values));
|
||||
|
||||
// oraclize values
|
||||
let _ =
|
||||
publish_tx(serai, &SeraiGenesisLiquidity::oraclize_values(*values, Signature(sig.to_bytes())))
|
||||
.await;
|
||||
let _ = publish_tx(serai, &SeraiGenesisLiquidity::oraclize_values(*values, sig)).await;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use blake2::{
|
||||
|
||||
use scale::Encode;
|
||||
|
||||
use sp_core::Pair;
|
||||
use sp_core::{sr25519::Pair, Pair as PairTrait};
|
||||
|
||||
use serai_client::{
|
||||
primitives::{insecure_pair_from_name, BlockHash, NetworkId, Balance, SeraiAddress},
|
||||
@@ -21,7 +21,7 @@ use serai_client::{
|
||||
use crate::common::{tx::publish_tx, validator_sets::set_keys};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn provide_batch(serai: &Serai, batch: Batch) -> [u8; 32] {
|
||||
pub async fn provide_batch(serai: &Serai, pairs: &[Pair], batch: Batch) -> [u8; 32] {
|
||||
let serai_latest = serai.as_of_latest_finalized_block().await.unwrap();
|
||||
let session = serai_latest.validator_sets().session(batch.network).await.unwrap().unwrap();
|
||||
let set = ValidatorSet { session, network: batch.network };
|
||||
@@ -31,7 +31,7 @@ pub async fn provide_batch(serai: &Serai, batch: Batch) -> [u8; 32] {
|
||||
keys
|
||||
} else {
|
||||
let keys = KeyPair(pair.public(), vec![].try_into().unwrap());
|
||||
set_keys(serai, set, keys.clone(), &[insecure_pair_from_name("Alice")]).await;
|
||||
set_keys(serai, set, keys.clone(), pairs).await;
|
||||
keys
|
||||
};
|
||||
assert_eq!(keys.0, pair.public());
|
||||
@@ -83,5 +83,5 @@ pub async fn mint_coin(
|
||||
}],
|
||||
};
|
||||
|
||||
provide_batch(serai, batch).await
|
||||
provide_batch(serai, &[insecure_pair_from_name("Alice")], batch).await
|
||||
}
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use rand_core::OsRng;
|
||||
use zeroize::Zeroizing;
|
||||
use serai_abi::validator_sets::primitives::{musig_context, ValidatorSet};
|
||||
|
||||
use tokio::time::sleep;
|
||||
|
||||
use serai_client::{Transaction, Serai};
|
||||
|
||||
use sp_core::{
|
||||
sr25519::{Pair, Signature},
|
||||
Pair as PairTrait,
|
||||
};
|
||||
|
||||
use ciphersuite::{Ciphersuite, Ristretto};
|
||||
use frost::dkg::musig::musig;
|
||||
use schnorrkel::Schnorrkel;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn publish_tx(serai: &Serai, tx: &Transaction) -> [u8; 32] {
|
||||
let mut latest = serai
|
||||
@@ -13,7 +28,12 @@ pub async fn publish_tx(serai: &Serai, tx: &Transaction) -> [u8; 32] {
|
||||
.unwrap()
|
||||
.number();
|
||||
|
||||
serai.publish(tx).await.unwrap();
|
||||
let r = serai.publish(tx).await;
|
||||
if r.is_err() {
|
||||
// put some delay before panic so that prints on the node side is flushed
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
r.unwrap();
|
||||
}
|
||||
|
||||
// Get the block it was included in
|
||||
// TODO: Add an RPC method for this/check the guarantee on the subscription
|
||||
@@ -44,3 +64,39 @@ pub async fn publish_tx(serai: &Serai, tx: &Transaction) -> [u8; 32] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_musig_of_pairs(pairs: &[Pair], set: ValidatorSet, msg: &[u8]) -> Signature {
|
||||
let mut pub_keys = vec![];
|
||||
for pair in pairs {
|
||||
let public_key =
|
||||
<Ristretto as Ciphersuite>::read_G::<&[u8]>(&mut pair.public().0.as_ref()).unwrap();
|
||||
pub_keys.push(public_key);
|
||||
}
|
||||
|
||||
let mut threshold_keys = vec![];
|
||||
for i in 0 .. pairs.len() {
|
||||
let secret_key = <Ristretto as Ciphersuite>::read_F::<&[u8]>(
|
||||
&mut pairs[i].as_ref().secret.to_bytes()[.. 32].as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(Ristretto::generator() * secret_key, pub_keys[i]);
|
||||
|
||||
threshold_keys.push(
|
||||
musig::<Ristretto>(&musig_context(set), &Zeroizing::new(secret_key), &pub_keys).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut musig_keys = HashMap::new();
|
||||
for tk in threshold_keys {
|
||||
musig_keys.insert(tk.params().i(), tk.into());
|
||||
}
|
||||
|
||||
let sig = frost::tests::sign_without_caching(
|
||||
&mut OsRng,
|
||||
frost::tests::algorithm_machines(&mut OsRng, &Schnorrkel::new(b"substrate"), &musig_keys),
|
||||
&msg,
|
||||
);
|
||||
|
||||
Signature(sig.to_bytes())
|
||||
}
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serai_abi::primitives::NetworkId;
|
||||
use zeroize::Zeroizing;
|
||||
use rand_core::OsRng;
|
||||
|
||||
use sp_core::{
|
||||
sr25519::{Pair, Signature},
|
||||
Pair as PairTrait,
|
||||
};
|
||||
|
||||
use ciphersuite::{Ciphersuite, Ristretto};
|
||||
use frost::dkg::musig::musig;
|
||||
use schnorrkel::Schnorrkel;
|
||||
use sp_core::{sr25519::Pair, Pair as PairTrait};
|
||||
|
||||
use serai_client::{
|
||||
validator_sets::{
|
||||
primitives::{ValidatorSet, KeyPair, musig_context, set_keys_message},
|
||||
primitives::{ValidatorSet, KeyPair, set_keys_message},
|
||||
ValidatorSetsEvent,
|
||||
},
|
||||
Amount, Serai, SeraiValidatorSets,
|
||||
};
|
||||
|
||||
use crate::common::tx::publish_tx;
|
||||
use crate::common::tx::{publish_tx, get_musig_of_pairs};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn set_keys(
|
||||
@@ -30,46 +19,12 @@ pub async fn set_keys(
|
||||
key_pair: KeyPair,
|
||||
pairs: &[Pair],
|
||||
) -> [u8; 32] {
|
||||
let mut pub_keys = vec![];
|
||||
for pair in pairs {
|
||||
let public_key =
|
||||
<Ristretto as Ciphersuite>::read_G::<&[u8]>(&mut pair.public().0.as_ref()).unwrap();
|
||||
pub_keys.push(public_key);
|
||||
}
|
||||
|
||||
let mut threshold_keys = vec![];
|
||||
for i in 0 .. pairs.len() {
|
||||
let secret_key = <Ristretto as Ciphersuite>::read_F::<&[u8]>(
|
||||
&mut pairs[i].as_ref().secret.to_bytes()[.. 32].as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(Ristretto::generator() * secret_key, pub_keys[i]);
|
||||
|
||||
threshold_keys.push(
|
||||
musig::<Ristretto>(&musig_context(set), &Zeroizing::new(secret_key), &pub_keys).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut musig_keys = HashMap::new();
|
||||
for tk in threshold_keys {
|
||||
musig_keys.insert(tk.params().i(), tk.into());
|
||||
}
|
||||
|
||||
let sig = frost::tests::sign_without_caching(
|
||||
&mut OsRng,
|
||||
frost::tests::algorithm_machines(&mut OsRng, &Schnorrkel::new(b"substrate"), &musig_keys),
|
||||
&set_keys_message(&set, &[], &key_pair),
|
||||
);
|
||||
let sig = get_musig_of_pairs(pairs, set, &set_keys_message(&set, &[], &key_pair));
|
||||
|
||||
// Set the key pair
|
||||
let block = publish_tx(
|
||||
serai,
|
||||
&SeraiValidatorSets::set_keys(
|
||||
set.network,
|
||||
vec![].try_into().unwrap(),
|
||||
key_pair.clone(),
|
||||
Signature(sig.to_bytes()),
|
||||
),
|
||||
&SeraiValidatorSets::set_keys(set.network, vec![].try_into().unwrap(), key_pair.clone(), sig),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -82,6 +37,29 @@ pub async fn set_keys(
|
||||
block
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn get_ordered_keys(serai: &Serai, network: NetworkId, accounts: &[Pair]) -> Vec<Pair> {
|
||||
// retrieve the current session validators so that we know the order of the keys
|
||||
// that is necessary for the correct musig signature.
|
||||
let validators = serai
|
||||
.as_of_latest_finalized_block()
|
||||
.await
|
||||
.unwrap()
|
||||
.validator_sets()
|
||||
.active_network_validators(network)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// collect the pairs of the validators
|
||||
let mut pairs = vec![];
|
||||
for v in validators {
|
||||
let p = accounts.iter().find(|pair| pair.public() == v).unwrap().clone();
|
||||
pairs.push(p);
|
||||
}
|
||||
|
||||
pairs
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn allocate_stake(
|
||||
serai: &Serai,
|
||||
|
||||
@@ -236,7 +236,7 @@ serai_test!(
|
||||
}],
|
||||
};
|
||||
|
||||
let block = provide_batch(&serai, batch).await;
|
||||
let block = provide_batch(&serai, &[insecure_pair_from_name("Alice")], batch).await;
|
||||
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||
events.retain(|e| matches!(e, DexEvent::LiquidityAdded { .. }));
|
||||
assert_eq!(
|
||||
@@ -299,6 +299,8 @@ serai_test!(
|
||||
let mut rand_bytes = vec![0; 32];
|
||||
OsRng.fill_bytes(&mut rand_bytes);
|
||||
|
||||
let pairs = [insecure_pair_from_name("Alice")];
|
||||
|
||||
// XMR -> ETH
|
||||
{
|
||||
// make an out address
|
||||
@@ -320,7 +322,7 @@ serai_test!(
|
||||
}],
|
||||
};
|
||||
|
||||
let block = provide_batch(&serai, batch).await;
|
||||
let block = provide_batch(&serai, &pairs, batch).await;
|
||||
coin1_batch_id += 1;
|
||||
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||
@@ -360,7 +362,7 @@ serai_test!(
|
||||
}],
|
||||
};
|
||||
|
||||
let block = provide_batch(&serai, batch).await;
|
||||
let block = provide_batch(&serai, &pairs, batch).await;
|
||||
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||
|
||||
@@ -398,7 +400,7 @@ serai_test!(
|
||||
}],
|
||||
};
|
||||
|
||||
let block = provide_batch(&serai, batch).await;
|
||||
let block = provide_batch(&serai, &pairs, batch).await;
|
||||
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ use serai_abi::{
|
||||
emissions::primitives::{INITIAL_REWARD_PER_BLOCK, SECURE_BY},
|
||||
in_instructions::primitives::Batch,
|
||||
primitives::{
|
||||
BlockHash, Coin, COINS, FAST_EPOCH_DURATION, FAST_EPOCH_INITIAL_PERIOD, NETWORKS,
|
||||
TARGET_BLOCK_TIME,
|
||||
insecure_pair_from_name, BlockHash, Coin, COINS, FAST_EPOCH_DURATION,
|
||||
FAST_EPOCH_INITIAL_PERIOD, NETWORKS, TARGET_BLOCK_TIME,
|
||||
},
|
||||
validator_sets::primitives::Session,
|
||||
};
|
||||
@@ -42,7 +42,12 @@ async fn send_batches(serai: &Serai, ids: &mut HashMap<NetworkId, u32>) {
|
||||
let mut block = BlockHash([0; 32]);
|
||||
OsRng.fill_bytes(&mut block.0);
|
||||
|
||||
provide_batch(serai, Batch { network, id: ids[&network], block, instructions: vec![] }).await;
|
||||
provide_batch(
|
||||
serai,
|
||||
&[insecure_pair_from_name("Alice")],
|
||||
Batch { network, id: ids[&network], block, instructions: vec![] },
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +56,8 @@ async fn test_emissions(serai: Serai) {
|
||||
// set up the genesis
|
||||
let coins = COINS.into_iter().filter(|c| *c != Coin::native()).collect::<Vec<_>>();
|
||||
let values = HashMap::from([(Coin::Monero, 184100), (Coin::Ether, 4785000), (Coin::Dai, 1500)]);
|
||||
let (_, mut batch_ids) = set_up_genesis(&serai, &coins, &values).await;
|
||||
let (_, mut batch_ids) =
|
||||
set_up_genesis(&serai, &coins, &[insecure_pair_from_name("Alice")], &values).await;
|
||||
|
||||
// wait until genesis is complete
|
||||
let mut genesis_complete_block = None;
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{time::Duration, collections::HashMap};
|
||||
|
||||
use serai_client::Serai;
|
||||
|
||||
use serai_abi::primitives::{Coin, COINS, Amount, GENESIS_SRI};
|
||||
use serai_abi::primitives::{insecure_pair_from_name, Amount, Coin, COINS, GENESIS_SRI};
|
||||
|
||||
use serai_client::genesis_liquidity::primitives::{
|
||||
GENESIS_LIQUIDITY_ACCOUNT, INITIAL_GENESIS_LP_SHARES,
|
||||
@@ -21,7 +21,8 @@ pub async fn test_genesis_liquidity(serai: Serai) {
|
||||
// set up the genesis
|
||||
let coins = COINS.into_iter().filter(|c| *c != Coin::native()).collect::<Vec<_>>();
|
||||
let values = HashMap::from([(Coin::Monero, 184100), (Coin::Ether, 4785000), (Coin::Dai, 1500)]);
|
||||
let (accounts, _) = set_up_genesis(&serai, &coins, &values).await;
|
||||
let (accounts, _) =
|
||||
set_up_genesis(&serai, &coins, &[insecure_pair_from_name("Alice")], &values).await;
|
||||
|
||||
// wait until genesis is complete
|
||||
while serai
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
use rand_core::{RngCore, OsRng};
|
||||
|
||||
use sp_core::{
|
||||
sr25519::{Public, Pair},
|
||||
Pair as PairTrait,
|
||||
};
|
||||
use sp_core::{sr25519::Public, Pair as PairTrait};
|
||||
|
||||
use serai_client::{
|
||||
primitives::{
|
||||
NETWORKS, NetworkId, BlockHash, insecure_pair_from_name, FAST_EPOCH_DURATION, TARGET_BLOCK_TIME,
|
||||
NETWORKS, NetworkId, BlockHash, insecure_pair_from_name, FAST_EPOCH_DURATION,
|
||||
TARGET_BLOCK_TIME, COINS, Coin,
|
||||
},
|
||||
validator_sets::{
|
||||
primitives::{Session, ValidatorSet, KeyPair},
|
||||
@@ -21,10 +19,7 @@ use serai_client::{
|
||||
};
|
||||
|
||||
mod common;
|
||||
use common::{
|
||||
tx::publish_tx,
|
||||
validator_sets::{allocate_stake, deallocate_stake, set_keys},
|
||||
};
|
||||
use common::{tx::publish_tx, validator_sets::*, genesis_liquidity::set_up_genesis};
|
||||
|
||||
fn get_random_key_pair() -> KeyPair {
|
||||
let mut ristretto_key = [0; 32];
|
||||
@@ -34,28 +29,6 @@ fn get_random_key_pair() -> KeyPair {
|
||||
KeyPair(Public(ristretto_key), external_key.try_into().unwrap())
|
||||
}
|
||||
|
||||
async fn get_ordered_keys(serai: &Serai, network: NetworkId, accounts: &[Pair]) -> Vec<Pair> {
|
||||
// retrieve the current session validators so that we know the order of the keys
|
||||
// that is necessary for the correct musig signature.
|
||||
let validators = serai
|
||||
.as_of_latest_finalized_block()
|
||||
.await
|
||||
.unwrap()
|
||||
.validator_sets()
|
||||
.active_network_validators(network)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// collect the pairs of the validators
|
||||
let mut pairs = vec![];
|
||||
for v in validators {
|
||||
let p = accounts.iter().find(|pair| pair.public() == v).unwrap().clone();
|
||||
pairs.push(p);
|
||||
}
|
||||
|
||||
pairs
|
||||
}
|
||||
|
||||
serai_test!(
|
||||
set_keys_test: (|serai: Serai| async move {
|
||||
let network = NetworkId::Bitcoin;
|
||||
@@ -213,13 +186,19 @@ async fn validator_set_rotation() {
|
||||
(NetworkId::Ethereum, default_participants),
|
||||
]);
|
||||
|
||||
// set up the genesis
|
||||
let coins = COINS.into_iter().filter(|c| *c != Coin::native()).collect::<Vec<_>>();
|
||||
let values =
|
||||
HashMap::from([(Coin::Monero, 184100), (Coin::Ether, 4785000), (Coin::Dai, 1500)]);
|
||||
let (_, mut batch_ids) = set_up_genesis(&serai, &coins, &accounts, &values).await;
|
||||
|
||||
// test the set rotation
|
||||
for (i, network) in NETWORKS.into_iter().enumerate() {
|
||||
let participants = participants.get_mut(&network).unwrap();
|
||||
|
||||
// we start the chain with 4 default participants that has a single key share each
|
||||
participants.sort();
|
||||
verify_session_and_active_validators(&serai, network, 0, participants).await;
|
||||
verify_session_and_active_validators(&serai, network, 1, participants).await;
|
||||
|
||||
// add 1 participant
|
||||
let last_participant = accounts[4].clone();
|
||||
@@ -236,33 +215,6 @@ async fn validator_set_rotation() {
|
||||
let activation_session = get_session_at_which_changes_activate(&serai, network, hash).await;
|
||||
|
||||
// set the keys if it is an external set
|
||||
if network != NetworkId::Serai {
|
||||
let set = ValidatorSet { session: Session(0), network };
|
||||
let key_pair = get_random_key_pair();
|
||||
let pairs = get_ordered_keys(&serai, network, &accounts).await;
|
||||
set_keys(&serai, set, key_pair, &pairs).await;
|
||||
}
|
||||
|
||||
// verify
|
||||
participants.sort();
|
||||
verify_session_and_active_validators(&serai, network, activation_session, participants)
|
||||
.await;
|
||||
|
||||
// remove 1 participant
|
||||
let participant_to_remove = accounts[1].clone();
|
||||
let hash = deallocate_stake(
|
||||
&serai,
|
||||
network,
|
||||
key_shares[&network],
|
||||
&participant_to_remove,
|
||||
i.try_into().unwrap(),
|
||||
)
|
||||
.await;
|
||||
participants.swap_remove(
|
||||
participants.iter().position(|k| *k == participant_to_remove.public()).unwrap(),
|
||||
);
|
||||
let activation_session = get_session_at_which_changes_activate(&serai, network, hash).await;
|
||||
|
||||
if network != NetworkId::Serai {
|
||||
// set the keys if it is an external set
|
||||
let set = ValidatorSet { session: Session(1), network };
|
||||
@@ -283,7 +235,87 @@ async fn validator_set_rotation() {
|
||||
// provide a batch to complete the handover and retire the previous set
|
||||
let mut block_hash = BlockHash([0; 32]);
|
||||
OsRng.fill_bytes(&mut block_hash.0);
|
||||
let batch = Batch { network, id: 0, block: block_hash, instructions: vec![] };
|
||||
|
||||
// set up batch id
|
||||
batch_ids
|
||||
.entry(network)
|
||||
.and_modify(|v| {
|
||||
*v += 1;
|
||||
})
|
||||
.or_insert(0);
|
||||
|
||||
let batch =
|
||||
Batch { network, id: batch_ids[&network], block: block_hash, instructions: vec![] };
|
||||
publish_tx(
|
||||
&serai,
|
||||
&SeraiInInstructions::execute_batch(SignedBatch {
|
||||
batch: batch.clone(),
|
||||
signature: substrate_pair.sign(&batch_message(&batch)),
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
// verify
|
||||
participants.sort();
|
||||
verify_session_and_active_validators(&serai, network, activation_session, participants)
|
||||
.await;
|
||||
|
||||
// remove 1 participant
|
||||
let participant_to_remove = accounts[1].clone();
|
||||
let allocation = serai
|
||||
.as_of_latest_finalized_block()
|
||||
.await
|
||||
.unwrap()
|
||||
.validator_sets()
|
||||
.allocation(network, participant_to_remove.public())
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let hash = deallocate_stake(
|
||||
&serai,
|
||||
network,
|
||||
allocation,
|
||||
&participant_to_remove,
|
||||
i.try_into().unwrap(),
|
||||
)
|
||||
.await;
|
||||
participants.swap_remove(
|
||||
participants.iter().position(|k| *k == participant_to_remove.public()).unwrap(),
|
||||
);
|
||||
let activation_session = get_session_at_which_changes_activate(&serai, network, hash).await;
|
||||
|
||||
if network != NetworkId::Serai {
|
||||
// set the keys if it is an external set
|
||||
let set = ValidatorSet { session: Session(2), network };
|
||||
|
||||
// we need the whole substrate key pair to sign the batch
|
||||
let (substrate_pair, key_pair) = {
|
||||
let pair = insecure_pair_from_name("session-2-key-pair");
|
||||
let public = pair.public();
|
||||
|
||||
let mut external_key = vec![0; 33];
|
||||
OsRng.fill_bytes(&mut external_key);
|
||||
|
||||
(pair, KeyPair(public, external_key.try_into().unwrap()))
|
||||
};
|
||||
let pairs = get_ordered_keys(&serai, network, &accounts).await;
|
||||
set_keys(&serai, set, key_pair, &pairs).await;
|
||||
|
||||
// provide a batch to complete the handover and retire the previous set
|
||||
let mut block_hash = BlockHash([0; 32]);
|
||||
OsRng.fill_bytes(&mut block_hash.0);
|
||||
|
||||
// set up batch id
|
||||
batch_ids
|
||||
.entry(network)
|
||||
.and_modify(|v| {
|
||||
*v += 1;
|
||||
})
|
||||
.or_insert(0);
|
||||
|
||||
let batch =
|
||||
Batch { network, id: batch_ids[&network], block: block_hash, instructions: vec![] };
|
||||
publish_tx(
|
||||
&serai,
|
||||
&SeraiInInstructions::execute_batch(SignedBatch {
|
||||
@@ -312,7 +344,7 @@ async fn validator_set_rotation() {
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(pending, Some(key_shares[&network]));
|
||||
assert_eq!(pending, Some(allocation));
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
||||
@@ -29,6 +29,8 @@ sp-std = { git = "https://github.com/serai-dex/substrate", default-features = fa
|
||||
sp-core = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||
sp-application-crypto = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||
|
||||
pallet-babe = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||
|
||||
dex-pallet = { package = "serai-dex-pallet", path = "../../dex/pallet", default-features = false }
|
||||
coins-pallet = { package = "serai-coins-pallet", path = "../../coins/pallet", default-features = false }
|
||||
validator-sets-pallet = { package = "serai-validator-sets-pallet", path = "../../validator-sets/pallet", default-features = false }
|
||||
@@ -51,6 +53,8 @@ std = [
|
||||
"sp-core/std",
|
||||
"sp-application-crypto/std",
|
||||
|
||||
"pallet-babe/std",
|
||||
|
||||
"coins-pallet/std",
|
||||
"dex-pallet/std",
|
||||
"validator-sets-pallet/std",
|
||||
|
||||
@@ -19,6 +19,7 @@ pub mod pallet {
|
||||
use dex_pallet::{Pallet as Dex, Config as DexConfig};
|
||||
use coins_pallet::{Config as CoinsConfig, Pallet as Coins};
|
||||
use validator_sets_pallet::{Config as VsConfig, Pallet as ValidatorSets, GenesisCompleted};
|
||||
use pallet_babe::{Config as BabeConfig, Pallet as Babe};
|
||||
|
||||
use economic_security_pallet::{Config as EconomicSecurityConfig, Pallet as EconomicSecurity};
|
||||
|
||||
@@ -35,6 +36,7 @@ pub mod pallet {
|
||||
pub trait Config:
|
||||
frame_system::Config
|
||||
+ VsConfig
|
||||
+ BabeConfig
|
||||
+ DexConfig
|
||||
+ EconomicSecurityConfig
|
||||
+ CoinsConfig
|
||||
@@ -425,11 +427,8 @@ pub mod pallet {
|
||||
};
|
||||
|
||||
let set = ValidatorSet { network, session };
|
||||
let signers = ValidatorSets::<T>::participants_for_latest_decided_set(network)
|
||||
.expect("no participant in the current set")
|
||||
.into_iter()
|
||||
.map(|(p, _)| p)
|
||||
.collect::<Vec<_>>();
|
||||
let signers =
|
||||
Babe::<T>::authorities().into_iter().map(|(p, _)| p.into_inner()).collect::<Vec<_>>();
|
||||
|
||||
// check this didn't get called before
|
||||
if Self::oraclization_is_done() {
|
||||
|
||||
Reference in New Issue
Block a user