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

Commit

Permalink
Transaction queue integration + submission RPC (#99)
Browse files Browse the repository at this point in the history
* Implement transaction queue RPC.

* whitespace

* Support without_std env in environmental!  (#110)

* Make environmental crate support without_std env.

* Small doc fixes.

* Remove dead code.
  • Loading branch information
gavofyork authored Apr 9, 2018
1 parent 9da1f10 commit 3a5431f
Show file tree
Hide file tree
Showing 19 changed files with 209 additions and 3 deletions.
4 changes: 4 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 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 @@ -118,7 +118,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 @@ -150,6 +150,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;

0 comments on commit 3a5431f

Please sign in to comment.