mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Remove async-trait from processor/
Part of https://github.com/serai-dex/issues/607.
This commit is contained in:
@@ -14,13 +14,12 @@ all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = ["borsh", "scale"]
|
||||
ignored = ["borsh"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
async-trait = { version = "0.1", default-features = false }
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
zeroize = { version = "1", default-features = false, features = ["std"] }
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use core::future::Future;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use ciphersuite::{group::GroupEncoding, Ristretto};
|
||||
@@ -75,114 +76,115 @@ impl<D: Db, E: GroupEncoding> BatchSignerTask<D, E> {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<D: Db, E: Send + GroupEncoding> ContinuallyRan for BatchSignerTask<D, E> {
|
||||
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||
let mut iterated = false;
|
||||
fn run_iteration(&mut self) -> impl Send + Future<Output = Result<bool, String>> {
|
||||
async move {
|
||||
let mut iterated = false;
|
||||
|
||||
// Check for new batches to sign
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(batch) = BatchesToSign::try_recv(&mut txn, &self.external_key) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
// Check for new batches to sign
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(batch) = BatchesToSign::try_recv(&mut txn, &self.external_key) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
// Save this to the database as a transaction to sign
|
||||
self.active_signing_protocols.insert(batch.id);
|
||||
ActiveSigningProtocols::set(
|
||||
&mut txn,
|
||||
self.session,
|
||||
&self.active_signing_protocols.iter().copied().collect(),
|
||||
);
|
||||
Batches::set(&mut txn, batch.id, &batch);
|
||||
// Save this to the database as a transaction to sign
|
||||
self.active_signing_protocols.insert(batch.id);
|
||||
ActiveSigningProtocols::set(
|
||||
&mut txn,
|
||||
self.session,
|
||||
&self.active_signing_protocols.iter().copied().collect(),
|
||||
);
|
||||
Batches::set(&mut txn, batch.id, &batch);
|
||||
|
||||
let mut machines = Vec::with_capacity(self.keys.len());
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), batch_message(&batch)));
|
||||
}
|
||||
for msg in self.attempt_manager.register(VariantSignId::Batch(batch.id), machines) {
|
||||
BatchSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
// Check for acknowledged Batches (meaning we should no longer sign for these Batches)
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(id) = AcknowledgedBatches::try_recv(&mut txn, &self.external_key) else {
|
||||
break;
|
||||
};
|
||||
|
||||
{
|
||||
let last_acknowledged = LastAcknowledgedBatch::get(&txn);
|
||||
if Some(id) > last_acknowledged {
|
||||
LastAcknowledgedBatch::set(&mut txn, &id);
|
||||
let mut machines = Vec::with_capacity(self.keys.len());
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), batch_message(&batch)));
|
||||
}
|
||||
for msg in self.attempt_manager.register(VariantSignId::Batch(batch.id), machines) {
|
||||
BatchSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
/*
|
||||
We may have yet to register this signing protocol.
|
||||
// Check for acknowledged Batches (meaning we should no longer sign for these Batches)
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(id) = AcknowledgedBatches::try_recv(&mut txn, &self.external_key) else {
|
||||
break;
|
||||
};
|
||||
|
||||
While `BatchesToSign` is populated before `AcknowledgedBatches`, we could theoretically have
|
||||
`BatchesToSign` populated with a new batch _while iterating over `AcknowledgedBatches`_, and
|
||||
then have `AcknowledgedBatched` populated. In that edge case, we will see the
|
||||
acknowledgement notification before we see the transaction.
|
||||
|
||||
In such a case, we break (dropping the txn, re-queueing the acknowledgement notification).
|
||||
On the task's next iteration, we'll process the Batch from `BatchesToSign` and be
|
||||
able to make progress.
|
||||
*/
|
||||
if !self.active_signing_protocols.remove(&id) {
|
||||
break;
|
||||
}
|
||||
iterated = true;
|
||||
|
||||
// Since it was, remove this as an active signing protocol
|
||||
ActiveSigningProtocols::set(
|
||||
&mut txn,
|
||||
self.session,
|
||||
&self.active_signing_protocols.iter().copied().collect(),
|
||||
);
|
||||
// Clean up the database
|
||||
Batches::del(&mut txn, id);
|
||||
SignedBatches::del(&mut txn, id);
|
||||
|
||||
// We retire with a txn so we either successfully flag this Batch as acknowledged, and
|
||||
// won't re-register it (making this retire safe), or we don't flag it, meaning we will
|
||||
// re-register it, yet that's safe as we have yet to retire it
|
||||
self.attempt_manager.retire(&mut txn, VariantSignId::Batch(id));
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
// Handle any messages sent to us
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = CoordinatorToBatchSignerMessages::try_recv(&mut txn, self.session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
match self.attempt_manager.handle(msg) {
|
||||
Response::Messages(msgs) => {
|
||||
for msg in msgs {
|
||||
BatchSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
{
|
||||
let last_acknowledged = LastAcknowledgedBatch::get(&txn);
|
||||
if Some(id) > last_acknowledged {
|
||||
LastAcknowledgedBatch::set(&mut txn, &id);
|
||||
}
|
||||
}
|
||||
Response::Signature { id, signature } => {
|
||||
let VariantSignId::Batch(id) = id else { panic!("BatchSignerTask signed a non-Batch") };
|
||||
let batch =
|
||||
Batches::get(&txn, id).expect("signed a Batch we didn't save to the database");
|
||||
let signed_batch = SignedBatch { batch, signature: signature.into() };
|
||||
SignedBatches::set(&mut txn, signed_batch.batch.id, &signed_batch);
|
||||
|
||||
/*
|
||||
We may have yet to register this signing protocol.
|
||||
|
||||
While `BatchesToSign` is populated before `AcknowledgedBatches`, we could theoretically
|
||||
have `BatchesToSign` populated with a new batch _while iterating over
|
||||
`AcknowledgedBatches`_, and then have `AcknowledgedBatched` populated. In that edge case,
|
||||
we will see the acknowledgement notification before we see the transaction.
|
||||
|
||||
In such a case, we break (dropping the txn, re-queueing the acknowledgement notification).
|
||||
On the task's next iteration, we'll process the Batch from `BatchesToSign` and be
|
||||
able to make progress.
|
||||
*/
|
||||
if !self.active_signing_protocols.remove(&id) {
|
||||
break;
|
||||
}
|
||||
iterated = true;
|
||||
|
||||
// Since it was, remove this as an active signing protocol
|
||||
ActiveSigningProtocols::set(
|
||||
&mut txn,
|
||||
self.session,
|
||||
&self.active_signing_protocols.iter().copied().collect(),
|
||||
);
|
||||
// Clean up the database
|
||||
Batches::del(&mut txn, id);
|
||||
SignedBatches::del(&mut txn, id);
|
||||
|
||||
// We retire with a txn so we either successfully flag this Batch as acknowledged, and
|
||||
// won't re-register it (making this retire safe), or we don't flag it, meaning we will
|
||||
// re-register it, yet that's safe as we have yet to retire it
|
||||
self.attempt_manager.retire(&mut txn, VariantSignId::Batch(id));
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
// Handle any messages sent to us
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = CoordinatorToBatchSignerMessages::try_recv(&mut txn, self.session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
Ok(iterated)
|
||||
match self.attempt_manager.handle(msg) {
|
||||
Response::Messages(msgs) => {
|
||||
for msg in msgs {
|
||||
BatchSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
}
|
||||
Response::Signature { id, signature } => {
|
||||
let VariantSignId::Batch(id) = id else { panic!("BatchSignerTask signed a non-Batch") };
|
||||
let batch =
|
||||
Batches::get(&txn, id).expect("signed a Batch we didn't save to the database");
|
||||
let signed_batch = SignedBatch { batch, signature: signature.into() };
|
||||
SignedBatches::set(&mut txn, signed_batch.batch.id, &signed_batch);
|
||||
}
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
Ok(iterated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use core::future::Future;
|
||||
|
||||
use scale::Decode;
|
||||
use serai_db::{DbTxn, Db};
|
||||
|
||||
@@ -19,149 +21,157 @@ impl<D: Db, C: Coordinator> CoordinatorTask<D, C> {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<D: Db, C: Coordinator> ContinuallyRan for CoordinatorTask<D, C> {
|
||||
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||
let mut iterated = false;
|
||||
fn run_iteration(&mut self) -> impl Send + Future<Output = Result<bool, String>> {
|
||||
async move {
|
||||
let mut iterated = false;
|
||||
|
||||
for session in RegisteredKeys::get(&self.db).unwrap_or(vec![]) {
|
||||
// Publish the messages generated by this key's signers
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = CosignerToCoordinatorMessages::try_recv(&mut txn, session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't send sign message to the coordinator: {e:?}"))?;
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = BatchSignerToCoordinatorMessages::try_recv(&mut txn, session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't send sign message to the coordinator: {e:?}"))?;
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = SlashReportSignerToCoordinatorMessages::try_recv(&mut txn, session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't send sign message to the coordinator: {e:?}"))?;
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = TransactionSignerToCoordinatorMessages::try_recv(&mut txn, session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't send sign message to the coordinator: {e:?}"))?;
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
iterated = true;
|
||||
self
|
||||
.coordinator
|
||||
.publish_cosign(block_number, block_id, <_>::decode(&mut signature.as_slice()).unwrap())
|
||||
.await
|
||||
.map_err(|e| format!("couldn't publish Cosign: {e:?}"))?;
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
for session in RegisteredKeys::get(&self.db).unwrap_or(vec![]) {
|
||||
// Publish the messages generated by this key's signers
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = CosignerToCoordinatorMessages::try_recv(&mut txn, session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.publish_slash_report_signature(
|
||||
session,
|
||||
<_>::decode(&mut slash_report_signature.as_slice()).unwrap(),
|
||||
)
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
format!("couldn't send slash report signature to the coordinator: {e:?}")
|
||||
})?;
|
||||
.map_err(|e| format!("couldn't send sign message to the coordinator: {e:?}"))?;
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Publish the Batches
|
||||
{
|
||||
let mut txn = self.db.txn();
|
||||
while let Some(batch) = scanner::Batches::try_recv(&mut txn) {
|
||||
iterated = true;
|
||||
self
|
||||
.coordinator
|
||||
.publish_batch(batch)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't publish Batch: {e:?}"))?;
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = BatchSignerToCoordinatorMessages::try_recv(&mut txn, session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
// Publish the signed Batches
|
||||
{
|
||||
let mut txn = self.db.txn();
|
||||
// The last acknowledged Batch may exceed the last Batch we published if we didn't sign for
|
||||
// the prior Batch(es) (and accordingly didn't publish them)
|
||||
let last_batch =
|
||||
crate::batch::last_acknowledged_batch(&txn).max(db::LastPublishedBatch::get(&txn));
|
||||
let mut next_batch = last_batch.map_or(0, |id| id + 1);
|
||||
while let Some(batch) = crate::batch::signed_batch(&txn, next_batch) {
|
||||
iterated = true;
|
||||
db::LastPublishedBatch::set(&mut txn, &batch.batch.id);
|
||||
self
|
||||
.coordinator
|
||||
.publish_signed_batch(batch)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't publish Batch: {e:?}"))?;
|
||||
next_batch += 1;
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
self
|
||||
.coordinator
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't send sign message to the coordinator: {e:?}"))?;
|
||||
|
||||
Ok(iterated)
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = SlashReportSignerToCoordinatorMessages::try_recv(&mut txn, session)
|
||||
else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't send sign message to the coordinator: {e:?}"))?;
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = TransactionSignerToCoordinatorMessages::try_recv(&mut txn, session)
|
||||
else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't send sign message to the coordinator: {e:?}"))?;
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
iterated = true;
|
||||
self
|
||||
.coordinator
|
||||
.publish_cosign(
|
||||
block_number,
|
||||
block_id,
|
||||
<_>::decode(&mut signature.as_slice()).unwrap(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't publish Cosign: {e:?}"))?;
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
iterated = true;
|
||||
|
||||
self
|
||||
.coordinator
|
||||
.publish_slash_report_signature(
|
||||
session,
|
||||
<_>::decode(&mut slash_report_signature.as_slice()).unwrap(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
format!("couldn't send slash report signature to the coordinator: {e:?}")
|
||||
})?;
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Publish the Batches
|
||||
{
|
||||
let mut txn = self.db.txn();
|
||||
while let Some(batch) = scanner::Batches::try_recv(&mut txn) {
|
||||
iterated = true;
|
||||
self
|
||||
.coordinator
|
||||
.publish_batch(batch)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't publish Batch: {e:?}"))?;
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
// Publish the signed Batches
|
||||
{
|
||||
let mut txn = self.db.txn();
|
||||
// The last acknowledged Batch may exceed the last Batch we published if we didn't sign for
|
||||
// the prior Batch(es) (and accordingly didn't publish them)
|
||||
let last_batch =
|
||||
crate::batch::last_acknowledged_batch(&txn).max(db::LastPublishedBatch::get(&txn));
|
||||
let mut next_batch = last_batch.map_or(0, |id| id + 1);
|
||||
while let Some(batch) = crate::batch::signed_batch(&txn, next_batch) {
|
||||
iterated = true;
|
||||
db::LastPublishedBatch::set(&mut txn, &batch.batch.id);
|
||||
self
|
||||
.coordinator
|
||||
.publish_signed_batch(batch)
|
||||
.await
|
||||
.map_err(|e| format!("couldn't publish Batch: {e:?}"))?;
|
||||
next_batch += 1;
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
Ok(iterated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use core::future::Future;
|
||||
|
||||
use ciphersuite::Ristretto;
|
||||
use frost::dkg::ThresholdKeys;
|
||||
|
||||
@@ -48,75 +50,76 @@ impl<D: Db> CosignerTask<D> {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<D: Db> ContinuallyRan for CosignerTask<D> {
|
||||
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||
let mut iterated = false;
|
||||
fn run_iteration(&mut self) -> impl Send + Future<Output = Result<bool, String>> {
|
||||
async move {
|
||||
let mut iterated = false;
|
||||
|
||||
// Check the cosign to work on
|
||||
{
|
||||
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 this isn't the cosign we're currently working on, meaning it's fresh
|
||||
if self.current_cosign != 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));
|
||||
}
|
||||
|
||||
// Set the cosign being worked on
|
||||
self.current_cosign = Some(cosign);
|
||||
|
||||
let mut machines = Vec::with_capacity(self.keys.len());
|
||||
{
|
||||
let message = cosign_block_msg(cosign.0, cosign.1);
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), message.clone()));
|
||||
// Check the cosign to work on
|
||||
{
|
||||
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 this isn't the cosign we're currently working on, meaning it's fresh
|
||||
if self.current_cosign != 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));
|
||||
}
|
||||
|
||||
// Set the cosign being worked on
|
||||
self.current_cosign = Some(cosign);
|
||||
|
||||
let mut machines = Vec::with_capacity(self.keys.len());
|
||||
{
|
||||
let message = cosign_block_msg(cosign.0, cosign.1);
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), message.clone()));
|
||||
}
|
||||
}
|
||||
for msg in self.attempt_manager.register(VariantSignId::Cosign(cosign.0), machines) {
|
||||
CosignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
for msg in self.attempt_manager.register(VariantSignId::Cosign(cosign.0), machines) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle any messages sent to us
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = CoordinatorToCosignerMessages::try_recv(&mut txn, self.session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
match self.attempt_manager.handle(msg) {
|
||||
Response::Messages(msgs) => {
|
||||
for msg in msgs {
|
||||
CosignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
}
|
||||
Response::Signature { id, signature } => {
|
||||
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));
|
||||
|
||||
txn.commit();
|
||||
let cosign = self.current_cosign.take().unwrap();
|
||||
LatestCosigned::set(&mut txn, self.session, &cosign.0);
|
||||
// Send the cosign
|
||||
Cosign::send(&mut txn, self.session, &(cosign, Signature::from(signature).encode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle any messages sent to us
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = CoordinatorToCosignerMessages::try_recv(&mut txn, self.session) else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
match self.attempt_manager.handle(msg) {
|
||||
Response::Messages(msgs) => {
|
||||
for msg in msgs {
|
||||
CosignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
}
|
||||
Response::Signature { id, signature } => {
|
||||
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));
|
||||
|
||||
let cosign = self.current_cosign.take().unwrap();
|
||||
LatestCosigned::set(&mut txn, self.session, &cosign.0);
|
||||
// Send the cosign
|
||||
Cosign::send(&mut txn, self.session, &(cosign, Signature::from(signature).encode()));
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
Ok(iterated)
|
||||
}
|
||||
|
||||
Ok(iterated)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use core::{fmt::Debug, marker::PhantomData};
|
||||
use core::{future::Future, fmt::Debug, marker::PhantomData};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use zeroize::Zeroizing;
|
||||
@@ -43,7 +43,6 @@ mod transaction;
|
||||
use transaction::TransactionSignerTask;
|
||||
|
||||
/// A connection to the Coordinator which messages can be published with.
|
||||
#[async_trait::async_trait]
|
||||
pub trait Coordinator: 'static + Send + Sync {
|
||||
/// An error encountered when interacting with a coordinator.
|
||||
///
|
||||
@@ -52,32 +51,38 @@ pub trait Coordinator: 'static + Send + Sync {
|
||||
type EphemeralError: Debug;
|
||||
|
||||
/// Send a `messages::sign::ProcessorMessage`.
|
||||
async fn send(&mut self, message: ProcessorMessage) -> Result<(), Self::EphemeralError>;
|
||||
fn send(
|
||||
&mut self,
|
||||
message: ProcessorMessage,
|
||||
) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
|
||||
|
||||
/// Publish a cosign.
|
||||
async fn publish_cosign(
|
||||
fn publish_cosign(
|
||||
&mut self,
|
||||
block_number: u64,
|
||||
block_id: [u8; 32],
|
||||
signature: Signature,
|
||||
) -> Result<(), Self::EphemeralError>;
|
||||
) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
|
||||
|
||||
/// Publish a `Batch`.
|
||||
async fn publish_batch(&mut self, batch: Batch) -> Result<(), Self::EphemeralError>;
|
||||
fn publish_batch(&mut self, batch: Batch)
|
||||
-> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
|
||||
|
||||
/// Publish a `SignedBatch`.
|
||||
async fn publish_signed_batch(&mut self, batch: SignedBatch) -> Result<(), Self::EphemeralError>;
|
||||
fn publish_signed_batch(
|
||||
&mut self,
|
||||
batch: SignedBatch,
|
||||
) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
|
||||
|
||||
/// Publish a slash report's signature.
|
||||
async fn publish_slash_report_signature(
|
||||
fn publish_slash_report_signature(
|
||||
&mut self,
|
||||
session: Session,
|
||||
signature: Signature,
|
||||
) -> Result<(), Self::EphemeralError>;
|
||||
) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
|
||||
}
|
||||
|
||||
/// An object capable of publishing a transaction.
|
||||
#[async_trait::async_trait]
|
||||
pub trait TransactionPublisher<T: Transaction>: 'static + Send + Sync + Clone {
|
||||
/// An error encountered when publishing a transaction.
|
||||
///
|
||||
@@ -92,7 +97,7 @@ pub trait TransactionPublisher<T: Transaction>: 'static + Send + Sync + Clone {
|
||||
///
|
||||
/// The transaction already being present in the mempool/on-chain MUST NOT be considered an
|
||||
/// error.
|
||||
async fn publish(&self, tx: T) -> Result<(), Self::EphemeralError>;
|
||||
fn publish(&self, tx: T) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
|
||||
}
|
||||
|
||||
struct Tasks {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use core::marker::PhantomData;
|
||||
use core::{marker::PhantomData, future::Future};
|
||||
|
||||
use ciphersuite::Ristretto;
|
||||
use frost::dkg::ThresholdKeys;
|
||||
@@ -51,70 +51,72 @@ impl<D: Db, S: ScannerFeed> SlashReportSignerTask<D, S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<D: Db, S: ScannerFeed> ContinuallyRan for SlashReportSignerTask<D, S> {
|
||||
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||
let mut iterated = false;
|
||||
fn run_iteration(&mut self) -> impl Send + Future<Output = Result<bool, String>> {
|
||||
async move {
|
||||
let mut iterated = false;
|
||||
|
||||
// Check for the slash report to sign
|
||||
if !self.has_slash_report {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(slash_report) = SlashReport::try_recv(&mut txn, self.session) else {
|
||||
return Ok(false);
|
||||
};
|
||||
// We only commit this upon successfully signing this slash report
|
||||
drop(txn);
|
||||
iterated = true;
|
||||
// Check for the slash report to sign
|
||||
if !self.has_slash_report {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(slash_report) = SlashReport::try_recv(&mut txn, self.session) else {
|
||||
return Ok(false);
|
||||
};
|
||||
// We only commit this upon successfully signing this slash report
|
||||
drop(txn);
|
||||
iterated = true;
|
||||
|
||||
self.has_slash_report = true;
|
||||
self.has_slash_report = true;
|
||||
|
||||
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()),
|
||||
);
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), message.clone()));
|
||||
}
|
||||
}
|
||||
let mut txn = self.db.txn();
|
||||
for msg in self.attempt_manager.register(VariantSignId::SlashReport(self.session), machines) {
|
||||
SlashReportSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
// Handle any messages sent to us
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = CoordinatorToSlashReportSignerMessages::try_recv(&mut txn, self.session)
|
||||
else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
match self.attempt_manager.handle(msg) {
|
||||
Response::Messages(msgs) => {
|
||||
for msg in msgs {
|
||||
SlashReportSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
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()),
|
||||
);
|
||||
for keys in &self.keys {
|
||||
machines.push(WrappedSchnorrkelMachine::new(keys.clone(), message.clone()));
|
||||
}
|
||||
}
|
||||
Response::Signature { id, signature } => {
|
||||
let VariantSignId::SlashReport(session) = id else {
|
||||
panic!("SlashReportSignerTask signed a non-SlashReport")
|
||||
};
|
||||
assert_eq!(session, self.session);
|
||||
// Drain the channel
|
||||
SlashReport::try_recv(&mut txn, self.session).unwrap();
|
||||
// Send the signature
|
||||
SlashReportSignature::send(&mut txn, session, &Signature::from(signature).encode());
|
||||
let mut txn = self.db.txn();
|
||||
for msg in self.attempt_manager.register(VariantSignId::SlashReport(self.session), machines)
|
||||
{
|
||||
SlashReportSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
// Handle any messages sent to us
|
||||
loop {
|
||||
let mut txn = self.db.txn();
|
||||
let Some(msg) = CoordinatorToSlashReportSignerMessages::try_recv(&mut txn, self.session)
|
||||
else {
|
||||
break;
|
||||
};
|
||||
iterated = true;
|
||||
|
||||
Ok(iterated)
|
||||
match self.attempt_manager.handle(msg) {
|
||||
Response::Messages(msgs) => {
|
||||
for msg in msgs {
|
||||
SlashReportSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
|
||||
}
|
||||
}
|
||||
Response::Signature { id, signature } => {
|
||||
let VariantSignId::SlashReport(session) = id else {
|
||||
panic!("SlashReportSignerTask signed a non-SlashReport")
|
||||
};
|
||||
assert_eq!(session, self.session);
|
||||
// Drain the channel
|
||||
SlashReport::try_recv(&mut txn, self.session).unwrap();
|
||||
// Send the signature
|
||||
SlashReportSignature::send(&mut txn, session, &Signature::from(signature).encode());
|
||||
}
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
Ok(iterated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use core::future::Future;
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
time::{Duration, Instant},
|
||||
@@ -88,11 +89,10 @@ impl<D: Db, ST: SignableTransaction, P: TransactionPublisher<TransactionFor<ST>>
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<D: Db, ST: SignableTransaction, P: TransactionPublisher<TransactionFor<ST>>> ContinuallyRan
|
||||
for TransactionSignerTask<D, ST, P>
|
||||
{
|
||||
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||
fn run_iteration(&mut self) -> impl Send + Future<Output = Result<bool, String>> {async{
|
||||
let mut iterated = false;
|
||||
|
||||
// Check for new transactions to sign
|
||||
@@ -233,3 +233,4 @@ impl<D: Db, ST: SignableTransaction, P: TransactionPublisher<TransactionFor<ST>>
|
||||
Ok(iterated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user