mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Route blame between Processor and Coordinator (#427)
* Have processor report errors during the DKG to the coordinator * Add RemoveParticipant, InvalidDkgShare to coordinator * Route DKG blame around coordinator * Allow public construction of AdditionalBlameMachine Necessary for upcoming work on handling DKG blame in the processor and coordinator. Additionally fixes a publicly reachable panic when commitments parsed with one ThresholdParams are used in a machine using another set of ThresholdParams. Renames InvalidProofOfKnowledge to InvalidCommitments. * Remove unused error from dleq * Implement support for VerifyBlame in the processor * Have coordinator send the processor share message relevant to Blame * Remove desync between processors reporting InvalidShare and ones reporting GeneratedKeyPair * Route blame on sign between processor and coordinator Doesn't yet act on it in coordinator. * Move txn usage as needed for stable Rust to build * Correct InvalidDkgShare serialization
This commit is contained in:
@@ -6,7 +6,7 @@ use rand_core::OsRng;
|
||||
use ciphersuite::group::GroupEncoding;
|
||||
use frost::{
|
||||
curve::Ristretto,
|
||||
ThresholdKeys,
|
||||
ThresholdKeys, FrostError,
|
||||
algorithm::Algorithm,
|
||||
sign::{
|
||||
Writable, PreprocessMachine, SignMachine, SignatureMachine, AlgorithmMachine,
|
||||
@@ -246,7 +246,7 @@ impl<D: Db> SubstrateSigner<D> {
|
||||
msg: CoordinatorMessage,
|
||||
) -> Option<messages::ProcessorMessage> {
|
||||
match msg {
|
||||
CoordinatorMessage::BatchPreprocesses { id, mut preprocesses } => {
|
||||
CoordinatorMessage::BatchPreprocesses { id, preprocesses } => {
|
||||
if self.verify_id(&id).is_err() {
|
||||
return None;
|
||||
}
|
||||
@@ -263,23 +263,22 @@ impl<D: Db> SubstrateSigner<D> {
|
||||
Some(preprocess) => preprocess,
|
||||
};
|
||||
|
||||
let preprocesses = match preprocesses
|
||||
.drain()
|
||||
.map(|(l, preprocess)| {
|
||||
let mut preprocess_ref = preprocess.as_ref();
|
||||
let res = machines[0]
|
||||
.read_preprocess::<&[u8]>(&mut preprocess_ref)
|
||||
.map(|preprocess| (l, preprocess));
|
||||
if !preprocess_ref.is_empty() {
|
||||
todo!("malicious signer: extra bytes");
|
||||
}
|
||||
res
|
||||
})
|
||||
.collect::<Result<HashMap<_, _>, _>>()
|
||||
{
|
||||
Ok(preprocesses) => preprocesses,
|
||||
Err(e) => todo!("malicious signer: {:?}", e),
|
||||
};
|
||||
let mut parsed = HashMap::new();
|
||||
for l in {
|
||||
let mut keys = preprocesses.keys().cloned().collect::<Vec<_>>();
|
||||
keys.sort();
|
||||
keys
|
||||
} {
|
||||
let mut preprocess_ref = preprocesses.get(&l).unwrap().as_slice();
|
||||
let Ok(res) = machines[0].read_preprocess(&mut preprocess_ref) else {
|
||||
return Some((ProcessorMessage::InvalidParticipant { id, participant: l }).into());
|
||||
};
|
||||
if !preprocess_ref.is_empty() {
|
||||
return Some((ProcessorMessage::InvalidParticipant { id, participant: l }).into());
|
||||
}
|
||||
parsed.insert(l, res);
|
||||
}
|
||||
let preprocesses = parsed;
|
||||
|
||||
// Only keep a single machine as we only need one to get the signature
|
||||
let mut signature_machine = None;
|
||||
@@ -296,7 +295,18 @@ impl<D: Db> SubstrateSigner<D> {
|
||||
let (machine, share) =
|
||||
match machine.sign(preprocesses, &batch_message(&self.signable[&id.id])) {
|
||||
Ok(res) => res,
|
||||
Err(e) => todo!("malicious signer: {:?}", e),
|
||||
Err(e) => match e {
|
||||
FrostError::InternalError(_) |
|
||||
FrostError::InvalidParticipant(_, _) |
|
||||
FrostError::InvalidSigningSet(_) |
|
||||
FrostError::InvalidParticipantQuantity(_, _) |
|
||||
FrostError::DuplicatedParticipant(_) |
|
||||
FrostError::MissingParticipant(_) => unreachable!(),
|
||||
|
||||
FrostError::InvalidPreprocess(l) | FrostError::InvalidShare(l) => {
|
||||
return Some((ProcessorMessage::InvalidParticipant { id, participant: l }).into())
|
||||
}
|
||||
},
|
||||
};
|
||||
if m == 0 {
|
||||
signature_machine = Some(machine);
|
||||
@@ -314,7 +324,7 @@ impl<D: Db> SubstrateSigner<D> {
|
||||
Some((ProcessorMessage::BatchShare { id, shares: serialized_shares }).into())
|
||||
}
|
||||
|
||||
CoordinatorMessage::BatchShares { id, mut shares } => {
|
||||
CoordinatorMessage::BatchShares { id, shares } => {
|
||||
if self.verify_id(&id).is_err() {
|
||||
return None;
|
||||
}
|
||||
@@ -337,21 +347,22 @@ impl<D: Db> SubstrateSigner<D> {
|
||||
Some(signing) => signing,
|
||||
};
|
||||
|
||||
let mut shares = match shares
|
||||
.drain()
|
||||
.map(|(l, share)| {
|
||||
let mut share_ref = share.as_ref();
|
||||
let res = machine.read_share::<&[u8]>(&mut share_ref).map(|share| (l, share));
|
||||
if !share_ref.is_empty() {
|
||||
todo!("malicious signer: extra bytes");
|
||||
}
|
||||
res
|
||||
})
|
||||
.collect::<Result<HashMap<_, _>, _>>()
|
||||
{
|
||||
Ok(shares) => shares,
|
||||
Err(e) => todo!("malicious signer: {:?}", e),
|
||||
};
|
||||
let mut parsed = HashMap::new();
|
||||
for l in {
|
||||
let mut keys = shares.keys().cloned().collect::<Vec<_>>();
|
||||
keys.sort();
|
||||
keys
|
||||
} {
|
||||
let mut share_ref = shares.get(&l).unwrap().as_slice();
|
||||
let Ok(res) = machine.read_share(&mut share_ref) else {
|
||||
return Some((ProcessorMessage::InvalidParticipant { id, participant: l }).into());
|
||||
};
|
||||
if !share_ref.is_empty() {
|
||||
return Some((ProcessorMessage::InvalidParticipant { id, participant: l }).into());
|
||||
}
|
||||
parsed.insert(l, res);
|
||||
}
|
||||
let mut shares = parsed;
|
||||
|
||||
for (i, our_share) in our_shares.into_iter().enumerate().skip(1) {
|
||||
assert!(shares.insert(self.keys[i].params().i(), our_share).is_none());
|
||||
@@ -359,7 +370,18 @@ impl<D: Db> SubstrateSigner<D> {
|
||||
|
||||
let sig = match machine.complete(shares) {
|
||||
Ok(res) => res,
|
||||
Err(e) => todo!("malicious signer: {:?}", e),
|
||||
Err(e) => match e {
|
||||
FrostError::InternalError(_) |
|
||||
FrostError::InvalidParticipant(_, _) |
|
||||
FrostError::InvalidSigningSet(_) |
|
||||
FrostError::InvalidParticipantQuantity(_, _) |
|
||||
FrostError::DuplicatedParticipant(_) |
|
||||
FrostError::MissingParticipant(_) => unreachable!(),
|
||||
|
||||
FrostError::InvalidPreprocess(l) | FrostError::InvalidShare(l) => {
|
||||
return Some((ProcessorMessage::InvalidParticipant { id, participant: l }).into())
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
info!("signed batch {} with attempt #{}", hex::encode(id.id), id.attempt);
|
||||
|
||||
Reference in New Issue
Block a user