Make sign asynchronous

Some relation to https://github.com/serai-dex/serai/issues/95.
This commit is contained in:
Luke Parker 2022-11-01 15:10:50 -04:00
parent e38a7e0f3c
commit 2947ef08e3
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
3 changed files with 20 additions and 11 deletions

View file

@ -1,6 +1,8 @@
use core::{hash::Hash, fmt::Debug};
use std::sync::Arc;
use async_trait::async_trait;
use parity_scale_codec::{Encode, Decode};
use crate::{SignedMessage, commit_msg};
@ -31,6 +33,7 @@ pub struct BlockNumber(pub u64);
pub struct Round(pub u32);
/// A signature scheme used by validators.
#[async_trait]
pub trait SignatureScheme: Send + Sync {
// Type used to identify validators.
type ValidatorId: ValidatorId;
@ -43,7 +46,7 @@ pub trait SignatureScheme: Send + Sync {
type AggregateSignature: Signature;
/// Sign a signature with the current validator's private key.
fn sign(&self, msg: &[u8]) -> Self::Signature;
async fn sign(&self, msg: &[u8]) -> Self::Signature;
/// Verify a signature from the validator in question.
#[must_use]
fn verify(&self, validator: Self::ValidatorId, msg: &[u8], sig: &Self::Signature) -> bool;
@ -121,7 +124,7 @@ impl<B: sp_runtime::traits::Block> Block for B {
}
/// Trait representing the distributed system Tendermint is providing consensus over.
#[async_trait::async_trait]
#[async_trait]
pub trait Network: Send + Sync {
// Type used to identify validators.
type ValidatorId: ValidatorId;

View file

@ -157,7 +157,9 @@ impl<N: Network + 'static> TendermintMachine<N> {
fn timeout(&self, step: Step) -> Instant {
let mut round_time = Duration::from_secs(N::BLOCK_TIME.into());
round_time *= self.round.0 + 1;
let step_time = round_time / 3; // TODO: Non-uniform timeouts
// TODO: Non-uniform timeouts. Proposal has to validate the block which will take much longer
// than any other step
let step_time = round_time / 3;
let offset = match step {
Step::Propose => step_time,
@ -382,7 +384,7 @@ impl<N: Network + 'static> TendermintMachine<N> {
}
if broadcast {
let sig = machine.signer.sign(&msg.encode());
let sig = machine.signer.sign(&msg.encode()).await;
machine.network.write().await.broadcast(SignedMessage { msg, sig }).await;
}
}
@ -435,10 +437,10 @@ impl<N: Network + 'static> TendermintMachine<N> {
if let Some(Data::Proposal(_, block)) = self.log.get(msg.round, proposer, Step::Propose) {
// Check if it has gotten a sufficient amount of precommits
// Use a junk signature since message equality disregards the signature
if self
.log
.has_consensus(msg.round, Data::Precommit(Some((block.id(), self.signer.sign(&[])))))
{
if self.log.has_consensus(
msg.round,
Data::Precommit(Some((block.id(), self.signer.sign(&[]).await))),
) {
return Ok(Some(block.clone()));
}
}
@ -549,7 +551,8 @@ impl<N: Network + 'static> TendermintMachine<N> {
block.id(),
self
.signer
.sign(&commit_msg(self.canonical_end_time(self.round), block.id().as_ref())),
.sign(&commit_msg(self.canonical_end_time(self.round), block.id().as_ref()))
.await,
))));
return Ok(None);
}

View file

@ -3,6 +3,8 @@ use std::{
time::{UNIX_EPOCH, SystemTime, Duration},
};
use async_trait::async_trait;
use parity_scale_codec::{Encode, Decode};
use tokio::{sync::RwLock, time::sleep};
@ -13,12 +15,13 @@ type TestValidatorId = u16;
type TestBlockId = [u8; 4];
struct TestSignatureScheme(u16);
#[async_trait]
impl SignatureScheme for TestSignatureScheme {
type ValidatorId = TestValidatorId;
type Signature = [u8; 32];
type AggregateSignature = Vec<[u8; 32]>;
fn sign(&self, msg: &[u8]) -> [u8; 32] {
async fn sign(&self, msg: &[u8]) -> [u8; 32] {
let mut sig = [0; 32];
sig[.. 2].copy_from_slice(&self.0.to_le_bytes());
sig[2 .. (2 + 30.min(msg.len()))].copy_from_slice(&msg[.. 30.min(msg.len())]);
@ -81,7 +84,7 @@ impl Block for TestBlock {
struct TestNetwork(u16, Arc<RwLock<Vec<TendermintHandle<Self>>>>);
#[async_trait::async_trait]
#[async_trait]
impl Network for TestNetwork {
type ValidatorId = TestValidatorId;
type SignatureScheme = TestSignatureScheme;