Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
482a074
reshuffle consensus libraries
rphmeier Feb 8, 2018
917b092
polkadot-useful type definitions for statement table
rphmeier Feb 8, 2018
8e2fd3c
begin BftService
rphmeier Feb 10, 2018
776cf13
Merge branch 'master' into rh-split-bft-table
rphmeier Feb 10, 2018
6abfed4
primary selection logic
rphmeier Feb 12, 2018
fc18524
bft service implementation without I/O
rphmeier Feb 12, 2018
017fd51
extract out `BlockImport` trait
rphmeier Feb 12, 2018
25990ee
Merge branch 'master' into rh-split-bft-table
rphmeier Feb 12, 2018
c33c3ff
allow bft primitives to compile on wasm
rphmeier Feb 12, 2018
acab9a3
Block builder (substrate)
gavofyork Feb 12, 2018
1830fa7
take polkadot-consensus down to the core.
rphmeier Feb 12, 2018
767a9d9
test for preemption
rphmeier Feb 12, 2018
7fc4b4d
fix test build
rphmeier Feb 12, 2018
9acd3f9
Fix wasm build
gavofyork Feb 12, 2018
ca5900f
Bulid on any block
gavofyork Feb 13, 2018
d11cfe1
Test for block builder.
gavofyork Feb 13, 2018
b973ccc
Block import tests for client.
gavofyork Feb 13, 2018
ec61865
Tidy ups
gavofyork Feb 13, 2018
23638cd
clean up block builder instantiation
rphmeier Feb 15, 2018
dda6d24
Merge branch 'rh-split-bft-table' into rh-justification-verification
rphmeier Feb 15, 2018
340ce39
justification verification logic
rphmeier Feb 15, 2018
170b0d1
JustifiedHeader and import
rphmeier Feb 15, 2018
6a1a851
Propert block generation for tests
arkpar Feb 15, 2018
a1247bd
Fixed rpc tests
arkpar Feb 15, 2018
673fc2c
Merge branch 'master' into rh-justification-verification
rphmeier Feb 15, 2018
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
Prev Previous commit
Next Next commit
primary selection logic
  • Loading branch information
rphmeier committed Feb 12, 2018
commit 6abfed425715e52dbb6494e82f236337eb17f160
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions substrate/bft/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ authors = ["Parity Technologies <[email protected]>"]
[dependencies]
futures = "0.1.17"
substrate-client = { path = "../client" }
substrate-codec = { path = "../codec" }
substrate-primitives = { path = "../primitives" }
ed25519 = { path = "../ed25519" }
tokio-timer = "0.1.2"
57 changes: 46 additions & 11 deletions substrate/bft/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,22 @@
mod accumulator;
pub mod generic;

#[cfg_attr(test, macro_use)]
extern crate futures;
extern crate substrate_codec as codec;
extern crate substrate_client as client;
extern crate substrate_primitives as primitives;
extern crate ed25519;
extern crate tokio_timer;

#[cfg_attr(test, macro_use)]
extern crate futures;

use client::Client;
use codec::Slicable;
use ed25519::Signature;
use primitives::block::{Block, Header, HeaderHash};
use primitives::AuthorityId;

use futures::{Stream, Sink, Future};
use futures::{Stream, Future};
use tokio_timer::Timer;

pub use generic::InputStreamConcluded;
Expand Down Expand Up @@ -73,7 +76,7 @@ pub enum Error {

impl From<InputStreamConcluded> for Error {
fn from(_: InputStreamConcluded) -> Error {
Error::IoTerminated;
Error::IoTerminated
}
}

Expand All @@ -82,7 +85,7 @@ impl From<InputStreamConcluded> for Error {
/// This will encapsulate creation and evaluation of proposals at a specific
/// block.
pub trait Proposer: Sized {
type CreateProposal: IntoFuture<Item=Block,Error=Error>;
type CreateProposal: Future<Item=Block,Error=Error>;

/// Initialize the proposal logic on top of a specific header.
// TODO: provide state context explicitly?
Expand Down Expand Up @@ -114,32 +117,66 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
type CreateProposal = P::CreateProposal;

fn local_id(&self) -> AuthorityId {
self.key.public()
self.key.public().0
}

fn proposal(&self) -> P::CreateProposal {
self.proposer.propose()
}

fn candidate_digest(&self, proposal: &Block) -> HeaderHash {
unimplemented!() // TODO: calculate header hash.
proposal.header.hash()
}

fn sign_local(&self, message: Message) -> LocalizedMessage {
unimplemented!() // TODO: figure out message encoding.
use primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction};

let action = match message.clone() {
::generic::Message::Propose(r, p) => PrimitiveAction::Propose(r as u32, p),
::generic::Message::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h),
::generic::Message::Commit(r, h) => PrimitiveAction::Commit(r as u32, h),
::generic::Message::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32),
};

let primitive = PrimitiveMessage {
parent: self.parent_hash,
action,
};

let to_sign = Slicable::encode(&primitive);
let signature = self.key.sign(&to_sign);

LocalizedMessage {
message,
signature,
sender: self.key.public().0
}
}

fn round_proposer(&self, round: usize) -> AuthorityId {
use primitives::hashing::blake2_256;

// repeat blake2_256 on parent hash round + 1 times.
// use as index into authorities vec.
unimplemented!()
// TODO: parent hash is really insecure as a randomness beacon as
// the prior can easily influence the block hash.
let hashed = (0..round + 1).fold(self.parent_hash.0, |a, _| {
blake2_256(&a[..])
});

let index = u32::decode(&mut &hashed[..])
.expect("there are more than 4 bytes in a 32 byte hash; qed");

self.authorities[(index as usize) % self.authorities.len()]
}

fn candidate_valid(&self, proposal: &Block) -> bool {
self.proposer.evaluate(proposal)
}

fn begin_round_timeout(&self, round: usize) -> Self::RoundTimeout {
use std::time::Duration;

let round = ::std::cmp::min(63, round) as u32;
let timeout = 1u64.checked_shl(round)
.unwrap_or_else(u64::max_value)
Expand All @@ -149,5 +186,3 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
.map_err(|_| Error::FaultyTimer))
}
}

/// Bft service built around
2 changes: 1 addition & 1 deletion substrate/ed25519/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool {

/// A public key.
#[derive(PartialEq, Clone, Debug)]
pub struct Public ([u8; 32]);
pub struct Public(pub [u8; 32]);

/// A key pair.
pub struct Pair(signature::Ed25519KeyPair);
Expand Down
75 changes: 71 additions & 4 deletions substrate/primitives/src/bft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,65 @@ enum ActionKind {
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Action {
/// Proposal of a block candidate.
Propose(usize, Block),
Propose(u32, Block),
/// Preparation to commit for a candidate.
Prepare(usize, HeaderHash),
Prepare(u32, HeaderHash),
/// Vote to commit to a candidate.
Commit(usize, HeaderHash),
Commit(u32, HeaderHash),
/// Vote to advance round after inactive primary.
AdvanceRound(usize),
AdvanceRound(u32),
}

impl Slicable for Action {
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
match *self {
Action::Propose(ref round, ref block) => {
v.push(ActionKind::Propose as u8);
round.using_encoded(|s| v.extend(s));
block.using_encoded(|s| v.extend(s));
}
Action::Prepare(ref round, ref hash) => {
v.push(ActionKind::Prepare as u8);
round.using_encoded(|s| v.extend(s));
hash.using_encoded(|s| v.extend(s));
}
Action::Commit(ref round, ref hash) => {
v.push(ActionKind::Commit as u8);
round.using_encoded(|s| v.extend(s));
hash.using_encoded(|s| v.extend(s));
}
Action::AdvanceRound(ref round) => {
v.push(ActionKind::AdvanceRound as u8);
round.using_encoded(|s| v.extend(s));
}
}

v
}

fn decode<I: Input>(value: &mut I) -> Option<Self> {
match u8::decode(value) {
Some(x) if x == ActionKind::Propose as u8 => {
let (round, block) = try_opt!(Slicable::decode(value));
Some(Action::Propose(round, block))
}
Some(x) if x == ActionKind::Prepare as u8 => {
let (round, hash) = try_opt!(Slicable::decode(value));

Some(Action::Prepare(round, hash))
}
Some(x) if x == ActionKind::Commit as u8 => {
let (round, hash) = try_opt!(Slicable::decode(value));

Some(Action::Commit(round, hash))
}
Some(x) if x == ActionKind::AdvanceRound as u8 => {
Slicable::decode(value).map(Action::AdvanceRound)
}
_ => None,
}
}
}

/// Messages exchanged between participants in the BFT consensus.
Expand All @@ -52,3 +104,18 @@ pub struct Message {
/// The action being broadcasted.
pub action: Action,
}

impl Slicable for Message {
fn encode(&self) -> Vec<u8> {
let mut v = self.parent.encode();
self.action.using_encoded(|s| v.extend(s));
v
}

fn decode<I: Input>(value: &mut I) -> Option<Self> {
Some(Message {
parent: try_opt!(Slicable::decode(value)),
action: try_opt!(Slicable::decode(value)),
})
}
}
5 changes: 3 additions & 2 deletions substrate/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@ pub use hashing::{blake2_256, twox_128, twox_256};
#[cfg(feature = "std")]
pub mod hexdisplay;

pub mod storage;
pub mod bft;
pub mod block;
pub mod hash;
pub mod storage;
pub mod uint;
pub mod block;

#[cfg(test)]
mod tests;
Expand Down