Skip to content

Commit

Permalink
Correct processor flow to have the coordinator decide signing set/re-…
Browse files Browse the repository at this point in the history
…attempts

The signing set should be the first group to submit preprocesses to Tributary.
Re-attempts shouldn't be once every 30s, yet n blocks since the last relevant
message.

Removes the use of an async task/channel in the signer (and Substrate signer).
Also removes the need to be able to get the time from a coin's block, which was
a fragile system marked with a TODO already.
  • Loading branch information
kayabaNerve committed Apr 16, 2023
1 parent e21fc5f commit e2571a4
Show file tree
Hide file tree
Showing 17 changed files with 446 additions and 711 deletions.
3 changes: 0 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions processor/messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
zeroize = { version = "1", features = ["derive"] }

rand_core = "0.6"
rand_chacha = "0.3"
transcript = { package = "flexible-transcript", path = "../../crypto/transcript" }

serde = { version = "1", features = ["derive"] }

dkg = { path = "../../crypto/dkg", features = ["serde"] }
Expand Down
35 changes: 7 additions & 28 deletions processor/messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ use std::collections::HashMap;

use zeroize::Zeroize;

use rand_core::{RngCore, SeedableRng};
use rand_chacha::ChaCha8Rng;
use transcript::{Transcript, RecommendedTranscript};

use serde::{Serialize, Deserialize};

use dkg::{Participant, ThresholdParams};
Expand All @@ -17,7 +13,6 @@ use validator_sets_primitives::ValidatorSet;

#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize, Serialize, Deserialize)]
pub struct SubstrateContext {
pub time: u64,
pub coin_latest_finalized_block: BlockHash,
}

Expand Down Expand Up @@ -73,35 +68,14 @@ pub mod sign {
pub attempt: u32,
}

impl SignId {
/// Determine a signing set for a given signing session.
// TODO: Replace with ROAST or the first available group of signers.
// https://github.com/serai-dex/serai/issues/163
pub fn signing_set(&self, params: &ThresholdParams) -> Vec<Participant> {
let mut transcript = RecommendedTranscript::new(b"SignId signing_set");
transcript.domain_separate(b"SignId");
transcript.append_message(b"key", &self.key);
transcript.append_message(b"id", self.id);
transcript.append_message(b"attempt", self.attempt.to_le_bytes());

let mut candidates =
(1 ..= params.n()).map(|i| Participant::new(i).unwrap()).collect::<Vec<_>>();
let mut rng = ChaCha8Rng::from_seed(transcript.rng_seed(b"signing_set"));
while candidates.len() > params.t().into() {
candidates.swap_remove(
usize::try_from(rng.next_u64() % u64::try_from(candidates.len()).unwrap()).unwrap(),
);
}
candidates
}
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub enum CoordinatorMessage {
// Received preprocesses for the specified signing protocol.
Preprocesses { id: SignId, preprocesses: HashMap<Participant, Vec<u8>> },
// Received shares for the specified signing protocol.
Shares { id: SignId, shares: HashMap<Participant, Vec<u8>> },
// Re-attempt a signing protocol.
Reattempt { id: SignId },
// Completed a signing protocol already.
Completed { key: Vec<u8>, id: [u8; 32], tx: Vec<u8> },
}
Expand All @@ -125,6 +99,7 @@ pub mod sign {
match self {
CoordinatorMessage::Preprocesses { id, .. } => &id.key,
CoordinatorMessage::Shares { id, .. } => &id.key,
CoordinatorMessage::Reattempt { id } => &id.key,
CoordinatorMessage::Completed { key, .. } => key,
}
}
Expand All @@ -139,6 +114,8 @@ pub mod coordinator {
// Uses Vec<u8> instead of [u8; 64] since serde Deserialize isn't implemented for [u8; 64]
BatchPreprocesses { id: SignId, preprocesses: HashMap<Participant, Vec<u8>> },
BatchShares { id: SignId, shares: HashMap<Participant, [u8; 32]> },
// Re-attempt a batch signing protocol.
BatchReattempt { id: SignId },
// Needed so a client which didn't participate in signing can still realize signing completed
BatchSigned { key: Vec<u8>, block: BlockHash },
}
Expand All @@ -148,6 +125,7 @@ pub mod coordinator {
Some(match self {
CoordinatorMessage::BatchPreprocesses { id, .. } => BlockHash(id.id),
CoordinatorMessage::BatchShares { id, .. } => BlockHash(id.id),
CoordinatorMessage::BatchReattempt { id } => BlockHash(id.id),
CoordinatorMessage::BatchSigned { block, .. } => *block,
})
}
Expand All @@ -156,6 +134,7 @@ pub mod coordinator {
match self {
CoordinatorMessage::BatchPreprocesses { id, .. } => &id.key,
CoordinatorMessage::BatchShares { id, .. } => &id.key,
CoordinatorMessage::BatchReattempt { id } => &id.key,
CoordinatorMessage::BatchSigned { key, .. } => key,
}
}
Expand Down
9 changes: 1 addition & 8 deletions processor/src/coins/bitcoin.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use std::{
time::{SystemTime, Duration},
io,
collections::HashMap,
};
use std::{time::Duration, io, collections::HashMap};

use async_trait::async_trait;

Expand Down Expand Up @@ -201,9 +197,6 @@ impl BlockTrait<Bitcoin> for Block {
hash.reverse();
hash
}
fn time(&self) -> SystemTime {
SystemTime::UNIX_EPOCH + Duration::from_secs(self.header.time.into())
}
fn median_fee(&self) -> Fee {
// TODO
Fee(20)
Expand Down
3 changes: 1 addition & 2 deletions processor/src/coins/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::fmt::Debug;
use std::{time::SystemTime, io, collections::HashMap};
use std::{io, collections::HashMap};

use async_trait::async_trait;
use thiserror::Error;
Expand Down Expand Up @@ -175,7 +175,6 @@ pub trait Block<C: Coin>: Send + Sync + Sized + Clone + Debug {
// This is currently bounded to being 32-bytes.
type Id: 'static + Id;
fn id(&self) -> Self::Id;
fn time(&self) -> SystemTime;
fn median_fee(&self) -> C::Fee;
}

Expand Down
10 changes: 1 addition & 9 deletions processor/src/coins/monero.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use std::{
time::{SystemTime, Duration},
collections::HashMap,
io,
};
use std::{time::Duration, collections::HashMap, io};

use async_trait::async_trait;

Expand Down Expand Up @@ -146,10 +142,6 @@ impl BlockTrait<Monero> for Block {
self.0
}

fn time(&self) -> SystemTime {
SystemTime::UNIX_EPOCH + Duration::from_secs(self.1.header.timestamp)
}

fn median_fee(&self) -> Fee {
// TODO
Fee { per_weight: 80000, mask: 10000 }
Expand Down
8 changes: 3 additions & 5 deletions processor/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl<C: Coin, D: Db> MainDb<C, D> {
fn signing_key(key: &[u8]) -> Vec<u8> {
Self::main_key(b"signing", key)
}
pub fn save_signing(&mut self, key: &[u8], block_number: u64, time: u64, plan: &Plan<C>) {
pub fn save_signing(&mut self, key: &[u8], block_number: u64, plan: &Plan<C>) {
let id = plan.id();
// Creating a TXN here is arguably an anti-pattern, yet nothing here expects atomicity
let mut txn = self.0.txn();
Expand All @@ -43,15 +43,14 @@ impl<C: Coin, D: Db> MainDb<C, D> {

{
let mut buf = block_number.to_le_bytes().to_vec();
buf.extend(&time.to_le_bytes());
plan.write(&mut buf).unwrap();
txn.put(Self::plan_key(&id), &buf);
}

txn.commit();
}

pub fn signing(&self, key: &[u8]) -> Vec<(u64, u64, Plan<C>)> {
pub fn signing(&self, key: &[u8]) -> Vec<(u64, Plan<C>)> {
let signing = self.0.get(Self::signing_key(key)).unwrap_or(vec![]);
let mut res = vec![];

Expand All @@ -61,10 +60,9 @@ impl<C: Coin, D: Db> MainDb<C, D> {
let buf = self.0.get(Self::plan_key(id)).unwrap();

let block_number = u64::from_le_bytes(buf[.. 8].try_into().unwrap());
let time = u64::from_le_bytes(buf[8 .. 16].try_into().unwrap());
let plan = Plan::<C>::read::<&[u8]>(&mut &buf[16 ..]).unwrap();
assert_eq!(id, &plan.id());
res.push((block_number, time, plan));
res.push((block_number, plan));
}

res
Expand Down
Loading

0 comments on commit e2571a4

Please sign in to comment.