mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-23 03:59:22 +00:00
Properly route attempt around DkgConfirmer
This commit is contained in:
parent
fa8ff62b09
commit
3f3f6b2d0c
3 changed files with 28 additions and 23 deletions
|
@ -480,11 +480,10 @@ pub async fn handle_processors<D: Db, Pro: Processors, P: P2p>(
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// TODO: Dispatch this message to a task dedicated to handling this processor, preventing one
|
// TODO: Dispatch this message to a task dedicated to handling this processor, preventing one
|
||||||
// processor from holding up all the others
|
// processor from holding up all the others. This would require a peek method be added to the
|
||||||
// In order to do so, we need to locally track if a message was handled, even if its ID is
|
// message-queue (to view multiple future messages at once)
|
||||||
// greater than what the message-queue tracks as ack'd
|
// TODO: Do we handle having handled a message, by DB, yet having rebooted before `ack`ing it?
|
||||||
// TODO: Shouldn't the processor also perform such checks? That its ack doesn't exceed the
|
// Does the processor?
|
||||||
// queue's?
|
|
||||||
let msg = processors.recv().await;
|
let msg = processors.recv().await;
|
||||||
|
|
||||||
// TODO2: This is slow, and only works as long as a network only has a single Tributary
|
// TODO2: This is slow, and only works as long as a network only has a single Tributary
|
||||||
|
@ -511,12 +510,7 @@ pub async fn handle_processors<D: Db, Pro: Processors, P: P2p>(
|
||||||
}
|
}
|
||||||
key_gen::ProcessorMessage::Shares { id, mut shares } => {
|
key_gen::ProcessorMessage::Shares { id, mut shares } => {
|
||||||
// Create a MuSig-based machine to inform Substrate of this key generation
|
// Create a MuSig-based machine to inform Substrate of this key generation
|
||||||
// DkgConfirmer has a TODO noting it's only secure for a single usage, yet this ensures
|
let nonces = crate::tributary::dkg_confirmation_nonces(&key, &spec, id.attempt);
|
||||||
// the TODO is resolved before unsafe usage
|
|
||||||
if id.attempt != 0 {
|
|
||||||
panic!("attempt wasn't 0");
|
|
||||||
}
|
|
||||||
let nonces = crate::tributary::dkg_confirmation_nonces(&key, &spec);
|
|
||||||
|
|
||||||
let mut tx_shares = Vec::with_capacity(shares.len());
|
let mut tx_shares = Vec::with_capacity(shares.len());
|
||||||
for i in 1 ..= spec.n() {
|
for i in 1 ..= spec.n() {
|
||||||
|
@ -549,6 +543,7 @@ pub async fn handle_processors<D: Db, Pro: Processors, P: P2p>(
|
||||||
&key,
|
&key,
|
||||||
&spec,
|
&spec,
|
||||||
&(Public(substrate_key), network_key.try_into().unwrap()),
|
&(Public(substrate_key), network_key.try_into().unwrap()),
|
||||||
|
id.attempt,
|
||||||
);
|
);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ async fn dkg_test() {
|
||||||
let mut tx = Transaction::DkgShares {
|
let mut tx = Transaction::DkgShares {
|
||||||
attempt,
|
attempt,
|
||||||
shares,
|
shares,
|
||||||
confirmation_nonces: crate::tributary::dkg_confirmation_nonces(key, &spec),
|
confirmation_nonces: crate::tributary::dkg_confirmation_nonces(key, &spec, 0),
|
||||||
signed: Transaction::empty_signed(),
|
signed: Transaction::empty_signed(),
|
||||||
};
|
};
|
||||||
tx.sign(&mut OsRng, spec.genesis(), key, 1);
|
tx.sign(&mut OsRng, spec.genesis(), key, 1);
|
||||||
|
@ -287,7 +287,7 @@ async fn dkg_test() {
|
||||||
// albeit poor
|
// albeit poor
|
||||||
let mut txn = scanner_db.0.txn();
|
let mut txn = scanner_db.0.txn();
|
||||||
let share =
|
let share =
|
||||||
crate::tributary::generated_key_pair::<MemDb>(&mut txn, key, &spec, &key_pair).unwrap();
|
crate::tributary::generated_key_pair::<MemDb>(&mut txn, key, &spec, &key_pair, 0).unwrap();
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
let mut tx = Transaction::DkgConfirmed(attempt, share, Transaction::empty_signed());
|
let mut tx = Transaction::DkgConfirmed(attempt, share, Transaction::empty_signed());
|
||||||
|
|
|
@ -48,6 +48,7 @@ impl DkgConfirmer {
|
||||||
fn preprocess_internal(
|
fn preprocess_internal(
|
||||||
spec: &TributarySpec,
|
spec: &TributarySpec,
|
||||||
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
||||||
|
attempt: u32,
|
||||||
) -> (AlgorithmSignMachine<Ristretto, Schnorrkel>, [u8; 64]) {
|
) -> (AlgorithmSignMachine<Ristretto, Schnorrkel>, [u8; 64]) {
|
||||||
// TODO: Does Substrate already have a validator-uniqueness check?
|
// TODO: Does Substrate already have a validator-uniqueness check?
|
||||||
let validators = spec.validators().iter().map(|val| val.0).collect::<Vec<_>>();
|
let validators = spec.validators().iter().map(|val| val.0).collect::<Vec<_>>();
|
||||||
|
@ -57,7 +58,7 @@ impl DkgConfirmer {
|
||||||
let mut entropy_transcript = RecommendedTranscript::new(b"DkgConfirmer Entropy");
|
let mut entropy_transcript = RecommendedTranscript::new(b"DkgConfirmer Entropy");
|
||||||
entropy_transcript.append_message(b"spec", spec.serialize());
|
entropy_transcript.append_message(b"spec", spec.serialize());
|
||||||
entropy_transcript.append_message(b"key", Zeroizing::new(key.to_bytes()));
|
entropy_transcript.append_message(b"key", Zeroizing::new(key.to_bytes()));
|
||||||
// TODO: This is incredibly insecure unless message-bound (or bound via the attempt)
|
entropy_transcript.append_message(b"attempt", attempt.to_le_bytes());
|
||||||
Zeroizing::new(entropy_transcript).rng_seed(b"preprocess")
|
Zeroizing::new(entropy_transcript).rng_seed(b"preprocess")
|
||||||
});
|
});
|
||||||
let (machine, preprocess) = AlgorithmMachine::new(
|
let (machine, preprocess) = AlgorithmMachine::new(
|
||||||
|
@ -71,17 +72,22 @@ impl DkgConfirmer {
|
||||||
(machine, preprocess.serialize().try_into().unwrap())
|
(machine, preprocess.serialize().try_into().unwrap())
|
||||||
}
|
}
|
||||||
// Get the preprocess for this confirmation.
|
// Get the preprocess for this confirmation.
|
||||||
fn preprocess(spec: &TributarySpec, key: &Zeroizing<<Ristretto as Ciphersuite>::F>) -> [u8; 64] {
|
fn preprocess(
|
||||||
Self::preprocess_internal(spec, key).1
|
spec: &TributarySpec,
|
||||||
|
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
||||||
|
attempt: u32,
|
||||||
|
) -> [u8; 64] {
|
||||||
|
Self::preprocess_internal(spec, key, attempt).1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn share_internal(
|
fn share_internal(
|
||||||
spec: &TributarySpec,
|
spec: &TributarySpec,
|
||||||
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
||||||
|
attempt: u32,
|
||||||
preprocesses: HashMap<Participant, Vec<u8>>,
|
preprocesses: HashMap<Participant, Vec<u8>>,
|
||||||
key_pair: &KeyPair,
|
key_pair: &KeyPair,
|
||||||
) -> Result<(AlgorithmSignatureMachine<Ristretto, Schnorrkel>, [u8; 32]), Participant> {
|
) -> Result<(AlgorithmSignatureMachine<Ristretto, Schnorrkel>, [u8; 32]), Participant> {
|
||||||
let machine = Self::preprocess_internal(spec, key).0;
|
let machine = Self::preprocess_internal(spec, key, attempt).0;
|
||||||
let preprocesses = preprocesses
|
let preprocesses = preprocesses
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(p, preprocess)| {
|
.map(|(p, preprocess)| {
|
||||||
|
@ -109,20 +115,22 @@ impl DkgConfirmer {
|
||||||
fn share(
|
fn share(
|
||||||
spec: &TributarySpec,
|
spec: &TributarySpec,
|
||||||
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
||||||
|
attempt: u32,
|
||||||
preprocesses: HashMap<Participant, Vec<u8>>,
|
preprocesses: HashMap<Participant, Vec<u8>>,
|
||||||
key_pair: &KeyPair,
|
key_pair: &KeyPair,
|
||||||
) -> Result<[u8; 32], Participant> {
|
) -> Result<[u8; 32], Participant> {
|
||||||
Self::share_internal(spec, key, preprocesses, key_pair).map(|(_, share)| share)
|
Self::share_internal(spec, key, attempt, preprocesses, key_pair).map(|(_, share)| share)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete(
|
fn complete(
|
||||||
spec: &TributarySpec,
|
spec: &TributarySpec,
|
||||||
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
||||||
|
attempt: u32,
|
||||||
preprocesses: HashMap<Participant, Vec<u8>>,
|
preprocesses: HashMap<Participant, Vec<u8>>,
|
||||||
key_pair: &KeyPair,
|
key_pair: &KeyPair,
|
||||||
shares: HashMap<Participant, Vec<u8>>,
|
shares: HashMap<Participant, Vec<u8>>,
|
||||||
) -> Result<[u8; 64], Participant> {
|
) -> Result<[u8; 64], Participant> {
|
||||||
let machine = Self::share_internal(spec, key, preprocesses, key_pair)
|
let machine = Self::share_internal(spec, key, attempt, preprocesses, key_pair)
|
||||||
.expect("trying to complete a machine which failed to preprocess")
|
.expect("trying to complete a machine which failed to preprocess")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
|
@ -193,8 +201,9 @@ fn read_known_to_exist_data<D: Db, G: Get>(
|
||||||
pub fn dkg_confirmation_nonces(
|
pub fn dkg_confirmation_nonces(
|
||||||
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
||||||
spec: &TributarySpec,
|
spec: &TributarySpec,
|
||||||
|
attempt: u32,
|
||||||
) -> [u8; 64] {
|
) -> [u8; 64] {
|
||||||
DkgConfirmer::preprocess(spec, key)
|
DkgConfirmer::preprocess(spec, key, attempt)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::needless_pass_by_ref_mut)]
|
#[allow(clippy::needless_pass_by_ref_mut)]
|
||||||
|
@ -203,10 +212,10 @@ pub fn generated_key_pair<D: Db>(
|
||||||
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
key: &Zeroizing<<Ristretto as Ciphersuite>::F>,
|
||||||
spec: &TributarySpec,
|
spec: &TributarySpec,
|
||||||
key_pair: &KeyPair,
|
key_pair: &KeyPair,
|
||||||
|
attempt: u32,
|
||||||
) -> Result<[u8; 32], Participant> {
|
) -> Result<[u8; 32], Participant> {
|
||||||
TributaryDb::<D>::save_currently_completing_key_pair(txn, spec.genesis(), key_pair);
|
TributaryDb::<D>::save_currently_completing_key_pair(txn, spec.genesis(), key_pair);
|
||||||
|
|
||||||
let attempt = 0; // TODO
|
|
||||||
let Some(preprocesses) = read_known_to_exist_data::<D, _>(
|
let Some(preprocesses) = read_known_to_exist_data::<D, _>(
|
||||||
txn,
|
txn,
|
||||||
spec,
|
spec,
|
||||||
|
@ -220,7 +229,7 @@ pub fn generated_key_pair<D: Db>(
|
||||||
) else {
|
) else {
|
||||||
panic!("wasn't a participant in confirming a key pair");
|
panic!("wasn't a participant in confirming a key pair");
|
||||||
};
|
};
|
||||||
DkgConfirmer::share(spec, key, preprocesses, key_pair)
|
DkgConfirmer::share(spec, key, attempt, preprocesses, key_pair)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)] // TODO
|
#[allow(clippy::too_many_arguments)] // TODO
|
||||||
|
@ -430,7 +439,8 @@ pub async fn handle_application_tx<
|
||||||
"(including us) fires DkgConfirmed, yet no confirming key pair"
|
"(including us) fires DkgConfirmed, yet no confirming key pair"
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let Ok(sig) = DkgConfirmer::complete(spec, key, preprocesses, &key_pair, shares) else {
|
let Ok(sig) = DkgConfirmer::complete(spec, key, attempt, preprocesses, &key_pair, shares)
|
||||||
|
else {
|
||||||
// TODO: Full slash
|
// TODO: Full slash
|
||||||
todo!();
|
todo!();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue