mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
\#339 addendum
This commit is contained in:
@@ -156,10 +156,11 @@ pub mod sign {
|
||||
pub mod coordinator {
|
||||
use super::*;
|
||||
|
||||
pub fn cosign_block_msg(block: [u8; 32]) -> Vec<u8> {
|
||||
pub fn cosign_block_msg(block_number: u64, block: [u8; 32]) -> Vec<u8> {
|
||||
const DST: &[u8] = b"Cosign";
|
||||
let mut res = vec![u8::try_from(DST.len()).unwrap()];
|
||||
res.extend(DST);
|
||||
res.extend(block_number.to_le_bytes());
|
||||
res.extend(block);
|
||||
res
|
||||
}
|
||||
@@ -181,7 +182,7 @@ pub mod coordinator {
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
pub enum CoordinatorMessage {
|
||||
CosignSubstrateBlock { id: SubstrateSignId },
|
||||
CosignSubstrateBlock { id: SubstrateSignId, block_number: u64 },
|
||||
// Uses Vec<u8> instead of [u8; 64] since serde Deserialize isn't implemented for [u8; 64]
|
||||
SubstratePreprocesses { id: SubstrateSignId, preprocesses: HashMap<Participant, Vec<u8>> },
|
||||
SubstrateShares { id: SubstrateSignId, shares: HashMap<Participant, [u8; 32]> },
|
||||
@@ -205,7 +206,7 @@ pub mod coordinator {
|
||||
|
||||
pub fn key(&self) -> &[u8] {
|
||||
match self {
|
||||
CoordinatorMessage::CosignSubstrateBlock { id } => &id.key,
|
||||
CoordinatorMessage::CosignSubstrateBlock { id, .. } => &id.key,
|
||||
CoordinatorMessage::SubstratePreprocesses { id, .. } => &id.key,
|
||||
CoordinatorMessage::SubstrateShares { id, .. } => &id.key,
|
||||
CoordinatorMessage::BatchReattempt { id } => &id.key,
|
||||
@@ -226,7 +227,7 @@ pub mod coordinator {
|
||||
CosignPreprocess { id: SubstrateSignId, preprocesses: Vec<Vec<u8>> },
|
||||
BatchPreprocess { id: SubstrateSignId, block: BlockHash, preprocesses: Vec<Vec<u8>> },
|
||||
SubstrateShare { id: SubstrateSignId, shares: Vec<[u8; 32]> },
|
||||
CosignedBlock { block: [u8; 32], signature: Vec<u8> },
|
||||
CosignedBlock { block_number: u64, block: [u8; 32], signature: Vec<u8> },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,7 +373,7 @@ impl CoordinatorMessage {
|
||||
CoordinatorMessage::Coordinator(msg) => {
|
||||
let (sub, id) = match msg {
|
||||
// Unique since this is the entire message
|
||||
coordinator::CoordinatorMessage::CosignSubstrateBlock { id } => (0, id.encode()),
|
||||
coordinator::CoordinatorMessage::CosignSubstrateBlock { id, .. } => (0, id.encode()),
|
||||
// Unique since this embeds the batch ID (including its network) and attempt
|
||||
coordinator::CoordinatorMessage::SubstratePreprocesses { id, .. } => (1, id.encode()),
|
||||
coordinator::CoordinatorMessage::SubstrateShares { id, .. } => (2, id.encode()),
|
||||
|
||||
@@ -38,6 +38,7 @@ pub struct Cosigner {
|
||||
#[allow(dead_code)] // False positive
|
||||
keys: Vec<ThresholdKeys<Ristretto>>,
|
||||
|
||||
block_number: u64,
|
||||
id: [u8; 32],
|
||||
attempt: u32,
|
||||
#[allow(clippy::type_complexity)]
|
||||
@@ -50,6 +51,7 @@ impl fmt::Debug for Cosigner {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt
|
||||
.debug_struct("Cosigner")
|
||||
.field("block_number", &self.block_number)
|
||||
.field("id", &self.id)
|
||||
.field("attempt", &self.attempt)
|
||||
.field("preprocessing", &self.preprocessing.is_some())
|
||||
@@ -62,6 +64,7 @@ impl Cosigner {
|
||||
pub fn new(
|
||||
txn: &mut impl DbTxn,
|
||||
keys: Vec<ThresholdKeys<Ristretto>>,
|
||||
block_number: u64,
|
||||
id: [u8; 32],
|
||||
attempt: u32,
|
||||
) -> Option<(Cosigner, ProcessorMessage)> {
|
||||
@@ -104,7 +107,7 @@ impl Cosigner {
|
||||
};
|
||||
|
||||
Some((
|
||||
Cosigner { keys, id, attempt, preprocessing, signing: None },
|
||||
Cosigner { keys, block_number, id, attempt, preprocessing, signing: None },
|
||||
ProcessorMessage::CosignPreprocess {
|
||||
id: substrate_sign_id,
|
||||
preprocesses: serialized_preprocesses,
|
||||
@@ -176,21 +179,22 @@ impl Cosigner {
|
||||
}
|
||||
}
|
||||
|
||||
let (machine, share) = match machine.sign(preprocesses, &cosign_block_msg(self.id)) {
|
||||
Ok(res) => res,
|
||||
Err(e) => match e {
|
||||
FrostError::InternalError(_) |
|
||||
FrostError::InvalidParticipant(_, _) |
|
||||
FrostError::InvalidSigningSet(_) |
|
||||
FrostError::InvalidParticipantQuantity(_, _) |
|
||||
FrostError::DuplicatedParticipant(_) |
|
||||
FrostError::MissingParticipant(_) => unreachable!(),
|
||||
let (machine, share) =
|
||||
match machine.sign(preprocesses, &cosign_block_msg(self.block_number, self.id)) {
|
||||
Ok(res) => res,
|
||||
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 })
|
||||
}
|
||||
},
|
||||
};
|
||||
FrostError::InvalidPreprocess(l) | FrostError::InvalidShare(l) => {
|
||||
return Some(ProcessorMessage::InvalidParticipant { id, participant: l })
|
||||
}
|
||||
},
|
||||
};
|
||||
if m == 0 {
|
||||
signature_machine = Some(machine);
|
||||
}
|
||||
@@ -278,7 +282,11 @@ impl Cosigner {
|
||||
|
||||
Completed::set(txn, block, &());
|
||||
|
||||
Some(ProcessorMessage::CosignedBlock { block, signature: sig.to_bytes().to_vec() })
|
||||
Some(ProcessorMessage::CosignedBlock {
|
||||
block_number: self.block_number,
|
||||
block,
|
||||
signature: sig.to_bytes().to_vec(),
|
||||
})
|
||||
}
|
||||
CoordinatorMessage::BatchReattempt { .. } => panic!("BatchReattempt passed to Cosigner"),
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
||||
}
|
||||
} else {
|
||||
match msg {
|
||||
CoordinatorCoordinatorMessage::CosignSubstrateBlock { id } => {
|
||||
CoordinatorCoordinatorMessage::CosignSubstrateBlock { id, block_number } => {
|
||||
let SubstrateSignableId::CosigningSubstrateBlock(block) = id.id else {
|
||||
panic!("CosignSubstrateBlock id didn't have a CosigningSubstrateBlock")
|
||||
};
|
||||
@@ -261,7 +261,8 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
||||
else {
|
||||
panic!("didn't have key shares for the key we were told to cosign with");
|
||||
};
|
||||
if let Some((cosigner, msg)) = Cosigner::new(txn, keys, block, id.attempt) {
|
||||
if let Some((cosigner, msg)) = Cosigner::new(txn, keys, block_number, block, id.attempt)
|
||||
{
|
||||
tributary_mutable.cosigner = Some(cosigner);
|
||||
coordinator.send(msg).await;
|
||||
} else {
|
||||
|
||||
@@ -24,6 +24,7 @@ async fn test_cosigner() {
|
||||
|
||||
let participant_one = Participant::new(1).unwrap();
|
||||
|
||||
let block_number = OsRng.next_u64();
|
||||
let block = [0xaa; 32];
|
||||
|
||||
let actual_id = SubstrateSignId {
|
||||
@@ -54,7 +55,7 @@ async fn test_cosigner() {
|
||||
let mut db = MemDb::new();
|
||||
let mut txn = db.txn();
|
||||
let (signer, preprocess) =
|
||||
Cosigner::new(&mut txn, vec![keys], block, actual_id.attempt).unwrap();
|
||||
Cosigner::new(&mut txn, vec![keys], block_number, block, actual_id.attempt).unwrap();
|
||||
|
||||
match preprocess {
|
||||
// All participants should emit a preprocess
|
||||
@@ -114,10 +115,12 @@ async fn test_cosigner() {
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
ProcessorMessage::CosignedBlock { block: signed_block, signature } => {
|
||||
ProcessorMessage::CosignedBlock { block_number, block: signed_block, signature } => {
|
||||
assert_eq!(signed_block, block);
|
||||
assert!(Public::from_raw(keys[&participant_one].group_key().to_bytes())
|
||||
.verify(&cosign_block_msg(block), &Signature(signature.try_into().unwrap())));
|
||||
assert!(Public::from_raw(keys[&participant_one].group_key().to_bytes()).verify(
|
||||
&cosign_block_msg(block_number, block),
|
||||
&Signature(signature.try_into().unwrap())
|
||||
));
|
||||
}
|
||||
_ => panic!("didn't get cosigned block back"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user