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

Implement the election trait #114

Merged
merged 5 commits into from
Apr 8, 2022
Merged
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: 1 addition & 1 deletion .github/workflows/build_libp2p_networking.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 25
steps:
- name: Checkout Repository
uses: actions/checkout@v3
Expand Down
8 changes: 6 additions & 2 deletions examples/dentry-simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use tracing::{debug, error, instrument};
use phaselock::{
demos::dentry::*,
tc,
traits::implementations::{MemoryStorage, Stateless, WNetwork},
traits::{
election::StaticCommittee,
implementations::{MemoryStorage, Stateless, WNetwork},
},
types::{Event, EventType, Message, PhaseLockHandle},
PhaseLock, PhaseLockConfig, PubKey, H_256,
};
Expand Down Expand Up @@ -341,7 +344,7 @@ async fn get_phaselock(
total_nodes: nodes as u32,
threshold: threshold as u32,
max_transactions: 100,
known_nodes,
known_nodes: known_nodes.clone(),
next_view_timeout: 100000,
timeout_ratio: (11, 10),
round_start_delay: 1,
Expand All @@ -359,6 +362,7 @@ async fn get_phaselock(
networking,
MemoryStorage::default(),
Stateless::default(),
StaticCommittee::new(known_nodes),
)
.await
.expect("Could not init phaselock");
Expand Down
8 changes: 6 additions & 2 deletions examples/multi-machine.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use phaselock::{
demos::dentry::*,
tc,
traits::implementations::{MemoryStorage, Stateless, WNetwork},
traits::{
election::StaticCommittee,
implementations::{MemoryStorage, Stateless, WNetwork},
},
types::{Event, EventType, Message, PhaseLockHandle},
PhaseLock, PhaseLockConfig, PubKey, H_256,
};
Expand Down Expand Up @@ -114,7 +117,7 @@ async fn init_state_and_phaselock(
total_nodes: nodes as u32,
threshold: threshold as u32,
max_transactions: 100,
known_nodes,
known_nodes: known_nodes.clone(),
next_view_timeout: 10000,
timeout_ratio: (11, 10),
round_start_delay: 1,
Expand All @@ -132,6 +135,7 @@ async fn init_state_and_phaselock(
networking,
MemoryStorage::default(),
Stateless::default(),
StaticCommittee::new(known_nodes),
)
.await
.expect("Could not init phaselock");
Expand Down
62 changes: 62 additions & 0 deletions phaselock-testing/src/impls/election.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use phaselock::{data::StateHash, PubKey};
use phaselock_types::traits::election::Election;
use tracing::{info, instrument};

/// A testable interface for the election trait.
#[derive(Debug)]
pub struct TestElection {
/// These leaders will be picked. If this list runs out the test will panic.
pub leaders: Vec<PubKey>,
}

impl<const N: usize> Election<N> for TestElection {
type StakeTable = ();
type SelectionThreshold = ();
type State = ();
type VoteToken = ();
type ValidatedVoteToken = ();

fn get_stake_table(&self, _: &Self::State) -> Self::StakeTable {}

fn get_leader(&self, _: &Self::StakeTable, view_number: u64) -> PubKey {
match self.leaders.get(view_number as usize) {
Some(leader) => {
info!("Round {} has leader {:?}", view_number, leader);
leader.clone()
}
None => {
panic!("Round {} has no leader", view_number);
}
}
}

#[instrument]
fn get_votes(
&self,
table: &Self::StakeTable,
selection_threshold: Self::SelectionThreshold,
view_number: u64,
pub_key: PubKey,
token: Self::VoteToken,
next_state: StateHash<N>,
) -> Option<Self::ValidatedVoteToken> {
None
}

#[instrument]
fn get_vote_count(&self, token: &Self::ValidatedVoteToken) -> u64 {
todo!()
}

#[instrument]
fn make_vote_token(
&self,
table: &Self::StakeTable,
selection_threshold: Self::SelectionThreshold,
view_number: u64,
private_key: &phaselock::PrivKey,
next_state: phaselock::data::StateHash<N>,
) -> Option<Self::VoteToken> {
todo!()
}
}
3 changes: 3 additions & 0 deletions phaselock-testing/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod election;

pub use election::TestElection;
8 changes: 7 additions & 1 deletion phaselock-testing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

#![warn(missing_docs)]

mod impls;
mod launcher;

pub use self::impls::TestElection;
pub use self::launcher::TestLauncher;

use async_std::prelude::FutureExt;
Expand All @@ -19,7 +21,8 @@ use phaselock::{
},
tc,
traits::{
implementations::Stateless, NetworkingImplementation, NodeImplementation, State, Storage,
election::StaticCommittee, implementations::Stateless, NetworkingImplementation,
NodeImplementation, State, Storage,
},
types::{EventType, Message, PhaseLockHandle},
PhaseLock, PhaseLockConfig, H_256,
Expand Down Expand Up @@ -118,6 +121,7 @@ impl<
) {
let node_id = self.next_node_id;
self.next_node_id += 1;
let known_nodes = config.known_nodes.clone();
let handle = PhaseLock::init(
block,
self.sks.public_keys(),
Expand All @@ -128,6 +132,7 @@ impl<
network,
storage,
Stateless::default(),
StaticCommittee::new(known_nodes),
)
.await
.expect("Could not init phaselock");
Expand Down Expand Up @@ -379,6 +384,7 @@ impl<
type Storage = STORAGE;
type Networking = NETWORK;
type StatefulHandler = Stateless<BLOCK, STATE, N>;
type Election = StaticCommittee<STATE, N>;
}

impl<NETWORK, STORAGE, BLOCK, STATE> fmt::Debug for TestNodeImpl<NETWORK, STORAGE, BLOCK, STATE> {
Expand Down
6 changes: 4 additions & 2 deletions phaselock-testing/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use phaselock::{
demos::dentry::{Account, Addition, Balance, State, Subtraction, Transaction},
tc,
traits::{
election::StaticCommittee,
implementations::{DummyReliability, MasterMap, MemoryNetwork},
NodeImplementation,
},
Expand Down Expand Up @@ -340,7 +341,7 @@ pub async fn init_state_and_phaselocks<I, const N: usize>(
Vec<PhaseLockHandle<I, N>>,
)
where
I: NodeImplementation<N>,
I: NodeImplementation<N, Election = StaticCommittee<<I as NodeImplementation<N>>::State, N>>,
<I as NodeImplementation<N>>::Block: Default,
<I as NodeImplementation<N>>::Storage: Default,
<I as NodeImplementation<N>>::StatefulHandler: Default,
Expand All @@ -350,7 +351,7 @@ where
total_nodes: num_nodes as u32,
threshold: threshold as u32,
max_transactions: 100,
known_nodes,
known_nodes: known_nodes.clone(),
next_view_timeout,
timeout_ratio,
round_start_delay: 1,
Expand All @@ -370,6 +371,7 @@ where
networkings[node_id as usize].0.clone(),
I::Storage::default(),
I::StatefulHandler::default(),
StaticCommittee::new(known_nodes.clone()),
)
.await
.expect("Could not init phaselock");
Expand Down
4 changes: 3 additions & 1 deletion phaselock-testing/tests/query_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use phaselock::{
demos::dentry::*,
tc,
traits::{
election::StaticCommittee,
implementations::{DummyReliability, MemoryNetwork},
NodeImplementation,
},
Expand Down Expand Up @@ -158,7 +159,7 @@ async fn sync_newest_quorom() {
total_nodes: num_nodes as u32,
threshold: threshold as u32,
max_transactions: 100,
known_nodes,
known_nodes: known_nodes.clone(),
next_view_timeout: NEXT_VIEW_TIMEOUT,
timeout_ratio: DEFAULT_TIMEOUT_RATIO,
round_start_delay: 1,
Expand All @@ -175,6 +176,7 @@ async fn sync_newest_quorom() {
new_network,
<NODE as NodeImplementation<H_256>>::Storage::default(),
<NODE as NodeImplementation<H_256>>::StatefulHandler::default(),
StaticCommittee::new(known_nodes),
)
.await
.expect("Could not init phaselock");
Expand Down
1 change: 1 addition & 0 deletions phaselock-testing/tests/random_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ proptest! {

#[async_std::test]
pub async fn test_harness() {
setup_logging();
let mut runner = TestLauncher::new(5).launch();

runner.add_nodes(5).await;
Expand Down
1 change: 1 addition & 0 deletions phaselock-types/src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Common traits for the `PhaseLock` protocol
pub mod block_contents;
pub mod election;
pub mod network;
pub mod node_implementation;
pub mod signature_key;
Expand Down
48 changes: 48 additions & 0 deletions phaselock-types/src/traits/election.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! The election trait, used to decide which node is the leader and determine if a vote is valid.

use crate::data::StateHash;
use crate::{PrivKey, PubKey};

/// Describes how `PhaseLock` chooses committees and leaders
pub trait Election<const N: usize>: Send + Sync {
/// Data structure describing the currently valid states
type StakeTable: Send + Sync;
/// The threshold for membership selection.
type SelectionThreshold;
/// The state type this election implementation is bound to
type State: Send + Sync + Default;
/// A membership proof
type VoteToken;
/// A type stated, validated membership proof
type ValidatedVoteToken;

/// Returns the table from the current committed state
fn get_stake_table(&self, state: &Self::State) -> Self::StakeTable;
/// Returns leader for the current view number, given the current stake table
fn get_leader(&self, table: &Self::StakeTable, view_number: u64) -> PubKey;
/// Validates a vote token and returns the number of seats that it has
///
/// Salt: Hash of the leaf that is being proposed
fn get_votes(
&self,
table: &Self::StakeTable,
selection_threshold: Self::SelectionThreshold,
view_number: u64,
pub_key: PubKey,
token: Self::VoteToken,
next_state: StateHash<N>,
) -> Option<Self::ValidatedVoteToken>;
/// Returns the number of votes the validated vote token has
fn get_vote_count(&self, token: &Self::ValidatedVoteToken) -> u64;
/// Attempts to generate a vote token for self
///
/// Returns `None` if the number of seats would be zero
fn make_vote_token(
&self,
table: &Self::StakeTable,
selection_threshold: Self::SelectionThreshold,
view_number: u64,
private_key: &PrivKey,
next_state: StateHash<N>,
) -> Option<Self::VoteToken>;
}
6 changes: 4 additions & 2 deletions phaselock-types/src/traits/node_implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
use crate::{
message::{ConsensusMessage, DataMessage, Message},
traits::{
network::NetworkingImplementation, stateful_handler::StatefulHandler, storage::Storage,
BlockContents,
election::Election, network::NetworkingImplementation, stateful_handler::StatefulHandler,
storage::Storage, BlockContents,
},
};
use std::fmt::Debug;
Expand Down Expand Up @@ -37,6 +37,8 @@ pub trait NodeImplementation<const N: usize>: Send + Sync + Debug + Clone + 'sta
> + Clone;
/// Stateful call back handler for this consensus implementation
type StatefulHandler: StatefulHandler<N, Block = Self::Block, State = Self::State>;
/// The election algorithm
type Election: Election<N>;
}

/// Helper trait to make aliases.
Expand Down
8 changes: 3 additions & 5 deletions src/demos/dentry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use tracing::error;
use crate::{
data::{BlockHash, LeafHash, StateHash, TransactionHash},
traits::{
implementations::MemoryStorage, BlockContents, NetworkingImplementation, NodeImplementation,
election::StaticCommittee, implementations::MemoryStorage, BlockContents,
NetworkingImplementation, NodeImplementation,
},
types::Message,
H_256,
Expand Down Expand Up @@ -355,14 +356,11 @@ where
+ 'static,
{
type Block = DEntryBlock;

type State = State;

type Storage = MemoryStorage<DEntryBlock, State, H_256>;

type Networking = NET;

type StatefulHandler = crate::traits::implementations::Stateless<DEntryBlock, State, H_256>;
type Election = StaticCommittee<Self::State, H_256>;
}

/// Provides a random valid transaction from the current state
Expand Down
Loading