use std::collections::HashMap; use serai_abi::primitives::NetworkId; use zeroize::Zeroizing; use rand_core::OsRng; use sp_core::{ ConstU32, bounded::BoundedVec, sr25519::{Pair, Signature}, Pair as PairTrait, }; use dalek_ff_group::Ristretto; use ciphersuite::Ciphersuite; use dkg_musig::musig; use schnorrkel::Schnorrkel; use serai_client::{ primitives::{EmbeddedEllipticCurve, Amount}, validator_sets::{ primitives::{MAX_KEY_LEN, ExternalValidatorSet, KeyPair, musig_context, set_keys_message}, ValidatorSetsEvent, }, SeraiValidatorSets, Serai, }; use crate::common::tx::publish_tx; #[allow(dead_code)] pub async fn set_keys( serai: &Serai, set: ExternalValidatorSet, key_pair: KeyPair, pairs: &[Pair], ) -> [u8; 32] { let mut pub_keys = vec![]; for pair in pairs { let public_key = ::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 = ::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::(musig_context(set.into()), Zeroizing::new(secret_key), &pub_keys).unwrap(), ); } let mut musig_keys = HashMap::new(); for threshold_keys in threshold_keys { musig_keys.insert(threshold_keys.params().i(), threshold_keys); } 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), ); // Set the key pair let block = publish_tx( serai, &SeraiValidatorSets::set_keys( set.network, key_pair.clone(), bitvec::bitvec!(u8, bitvec::prelude::Lsb0; 1; musig_keys.len()), Signature(sig.to_bytes()), ), ) .await; assert_eq!( serai.as_of(block).validator_sets().key_gen_events().await.unwrap(), vec![ValidatorSetsEvent::KeyGen { set, key_pair: key_pair.clone() }] ); assert_eq!(serai.as_of(block).validator_sets().keys(set).await.unwrap(), Some(key_pair)); block } #[allow(dead_code)] pub async fn set_embedded_elliptic_curve_key( serai: &Serai, pair: &Pair, embedded_elliptic_curve: EmbeddedEllipticCurve, key: BoundedVec>, nonce: u32, ) -> [u8; 32] { // get the call let tx = serai.sign( pair, SeraiValidatorSets::set_embedded_elliptic_curve_key(embedded_elliptic_curve, key), nonce, 0, ); publish_tx(serai, &tx).await } #[allow(dead_code)] pub async fn allocate_stake( serai: &Serai, network: NetworkId, amount: Amount, pair: &Pair, nonce: u32, ) -> [u8; 32] { // get the call let tx = serai.sign(pair, SeraiValidatorSets::allocate(network, amount), nonce, 0); publish_tx(serai, &tx).await } #[allow(dead_code)] pub async fn deallocate_stake( serai: &Serai, network: NetworkId, amount: Amount, pair: &Pair, nonce: u32, ) -> [u8; 32] { // get the call let tx = serai.sign(pair, SeraiValidatorSets::deallocate(network, amount), nonce, 0); publish_tx(serai, &tx).await }