mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-24 11:36:18 +00:00
Move ConfirmKeyPair from key_gen to substrate
Clarifies the emitter and accordingly why its mutations are justified.
This commit is contained in:
parent
059e79c98a
commit
e26b861d25
5 changed files with 81 additions and 99 deletions
|
@ -117,7 +117,7 @@ async fn handle_key_gen<D: Db, Pro: Processor>(
|
||||||
// TODO: Check how the processor handles thi being fired multiple times
|
// TODO: Check how the processor handles thi being fired multiple times
|
||||||
processor
|
processor
|
||||||
.send(CoordinatorMessage::KeyGen(
|
.send(CoordinatorMessage::KeyGen(
|
||||||
processor_messages::key_gen::CoordinatorMessage::ConfirmKeyPair {
|
processor_messages::substrate::CoordinatorMessage::ConfirmKeyPair {
|
||||||
context: SubstrateContext {
|
context: SubstrateContext {
|
||||||
coin_latest_finalized_block: serai
|
coin_latest_finalized_block: serai
|
||||||
.get_latest_block_for_network(block.hash(), set.network)
|
.get_latest_block_for_network(block.hash(), set.network)
|
||||||
|
|
|
@ -33,19 +33,13 @@ pub mod key_gen {
|
||||||
Commitments { id: KeyGenId, commitments: HashMap<Participant, Vec<u8>> },
|
Commitments { id: KeyGenId, commitments: HashMap<Participant, Vec<u8>> },
|
||||||
// Received shares for the specified key generation protocol.
|
// Received shares for the specified key generation protocol.
|
||||||
Shares { id: KeyGenId, shares: HashMap<Participant, Vec<u8>> },
|
Shares { id: KeyGenId, shares: HashMap<Participant, Vec<u8>> },
|
||||||
// Confirm a key pair.
|
|
||||||
ConfirmKeyPair { context: SubstrateContext, id: KeyGenId },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CoordinatorMessage {
|
impl CoordinatorMessage {
|
||||||
pub fn required_block(&self) -> Option<BlockHash> {
|
pub fn required_block(&self) -> Option<BlockHash> {
|
||||||
if let CoordinatorMessage::ConfirmKeyPair { context, .. } = self {
|
|
||||||
Some(context.coin_latest_finalized_block)
|
|
||||||
} else {
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
pub enum ProcessorMessage {
|
pub enum ProcessorMessage {
|
||||||
|
@ -152,6 +146,10 @@ pub mod substrate {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, Serialize, Deserialize)]
|
||||||
pub enum CoordinatorMessage {
|
pub enum CoordinatorMessage {
|
||||||
|
ConfirmKeyPair {
|
||||||
|
context: SubstrateContext,
|
||||||
|
id: key_gen::KeyGenId,
|
||||||
|
},
|
||||||
SubstrateBlock {
|
SubstrateBlock {
|
||||||
context: SubstrateContext,
|
context: SubstrateContext,
|
||||||
key: Vec<u8>,
|
key: Vec<u8>,
|
||||||
|
@ -162,6 +160,7 @@ pub mod substrate {
|
||||||
impl CoordinatorMessage {
|
impl CoordinatorMessage {
|
||||||
pub fn required_block(&self) -> Option<BlockHash> {
|
pub fn required_block(&self) -> Option<BlockHash> {
|
||||||
let context = match self {
|
let context = match self {
|
||||||
|
CoordinatorMessage::ConfirmKeyPair { context, .. } => context,
|
||||||
CoordinatorMessage::SubstrateBlock { context, .. } => context,
|
CoordinatorMessage::SubstrateBlock { context, .. } => context,
|
||||||
};
|
};
|
||||||
Some(context.coin_latest_finalized_block)
|
Some(context.coin_latest_finalized_block)
|
||||||
|
|
|
@ -16,18 +16,15 @@ use frost::{
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use serai_client::{primitives::BlockHash, validator_sets::primitives::ValidatorSet};
|
use serai_client::{primitives::BlockHash, validator_sets::primitives::ValidatorSet};
|
||||||
use messages::key_gen::*;
|
use messages::{SubstrateContext, key_gen::*};
|
||||||
|
|
||||||
use crate::{Get, DbTxn, Db, coins::Coin};
|
use crate::{Get, DbTxn, Db, coins::Coin};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum KeyGenEvent<C: Ciphersuite> {
|
pub struct KeyConfirmed<C: Ciphersuite> {
|
||||||
KeyConfirmed {
|
pub activation_block: BlockHash,
|
||||||
activation_block: BlockHash,
|
pub substrate_keys: ThresholdKeys<Ristretto>,
|
||||||
substrate_keys: ThresholdKeys<Ristretto>,
|
pub coin_keys: ThresholdKeys<C>,
|
||||||
coin_keys: ThresholdKeys<C>,
|
|
||||||
},
|
|
||||||
ProcessorMessage(ProcessorMessage),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -145,7 +142,7 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
||||||
self.db.keys(key)
|
self.db.keys(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle(&mut self, msg: CoordinatorMessage) -> KeyGenEvent<C::Curve> {
|
pub async fn handle(&mut self, msg: CoordinatorMessage) -> ProcessorMessage {
|
||||||
let context = |id: &KeyGenId| {
|
let context = |id: &KeyGenId| {
|
||||||
// TODO2: Also embed the chain ID/genesis block
|
// TODO2: Also embed the chain ID/genesis block
|
||||||
format!(
|
format!(
|
||||||
|
@ -192,7 +189,7 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
||||||
serialized.extend(commitments.1.serialize());
|
serialized.extend(commitments.1.serialize());
|
||||||
self.active_commit.insert(id.set, machines);
|
self.active_commit.insert(id.set, machines);
|
||||||
|
|
||||||
KeyGenEvent::ProcessorMessage(ProcessorMessage::Commitments { id, commitments: serialized })
|
ProcessorMessage::Commitments { id, commitments: serialized }
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordinatorMessage::Commitments { id, commitments } => {
|
CoordinatorMessage::Commitments { id, commitments } => {
|
||||||
|
@ -263,7 +260,7 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
||||||
KeyGenDb::<C, D>::save_commitments(&mut txn, &id, &commitments);
|
KeyGenDb::<C, D>::save_commitments(&mut txn, &id, &commitments);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
KeyGenEvent::ProcessorMessage(ProcessorMessage::Shares { id, shares })
|
ProcessorMessage::Shares { id, shares }
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordinatorMessage::Shares { id, shares } => {
|
CoordinatorMessage::Shares { id, shares } => {
|
||||||
|
@ -346,14 +343,20 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
||||||
|
|
||||||
let mut coin_keys = ThresholdKeys::new(coin_keys);
|
let mut coin_keys = ThresholdKeys::new(coin_keys);
|
||||||
C::tweak_keys(&mut coin_keys);
|
C::tweak_keys(&mut coin_keys);
|
||||||
KeyGenEvent::ProcessorMessage(ProcessorMessage::GeneratedKeyPair {
|
ProcessorMessage::GeneratedKeyPair {
|
||||||
id,
|
id,
|
||||||
substrate_key: substrate_keys.group_key().to_bytes(),
|
substrate_key: substrate_keys.group_key().to_bytes(),
|
||||||
coin_key: coin_keys.group_key().to_bytes().as_ref().to_vec(),
|
coin_key: coin_keys.group_key().to_bytes().as_ref().to_vec(),
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordinatorMessage::ConfirmKeyPair { context, id } => {
|
pub async fn confirm(
|
||||||
|
&mut self,
|
||||||
|
context: SubstrateContext,
|
||||||
|
id: KeyGenId,
|
||||||
|
) -> KeyConfirmed<C::Curve> {
|
||||||
let mut txn = self.db.0.txn();
|
let mut txn = self.db.0.txn();
|
||||||
let (substrate_keys, coin_keys) = KeyGenDb::<C, D>::confirm_keys(&mut txn, &id);
|
let (substrate_keys, coin_keys) = KeyGenDb::<C, D>::confirm_keys(&mut txn, &id);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
@ -365,12 +368,10 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
||||||
id
|
id
|
||||||
);
|
);
|
||||||
|
|
||||||
KeyGenEvent::KeyConfirmed {
|
KeyConfirmed {
|
||||||
activation_block: context.coin_latest_finalized_block,
|
activation_block: context.coin_latest_finalized_block,
|
||||||
substrate_keys,
|
substrate_keys,
|
||||||
coin_keys,
|
coin_keys,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ use coins::Bitcoin;
|
||||||
use coins::Monero;
|
use coins::Monero;
|
||||||
|
|
||||||
mod key_gen;
|
mod key_gen;
|
||||||
use key_gen::{KeyGenEvent, KeyGen};
|
use key_gen::{KeyConfirmed, KeyGen};
|
||||||
|
|
||||||
mod signer;
|
mod signer;
|
||||||
use signer::{SignerEvent, Signer};
|
use signer::{SignerEvent, Signer};
|
||||||
|
@ -288,11 +288,24 @@ async fn handle_coordinator_msg<D: Db, C: Coin, Co: Coordinator>(
|
||||||
|
|
||||||
match msg.msg.clone() {
|
match msg.msg.clone() {
|
||||||
CoordinatorMessage::KeyGen(msg) => {
|
CoordinatorMessage::KeyGen(msg) => {
|
||||||
match tributary_mutable.key_gen.handle(msg).await {
|
// TODO: This may be fired multiple times. What's our plan for that?
|
||||||
// This should only occur when Substrate confirms a key, enabling access of
|
coordinator.send(ProcessorMessage::KeyGen(tributary_mutable.key_gen.handle(msg).await)).await;
|
||||||
// substrate_mutable
|
}
|
||||||
// TODO: Move this under Substrate accordingly
|
|
||||||
KeyGenEvent::KeyConfirmed { activation_block, substrate_keys, coin_keys } => {
|
CoordinatorMessage::Sign(msg) => {
|
||||||
|
tributary_mutable.signers.get_mut(msg.key()).unwrap().handle(msg).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoordinatorMessage::Coordinator(msg) => {
|
||||||
|
tributary_mutable.substrate_signers.get_mut(msg.key()).unwrap().handle(msg).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoordinatorMessage::Substrate(msg) => {
|
||||||
|
match msg {
|
||||||
|
messages::substrate::CoordinatorMessage::ConfirmKeyPair { context, id } => {
|
||||||
|
// See TributaryMutable's struct definition for why this block is safe
|
||||||
|
let KeyConfirmed { activation_block, substrate_keys, coin_keys } =
|
||||||
|
tributary_mutable.key_gen.confirm(context, id).await;
|
||||||
tributary_mutable.substrate_signers.insert(
|
tributary_mutable.substrate_signers.insert(
|
||||||
substrate_keys.group_key().to_bytes().to_vec(),
|
substrate_keys.group_key().to_bytes().to_vec(),
|
||||||
SubstrateSigner::new(raw_db.clone(), substrate_keys),
|
SubstrateSigner::new(raw_db.clone(), substrate_keys),
|
||||||
|
@ -312,29 +325,13 @@ async fn handle_coordinator_msg<D: Db, C: Coin, Co: Coordinator>(
|
||||||
substrate_mutable
|
substrate_mutable
|
||||||
.schedulers
|
.schedulers
|
||||||
.insert(key.to_bytes().as_ref().to_vec(), Scheduler::<C>::new(key));
|
.insert(key.to_bytes().as_ref().to_vec(), Scheduler::<C>::new(key));
|
||||||
|
|
||||||
tributary_mutable.signers.insert(
|
tributary_mutable.signers.insert(
|
||||||
key.to_bytes().as_ref().to_vec(),
|
key.to_bytes().as_ref().to_vec(),
|
||||||
Signer::new(raw_db.clone(), coin.clone(), coin_keys),
|
Signer::new(raw_db.clone(), coin.clone(), coin_keys),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This may be fired multiple times. What's our plan for that?
|
|
||||||
KeyGenEvent::ProcessorMessage(msg) => {
|
|
||||||
coordinator.send(ProcessorMessage::KeyGen(msg)).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CoordinatorMessage::Sign(msg) => {
|
|
||||||
tributary_mutable.signers.get_mut(msg.key()).unwrap().handle(msg).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoordinatorMessage::Coordinator(msg) => {
|
|
||||||
tributary_mutable.substrate_signers.get_mut(msg.key()).unwrap().handle(msg).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoordinatorMessage::Substrate(msg) => {
|
|
||||||
match msg {
|
|
||||||
messages::substrate::CoordinatorMessage::SubstrateBlock {
|
messages::substrate::CoordinatorMessage::SubstrateBlock {
|
||||||
context,
|
context,
|
||||||
key: key_vec,
|
key: key_vec,
|
||||||
|
|
|
@ -17,7 +17,7 @@ use serai_client::{
|
||||||
use messages::{SubstrateContext, key_gen::*};
|
use messages::{SubstrateContext, key_gen::*};
|
||||||
use crate::{
|
use crate::{
|
||||||
coins::Coin,
|
coins::Coin,
|
||||||
key_gen::{KeyGenEvent, KeyGen},
|
key_gen::{KeyConfirmed, KeyGen},
|
||||||
};
|
};
|
||||||
|
|
||||||
const ID: KeyGenId =
|
const ID: KeyGenId =
|
||||||
|
@ -38,8 +38,7 @@ pub async fn test_key_gen<C: Coin>() {
|
||||||
let mut all_commitments = HashMap::new();
|
let mut all_commitments = HashMap::new();
|
||||||
for i in 1 ..= 5 {
|
for i in 1 ..= 5 {
|
||||||
let key_gen = key_gens.get_mut(&i).unwrap();
|
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||||
if let KeyGenEvent::ProcessorMessage(ProcessorMessage::Commitments { id, commitments }) =
|
if let ProcessorMessage::Commitments { id, commitments } = key_gen
|
||||||
key_gen
|
|
||||||
.handle(CoordinatorMessage::GenerateKey {
|
.handle(CoordinatorMessage::GenerateKey {
|
||||||
id: ID,
|
id: ID,
|
||||||
params: ThresholdParams::new(3, 5, Participant::new(u16::try_from(i).unwrap()).unwrap())
|
params: ThresholdParams::new(3, 5, Participant::new(u16::try_from(i).unwrap()).unwrap())
|
||||||
|
@ -68,7 +67,7 @@ pub async fn test_key_gen<C: Coin>() {
|
||||||
for i in 1 ..= 5 {
|
for i in 1 ..= 5 {
|
||||||
let key_gen = key_gens.get_mut(&i).unwrap();
|
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||||
let i = Participant::new(u16::try_from(i).unwrap()).unwrap();
|
let i = Participant::new(u16::try_from(i).unwrap()).unwrap();
|
||||||
if let KeyGenEvent::ProcessorMessage(ProcessorMessage::Shares { id, shares }) = key_gen
|
if let ProcessorMessage::Shares { id, shares } = key_gen
|
||||||
.handle(CoordinatorMessage::Commitments {
|
.handle(CoordinatorMessage::Commitments {
|
||||||
id: ID,
|
id: ID,
|
||||||
commitments: clone_without(&all_commitments, &i),
|
commitments: clone_without(&all_commitments, &i),
|
||||||
|
@ -90,11 +89,7 @@ pub async fn test_key_gen<C: Coin>() {
|
||||||
for i in 1 ..= 5 {
|
for i in 1 ..= 5 {
|
||||||
let key_gen = key_gens.get_mut(&i).unwrap();
|
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||||
let i = Participant::new(u16::try_from(i).unwrap()).unwrap();
|
let i = Participant::new(u16::try_from(i).unwrap()).unwrap();
|
||||||
if let KeyGenEvent::ProcessorMessage(ProcessorMessage::GeneratedKeyPair {
|
if let ProcessorMessage::GeneratedKeyPair { id, substrate_key, coin_key } = key_gen
|
||||||
id,
|
|
||||||
substrate_key,
|
|
||||||
coin_key,
|
|
||||||
}) = key_gen
|
|
||||||
.handle(CoordinatorMessage::Shares {
|
.handle(CoordinatorMessage::Shares {
|
||||||
id: ID,
|
id: ID,
|
||||||
shares: all_shares
|
shares: all_shares
|
||||||
|
@ -120,27 +115,17 @@ pub async fn test_key_gen<C: Coin>() {
|
||||||
|
|
||||||
for i in 1 ..= 5 {
|
for i in 1 ..= 5 {
|
||||||
let key_gen = key_gens.get_mut(&i).unwrap();
|
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||||
if let KeyGenEvent::KeyConfirmed { activation_block, substrate_keys, coin_keys } = key_gen
|
let KeyConfirmed { activation_block, substrate_keys, coin_keys } = key_gen
|
||||||
.handle(CoordinatorMessage::ConfirmKeyPair {
|
.confirm(SubstrateContext { coin_latest_finalized_block: BlockHash([0x11; 32]) }, ID)
|
||||||
context: SubstrateContext { coin_latest_finalized_block: BlockHash([0x11; 32]) },
|
.await;
|
||||||
id: ID,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
assert_eq!(activation_block, BlockHash([0x11; 32]));
|
assert_eq!(activation_block, BlockHash([0x11; 32]));
|
||||||
let params =
|
let params =
|
||||||
ThresholdParams::new(3, 5, Participant::new(u16::try_from(i).unwrap()).unwrap()).unwrap();
|
ThresholdParams::new(3, 5, Participant::new(u16::try_from(i).unwrap()).unwrap()).unwrap();
|
||||||
assert_eq!(substrate_keys.params(), params);
|
assert_eq!(substrate_keys.params(), params);
|
||||||
assert_eq!(coin_keys.params(), params);
|
assert_eq!(coin_keys.params(), params);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&(
|
&(substrate_keys.group_key().to_bytes(), coin_keys.group_key().to_bytes().as_ref().to_vec()),
|
||||||
substrate_keys.group_key().to_bytes(),
|
|
||||||
coin_keys.group_key().to_bytes().as_ref().to_vec()
|
|
||||||
),
|
|
||||||
res.as_ref().unwrap()
|
res.as_ref().unwrap()
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
panic!("didn't get key back");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue