From 85962c00a9b95e77a0d0a659321e2cc6b0e59a5a Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Sun, 16 Oct 2022 09:42:33 -0400 Subject: [PATCH] Define a signature scheme trait --- substrate/tendermint/src/ext.rs | 36 ++++++++++++++------- substrate/tendermint/tests/ext.rs | 54 +++++++++++++++++++++++-------- 2 files changed, 66 insertions(+), 24 deletions(-) diff --git a/substrate/tendermint/src/ext.rs b/substrate/tendermint/src/ext.rs index 642553c9..7e0f9ec3 100644 --- a/substrate/tendermint/src/ext.rs +++ b/substrate/tendermint/src/ext.rs @@ -12,18 +12,16 @@ pub struct BlockNumber(pub u32); #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct Round(pub u16); -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum BlockError { - // Invalid behavior entirely - Fatal, - // Potentially valid behavior dependent on unsynchronized state - Temporal, -} +pub trait SignatureScheme { + type ValidatorId: ValidatorId; + type Signature: Clone + Copy + PartialEq; + type AggregateSignature: Clone + PartialEq; -pub trait Block: Send + Sync + Clone + PartialEq + Debug { - type Id: Send + Sync + Copy + Clone + PartialEq + Debug; - - fn id(&self) -> Self::Id; + fn sign(&self, msg: &[u8]) -> Self::Signature; + #[must_use] + fn verify(&self, validator: Self::ValidatorId, msg: &[u8], sig: Self::Signature) -> bool; + // Intended to be a BLS signature, a Schnorr signature half-aggregation, or a Vec. + fn aggregate(signatures: &[Self::Signature]) -> Self::AggregateSignature; } pub trait Weights: Send + Sync { @@ -42,15 +40,31 @@ pub trait Weights: Send + Sync { fn proposer(&self, number: BlockNumber, round: Round) -> Self::ValidatorId; } +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum BlockError { + // Invalid behavior entirely + Fatal, + // Potentially valid behavior dependent on unsynchronized state + Temporal, +} + +pub trait Block: Send + Sync + Clone + PartialEq + Debug { + type Id: Send + Sync + Copy + Clone + PartialEq + Debug; + + fn id(&self) -> Self::Id; +} + #[async_trait::async_trait] pub trait Network: Send + Sync { type ValidatorId: ValidatorId; + type SignatureScheme: SignatureScheme; type Weights: Weights; type Block: Block; // Block time in seconds const BLOCK_TIME: u32; + fn signature_scheme(&self) -> Arc; fn weights(&self) -> Arc; async fn broadcast(&mut self, msg: Message); diff --git a/substrate/tendermint/tests/ext.rs b/substrate/tendermint/tests/ext.rs index ce15507f..5846b8fc 100644 --- a/substrate/tendermint/tests/ext.rs +++ b/substrate/tendermint/tests/ext.rs @@ -7,17 +7,25 @@ use tendermint_machine::{ext::*, Message, TendermintMachine, TendermintHandle}; type TestValidatorId = u16; type TestBlockId = u32; -#[derive(Clone, PartialEq, Debug)] -struct TestBlock { - id: TestBlockId, - valid: Result<(), BlockError>, -} +struct TestSignatureScheme(u16); +impl SignatureScheme for TestSignatureScheme { + type ValidatorId = TestValidatorId; + type Signature = [u8; 32]; + type AggregateSignature = Vec<[u8; 32]>; -impl Block for TestBlock { - type Id = TestBlockId; + 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); + sig + } - fn id(&self) -> TestBlockId { - self.id + fn verify(&self, validator: u16, msg: &[u8], sig: [u8; 32]) -> bool { + (sig[.. 2] == validator.to_le_bytes()) && (&sig[2 ..] == &[msg, &[0; 30]].concat()[.. 30]) + } + + fn aggregate(sigs: &[[u8; 32]]) -> Vec<[u8; 32]> { + sigs.to_vec() } } @@ -37,22 +45,41 @@ impl Weights for TestWeights { } } -struct TestNetwork(Arc>>>); +#[derive(Clone, PartialEq, Debug)] +struct TestBlock { + id: TestBlockId, + valid: Result<(), BlockError>, +} + +impl Block for TestBlock { + type Id = TestBlockId; + + fn id(&self) -> TestBlockId { + self.id + } +} + +struct TestNetwork(u16, Arc>>>); #[async_trait::async_trait] impl Network for TestNetwork { type ValidatorId = TestValidatorId; + type SignatureScheme = TestSignatureScheme; type Weights = TestWeights; type Block = TestBlock; const BLOCK_TIME: u32 = 1; + fn signature_scheme(&self) -> Arc { + Arc::new(TestSignatureScheme(self.0)) + } + fn weights(&self) -> Arc { Arc::new(TestWeights) } async fn broadcast(&mut self, msg: Message) { - for handle in self.0.write().await.iter_mut() { + for handle in self.1.write().await.iter_mut() { handle.messages.send(msg.clone()).await.unwrap(); } } @@ -79,9 +106,10 @@ impl TestNetwork { { let mut write = arc.write().await; for i in 0 .. validators { + let i = u16::try_from(i).unwrap(); write.push(TendermintMachine::new( - TestNetwork(arc.clone()), - u16::try_from(i).unwrap(), + TestNetwork(i, arc.clone()), + i, BlockNumber(1), TestBlock { id: 1, valid: Ok(()) }, ));