Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tendermint): Instantiate Context for Tendermint types #54

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Code/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ members = [
"driver",
"itf",
"round",
"tendermint",
"test",
"vote",
]
Expand All @@ -26,3 +27,4 @@ rand = { version = "0.8.5", features = ["std_rng"] }
serde = "1.0"
sha2 = "0.10.8"
signature = "2.1.0"
tendermint = { version = "0.34.0", default-features = false, features = ["rust-crypto"] }
2 changes: 1 addition & 1 deletion Code/common/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ where
type Vote: Vote<Self>;
type SigningScheme: SigningScheme; // TODO: Do we need to support multiple signing schemes?

/// Sign the given vote our private key.
/// Sign the given vote with our private key.
fn sign_vote(&self, vote: Self::Vote) -> SignedVote<Self>;

/// Verify the given vote's signature using the given public key.
Expand Down
4 changes: 2 additions & 2 deletions Code/common/src/proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ where
fn round(&self) -> Round;

/// The value that is proposed.
fn value(&self) -> &Ctx::Value;
fn value(&self) -> Ctx::Value;

/// The POL round for which the proposal is for.
/// The POL round for which the proposal is for, can be `nil`.
fn pol_round(&self) -> Round;
}
27 changes: 27 additions & 0 deletions Code/common/src/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,33 @@ impl Ord for Round {
}
}

impl From<i64> for Round {
fn from(round: i64) -> Self {
Self::new(round)
}
}

impl From<i32> for Round {
fn from(round: i32) -> Self {
Self::new(i64::from(round))
}
}

impl From<u32> for Round {
fn from(round: u32) -> Self {
Self::new(i64::from(round))
}
}

impl From<Option<u32>> for Round {
fn from(value: Option<u32>) -> Self {
match value {
Some(round) => Self::new(i64::from(round)),
None => Self::Nil,
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion Code/common/src/signed_vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ where
Self { vote, signature }
}

pub fn validator_address(&self) -> &Ctx::Address {
pub fn validator_address(&self) -> Ctx::Address {
self.vote.validator_address()
}
}
Expand Down
9 changes: 3 additions & 6 deletions Code/common/src/validator_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ where
Ctx: Context,
{
/// The address of the validator, typically derived from its public key.
fn address(&self) -> &Ctx::Address;
fn address(&self) -> Ctx::Address;

/// The public key of the validator, used to verify signatures.
fn public_key(&self) -> &PublicKey<Ctx>;
fn public_key(&self) -> PublicKey<Ctx>;

/// The voting power held by the validaror.
fn voting_power(&self) -> VotingPower;
Expand All @@ -42,9 +42,6 @@ where
/// The total voting power of the validator set.
fn total_voting_power(&self) -> VotingPower;

/// Get the validator with the given public key.
fn get_by_public_key(&self, public_key: &PublicKey<Ctx>) -> Option<&Ctx::Validator>;

/// Get the validator with the given address.
fn get_by_address(&self, address: &Ctx::Address) -> Option<&Ctx::Validator>;
fn get_by_address(&self, address: &Ctx::Address) -> Option<Ctx::Validator>;
}
4 changes: 2 additions & 2 deletions Code/common/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use core::fmt::Debug;
/// Defines the requirements for the type of value to decide on.
pub trait Value
where
Self: Clone + Debug + PartialEq + Eq + PartialOrd + Ord,
Self: Clone + Debug + Eq,
{
/// The type of the ID of the value.
/// Typically a representation of the value with a lower memory footprint.
type Id: Clone + Debug + PartialEq + Eq + PartialOrd + Ord;
type Id: Clone + Debug + Eq + Ord;

/// The ID of the value.
fn id(&self) -> Self::Id;
Expand Down
7 changes: 2 additions & 5 deletions Code/common/src/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,11 @@ where
fn round(&self) -> Round;

/// Get a reference to the value being voted for.
fn value(&self) -> Option<&<Ctx::Value as Value>::Id>;

/// Take ownership of the value being voted for.
fn take_value(self) -> Option<<Ctx::Value as Value>::Id>;
fn value(&self) -> Option<<Ctx::Value as Value>::Id>;

/// The type of vote.
fn vote_type(&self) -> VoteType;

/// Address of the validator who issued this vote
fn validator_address(&self) -> &Ctx::Address;
fn validator_address(&self) -> Ctx::Address;
}
6 changes: 3 additions & 3 deletions Code/driver/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ where
.get_by_address(&proposer_address)
.ok_or_else(|| Error::ProposerNotFound(proposer_address.clone()))?;

let event = if proposer.address() == &self.address {
let event = if proposer.address() == self.address {
// We are the proposer
// TODO: Schedule propose timeout

Expand Down Expand Up @@ -215,12 +215,12 @@ where
) -> Result<Option<RoundMessage<Ctx>>, Error<Ctx>> {
let validator = self
.validator_set
.get_by_address(signed_vote.validator_address())
.get_by_address(&signed_vote.validator_address())
.ok_or_else(|| Error::ValidatorNotFound(signed_vote.validator_address().clone()))?;

if !self
.ctx
.verify_signed_vote(&signed_vote, validator.public_key())
.verify_signed_vote(&signed_vote, &validator.public_key())
{
return Err(Error::InvalidVoteSignature(
signed_vote.clone(),
Expand Down
8 changes: 8 additions & 0 deletions Code/driver/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@ pub enum Event<Ctx>
where
Ctx: Context,
{
/// A new round has started.
/// The boolean indicates whether we are the proposer or not.
NewRound(Ctx::Height, Round),

/// A new proposal has been received.
Proposal(Ctx::Proposal, Validity),

/// A new vote has been received.
Vote(SignedVote<Ctx>),

/// A timeout has elapsed.
TimeoutElapsed(Timeout),
}
4 changes: 2 additions & 2 deletions Code/round/src/state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ where
if state
.locked
.as_ref()
.map_or(true, |locked| &locked.value == proposal.value())
.map_or(true, |locked| locked.value == proposal.value())
{
state.proposal = Some(proposal.clone());
prevote(state, data.address, &proposal)
Expand All @@ -91,7 +91,7 @@ where
return prevote_nil(state, data.address);
};

if locked.round <= proposal.pol_round() || &locked.value == proposal.value() {
if locked.round <= proposal.pol_round() || locked.value == proposal.value() {
prevote(state, data.address, &proposal)
} else {
prevote_nil(state, data.address)
Expand Down
17 changes: 17 additions & 0 deletions Code/tendermint/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "malachite-tendermint"

version.workspace = true
edition.workspace = true
repository.workspace = true
license.workspace = true
publish.workspace = true

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

ed25519-consensus.workspace = true
rand.workspace = true
sha2.workspace = true
signature.workspace = true
tendermint.workspace = true
79 changes: 79 additions & 0 deletions Code/tendermint/src/ed25519.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use malachite_common::SigningScheme;
use rand::{CryptoRng, RngCore};
use signature::{Keypair, Signer, Verifier};

pub use ed25519_consensus::Signature;

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

impl Ed25519 {
pub fn generate_keypair<R>(rng: R) -> PrivateKey
where
R: RngCore + CryptoRng,
{
PrivateKey::generate(rng)
}
}

impl SigningScheme for Ed25519 {
type Signature = Signature;
type PublicKey = PublicKey;
type PrivateKey = PrivateKey;
}

#[derive(Clone, Debug)]
pub struct PrivateKey(ed25519_consensus::SigningKey);

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

Self(signing_key)
}

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

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

impl Keypair for PrivateKey {
type VerifyingKey = PublicKey;

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

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

impl PublicKey {
pub fn new(key: impl Into<ed25519_consensus::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 Verifier<Signature> for PublicKey {
fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), signature::Error> {
self.0
.verify(signature, msg)
.map_err(|_| signature::Error::new())
}
}
Loading
Loading