Skip to content

Commit

Permalink
Add facility for signing votes
Browse files Browse the repository at this point in the history
  • Loading branch information
romac committed Oct 27, 2023
1 parent 3c87aa3 commit 99f33d5
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 131 deletions.
1 change: 1 addition & 0 deletions Code/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ edition = "2021"
publish = false

[dependencies]
signature = "2.1.0"
9 changes: 8 additions & 1 deletion Code/common/src/consensus.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::public_key::PrivateKey;
use crate::{
Address, Height, Proposal, PublicKey, Round, Validator, ValidatorSet, Value, ValueId, Vote,
};
Expand All @@ -11,7 +12,8 @@ where
type Address: Address;
type Height: Height;
type Proposal: Proposal<Self>;
type PublicKey: PublicKey;
type PrivateKey: PrivateKey<PublicKey = Self::PublicKey>;
type PublicKey: PublicKey<Signature = <Self::PrivateKey as PrivateKey>::Signature>;
type Validator: Validator<Self>;
type ValidatorSet: ValidatorSet<Self>;
type Value: Value;
Expand All @@ -20,6 +22,11 @@ where
// FIXME: Remove altogether
const DUMMY_VALUE: Self::Value;

fn sign_vote(
vote: &Self::Vote,
private_key: &Self::PrivateKey,
) -> <Self::PrivateKey as PrivateKey>::Signature;

/// Build a new proposal for the given value at the given height, round and POL round.
fn new_proposal(
height: Self::Height,
Expand Down
5 changes: 4 additions & 1 deletion Code/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Common data types and abstractions for the consensus engine.
#![no_std]
#![forbid(unsafe_code)]
#![deny(unused_crate_dependencies, trivial_casts, trivial_numeric_casts)]
#![warn(
Expand All @@ -13,6 +14,7 @@
mod consensus;
mod height;
mod proposal;
mod public_key;
mod round;
mod timeout;
mod validator_set;
Expand All @@ -25,8 +27,9 @@ pub type ValueId<C> = <<C as Consensus>::Value as Value>::Id;
pub use consensus::Consensus;
pub use height::Height;
pub use proposal::Proposal;
pub use public_key::{PrivateKey, PublicKey};
pub use round::Round;
pub use timeout::{Timeout, TimeoutStep};
pub use validator_set::{Address, PublicKey, Validator, ValidatorSet, VotingPower};
pub use validator_set::{Address, Validator, ValidatorSet, VotingPower};
pub use value::Value;
pub use vote::{Vote, VoteType};
22 changes: 22 additions & 0 deletions Code/common/src/public_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use core::fmt::Debug;

use signature::{Signer, Verifier};

/// Defines the requirements for a private key type.
pub trait PrivateKey
where
Self: Clone + Debug + Signer<Self::Signature>,
{
type Signature: Clone + Debug + PartialEq + Eq;
type PublicKey: PublicKey<Signature = Self::Signature>;

fn public_key(&self) -> Self::PublicKey;
}

/// Defines the requirements for a public key type.
pub trait PublicKey
where
Self: Clone + Debug + PartialEq + Eq + Verifier<Self::Signature>,
{
type Signature: Clone + Debug + PartialEq + Eq;
}
6 changes: 4 additions & 2 deletions Code/common/src/round.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::cmp;

/// A round number.
///
/// Can be either:
Expand Down Expand Up @@ -69,13 +71,13 @@ impl Round {
}

impl PartialOrd for Round {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Round {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_i64().cmp(&other.as_i64())
}
}
Expand Down
7 changes: 0 additions & 7 deletions Code/common/src/validator_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@ use crate::Consensus;
/// TODO: Do we need to abstract over this as well?
pub type VotingPower = u64;

/// Defines the requirements for a public key type.
pub trait PublicKey
where
Self: Clone + Debug + PartialEq + Eq,
{
}

/// Defines the requirements for an address.
///
/// TODO: Keep this trait or just add the bounds to Consensus::Address?
Expand Down
16 changes: 8 additions & 8 deletions Code/consensus/src/executor.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::collections::BTreeMap;

use malachite_common::{
Consensus, Proposal, Round, Timeout, TimeoutStep, Validator, ValidatorSet, Value, Vote,
VoteType,
Consensus, PrivateKey, Proposal, Round, Timeout, TimeoutStep, Validator, ValidatorSet, Value,
Vote, VoteType,
};
use malachite_round::events::Event as RoundEvent;
use malachite_round::message::Message as RoundMessage;
Expand All @@ -19,7 +19,7 @@ where
C: Consensus,
{
height: C::Height,
key: C::PublicKey,
key: C::PrivateKey,
validator_set: C::ValidatorSet,
round: Round,
votes: VoteKeeper<C>,
Expand All @@ -30,7 +30,7 @@ impl<C> Executor<C>
where
C: Consensus,
{
pub fn new(height: C::Height, validator_set: C::ValidatorSet, key: C::PublicKey) -> Self {
pub fn new(height: C::Height, validator_set: C::ValidatorSet, key: C::PrivateKey) -> Self {
let votes = VoteKeeper::new(
height.clone(),
Round::INITIAL,
Expand Down Expand Up @@ -76,12 +76,12 @@ where
RoundMessage::Vote(vote) => {
let address = self
.validator_set
.get_by_public_key(&self.key)?
.get_by_public_key(&self.key.public_key())?
.address()
.clone();

// TODO: sign the vote
let signed_vote = SignedVote::new(vote, address);
let signature = C::sign_vote(&vote, &self.key);
let signed_vote = SignedVote::new(vote, address, signature);

Some(Message::Vote(signed_vote))
}
Expand Down Expand Up @@ -110,7 +110,7 @@ where
fn apply_new_round(&mut self, round: Round) -> Option<RoundMessage<C>> {
let proposer = self.validator_set.get_proposer();

let event = if proposer.public_key() == &self.key {
let event = if proposer.public_key() == &self.key.public_key() {
let value = self.get_value();
RoundEvent::NewRoundProposer(value)
} else {
Expand Down
17 changes: 12 additions & 5 deletions Code/consensus/src/signed_vote.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use malachite_common::Consensus;
use malachite_common::{Consensus, PublicKey};

// TODO: Do we need to abstract over `SignedVote` as well?

Expand All @@ -9,15 +9,22 @@ where
{
pub vote: C::Vote,
pub address: C::Address,
// TODO
// pub signature: C::Signature,
pub signature: <C::PublicKey as PublicKey>::Signature,
}

impl<C> SignedVote<C>
where
C: Consensus,
{
pub fn new(vote: C::Vote, address: C::Address) -> Self {
Self { vote, address }
pub fn new(
vote: C::Vote,
address: C::Address,
signature: <C::PublicKey as PublicKey>::Signature,
) -> Self {
Self {
vote,
address,
signature,
}
}
}
15 changes: 9 additions & 6 deletions Code/test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
[package]
name = "malachite-test"
name = "malachite-test"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
malachite-common = { version = "0.1.0", path = "../common" }
malachite-common = { version = "0.1.0", path = "../common" }
malachite-consensus = { version = "0.1.0", path = "../consensus" }
malachite-round = { version = "0.1.0", path = "../round" }
malachite-vote = { version = "0.1.0", path = "../vote" }
malachite-round = { version = "0.1.0", path = "../round" }
malachite-vote = { version = "0.1.0", path = "../vote" }

ed25519-consensus = "2.1.0"
signature = "2.1.0"
rand = { version = "0.8.5", features = ["std_rng"] }
sha2 = "0.10.8"
9 changes: 8 additions & 1 deletion Code/test/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use malachite_common::Round;

use crate::height::*;
use crate::proposal::*;
use crate::public_key::{Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature};
use crate::validator_set::*;
use crate::value::*;
use crate::vote::*;
Expand All @@ -14,14 +15,20 @@ impl Consensus for TestConsensus {
type Address = Address;
type Height = Height;
type Proposal = Proposal;
type PublicKey = PublicKey;
type PublicKey = Ed25519PublicKey;
type PrivateKey = Ed25519PrivateKey;
type ValidatorSet = ValidatorSet;
type Validator = Validator;
type Value = Value;
type Vote = Vote;

const DUMMY_VALUE: Self::Value = Value::new(9999);

fn sign_vote(vote: &Self::Vote, private_key: &Self::PrivateKey) -> Ed25519Signature {
use signature::Signer;
private_key.sign(&vote.to_bytes())
}

fn new_proposal(height: Height, round: Round, value: Value, pol_round: Round) -> Proposal {
Proposal::new(height, round, value, pol_round)
}
Expand Down
2 changes: 2 additions & 0 deletions Code/test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
mod consensus;
mod height;
mod proposal;
mod public_key;
mod validator_set;
mod value;
mod vote;

pub use crate::consensus::*;
pub use crate::height::*;
pub use crate::proposal::*;
pub use crate::public_key::*;
pub use crate::validator_set::*;
pub use crate::value::*;
pub use crate::vote::*;
68 changes: 68 additions & 0 deletions Code/test/src/public_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use ed25519_consensus::{Signature, SigningKey, VerificationKey};

use malachite_common::{PrivateKey, PublicKey};
use rand::{CryptoRng, RngCore};
use signature::{Signer, Verifier};

pub type Ed25519Signature = Signature;

#[derive(Clone, Debug)]
pub struct Ed25519PrivateKey(SigningKey);

impl Ed25519PrivateKey {
pub fn generate<R>(rng: R) -> Self
where
R: RngCore + CryptoRng,
{
let signing_key = SigningKey::new(rng);

Self(signing_key)
}

pub fn public_key(&self) -> Ed25519PublicKey {
Ed25519PublicKey::new(self.0.verification_key())
}
}

impl PrivateKey for Ed25519PrivateKey {
type Signature = Signature;
type PublicKey = Ed25519PublicKey;

fn public_key(&self) -> Self::PublicKey {
self.public_key()
}
}

impl Signer<Signature> for Ed25519PrivateKey {
fn try_sign(&self, msg: &[u8]) -> Result<Signature, signature::Error> {
Ok(self.0.sign(msg))
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Ed25519PublicKey(VerificationKey);

impl Ed25519PublicKey {
pub fn new(key: impl Into<VerificationKey>) -> Self {
Self(key.into())
}

pub fn hash(&self) -> [u8; 32] {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(self.0.as_bytes());
hasher.finalize().into()
}
}

impl PublicKey for Ed25519PublicKey {
type Signature = Signature;
}

impl Verifier<Signature> for Ed25519PublicKey {
fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), signature::Error> {
self.0
.verify(signature, msg)
.map_err(|_| signature::Error::new())
}
}
Loading

0 comments on commit 99f33d5

Please sign in to comment.