diff --git a/Cargo.lock b/Cargo.lock index c389c142..c7709067 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2444,7 +2444,6 @@ dependencies = [ name = "dkg" version = "0.6.1" dependencies = [ - "borsh", "ciphersuite 0.4.2", "std-shims 0.1.5", "thiserror 2.0.17", diff --git a/coordinator/src/db.rs b/coordinator/src/db.rs index 108e0f32..09302d25 100644 --- a/coordinator/src/db.rs +++ b/coordinator/src/db.rs @@ -103,7 +103,7 @@ mod _internal_db { // Tributary transactions to publish from the DKG confirmation task TributaryTransactionsFromDkgConfirmation: (set: ExternalValidatorSet) -> Transaction, // Participants to remove - RemoveParticipant: (set: ExternalValidatorSet) -> Participant, + RemoveParticipant: (set: ExternalValidatorSet) -> u16, } } } @@ -139,10 +139,11 @@ impl RemoveParticipant { pub(crate) fn send(txn: &mut impl DbTxn, set: ExternalValidatorSet, participant: Participant) { // If this set has yet to be retired, send this transaction if RetiredTributary::get(txn, set.network).map(|session| session.0) < Some(set.session.0) { - _internal_db::RemoveParticipant::send(txn, set, &participant); + _internal_db::RemoveParticipant::send(txn, set, &u16::from(participant)); } } pub(crate) fn try_recv(txn: &mut impl DbTxn, set: ExternalValidatorSet) -> Option { _internal_db::RemoveParticipant::try_recv(txn, set) + .map(|i| Participant::new(i).expect("sent invalid participant index for removal")) } } diff --git a/crypto/dkg/Cargo.toml b/crypto/dkg/Cargo.toml index 1c6e3073..86e9ae1c 100644 --- a/crypto/dkg/Cargo.toml +++ b/crypto/dkg/Cargo.toml @@ -23,19 +23,12 @@ thiserror = { version = "2", default-features = false } std-shims = { version = "0.1", path = "../../common/std-shims", default-features = false, features = ["alloc"] } -borsh = { version = "1", default-features = false, features = ["derive", "de_strict_order"], optional = true } - ciphersuite = { path = "../ciphersuite", version = "^0.4.1", default-features = false, features = ["alloc"] } [features] std = [ "thiserror/std", - "std-shims/std", - - "borsh?/std", - "ciphersuite/std", ] -borsh = ["dep:borsh"] default = ["std"] diff --git a/crypto/dkg/src/lib.rs b/crypto/dkg/src/lib.rs index cbbcb60e..36fadb51 100644 --- a/crypto/dkg/src/lib.rs +++ b/crypto/dkg/src/lib.rs @@ -22,7 +22,6 @@ use ciphersuite::{ /// The ID of a participant, defined as a non-zero u16. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Zeroize)] -#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize))] pub struct Participant(u16); impl Participant { /// Create a new Participant identifier from a u16. @@ -129,18 +128,8 @@ pub enum DkgError { NotParticipating, } -// Manually implements BorshDeserialize so we can enforce it's a valid index -#[cfg(feature = "borsh")] -impl borsh::BorshDeserialize for Participant { - fn deserialize_reader(reader: &mut R) -> io::Result { - Participant::new(u16::deserialize_reader(reader)?) - .ok_or_else(|| io::Error::other("invalid participant")) - } -} - /// Parameters for a multisig. #[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)] -#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize))] pub struct ThresholdParams { /// Participants needed to sign on behalf of the group. t: u16, @@ -210,16 +199,6 @@ impl ThresholdParams { } } -#[cfg(feature = "borsh")] -impl borsh::BorshDeserialize for ThresholdParams { - fn deserialize_reader(reader: &mut R) -> io::Result { - let t = u16::deserialize_reader(reader)?; - let n = u16::deserialize_reader(reader)?; - let i = Participant::deserialize_reader(reader)?; - ThresholdParams::new(t, n, i).map_err(|e| io::Error::other(format!("{e:?}"))) - } -} - /// A method of interpolation. #[derive(Clone, PartialEq, Eq, Debug, Zeroize)] pub enum Interpolation { diff --git a/processor/key-gen/src/db.rs b/processor/key-gen/src/db.rs index bd656b90..f3523c7e 100644 --- a/processor/key-gen/src/db.rs +++ b/processor/key-gen/src/db.rs @@ -31,7 +31,15 @@ struct RawParams { #[derive(BorshSerialize, BorshDeserialize)] pub(crate) struct Participations { + #[borsh( + serialize_with = "messages::borsh_serialize_participant_map", + deserialize_with = "messages::borsh_deserialize_participant_map" + )] pub(crate) substrate_participations: HashMap>, + #[borsh( + serialize_with = "messages::borsh_serialize_participant_map", + deserialize_with = "messages::borsh_deserialize_participant_map" + )] pub(crate) network_participations: HashMap>, } diff --git a/processor/messages/Cargo.toml b/processor/messages/Cargo.toml index a505b0a9..47e1b2ea 100644 --- a/processor/messages/Cargo.toml +++ b/processor/messages/Cargo.toml @@ -23,7 +23,7 @@ hex = { version = "0.4", default-features = false, features = ["std"] } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } -dkg = { path = "../../crypto/dkg", default-features = false, features = ["std", "borsh"] } +dkg = { path = "../../crypto/dkg", default-features = false, features = ["std"] } serai-primitives = { path = "../../substrate/primitives", default-features = false, features = ["std", "borsh"] } in-instructions-primitives = { package = "serai-in-instructions-primitives", path = "../../substrate/in-instructions/primitives", default-features = false, features = ["std", "borsh"] } diff --git a/processor/messages/src/lib.rs b/processor/messages/src/lib.rs index f3ec47ac..c2782d24 100644 --- a/processor/messages/src/lib.rs +++ b/processor/messages/src/lib.rs @@ -21,6 +21,44 @@ pub struct SubstrateContext { pub network_latest_finalized_block: BlockHash, } +pub fn borsh_serialize_participant( + value: &Participant, + writer: &mut W, +) -> borsh::io::Result<()> { + u16::from(*value).serialize(writer) +} +pub fn borsh_deserialize_participant( + reader: &mut R, +) -> borsh::io::Result { + u16::deserialize_reader(reader).and_then(|p| { + Participant::new(p) + .ok_or_else(|| borsh::io::Error::other("invalid `Participant` despite valid `u16`")) + }) +} + +pub fn borsh_serialize_participant_map( + value: &HashMap>, + writer: &mut W, +) -> borsh::io::Result<()> { + value + .iter() + .map(|(key, value)| (u16::from(*key), value)) + .collect::>>() + .serialize(writer) +} +pub fn borsh_deserialize_participant_map( + reader: &mut R, +) -> borsh::io::Result>> { + HashMap::>::deserialize_reader(reader)? + .into_iter() + .map(|(key, value)| { + Participant::new(key) + .ok_or_else(|| borsh::io::Error::other("invalid `Participant` despite valid `u16` in map")) + .map(|key| (key, value)) + }) + .collect() +} + pub mod key_gen { use super::*; @@ -33,7 +71,15 @@ pub mod key_gen { /// Received participations for the specified key generation protocol. /// /// This is sent by the Coordinator's Tributary scanner. - Participation { session: Session, participant: Participant, participation: Vec }, + Participation { + session: Session, + #[borsh( + serialize_with = "borsh_serialize_participant", + deserialize_with = "borsh_deserialize_participant" + )] + participant: Participant, + participation: Vec, + }, } impl core::fmt::Debug for CoordinatorMessage { @@ -58,11 +104,25 @@ pub mod key_gen { #[derive(Clone, BorshSerialize, BorshDeserialize)] pub enum ProcessorMessage { // Participated in the specified key generation protocol. - Participation { session: Session, participation: Vec }, + Participation { + session: Session, + participation: Vec, + }, // Resulting keys from the specified key generation protocol. - GeneratedKeyPair { session: Session, substrate_key: [u8; 32], network_key: Vec }, + GeneratedKeyPair { + session: Session, + substrate_key: [u8; 32], + network_key: Vec, + }, // Blame this participant. - Blame { session: Session, participant: Participant }, + Blame { + session: Session, + #[borsh( + serialize_with = "borsh_serialize_participant", + deserialize_with = "borsh_deserialize_participant" + )] + participant: Participant, + }, } impl core::fmt::Debug for ProcessorMessage { @@ -127,11 +187,25 @@ pub mod sign { /// Received preprocesses for the specified signing protocol. /// /// This is sent by the Coordinator's Tributary scanner. - Preprocesses { id: SignId, preprocesses: HashMap> }, + Preprocesses { + id: SignId, + #[borsh( + serialize_with = "borsh_serialize_participant_map", + deserialize_with = "borsh_deserialize_participant_map" + )] + preprocesses: HashMap>, + }, // Received shares for the specified signing protocol. /// /// This is sent by the Coordinator's Tributary scanner. - Shares { id: SignId, shares: HashMap> }, + Shares { + id: SignId, + #[borsh( + serialize_with = "borsh_serialize_participant_map", + deserialize_with = "borsh_deserialize_participant_map" + )] + shares: HashMap>, + }, // Re-attempt a signing protocol. /// /// This is sent by the Coordinator's Tributary re-attempt scheduling logic. @@ -152,11 +226,24 @@ pub mod sign { #[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] pub enum ProcessorMessage { // Participant sent an invalid message during the sign protocol. - InvalidParticipant { session: Session, participant: Participant }, + InvalidParticipant { + session: Session, + #[borsh( + serialize_with = "borsh_serialize_participant", + deserialize_with = "borsh_deserialize_participant" + )] + participant: Participant, + }, // Created preprocesses for the specified signing protocol. - Preprocesses { id: SignId, preprocesses: Vec> }, + Preprocesses { + id: SignId, + preprocesses: Vec>, + }, // Signed shares for the specified signing protocol. - Shares { id: SignId, shares: Vec> }, + Shares { + id: SignId, + shares: Vec>, + }, } } @@ -301,7 +388,7 @@ impl CoordinatorMessage { } // Unique since one participation per participant per session key_gen::CoordinatorMessage::Participation { session, participant, .. } => { - (1, borsh::to_vec(&(session, participant)).unwrap()) + (1, borsh::to_vec(&(session, u16::from(*participant))).unwrap()) } }; @@ -372,7 +459,7 @@ impl ProcessorMessage { } // Unique since we only blame a participant once (as this is fatal) key_gen::ProcessorMessage::Blame { session, participant } => { - (2, borsh::to_vec(&(session, participant)).unwrap()) + (2, borsh::to_vec(&(session, u16::from(*participant))).unwrap()) } };