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

Transaction queue integration + submission RPC #99

Merged
merged 5 commits into from
Apr 9, 2018
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
5 changes: 4 additions & 1 deletion 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 demo/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ substrate-state-machine = { path = "../../substrate/state-machine" }
substrate-executor = { path = "../../substrate/executor" }
substrate-primitives = { path = "../../substrate/primitives" }
substrate-rpc-servers = { path = "../../substrate/rpc-servers" }
substrate-rpc = { path = "../../substrate/rpc" }
demo-primitives = { path = "../primitives" }
demo-executor = { path = "../executor" }
demo-runtime = { path = "../runtime" }
10 changes: 9 additions & 1 deletion demo/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extern crate substrate_runtime_io as runtime_io;
extern crate substrate_state_machine as state_machine;
extern crate substrate_client as client;
extern crate substrate_primitives as primitives;
extern crate substrate_rpc;
extern crate substrate_rpc_servers as rpc;
extern crate demo_primitives;
extern crate demo_executor;
Expand All @@ -49,6 +50,13 @@ use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfi
SessionConfig, StakingConfig, BuildExternalities};
use client::genesis;

struct DummyPool;
impl substrate_rpc::author::AuthorApi for DummyPool {
fn submit_extrinsic(&self, _: primitives::block::Extrinsic) -> substrate_rpc::author::error::Result<()> {
Err(substrate_rpc::author::error::ErrorKind::Unimplemented.into())
}
}

/// Parse command line arguments and start the node.
///
/// IANA unassigned port ranges that we could use:
Expand Down Expand Up @@ -126,7 +134,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
let client = Arc::new(client::new_in_mem(executor, prepare_genesis)?);

let address = "127.0.0.1:9933".parse().unwrap();
let handler = rpc::rpc_handler(client);
let handler = rpc::rpc_handler(client, DummyPool);
let server = rpc::start_http(&address, handler)?;

if let Some(_) = matches.subcommand_matches("validator") {
Expand Down
Binary file not shown.
Binary file not shown.
3 changes: 2 additions & 1 deletion polkadot/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub fn run<I, T>(args: I, exit: mpsc::Receiver<()>) -> error::Result<()> where
let rpc_port: u16 = port.parse().expect("Invalid RPC port value specified.");
address.set_port(rpc_port);
}
let handler = rpc::rpc_handler(service.client());
let handler = rpc::rpc_handler(service.client(), service.transaction_pool());
let _server = rpc::start_http(&address, handler)?;

exit.recv().ok();
Expand Down Expand Up @@ -148,6 +148,7 @@ fn default_base_path() -> PathBuf {
&app_info,
).expect("app directories exist on all supported platforms; qed")
}

fn init_logger(pattern: &str) {
let mut builder = env_logger::LogBuilder::new();
// Disable info logging by default for some modules:
Expand Down
4 changes: 4 additions & 0 deletions polkadot/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,9 +570,13 @@ impl<C: PolkadotApi, R: TableRouter> bft::Proposer for Proposer<C, R> {
}

let polkadot_block = block_builder.bake();
info!("Proposing block [number: {}; extrinsics: [{}], parent_hash: {}]", polkadot_block.header.number, polkadot_block.extrinsics.len(), polkadot_block.header.parent_hash);

let substrate_block = Slicable::decode(&mut polkadot_block.encode().as_slice())
.expect("polkadot blocks defined to serialize to substrate blocks correctly; qed");

assert!(evaluate_proposal(&substrate_block, &*self.client, current_timestamp(), &self.parent_hash, &self.parent_id).is_ok());

Ok(substrate_block)
}

Expand Down
Binary file modified polkadot/runtime/wasm/genesis.wasm
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions polkadot/transaction-pool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ error-chain = "0.11"
polkadot-api = { path = "../api" }
polkadot-primitives = { path = "../primitives" }
polkadot-runtime = { path = "../runtime" }
substrate-client = { path = "../../substrate/client" }
substrate-rpc = { path = "../../substrate/rpc" }
substrate-primitives = { path = "../../substrate/primitives" }
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" }
substrate-codec = { path = "../../substrate/codec" }
Expand Down
13 changes: 13 additions & 0 deletions polkadot/transaction-pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
extern crate ed25519;
extern crate ethereum_types;
extern crate substrate_codec as codec;
extern crate substrate_rpc;
extern crate substrate_primitives as substrate_primitives;
extern crate substrate_runtime_primitives as substrate_runtime_primitives;
extern crate polkadot_runtime as runtime;
Expand All @@ -31,8 +32,10 @@ use std::collections::HashMap;
use std::cmp::Ordering;
use std::sync::Arc;

use codec::Slicable;
use polkadot_api::PolkadotApi;
use primitives::{AccountId, Timestamp};
use substrate_primitives::block::Extrinsic;
use runtime::{Block, UncheckedExtrinsic, TimestampCall, Call};
use substrate_runtime_primitives::traits::Checkable;
use transaction_pool::{Pool, Readiness};
Expand Down Expand Up @@ -371,6 +374,16 @@ impl TransactionPool {
}
}

impl substrate_rpc::author::AsyncAuthorApi for TransactionPool {
fn submit_extrinsic(&mut self, xt: Extrinsic) -> substrate_rpc::author::error::Result<()> {
self.import(xt
.using_encoded(|ref mut s| UncheckedExtrinsic::decode(s))
.ok_or(substrate_rpc::author::error::ErrorKind::InvalidFormat)?)
.map(|_| ())
.map_err(|_| substrate_rpc::author::error::ErrorKind::PoolError.into())
}
}

#[cfg(test)]
mod tests {
}
15 changes: 15 additions & 0 deletions substrate/primitives/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ impl Slicable for Transaction {
}
}

/// Simple generic extrinsic type.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Extrinsic(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);

impl Slicable for Extrinsic {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<u8>::decode(input).map(Extrinsic)
}

fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}

/// Execution log (event)
#[derive(PartialEq, Eq, Clone, Default)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
Expand Down
4 changes: 3 additions & 1 deletion substrate/rpc-servers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ extern crate jsonrpc_http_server as http;
use std::io;

/// Construct rpc `IoHandler`
pub fn rpc_handler<S>(state: S) -> rpc::IoHandler where
pub fn rpc_handler<S, T>(state: S, transaction_pool: T) -> rpc::IoHandler where
S: apis::state::StateApi,
T: apis::author::AuthorApi,
{
let mut io = rpc::IoHandler::new();
io.extend_with(state.to_delegate());
io.extend_with(transaction_pool.to_delegate());
io
}

Expand Down
1 change: 1 addition & 0 deletions substrate/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Parity Technologies <[email protected]>"]

[dependencies]
parking_lot = "0.4"
error-chain = "0.11"
jsonrpc-core = { git="https://github.com/paritytech/jsonrpc.git" }
jsonrpc-macros = { git="https://github.com/paritytech/jsonrpc.git" }
Expand Down
54 changes: 54 additions & 0 deletions substrate/rpc/src/author/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Substrate.

// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

use client;
use rpc;

error_chain! {
links {
Client(client::error::Error, client::error::ErrorKind) #[doc = "Client error"];
}
errors {
/// Not implemented yet
Unimplemented {
description("not yet implemented"),
display("Method Not Implemented"),
}
/// Invalid format
InvalidFormat {
description("invalid format"),
display("Invalid format for the extrinsic data"),
}
/// Some error with the pool since the import failed.
PoolError {
description("pool import failed"),
display("Pool import failed"),
}
}
}

impl From<Error> for rpc::Error {
fn from(e: Error) -> Self {
match e {
Error(ErrorKind::Unimplemented, _) => rpc::Error {
code: rpc::ErrorCode::ServerError(-1),
message: "Not implemented yet".into(),
data: None,
},
_ => rpc::Error::internal_error(),
}
}
}
49 changes: 49 additions & 0 deletions substrate/rpc/src/author/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Substrate.

// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

//! Substrate block-author/full-node API.

use std::sync::Arc;
use parking_lot::Mutex;
use primitives::block::Extrinsic;

pub mod error;

#[cfg(test)]
mod tests;

use self::error::Result;

build_rpc_trait! {
/// Substrate authoring RPC API
pub trait AuthorApi {
/// Submit extrinsic for inclusion in block.
#[rpc(name = "author_submitExtrinsic")]
fn submit_extrinsic(&self, Extrinsic) -> Result<()>;
}
}

/// Variant of the AuthorApi that doesn't need to be Sync + Send + 'static.
pub trait AsyncAuthorApi: Send + 'static {
/// Submit extrinsic for inclusion in block.
fn submit_extrinsic(&mut self, Extrinsic) -> Result<()>;
}

impl<T: AsyncAuthorApi> AuthorApi for Arc<Mutex<T>> {
fn submit_extrinsic(&self, xt: Extrinsic) -> Result<()> {
self.as_ref().lock().submit_extrinsic(xt)
}
}
50 changes: 50 additions & 0 deletions substrate/rpc/src/author/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Substrate.

// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

use primitives::block;
use substrate_executor as executor;
use super::*;
use super::error::*;

#[derive(Default)]
struct DummyTxPool {
submitted: Vec<block::Extrinsic>,
}

impl AsyncAuthorApi for DummyTxPool {
/// Submit extrinsic for inclusion in block.
fn submit_extrinsic(&mut self, xt: Extrinsic) -> Result<()> {
if self.submitted.len() < 1 {
self.submitted.push(xt);
Ok(())
} else {
Err(ErrorKind::PoolError.into())
}
}
}

#[test]
fn submit_transaction_should_not_cause_error() {
let mut p = Arc::new(Mutex::new(DummyTxPool::default()));

assert_matches!(
AuthorApi::submit_extrinsic(&p, block::Extrinsic(vec![])),
Ok(())
);
assert!(
AuthorApi::submit_extrinsic(&p, block::Extrinsic(vec![])).is_err()
);
}
2 changes: 2 additions & 0 deletions substrate/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#![warn(missing_docs)]

extern crate parking_lot;
extern crate jsonrpc_core as rpc;
extern crate substrate_client as client;
extern crate substrate_primitives as primitives;
Expand All @@ -38,3 +39,4 @@ extern crate substrate_runtime_support as runtime_support;

pub mod chain;
pub mod state;
pub mod author;