mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Have the Tributary scanner yield DKG confirmation signing protocol data
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -8431,6 +8431,7 @@ dependencies = [
|
|||||||
"blake2",
|
"blake2",
|
||||||
"borsh",
|
"borsh",
|
||||||
"ciphersuite",
|
"ciphersuite",
|
||||||
|
"dkg",
|
||||||
"log",
|
"log",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
|
|||||||
@@ -21,13 +21,14 @@ workspace = true
|
|||||||
zeroize = { version = "^1.5", default-features = false, features = ["std"] }
|
zeroize = { version = "^1.5", default-features = false, features = ["std"] }
|
||||||
rand_core = { version = "0.6", default-features = false, features = ["std"] }
|
rand_core = { version = "0.6", default-features = false, features = ["std"] }
|
||||||
|
|
||||||
blake2 = { version = "0.10", default-features = false, features = ["std"] }
|
|
||||||
ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["std"] }
|
|
||||||
schnorr = { package = "schnorr-signatures", path = "../../crypto/schnorr", default-features = false, features = ["std"] }
|
|
||||||
|
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std", "derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std", "derive"] }
|
||||||
borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] }
|
borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] }
|
||||||
|
|
||||||
|
blake2 = { version = "0.10", default-features = false, features = ["std"] }
|
||||||
|
ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["std"] }
|
||||||
|
dkg = { path = "../../crypto/dkg", default-features = false, features = ["std"] }
|
||||||
|
schnorr = { package = "schnorr-signatures", path = "../../crypto/schnorr", default-features = false, features = ["std"] }
|
||||||
|
|
||||||
serai-client = { path = "../../substrate/client", default-features = false, features = ["serai", "borsh"] }
|
serai-client = { path = "../../substrate/client", default-features = false, features = ["serai", "borsh"] }
|
||||||
|
|
||||||
serai-db = { path = "../../common/db" }
|
serai-db = { path = "../../common/db" }
|
||||||
|
|||||||
@@ -229,7 +229,11 @@ create_db!(
|
|||||||
|
|
||||||
db_channel!(
|
db_channel!(
|
||||||
CoordinatorTributary {
|
CoordinatorTributary {
|
||||||
|
// Messages to send to the processor
|
||||||
ProcessorMessages: (set: ValidatorSet) -> messages::CoordinatorMessage,
|
ProcessorMessages: (set: ValidatorSet) -> messages::CoordinatorMessage,
|
||||||
|
// Messages for the DKG confirmation
|
||||||
|
DkgConfirmationMessages: (set: ValidatorSet) -> messages::sign::CoordinatorMessage,
|
||||||
|
// Topics which have been explicitly recognized
|
||||||
RecognizedTopics: (set: ValidatorSet) -> Topic,
|
RecognizedTopics: (set: ValidatorSet) -> Topic,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
use core::{marker::PhantomData, future::Future};
|
use core::{marker::PhantomData, future::Future};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use scale::Encode;
|
||||||
|
|
||||||
use ciphersuite::group::GroupEncoding;
|
use ciphersuite::group::GroupEncoding;
|
||||||
|
use dkg::Participant;
|
||||||
|
|
||||||
use serai_client::{
|
use serai_client::{
|
||||||
primitives::SeraiAddress,
|
primitives::SeraiAddress,
|
||||||
@@ -27,7 +30,7 @@ use tributary_sdk::{
|
|||||||
use serai_cosign::CosignIntent;
|
use serai_cosign::CosignIntent;
|
||||||
use serai_coordinator_substrate::NewSetInformation;
|
use serai_coordinator_substrate::NewSetInformation;
|
||||||
|
|
||||||
use messages::sign::VariantSignId;
|
use messages::sign::{VariantSignId, SignId};
|
||||||
|
|
||||||
mod transaction;
|
mod transaction;
|
||||||
pub use transaction::{SigningProtocolRound, Signed, Transaction};
|
pub use transaction::{SigningProtocolRound, Signed, Transaction};
|
||||||
@@ -45,6 +48,24 @@ impl ProcessorMessages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Messages for the DKG confirmation.
|
||||||
|
pub struct DkgConfirmationMessages;
|
||||||
|
impl DkgConfirmationMessages {
|
||||||
|
/// Receive a message for the DKG confirmation.
|
||||||
|
///
|
||||||
|
/// These messages use the ProcessorMessage API as that's what existing flows are designed
|
||||||
|
/// around, enabling their reuse. The ProcessorMessage includes a VariantSignId which isn't
|
||||||
|
/// applicable to the DKG confirmation (as there's no such variant of the VariantSignId). The
|
||||||
|
/// actual ID is undefined other than it will be consistent to the signing protocol and unique
|
||||||
|
/// across validator sets, with no guarantees of uniqueness across contexts.
|
||||||
|
pub fn try_recv(
|
||||||
|
txn: &mut impl DbTxn,
|
||||||
|
set: ValidatorSet,
|
||||||
|
) -> Option<messages::sign::CoordinatorMessage> {
|
||||||
|
db::DkgConfirmationMessages::try_recv(txn, set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The cosign intents.
|
/// The cosign intents.
|
||||||
pub struct CosignIntents;
|
pub struct CosignIntents;
|
||||||
impl CosignIntents {
|
impl CosignIntents {
|
||||||
@@ -158,6 +179,62 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn accumulate_dkg_confirmation<D: AsRef<[u8]> + Borshy>(
|
||||||
|
&mut self,
|
||||||
|
block_number: u64,
|
||||||
|
topic: Topic,
|
||||||
|
attempt: u32,
|
||||||
|
data: &D,
|
||||||
|
signer: SeraiAddress,
|
||||||
|
) -> Option<(SignId, HashMap<Participant, Vec<u8>>)> {
|
||||||
|
match TributaryDb::accumulate::<D>(
|
||||||
|
self.tributary_txn,
|
||||||
|
self.set.set,
|
||||||
|
self.validators,
|
||||||
|
self.total_weight,
|
||||||
|
block_number,
|
||||||
|
topic,
|
||||||
|
signer,
|
||||||
|
self.validator_weights[&signer],
|
||||||
|
data,
|
||||||
|
) {
|
||||||
|
DataSet::None => None,
|
||||||
|
DataSet::Participating(data_set) => {
|
||||||
|
// Consistent ID for the DKG confirmation, unqie across sets
|
||||||
|
let id = {
|
||||||
|
let mut id = [0; 32];
|
||||||
|
let encoded_set = self.set.set.encode();
|
||||||
|
id[.. encoded_set.len()].copy_from_slice(&encoded_set);
|
||||||
|
VariantSignId::Batch(id)
|
||||||
|
};
|
||||||
|
let id = SignId { session: self.set.set.session, id, attempt };
|
||||||
|
|
||||||
|
// This will be used in a MuSig protocol, so the Participant indexes are the validator's
|
||||||
|
// position in the list regardless of their weight
|
||||||
|
let flatten_data_set = |data_set: HashMap<_, D>| {
|
||||||
|
let mut entries = HashMap::with_capacity(usize::from(self.total_weight));
|
||||||
|
for (validator, participation) in data_set {
|
||||||
|
let (index, (_validator, _weight)) = &self
|
||||||
|
.set
|
||||||
|
.validators
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_i, (validator_i, _weight))| validator == *validator_i)
|
||||||
|
.unwrap();
|
||||||
|
entries.insert(
|
||||||
|
Participant::new(u16::try_from(*index).unwrap()).unwrap(),
|
||||||
|
participation.as_ref().to_vec(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
entries
|
||||||
|
};
|
||||||
|
let data_set = flatten_data_set(data_set);
|
||||||
|
Some((id, data_set))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_application_tx(&mut self, block_number: u64, tx: Transaction) {
|
fn handle_application_tx(&mut self, block_number: u64, tx: Transaction) {
|
||||||
let signer = |signed: Signed| SeraiAddress(signed.signer().to_bytes());
|
let signer = |signed: Signed| SeraiAddress(signed.signer().to_bytes());
|
||||||
|
|
||||||
@@ -226,12 +303,36 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Transaction::DkgConfirmationPreprocess { attempt, preprocess, signed } => {
|
Transaction::DkgConfirmationPreprocess { attempt, preprocess, signed } => {
|
||||||
// Accumulate the preprocesses into our own FROST attempt manager
|
let topic = topic.unwrap();
|
||||||
todo!("TODO")
|
let signer = signer(signed);
|
||||||
|
|
||||||
|
let Some((id, data_set)) =
|
||||||
|
self.accumulate_dkg_confirmation(block_number, topic, attempt, &preprocess, signer)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
db::DkgConfirmationMessages::send(
|
||||||
|
self.tributary_txn,
|
||||||
|
self.set.set,
|
||||||
|
&messages::sign::CoordinatorMessage::Preprocesses { id, preprocesses: data_set },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Transaction::DkgConfirmationShare { attempt, share, signed } => {
|
Transaction::DkgConfirmationShare { attempt, share, signed } => {
|
||||||
// Accumulate the shares into our own FROST attempt manager
|
let topic = topic.unwrap();
|
||||||
todo!("TODO: SetKeysTask")
|
let signer = signer(signed);
|
||||||
|
|
||||||
|
let Some((id, data_set)) =
|
||||||
|
self.accumulate_dkg_confirmation(block_number, topic, attempt, &share, signer)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
db::DkgConfirmationMessages::send(
|
||||||
|
self.tributary_txn,
|
||||||
|
self.set.set,
|
||||||
|
&messages::sign::CoordinatorMessage::Shares { id, shares: data_set },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::Cosign { substrate_block_hash } => {
|
Transaction::Cosign { substrate_block_hash } => {
|
||||||
@@ -405,7 +506,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::Sign { id, attempt, round, data, signed } => {
|
Transaction::Sign { id: _, attempt: _, round, data, signed } => {
|
||||||
let topic = topic.unwrap();
|
let topic = topic.unwrap();
|
||||||
let signer = signer(signed);
|
let signer = signer(signed);
|
||||||
|
|
||||||
@@ -458,7 +559,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user