mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-22 10:44:53 +00:00
Don't bind to the entire batch, solely the network and ID
This avoids needing to know the Batch in advance, avoiding a race condition.
This commit is contained in:
parent
67109c648c
commit
dc2656a538
3 changed files with 29 additions and 40 deletions
|
@ -373,9 +373,10 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
||||||
// See TributaryMutable's struct definition for why this block is safe
|
// See TributaryMutable's struct definition for why this block is safe
|
||||||
let KeyConfirmed { substrate_keys, network_keys } =
|
let KeyConfirmed { substrate_keys, network_keys } =
|
||||||
tributary_mutable.key_gen.confirm(txn, set, key_pair).await;
|
tributary_mutable.key_gen.confirm(txn, set, key_pair).await;
|
||||||
tributary_mutable
|
tributary_mutable.substrate_signers.insert(
|
||||||
.substrate_signers
|
substrate_keys.group_key().to_bytes(),
|
||||||
.insert(substrate_keys.group_key().to_bytes(), SubstrateSigner::new(substrate_keys));
|
SubstrateSigner::new(N::NETWORK, substrate_keys),
|
||||||
|
);
|
||||||
|
|
||||||
let key = network_keys.group_key();
|
let key = network_keys.group_key();
|
||||||
|
|
||||||
|
@ -516,7 +517,7 @@ async fn boot<N: Network, D: Db>(
|
||||||
let (substrate_keys, network_keys) = key_gen.keys(key);
|
let (substrate_keys, network_keys) = key_gen.keys(key);
|
||||||
|
|
||||||
let substrate_key = substrate_keys.group_key();
|
let substrate_key = substrate_keys.group_key();
|
||||||
let substrate_signer = SubstrateSigner::new(substrate_keys);
|
let substrate_signer = SubstrateSigner::new(N::NETWORK, substrate_keys);
|
||||||
// We don't have to load any state for this since the Scanner will re-fire any events
|
// We don't have to load any state for this since the Scanner will re-fire any events
|
||||||
// necessary
|
// necessary
|
||||||
substrate_signers.insert(substrate_key.to_bytes(), substrate_signer);
|
substrate_signers.insert(substrate_key.to_bytes(), substrate_signer);
|
||||||
|
|
|
@ -19,11 +19,27 @@ use frost_schnorrkel::Schnorrkel;
|
||||||
|
|
||||||
use log::{info, debug, warn};
|
use log::{info, debug, warn};
|
||||||
|
|
||||||
use serai_client::in_instructions::primitives::{Batch, SignedBatch, batch_message};
|
use serai_client::{
|
||||||
|
primitives::NetworkId,
|
||||||
|
in_instructions::primitives::{Batch, SignedBatch, batch_message},
|
||||||
|
};
|
||||||
|
|
||||||
use messages::{sign::SignId, coordinator::*};
|
use messages::{sign::SignId, coordinator::*};
|
||||||
use crate::{Get, DbTxn, Db};
|
use crate::{Get, DbTxn, Db};
|
||||||
|
|
||||||
|
// Generate an ID unique to a Batch
|
||||||
|
// TODO: Fork SignId to BatchSignId in order to just use the 5-byte encoding, not the hash of the
|
||||||
|
// 5-byte encoding
|
||||||
|
fn sign_id(network: NetworkId, id: u32) -> [u8; 32] {
|
||||||
|
let mut transcript = RecommendedTranscript::new(b"Serai Processor Batch Sign ID");
|
||||||
|
transcript.append_message(b"network", network.encode());
|
||||||
|
transcript.append_message(b"id", id.to_le_bytes());
|
||||||
|
|
||||||
|
let mut res = [0; 32];
|
||||||
|
res.copy_from_slice(&transcript.challenge(b"id")[.. 32]);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SubstrateSignerEvent {
|
pub enum SubstrateSignerEvent {
|
||||||
ProcessorMessage(ProcessorMessage),
|
ProcessorMessage(ProcessorMessage),
|
||||||
|
@ -37,16 +53,6 @@ impl<D: Db> SubstrateSignerDb<D> {
|
||||||
D::key(b"SUBSTRATE_SIGNER", dst, key)
|
D::key(b"SUBSTRATE_SIGNER", dst, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_id_key(id: u32) -> Vec<u8> {
|
|
||||||
Self::sign_key(b"sign_id", id.to_le_bytes())
|
|
||||||
}
|
|
||||||
fn save_sign_id(txn: &mut D::Transaction<'_>, id: u32, sign_id: [u8; 32]) {
|
|
||||||
txn.put(Self::sign_id_key(id), sign_id);
|
|
||||||
}
|
|
||||||
fn sign_id(txn: &mut D::Transaction<'_>, id: u32) -> [u8; 32] {
|
|
||||||
txn.get(Self::sign_id_key(id)).expect("completing a batch we never started").try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn completed_key(id: [u8; 32]) -> Vec<u8> {
|
fn completed_key(id: [u8; 32]) -> Vec<u8> {
|
||||||
Self::sign_key(b"completed", id)
|
Self::sign_key(b"completed", id)
|
||||||
}
|
}
|
||||||
|
@ -75,6 +81,7 @@ impl<D: Db> SubstrateSignerDb<D> {
|
||||||
pub struct SubstrateSigner<D: Db> {
|
pub struct SubstrateSigner<D: Db> {
|
||||||
db: PhantomData<D>,
|
db: PhantomData<D>,
|
||||||
|
|
||||||
|
network: NetworkId,
|
||||||
keys: ThresholdKeys<Ristretto>,
|
keys: ThresholdKeys<Ristretto>,
|
||||||
|
|
||||||
signable: HashMap<[u8; 32], Batch>,
|
signable: HashMap<[u8; 32], Batch>,
|
||||||
|
@ -96,10 +103,11 @@ impl<D: Db> fmt::Debug for SubstrateSigner<D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Db> SubstrateSigner<D> {
|
impl<D: Db> SubstrateSigner<D> {
|
||||||
pub fn new(keys: ThresholdKeys<Ristretto>) -> SubstrateSigner<D> {
|
pub fn new(network: NetworkId, keys: ThresholdKeys<Ristretto>) -> SubstrateSigner<D> {
|
||||||
SubstrateSigner {
|
SubstrateSigner {
|
||||||
db: PhantomData,
|
db: PhantomData,
|
||||||
|
|
||||||
|
network,
|
||||||
keys,
|
keys,
|
||||||
|
|
||||||
signable: HashMap::new(),
|
signable: HashMap::new(),
|
||||||
|
@ -214,28 +222,8 @@ impl<D: Db> SubstrateSigner<D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn sign(&mut self, txn: &mut D::Transaction<'_>, batch: Batch) {
|
pub async fn sign(&mut self, txn: &mut D::Transaction<'_>, batch: Batch) {
|
||||||
// Generate a unique ID to sign with
|
debug_assert_eq!(self.network, batch.network);
|
||||||
let id = {
|
let id = sign_id(batch.network, batch.id);
|
||||||
// TODO: Add this to in-instructions primitives
|
|
||||||
let mut transcript = RecommendedTranscript::new(b"Serai Processor Batch ID");
|
|
||||||
transcript.domain_separate(b"header");
|
|
||||||
transcript.append_message(b"network", batch.network.encode());
|
|
||||||
transcript.append_message(b"id", batch.id.to_le_bytes());
|
|
||||||
transcript.append_message(b"block", batch.block.0);
|
|
||||||
|
|
||||||
transcript.domain_separate(b"instructions");
|
|
||||||
for instruction in &batch.instructions {
|
|
||||||
// TODO: Either properly transcript this or simply encode the entire batch (since SCALE is
|
|
||||||
// canonical)
|
|
||||||
transcript.append_message(b"instruction", instruction.encode());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut res = [0; 32];
|
|
||||||
res.copy_from_slice(&transcript.challenge(b"id")[.. 32]);
|
|
||||||
res
|
|
||||||
};
|
|
||||||
SubstrateSignerDb::<D>::save_sign_id(txn, batch.id, id);
|
|
||||||
|
|
||||||
if SubstrateSignerDb::<D>::completed(txn, id) {
|
if SubstrateSignerDb::<D>::completed(txn, id) {
|
||||||
debug!("Sign batch order for ID we've already completed signing");
|
debug!("Sign batch order for ID we've already completed signing");
|
||||||
// See batch_signed for commentary on why this simply returns
|
// See batch_signed for commentary on why this simply returns
|
||||||
|
@ -370,7 +358,7 @@ impl<D: Db> SubstrateSigner<D> {
|
||||||
// block behind it, which will trigger starting the Batch
|
// block behind it, which will trigger starting the Batch
|
||||||
// TODO: There is a race condition between the Scanner recognizing the block and the Batch
|
// TODO: There is a race condition between the Scanner recognizing the block and the Batch
|
||||||
// having signing started
|
// having signing started
|
||||||
let sign_id = SubstrateSignerDb::<D>::sign_id(txn, id);
|
let sign_id = sign_id(self.network, id);
|
||||||
|
|
||||||
// Stop trying to sign for this batch
|
// Stop trying to sign for this batch
|
||||||
SubstrateSignerDb::<D>::complete(txn, sign_id);
|
SubstrateSignerDb::<D>::complete(txn, sign_id);
|
||||||
|
|
|
@ -53,7 +53,7 @@ async fn test_substrate_signer() {
|
||||||
let keys = keys.remove(&i).unwrap();
|
let keys = keys.remove(&i).unwrap();
|
||||||
t = keys.params().t();
|
t = keys.params().t();
|
||||||
|
|
||||||
let mut signer = SubstrateSigner::<MemDb>::new(keys);
|
let mut signer = SubstrateSigner::<MemDb>::new(NetworkId::Monero, keys);
|
||||||
let mut db = MemDb::new();
|
let mut db = MemDb::new();
|
||||||
let mut txn = db.txn();
|
let mut txn = db.txn();
|
||||||
signer.sign(&mut txn, batch.clone()).await;
|
signer.sign(&mut txn, batch.clone()).await;
|
||||||
|
|
Loading…
Reference in a new issue