-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
251 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,5 +2,6 @@ | |
name = "malachite-common" | ||
version = "0.1.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[dependencies] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// TODO: Abstract over all of this | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] // TODO: Remove PartialOrd, Ord | ||
pub struct PublicKey(Vec<u8>); | ||
|
||
pub type VotingPower = u64; | ||
|
||
// TODO: Use an actual address | ||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] | ||
pub struct Address(PublicKey); | ||
|
||
/// A validator is a public key and voting power | ||
#[derive(Clone, Debug, PartialEq, Eq)] | ||
pub struct Validator { | ||
pub public_key: PublicKey, | ||
pub voting_power: VotingPower, | ||
} | ||
|
||
impl Validator { | ||
pub fn new(public_key: PublicKey, voting_power: VotingPower) -> Self { | ||
Self { | ||
public_key, | ||
voting_power, | ||
} | ||
} | ||
|
||
pub fn hash(&self) -> Vec<u8> { | ||
self.public_key.0.clone() // TODO | ||
} | ||
|
||
pub fn address(&self) -> Address { | ||
Address(self.public_key.clone()) // TODO | ||
} | ||
} | ||
|
||
/// A validator set contains a list of validators sorted by address. | ||
#[derive(Clone, Debug, PartialEq, Eq)] | ||
pub struct ValidatorSet { | ||
validators: Vec<Validator>, | ||
total_voting_power: VotingPower, | ||
} | ||
|
||
impl ValidatorSet { | ||
pub fn new(validators: impl IntoIterator<Item = Validator>) -> Self { | ||
let mut validators: Vec<_> = validators.into_iter().collect(); | ||
ValidatorSet::sort_validators(&mut validators); | ||
|
||
let total_voting_power = validators.iter().map(|v| v.voting_power).sum(); | ||
|
||
Self { | ||
validators, | ||
total_voting_power, | ||
} | ||
} | ||
|
||
pub fn total_voting_power(&self) -> VotingPower { | ||
self.total_voting_power | ||
} | ||
|
||
pub fn add(&mut self, validator: Validator) { | ||
self.validators.push(validator); | ||
ValidatorSet::sort_validators(&mut self.validators); | ||
} | ||
|
||
/// Update the voting power of the given validator | ||
pub fn update(&mut self, val: Validator) { | ||
if let Some(v) = self | ||
.validators | ||
.iter_mut() | ||
.find(|v| v.address() == val.address()) | ||
{ | ||
v.voting_power = val.voting_power; | ||
} | ||
|
||
Self::sort_validators(&mut self.validators); | ||
} | ||
|
||
pub fn remove(&mut self, val: Validator) { | ||
self.validators.retain(|v| v.address() != val.address()); | ||
|
||
Self::sort_validators(&mut self.validators); // TODO: Not needed | ||
} | ||
|
||
/// In place sort and deduplication of a list of validators | ||
fn sort_validators(vals: &mut Vec<Validator>) { | ||
use core::cmp::Reverse; | ||
|
||
// Sort the validators according to the current Tendermint requirements | ||
// (v. 0.34 -> first by validator power, descending, then by address, ascending) | ||
vals.sort_unstable_by_key(|v| (Reverse(v.voting_power), v.address())); | ||
|
||
vals.dedup(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
use std::collections::BTreeMap; | ||
|
||
use malachite_common::{Height, Proposal, Round, Timeout, TimeoutStep, ValidatorSet, Vote}; | ||
use malachite_round::events::Event as RoundEvent; | ||
use malachite_round::message::Message as RoundMessage; | ||
use malachite_round::state::State as RoundState; | ||
use malachite_vote::keeper::VoteKeeper; | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct Executor { | ||
height: Height, | ||
validator_set: ValidatorSet, | ||
|
||
vote_keeper: VoteKeeper, | ||
round_states: BTreeMap<Round, RoundState>, | ||
} | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq)] | ||
pub enum Message { | ||
Proposal(Proposal), | ||
Vote(Vote), | ||
Timeout(Timeout), | ||
} | ||
|
||
impl Executor { | ||
pub fn new(height: Height, validator_set: ValidatorSet) -> Self { | ||
let vote_keeper = VoteKeeper::new(height, validator_set.total_voting_power()); | ||
|
||
Self { | ||
height, | ||
validator_set, | ||
vote_keeper, | ||
round_states: BTreeMap::new(), | ||
} | ||
} | ||
|
||
pub fn execute(&mut self, msg: Message) { | ||
let msg = match self.apply(msg) { | ||
Some(msg) => msg, | ||
None => return, | ||
}; | ||
|
||
match msg { | ||
RoundMessage::NewRound(_) => { | ||
// check if we are the proposer | ||
} | ||
RoundMessage::Proposal(_) => { | ||
// sign the proposal | ||
// call execute | ||
} | ||
RoundMessage::Vote(_) => { | ||
// sign the vote | ||
// call execute | ||
} | ||
RoundMessage::Timeout(_) => { | ||
// schedule the timeout | ||
} | ||
RoundMessage::Decision(_) => { | ||
// update the state | ||
} | ||
} | ||
} | ||
|
||
fn apply(&mut self, msg: Message) -> Option<RoundMessage> { | ||
match msg { | ||
Message::Proposal(proposal) => self.apply_proposal(proposal), | ||
Message::Vote(vote) => self.apply_vote(vote), | ||
Message::Timeout(timeout) => self.apply_timeout(timeout), | ||
} | ||
} | ||
|
||
fn apply_proposal(&mut self, proposal: Proposal) -> Option<RoundMessage> { | ||
// TODO: Check for invalid proposal | ||
let event = RoundEvent::Proposal(proposal.value, Round::new(0)); | ||
self.apply_event(proposal.round, event) | ||
} | ||
|
||
fn apply_vote(&mut self, vote: Vote) -> Option<RoundMessage> { | ||
// TODO: Get weight | ||
let weight = 1; | ||
|
||
let round = vote.round; | ||
|
||
let event = match self.vote_keeper.apply_vote(vote, weight) { | ||
Some(event) => event, | ||
None => return None, | ||
}; | ||
|
||
self.apply_event(round, event) | ||
} | ||
|
||
fn apply_timeout(&mut self, timeout: Timeout) -> Option<RoundMessage> { | ||
let event = match timeout.step { | ||
TimeoutStep::Propose => RoundEvent::TimeoutPropose, | ||
TimeoutStep::Prevote => RoundEvent::TimeoutPrevote, | ||
TimeoutStep::Precommit => RoundEvent::TimeoutPrecommit, | ||
}; | ||
|
||
self.apply_event(timeout.round, event) | ||
} | ||
|
||
/// Apply the event, update the state. | ||
fn apply_event(&mut self, round: Round, event: RoundEvent) -> Option<RoundMessage> { | ||
// Get the round state, or create a new one | ||
let round_state = self | ||
.round_states | ||
.remove(&round) | ||
.unwrap_or_else(|| RoundState::new(self.height)); | ||
|
||
// Apply the event to the round state machine | ||
let transition = round_state.apply_event(round, event); | ||
|
||
// Update state | ||
self.round_states.insert(round, transition.state); | ||
|
||
// Return message, if any | ||
transition.message | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod executor; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters