mirror of
https://github.com/serai-dex/serai.git
synced 2025-04-06 06:17:28 +00:00
Correct accumulated errors in the processor
This commit is contained in:
parent
cb906242e7
commit
8222ce78d8
16 changed files with 133 additions and 98 deletions
Cargo.lock
coordinator
processor
substrate/validator-sets/primitives/src
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -6906,6 +6906,7 @@ dependencies = [
|
|||
"log",
|
||||
"parity-scale-codec",
|
||||
"serai-client",
|
||||
"serai-cosign",
|
||||
"serai-db",
|
||||
"serai-env",
|
||||
"serai-message-queue",
|
||||
|
@ -7097,6 +7098,7 @@ dependencies = [
|
|||
"modular-frost",
|
||||
"parity-scale-codec",
|
||||
"rand_core",
|
||||
"serai-cosign",
|
||||
"serai-db",
|
||||
"serai-in-instructions-primitives",
|
||||
"serai-primitives",
|
||||
|
|
|
@ -104,6 +104,24 @@ pub struct Cosign {
|
|||
pub cosigner: NetworkId,
|
||||
}
|
||||
|
||||
impl CosignIntent {
|
||||
/// Convert this into a `Cosign`.
|
||||
pub fn into_cosign(self, cosigner: NetworkId) -> Cosign {
|
||||
let CosignIntent { global_session, block_number, block_hash, notable: _ } = self;
|
||||
Cosign { global_session, block_number, block_hash, cosigner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Cosign {
|
||||
/// The message to sign to sign this cosign.
|
||||
///
|
||||
/// This must be signed with schnorrkel, the context set to `COSIGN_CONTEXT`.
|
||||
pub fn signature_message(&self) -> Vec<u8> {
|
||||
// We use a schnorrkel context to domain-separate this
|
||||
self.encode()
|
||||
}
|
||||
}
|
||||
|
||||
/// A signed cosign.
|
||||
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
|
||||
pub struct SignedCosign {
|
||||
|
@ -118,7 +136,7 @@ impl SignedCosign {
|
|||
let Ok(signer) = schnorrkel::PublicKey::from_bytes(&signer.0) else { return false };
|
||||
let Ok(signature) = schnorrkel::Signature::from_bytes(&self.signature) else { return false };
|
||||
|
||||
signer.verify_simple(COSIGN_CONTEXT, &self.cosign.encode(), &signature).is_ok()
|
||||
signer.verify_simple(COSIGN_CONTEXT, &self.cosign.signature_message(), &signature).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -365,10 +365,12 @@ impl Transaction {
|
|||
Transaction::DkgConfirmationPreprocess { ref mut signed, .. } => signed,
|
||||
Transaction::DkgConfirmationShare { ref mut signed, .. } => signed,
|
||||
|
||||
Transaction::Cosign { .. } => panic!("signing CosignSubstrateBlock"),
|
||||
Transaction::Cosigned { .. } => panic!("signing Cosigned"),
|
||||
Transaction::SubstrateBlock { .. } => panic!("signing SubstrateBlock"),
|
||||
Transaction::Batch { .. } => panic!("signing Batch"),
|
||||
Transaction::Cosign { .. } => panic!("signing Cosign transaction (provided)"),
|
||||
Transaction::Cosigned { .. } => panic!("signing Cosigned transaction (provided)"),
|
||||
Transaction::SubstrateBlock { .. } => {
|
||||
panic!("signing SubstrateBlock transaction (provided)")
|
||||
}
|
||||
Transaction::Batch { .. } => panic!("signing Batch transaction (provided)"),
|
||||
|
||||
Transaction::Sign { ref mut signed, .. } => signed,
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, fea
|
|||
dkg = { path = "../../crypto/dkg", default-features = false, features = ["std", "evrf-ristretto"] }
|
||||
|
||||
serai-client = { path = "../../substrate/client", default-features = false }
|
||||
serai-cosign = { path = "../../coordinator/cosign" }
|
||||
|
||||
log = { version = "0.4", default-features = false, features = ["std"] }
|
||||
env_logger = { version = "0.10", default-features = false, features = ["humantime"] }
|
||||
|
|
|
@ -3,12 +3,14 @@ use std::sync::{LazyLock, Arc, Mutex};
|
|||
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use scale::Encode;
|
||||
use serai_client::{
|
||||
primitives::Signature, validator_sets::primitives::Session,
|
||||
primitives::Signature,
|
||||
validator_sets::primitives::{Session, SlashReport},
|
||||
in_instructions::primitives::SignedBatch,
|
||||
};
|
||||
|
||||
use serai_cosign::SignedCosign;
|
||||
|
||||
use serai_db::{Get, DbTxn, Db, create_db, db_channel};
|
||||
|
||||
use scanner::ScannerFeed;
|
||||
|
@ -181,17 +183,11 @@ impl signers::Coordinator for CoordinatorSend {
|
|||
|
||||
fn publish_cosign(
|
||||
&mut self,
|
||||
block_number: u64,
|
||||
block: [u8; 32],
|
||||
signature: Signature,
|
||||
cosign: SignedCosign,
|
||||
) -> impl Send + Future<Output = Result<(), Self::EphemeralError>> {
|
||||
async move {
|
||||
self.send(&messages::ProcessorMessage::Coordinator(
|
||||
messages::coordinator::ProcessorMessage::CosignedBlock {
|
||||
block_number,
|
||||
block,
|
||||
signature: signature.encode(),
|
||||
},
|
||||
messages::coordinator::ProcessorMessage::CosignedBlock { cosign },
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
@ -212,13 +208,15 @@ impl signers::Coordinator for CoordinatorSend {
|
|||
fn publish_slash_report_signature(
|
||||
&mut self,
|
||||
session: Session,
|
||||
slash_report: SlashReport,
|
||||
signature: Signature,
|
||||
) -> impl Send + Future<Output = Result<(), Self::EphemeralError>> {
|
||||
async move {
|
||||
self.send(&messages::ProcessorMessage::Coordinator(
|
||||
messages::coordinator::ProcessorMessage::SignedSlashReport {
|
||||
session,
|
||||
signature: signature.encode(),
|
||||
slash_report,
|
||||
signature: signature.0,
|
||||
},
|
||||
));
|
||||
Ok(())
|
||||
|
|
|
@ -221,20 +221,16 @@ pub async fn main_loop<
|
|||
signers.queue_message(txn, &msg)
|
||||
}
|
||||
messages::CoordinatorMessage::Coordinator(
|
||||
messages::coordinator::CoordinatorMessage::CosignSubstrateBlock {
|
||||
session,
|
||||
block_number,
|
||||
block,
|
||||
},
|
||||
messages::coordinator::CoordinatorMessage::CosignSubstrateBlock { session, cosign },
|
||||
) => {
|
||||
let txn = txn.take().unwrap();
|
||||
signers.cosign_block(txn, session, block_number, block)
|
||||
signers.cosign_block(txn, session, &cosign)
|
||||
}
|
||||
messages::CoordinatorMessage::Coordinator(
|
||||
messages::coordinator::CoordinatorMessage::SignSlashReport { session, report },
|
||||
messages::coordinator::CoordinatorMessage::SignSlashReport { session, slash_report },
|
||||
) => {
|
||||
let txn = txn.take().unwrap();
|
||||
signers.sign_slash_report(txn, session, &report)
|
||||
signers.sign_slash_report(txn, session, &slash_report)
|
||||
}
|
||||
|
||||
messages::CoordinatorMessage::Substrate(msg) => match msg {
|
||||
|
|
|
@ -11,7 +11,7 @@ use validator_sets_primitives::{Session, KeyPair, SlashReport};
|
|||
use coins_primitives::OutInstructionWithBalance;
|
||||
use in_instructions_primitives::SignedBatch;
|
||||
|
||||
use serai_cosign::{CosignIntent, SignedCosign};
|
||||
use serai_cosign::{Cosign, SignedCosign};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||
pub struct SubstrateContext {
|
||||
|
@ -166,7 +166,7 @@ pub mod coordinator {
|
|||
/// Cosign the specified Substrate block.
|
||||
///
|
||||
/// This is sent by the Coordinator's Tributary scanner.
|
||||
CosignSubstrateBlock { session: Session, intent: CosignIntent },
|
||||
CosignSubstrateBlock { session: Session, cosign: Cosign },
|
||||
/// Sign the slash report for this session.
|
||||
///
|
||||
/// This is sent by the Coordinator's Tributary scanner.
|
||||
|
@ -322,8 +322,8 @@ impl CoordinatorMessage {
|
|||
CoordinatorMessage::Coordinator(msg) => {
|
||||
let (sub, id) = match msg {
|
||||
// We only cosign a block once, and Reattempt is a separate message
|
||||
coordinator::CoordinatorMessage::CosignSubstrateBlock { intent, .. } => {
|
||||
(0, intent.block_number.encode())
|
||||
coordinator::CoordinatorMessage::CosignSubstrateBlock { cosign, .. } => {
|
||||
(0, cosign.block_number.encode())
|
||||
}
|
||||
// We only sign one slash report, and Reattempt is a separate message
|
||||
coordinator::CoordinatorMessage::SignSlashReport { session, .. } => (1, session.encode()),
|
||||
|
|
|
@ -40,6 +40,7 @@ serai-db = { path = "../../common/db" }
|
|||
log = { version = "0.4", default-features = false, features = ["std"] }
|
||||
tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "sync", "time", "macros"] }
|
||||
|
||||
serai-cosign = { path = "../../coordinator/cosign" }
|
||||
messages = { package = "serai-processor-messages", path = "../messages" }
|
||||
primitives = { package = "serai-processor-primitives", path = "../primitives" }
|
||||
scanner = { package = "serai-processor-scanner", path = "../scanner" }
|
||||
|
|
|
@ -69,7 +69,12 @@ impl<D: Db, E: GroupEncoding> BatchSignerTask<D, E> {
|
|||
|
||||
let mut machines = Vec::with_capacity(keys.len());
|
||||
for keys in &keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), batch_message(&batch)));
|
||||
// TODO: Fetch the context for this from a constant instead of re-defining it
|
||||
machines.push(WrappedSchnorrkelMachine::new(
|
||||
keys.clone(),
|
||||
b"substrate",
|
||||
batch_message(&batch),
|
||||
));
|
||||
}
|
||||
attempt_manager.register(VariantSignId::Batch(id), machines);
|
||||
}
|
||||
|
@ -106,7 +111,12 @@ impl<D: Db, E: Send + GroupEncoding> ContinuallyRan for BatchSignerTask<D, E> {
|
|||
|
||||
let mut machines = Vec::with_capacity(self.keys.len());
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), batch_message(&batch)));
|
||||
// TODO: Also fetch the constant here
|
||||
machines.push(WrappedSchnorrkelMachine::new(
|
||||
keys.clone(),
|
||||
b"substrate",
|
||||
batch_message(&batch),
|
||||
));
|
||||
}
|
||||
for msg in self.attempt_manager.register(VariantSignId::Batch(batch_hash), machines) {
|
||||
BatchSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use core::future::Future;
|
||||
|
||||
use scale::Decode;
|
||||
use serai_primitives::Signature;
|
||||
|
||||
use serai_db::{DbTxn, Db};
|
||||
|
||||
use primitives::task::ContinuallyRan;
|
||||
|
@ -99,17 +100,11 @@ impl<D: Db, C: Coordinator> ContinuallyRan for CoordinatorTask<D, C> {
|
|||
// Publish the cosigns from this session
|
||||
{
|
||||
let mut txn = self.db.txn();
|
||||
while let Some(((block_number, block_id), signature)) =
|
||||
Cosign::try_recv(&mut txn, session)
|
||||
{
|
||||
while let Some(signed_cosign) = Cosign::try_recv(&mut txn, session) {
|
||||
iterated = true;
|
||||
self
|
||||
.coordinator
|
||||
.publish_cosign(
|
||||
block_number,
|
||||
block_id,
|
||||
<_>::decode(&mut signature.as_slice()).unwrap(),
|
||||
)
|
||||
.publish_cosign(signed_cosign)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't publish Cosign: {e:?}"))?;
|
||||
}
|
||||
|
@ -119,15 +114,12 @@ impl<D: Db, C: Coordinator> ContinuallyRan for CoordinatorTask<D, C> {
|
|||
// If this session signed its slash report, publish its signature
|
||||
{
|
||||
let mut txn = self.db.txn();
|
||||
if let Some(slash_report_signature) = SlashReportSignature::try_recv(&mut txn, session) {
|
||||
if let Some((slash_report, signature)) = SignedSlashReport::try_recv(&mut txn, session) {
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.publish_slash_report_signature(
|
||||
session,
|
||||
<_>::decode(&mut slash_report_signature.as_slice()).unwrap(),
|
||||
)
|
||||
.publish_slash_report_signature(session, slash_report, Signature(signature))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
format!("couldn't send slash report signature to the coordinator: {e:?}")
|
||||
|
|
|
@ -9,7 +9,8 @@ use serai_validator_sets_primitives::Session;
|
|||
|
||||
use serai_db::{DbTxn, Db};
|
||||
|
||||
use messages::{sign::VariantSignId, coordinator::cosign_block_msg};
|
||||
use serai_cosign::{COSIGN_CONTEXT, Cosign as CosignStruct, SignedCosign};
|
||||
use messages::sign::VariantSignId;
|
||||
|
||||
use primitives::task::{DoesNotError, ContinuallyRan};
|
||||
|
||||
|
@ -34,7 +35,7 @@ pub(crate) struct CosignerTask<D: Db> {
|
|||
session: Session,
|
||||
keys: Vec<ThresholdKeys<Ristretto>>,
|
||||
|
||||
current_cosign: Option<(u64, [u8; 32])>,
|
||||
current_cosign: Option<CosignStruct>,
|
||||
attempt_manager: AttemptManager<D, WrappedSchnorrkelMachine>,
|
||||
}
|
||||
|
||||
|
@ -62,26 +63,34 @@ impl<D: Db> ContinuallyRan for CosignerTask<D> {
|
|||
let mut txn = self.db.txn();
|
||||
if let Some(cosign) = ToCosign::get(&txn, self.session) {
|
||||
// If this wasn't already signed for...
|
||||
if LatestCosigned::get(&txn, self.session) < Some(cosign.0) {
|
||||
if LatestCosigned::get(&txn, self.session) < Some(cosign.block_number) {
|
||||
// If this isn't the cosign we're currently working on, meaning it's fresh
|
||||
if self.current_cosign != Some(cosign) {
|
||||
if self.current_cosign.as_ref() != Some(&cosign) {
|
||||
// Retire the current cosign
|
||||
if let Some(current_cosign) = self.current_cosign {
|
||||
assert!(current_cosign.0 < cosign.0);
|
||||
self.attempt_manager.retire(&mut txn, VariantSignId::Cosign(current_cosign.0));
|
||||
if let Some(current_cosign) = &self.current_cosign {
|
||||
assert!(current_cosign.block_number < cosign.block_number);
|
||||
self
|
||||
.attempt_manager
|
||||
.retire(&mut txn, VariantSignId::Cosign(current_cosign.block_number));
|
||||
}
|
||||
|
||||
// Set the cosign being worked on
|
||||
self.current_cosign = Some(cosign);
|
||||
self.current_cosign = Some(cosign.clone());
|
||||
|
||||
let mut machines = Vec::with_capacity(self.keys.len());
|
||||
{
|
||||
let message = cosign_block_msg(cosign.0, cosign.1);
|
||||
let message = cosign.signature_message();
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), message.clone()));
|
||||
machines.push(WrappedSchnorrkelMachine::new(
|
||||
keys.clone(),
|
||||
COSIGN_CONTEXT,
|
||||
message.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
for msg in self.attempt_manager.register(VariantSignId::Cosign(cosign.0), machines) {
|
||||
for msg in
|
||||
self.attempt_manager.register(VariantSignId::Cosign(cosign.block_number), machines)
|
||||
{
|
||||
CosignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
|
||||
|
@ -109,12 +118,19 @@ impl<D: Db> ContinuallyRan for CosignerTask<D> {
|
|||
let VariantSignId::Cosign(block_number) = id else {
|
||||
panic!("CosignerTask signed a non-Cosign")
|
||||
};
|
||||
assert_eq!(Some(block_number), self.current_cosign.map(|cosign| cosign.0));
|
||||
assert_eq!(
|
||||
Some(block_number),
|
||||
self.current_cosign.as_ref().map(|cosign| cosign.block_number)
|
||||
);
|
||||
|
||||
let cosign = self.current_cosign.take().unwrap();
|
||||
LatestCosigned::set(&mut txn, self.session, &cosign.0);
|
||||
LatestCosigned::set(&mut txn, self.session, &cosign.block_number);
|
||||
let cosign = SignedCosign {
|
||||
cosign,
|
||||
signature: Signature::from(signature).encode().try_into().unwrap(),
|
||||
};
|
||||
// Send the cosign
|
||||
Cosign::send(&mut txn, self.session, &(cosign, Signature::from(signature).encode()));
|
||||
Cosign::send(&mut txn, self.session, &cosign);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use serai_validator_sets_primitives::{Session, Slash};
|
||||
use serai_validator_sets_primitives::{Session, SlashReport as SlashReportStruct};
|
||||
|
||||
use serai_db::{Get, DbTxn, create_db, db_channel};
|
||||
|
||||
use serai_cosign::{Cosign as CosignStruct, SignedCosign};
|
||||
|
||||
use messages::sign::{ProcessorMessage, CoordinatorMessage};
|
||||
|
||||
create_db! {
|
||||
|
@ -11,16 +13,16 @@ create_db! {
|
|||
LatestRetiredSession: () -> Session,
|
||||
ToCleanup: () -> Vec<(Session, Vec<u8>)>,
|
||||
|
||||
ToCosign: (session: Session) -> (u64, [u8; 32]),
|
||||
ToCosign: (session: Session) -> CosignStruct,
|
||||
}
|
||||
}
|
||||
|
||||
db_channel! {
|
||||
SignersGlobal {
|
||||
Cosign: (session: Session) -> ((u64, [u8; 32]), Vec<u8>),
|
||||
Cosign: (session: Session) -> SignedCosign,
|
||||
|
||||
SlashReport: (session: Session) -> Vec<Slash>,
|
||||
SlashReportSignature: (session: Session) -> Vec<u8>,
|
||||
SlashReport: (session: Session) -> SlashReportStruct,
|
||||
SignedSlashReport: (session: Session) -> (SlashReportStruct, [u8; 64]),
|
||||
|
||||
/*
|
||||
TODO: Most of these are pointless? We drop all active signing sessions on reboot. It's
|
||||
|
|
|
@ -11,11 +11,13 @@ use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto};
|
|||
use frost::dkg::{ThresholdCore, ThresholdKeys};
|
||||
|
||||
use serai_primitives::Signature;
|
||||
use serai_validator_sets_primitives::{Session, Slash};
|
||||
use serai_validator_sets_primitives::{Session, SlashReport};
|
||||
use serai_in_instructions_primitives::SignedBatch;
|
||||
|
||||
use serai_db::{DbTxn, Db};
|
||||
|
||||
use serai_cosign::{Cosign, SignedCosign};
|
||||
|
||||
use messages::sign::{VariantSignId, ProcessorMessage, CoordinatorMessage};
|
||||
|
||||
use primitives::task::{Task, TaskHandle, ContinuallyRan};
|
||||
|
@ -59,9 +61,7 @@ pub trait Coordinator: 'static + Send + Sync {
|
|||
/// Publish a cosign.
|
||||
fn publish_cosign(
|
||||
&mut self,
|
||||
block_number: u64,
|
||||
block_id: [u8; 32],
|
||||
signature: Signature,
|
||||
signed_cosign: SignedCosign,
|
||||
) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
|
||||
|
||||
/// Publish a `SignedBatch`.
|
||||
|
@ -74,6 +74,7 @@ pub trait Coordinator: 'static + Send + Sync {
|
|||
fn publish_slash_report_signature(
|
||||
&mut self,
|
||||
session: Session,
|
||||
slash_report: SlashReport,
|
||||
signature: Signature,
|
||||
) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
|
||||
}
|
||||
|
@ -408,19 +409,13 @@ impl<
|
|||
/// Cosign a block.
|
||||
///
|
||||
/// This is a cheap call and able to be done inline from a higher-level loop.
|
||||
pub fn cosign_block(
|
||||
&mut self,
|
||||
mut txn: impl DbTxn,
|
||||
session: Session,
|
||||
block_number: u64,
|
||||
block: [u8; 32],
|
||||
) {
|
||||
pub fn cosign_block(&mut self, mut txn: impl DbTxn, session: Session, cosign: &Cosign) {
|
||||
// Don't cosign blocks with already retired keys
|
||||
if Some(session.0) <= db::LatestRetiredSession::get(&txn).map(|session| session.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::ToCosign::set(&mut txn, session, &(block_number, block));
|
||||
db::ToCosign::set(&mut txn, session, cosign);
|
||||
txn.commit();
|
||||
|
||||
if let Some(tasks) = self.tasks.get(&session) {
|
||||
|
@ -435,7 +430,7 @@ impl<
|
|||
&mut self,
|
||||
mut txn: impl DbTxn,
|
||||
session: Session,
|
||||
slash_report: &Vec<Slash>,
|
||||
slash_report: &SlashReport,
|
||||
) {
|
||||
// Don't sign slash reports with already retired keys
|
||||
if Some(session.0) <= db::LatestRetiredSession::get(&txn).map(|session| session.0) {
|
||||
|
|
|
@ -3,11 +3,8 @@ use core::{marker::PhantomData, future::Future};
|
|||
use ciphersuite::Ristretto;
|
||||
use frost::dkg::ThresholdKeys;
|
||||
|
||||
use scale::Encode;
|
||||
use serai_primitives::Signature;
|
||||
use serai_validator_sets_primitives::{
|
||||
Session, ValidatorSet, SlashReport as SlashReportStruct, report_slashes_message,
|
||||
};
|
||||
use serai_validator_sets_primitives::Session;
|
||||
|
||||
use serai_db::{DbTxn, Db};
|
||||
|
||||
|
@ -20,7 +17,7 @@ use frost_attempt_manager::*;
|
|||
|
||||
use crate::{
|
||||
db::{
|
||||
SlashReport, SlashReportSignature, CoordinatorToSlashReportSignerMessages,
|
||||
SlashReport, SignedSlashReport, CoordinatorToSlashReportSignerMessages,
|
||||
SlashReportSignerToCoordinatorMessages,
|
||||
},
|
||||
WrappedSchnorrkelMachine,
|
||||
|
@ -72,12 +69,14 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for SlashReportSignerTask<D, S> {
|
|||
|
||||
let mut machines = Vec::with_capacity(self.keys.len());
|
||||
{
|
||||
let message = report_slashes_message(
|
||||
&ValidatorSet { network: S::NETWORK, session: self.session },
|
||||
&SlashReportStruct(slash_report.try_into().unwrap()),
|
||||
);
|
||||
let message = slash_report.report_slashes_message();
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), message.clone()));
|
||||
// TODO: Fetch this constant from somewhere instead of inlining it
|
||||
machines.push(WrappedSchnorrkelMachine::new(
|
||||
keys.clone(),
|
||||
b"substrate",
|
||||
message.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let mut txn = self.db.txn();
|
||||
|
@ -105,12 +104,12 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for SlashReportSignerTask<D, S> {
|
|||
Response::Signature { id, signature } => {
|
||||
assert_eq!(id, VariantSignId::SlashReport);
|
||||
// Drain the channel
|
||||
SlashReport::try_recv(&mut txn, self.session).unwrap();
|
||||
let slash_report = SlashReport::try_recv(&mut txn, self.session).unwrap();
|
||||
// Send the signature
|
||||
SlashReportSignature::send(
|
||||
SignedSlashReport::send(
|
||||
&mut txn,
|
||||
self.session,
|
||||
&Signature::from(signature).encode(),
|
||||
&(slash_report, Signature::from(signature).0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ use frost_schnorrkel::Schnorrkel;
|
|||
|
||||
// This wraps a Schnorrkel sign machine into one with a preset message.
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct WrappedSchnorrkelMachine(ThresholdKeys<Ristretto>, Vec<u8>);
|
||||
pub(crate) struct WrappedSchnorrkelMachine(ThresholdKeys<Ristretto>, &'static [u8], Vec<u8>);
|
||||
impl WrappedSchnorrkelMachine {
|
||||
pub(crate) fn new(keys: ThresholdKeys<Ristretto>, msg: Vec<u8>) -> Self {
|
||||
Self(keys, msg)
|
||||
pub(crate) fn new(keys: ThresholdKeys<Ristretto>, context: &'static [u8], msg: Vec<u8>) -> Self {
|
||||
Self(keys, context, msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,10 @@ impl PreprocessMachine for WrappedSchnorrkelMachine {
|
|||
rng: &mut R,
|
||||
) -> (Self::SignMachine, Preprocess<Ristretto, <Schnorrkel as Algorithm<Ristretto>>::Addendum>)
|
||||
{
|
||||
let WrappedSchnorrkelMachine(keys, batch) = self;
|
||||
let WrappedSchnorrkelMachine(keys, context, msg) = self;
|
||||
let (machine, preprocess) =
|
||||
AlgorithmMachine::new(Schnorrkel::new(b"substrate"), keys).preprocess(rng);
|
||||
(WrappedSchnorrkelSignMachine(machine, batch), preprocess)
|
||||
AlgorithmMachine::new(Schnorrkel::new(context), keys).preprocess(rng);
|
||||
(WrappedSchnorrkelSignMachine(machine, msg), preprocess)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -234,9 +234,12 @@ impl TryFrom<Vec<Slash>> for SlashReport {
|
|||
}
|
||||
}
|
||||
|
||||
// This is assumed binding to the ValidatorSet via the key signed with
|
||||
pub fn report_slashes_message(slashes: &SlashReport) -> Vec<u8> {
|
||||
(b"ValidatorSets-report_slashes", slashes).encode()
|
||||
impl SlashReport {
|
||||
/// The message to sign when publishing this SlashReport.
|
||||
// This is assumed binding to the ValidatorSet via the key signed with
|
||||
pub fn report_slashes_message(&self) -> Vec<u8> {
|
||||
(b"ValidatorSets-report_slashes", &self.0).encode()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue