Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Integrate transaction pool to the proposal logic (#80)
Browse files Browse the repository at this point in the history
* reshuffle consensus libraries

* polkadot-useful type definitions for statement table

* begin BftService

* primary selection logic

* bft service implementation without I/O

* extract out `BlockImport` trait

* allow bft primitives to compile on wasm

* Block builder (substrate)

* take polkadot-consensus down to the core.

* test for preemption

* fix test build

* Fix wasm build

* Bulid on any block

* Test for block builder.

* Block import tests for client.

* Tidy ups

* clean up block builder instantiation

* justification verification logic

* JustifiedHeader and import

* Propert block generation for tests

* network and tablerouter trait

* use statement import to drive creation of further statements

* Fixed rpc tests

* custom error type for consensus

* create proposer

* asynchronous proposal evaluation

* inherent transactions in polkadot runtime

* fix tests to match real polkadot block constraints

* implicitly generate inherent functions

* add inherent transaction functionality to block body

* block builder logic for polkadot

* some tests for the polkadot API

* avoid redundancy in native code compatibility check

* helper for extracting nonce

* transaction pool implementation

* transaction pool

* integrate transaction pool with proposer

* indentation

* kill storage keys module

* accept new transactions to replace old
  • Loading branch information
rphmeier authored and gavofyork committed Mar 2, 2018
1 parent 4fbd3e2 commit 239acad
Show file tree
Hide file tree
Showing 16 changed files with 551 additions and 50 deletions.
70 changes: 70 additions & 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ members = [
"polkadot/primitives",
"polkadot/runtime",
"polkadot/statement-table",
"polkadot/transaction-pool",
"polkadot/validator",
"substrate/bft",
"substrate/client",
Expand Down
93 changes: 65 additions & 28 deletions polkadot/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use polkadot_runtime::runtime;
use polkadot_executor::Executor as LocalDispatch;
use substrate_executor::{NativeExecutionDispatch, NativeExecutor};
use state_machine::OverlayedChanges;
use primitives::{AccountId, SessionKey, Timestamp};
use primitives::{AccountId, SessionKey, Timestamp, TxOrder};
use primitives::block::{Id as BlockId, Block, Header, Body};
use primitives::transaction::UncheckedTransaction;
use primitives::parachain::DutyRoster;
Expand Down Expand Up @@ -85,6 +85,7 @@ impl From<client::error::Error> for Error {
}
}

/// A builder for blocks.
pub trait BlockBuilder: Sized {
/// Push a non-inherent transaction.
fn push_transaction(&mut self, transaction: UncheckedTransaction) -> Result<()>;
Expand All @@ -93,40 +94,64 @@ pub trait BlockBuilder: Sized {
fn bake(self) -> Block;
}

/// A checked block identifier.
pub trait CheckedBlockId: Clone {
/// Yield the underlying block ID.
fn block_id(&self) -> &BlockId;
}

/// Trait encapsulating the Polkadot API.
///
/// All calls should fail when the exact runtime is unknown.
pub trait PolkadotApi {
/// A checked block ID. Used to avoid redundancy of code check.
type CheckedBlockId: CheckedBlockId;
/// The type used to build blocks.
type BlockBuilder: BlockBuilder;

/// Check whether requests at the given block ID can be served.
///
/// It should not be possible to instantiate this type without going
/// through this function.
fn check_id(&self, id: BlockId) -> Result<Self::CheckedBlockId>;

/// Get session keys at a given block.
fn session_keys(&self, at: &BlockId) -> Result<Vec<SessionKey>>;
fn session_keys(&self, at: &Self::CheckedBlockId) -> Result<Vec<SessionKey>>;

/// Get validators at a given block.
fn validators(&self, at: &BlockId) -> Result<Vec<AccountId>>;
fn validators(&self, at: &Self::CheckedBlockId) -> Result<Vec<AccountId>>;

/// Get the authority duty roster at a block.
fn duty_roster(&self, at: &BlockId) -> Result<DutyRoster>;
fn duty_roster(&self, at: &Self::CheckedBlockId) -> Result<DutyRoster>;

/// Get the timestamp registered at a block.
fn timestamp(&self, at: &BlockId) -> Result<Timestamp>;
fn timestamp(&self, at: &Self::CheckedBlockId) -> Result<Timestamp>;

/// Get the nonce of an account at a block.
fn nonce(&self, at: &Self::CheckedBlockId, account: AccountId) -> Result<TxOrder>;


/// Evaluate a block and see if it gives an error.
fn evaluate_block(&self, at: &BlockId, block: Block) -> Result<()>;
fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result<()>;

/// Create a block builder on top of the parent block.
fn build_block(&self, parent: &BlockId, timestamp: u64) -> Result<Self::BlockBuilder>;
fn build_block(&self, parent: &Self::CheckedBlockId, timestamp: u64) -> Result<Self::BlockBuilder>;
}

/// A checked block ID used for the substrate-client implementation of CheckedBlockId;
#[derive(Debug, Clone, Copy)]
pub struct CheckedId(BlockId);

impl CheckedBlockId for CheckedId {
fn block_id(&self) -> &BlockId {
&self.0
}
}

// set up the necessary scaffolding to execute the runtime.
macro_rules! with_runtime {
($client: ident, $at: expr, $exec: expr) => {{
// bail if the code is not the same as the natively linked.
if $client.code_at($at)? != LocalDispatch::native_equivalent() {
bail!(ErrorKind::UnknownRuntime);
}

$client.state_at($at).map_err(Error::from).and_then(|state| {
$client.state_at($at.block_id()).map_err(Error::from).and_then(|state| {
let mut changes = Default::default();
let mut ext = state_machine::Ext {
overlay: &mut changes,
Expand All @@ -141,33 +166,44 @@ macro_rules! with_runtime {
impl<B: Backend> PolkadotApi for Client<B, NativeExecutor<LocalDispatch>>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
{
type CheckedBlockId = CheckedId;
type BlockBuilder = ClientBlockBuilder<B::State>;

fn session_keys(&self, at: &BlockId) -> Result<Vec<SessionKey>> {
fn check_id(&self, id: BlockId) -> Result<CheckedId> {
// bail if the code is not the same as the natively linked.
if self.code_at(&id)? != LocalDispatch::native_equivalent() {
bail!(ErrorKind::UnknownRuntime);
}

Ok(CheckedId(id))
}

fn session_keys(&self, at: &CheckedId) -> Result<Vec<SessionKey>> {
with_runtime!(self, at, ::runtime::consensus::authorities)
}

fn validators(&self, at: &BlockId) -> Result<Vec<AccountId>> {
fn validators(&self, at: &CheckedId) -> Result<Vec<AccountId>> {
with_runtime!(self, at, ::runtime::session::validators)
}

fn duty_roster(&self, at: &BlockId) -> Result<DutyRoster> {
fn duty_roster(&self, at: &CheckedId) -> Result<DutyRoster> {
with_runtime!(self, at, ::runtime::parachains::calculate_duty_roster)
}

fn timestamp(&self, at: &BlockId) -> Result<Timestamp> {
fn timestamp(&self, at: &CheckedId) -> Result<Timestamp> {
with_runtime!(self, at, ::runtime::timestamp::get)
}

fn evaluate_block(&self, at: &BlockId, block: Block) -> Result<()> {
fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result<()> {
with_runtime!(self, at, || ::runtime::system::internal::execute_block(block))
}

fn build_block(&self, parent: &BlockId, timestamp: Timestamp) -> Result<Self::BlockBuilder> {
if self.code_at(parent)? != LocalDispatch::native_equivalent() {
bail!(ErrorKind::UnknownRuntime);
}
fn nonce(&self, at: &Self::CheckedBlockId, account: AccountId) -> Result<TxOrder> {
with_runtime!(self, at, || ::runtime::system::nonce(account))
}

fn build_block(&self, parent: &CheckedId, timestamp: Timestamp) -> Result<Self::BlockBuilder> {
let parent = parent.block_id();
let header = Header {
parent_hash: self.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?,
number: self.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1,
Expand Down Expand Up @@ -316,23 +352,24 @@ mod tests {
#[test]
fn gets_session_and_validator_keys() {
let client = client();
assert_eq!(client.session_keys(&BlockId::Number(0)).unwrap(), validators());
assert_eq!(client.validators(&BlockId::Number(0)).unwrap(), validators());
let id = client.check_id(BlockId::Number(0)).unwrap();
assert_eq!(client.session_keys(&id).unwrap(), validators());
assert_eq!(client.validators(&id).unwrap(), validators());
}

#[test]
fn build_block() {
let client = client();

let block_builder = client.build_block(&BlockId::Number(0), 1_000_000).unwrap();
let id = client.check_id(BlockId::Number(0)).unwrap();
let block_builder = client.build_block(&id, 1_000_000).unwrap();
let block = block_builder.bake();

assert_eq!(block.header.number, 1);
}

#[test]
fn cannot_build_block_on_unknown_parent() {
let client = client();
assert!(client.build_block(&BlockId::Number(100), 1_000_000).is_err());
fn fails_to_check_id_for_unknown_block() {
assert!(client().check_id(BlockId::Number(100)).is_err());
}
}
1 change: 1 addition & 0 deletions polkadot/consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ polkadot-api = { path = "../api" }
polkadot-collator = { path = "../collator" }
polkadot-primitives = { path = "../primitives" }
polkadot-statement-table = { path = "../statement-table" }
polkadot-transaction-pool = { path = "../transaction-pool" }
substrate-bft = { path = "../../substrate/bft" }
substrate-codec = { path = "../../substrate/codec" }
substrate-primitives = { path = "../../substrate/primitives" }
7 changes: 7 additions & 0 deletions polkadot/consensus/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ error_chain! {
description("Proposal had wrong parent hash."),
display("Proposal had wrong parent hash. Expected {:?}, got {:?}", expected, got),
}
ProposalTooLarge(size: usize) {
description("Proposal exceeded the maximum size."),
display(
"Proposal exceeded the maximum size of {} by {} bytes.",
::MAX_TRANSACTIONS_SIZE, ::MAX_TRANSACTIONS_SIZE.saturating_sub(*size)
),
}
}
}

Expand Down
Loading

0 comments on commit 239acad

Please sign in to comment.