Files
pezkuwi-subxt/substrate/substrate/rpc/src/author/mod.rs
T
Gav Wood 3d6aaab26c Refactor/substrate state machine generic (#553)
* Genric over hasher

* WIP start adding NodeCodec

* Add codec to TrieBackend

* Typechecks

* Fix error type

* Cleanup

* Tests build (and fail)

* Fix tests: don't use MemoryDB::default()

* Lockfile

* Address grumbles

* Teach environmental! about generics

* Add Finder artifacts

* whitespace

* Add a toy impl of Hasher and plug it in to Externalities

* Use `uint` and `fixed-hash` from `parity-common`
Remove unused U512
Add test to ensure H256 impls heapsizeof

* lock file updates

* Make hashes Encodable/Decodable

* lock file updates

* Impl FromIterator for TestExternalities so we can collect() and use map!

* Use rustc-hex from crates
Use rlp from master so dependencies do not mess up the scope

* Fix tests in runtime-io

* lockfile shenanigans

* Add a BlakeHasher impl

* Use BlakeHasher in runtime-io

* lockfile updates

* ws

* Add a Blake2/RLP-flavoured NodeCodec

* Use Blake-flavoured Hasher and NodeCodec

* lockfile

* Implement PartialEq and Default for TestExternalities

* Add note about limitations of environmental!

* Make it compile, but this is probably broken

* Derive Debug so tests in executor can work

* Make executor use BlakeHasher

* ws

* WIP make client generic

* typechecks

* cleanup

* client tests pass

* Fix client/db

* cleanup

* Fix network

* Fix rpc

* Fix service

* Make TestExternalities work better au lieu d'un HashMap

* Fix tests in council

* Fix tests in contract

* Fix tests in council

* Fix democracy

* Add comment about odd-looking reexports in tests

* Don't need to load branch

* Fix staking

* Fix session

* Some polkadot fixes and lockfile

* Fix executive

* fixup lockfile

* Fix polkadot/api

* Fix polkadot/service

* Fix polkadot/runtime tests

* Fix tests in test-runtime

* Test fixes

* Fix missing component in the `std` feature

* Use PhantomData and Result from core

* Fix paths
Use core

* load heapsize on wasm

* implement `HeapSizeOf` for wasm

* Add toy impl of `blake2_256` for no_std

* lockfile

* Use kvdb* from parity-common and fix errors

* rebuilt lockfile

* Add dummy impl of `on_advance_round` for rhododendron::Context

* Fix build after merge

* Add HeapSizeOf bound where needed

* Sort out dependencies for no_std

* Add HeapSizeOf bound where needed

* use temp branch pending PR merges

* Remove unneeded tests

* Lock file and wasm artifacts

* lockfile

* Use magic commit for libp2p

* Cleanup

* Implement blake2_256 for no_std

* Back on parity-common master

* missing type params

* Update Cargo.lock

* whitespace

* Rename concrete Rlp node codec "RlpCodec" and use everywhere
Implement a Keccak-flavoured Rlp NodeCodec and use everywhere
Add a KeccakHasher

* Switch to use KeccakHasher

* Lock file and runtimes

* fixup lockfile

* Fix outstanding issue using concrete types (thanks @gnunicorn)

* Cleanup

* More cleanup

* Comment out Blake2 Hasher

* implement ext_keccak256

* Address todo: FetchChecker is generic

* all tests passing
2018-08-15 13:13:11 +02:00

158 lines
5.0 KiB
Rust

// 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 client::{self, Client};
use codec::Codec;
use extrinsic_pool::{
api::{Error, ExtrinsicPool},
watcher::Status,
};
use jsonrpc_macros::pubsub;
use jsonrpc_pubsub::SubscriptionId;
use primitives::{Bytes, KeccakHasher, RlpCodec};
use rpc::futures::{Sink, Stream, Future};
use runtime_primitives::{generic, traits};
use subscriptions::Subscriptions;
use tokio::runtime::TaskExecutor;
pub mod error;
#[cfg(test)]
mod tests;
use self::error::Result;
build_rpc_trait! {
/// Substrate authoring RPC API
pub trait AuthorApi<Hash, Extrinsic, PendingExtrinsics> {
type Metadata;
/// Submit extrinsic for inclusion in block.
#[rpc(name = "author_submitRichExtrinsic")]
fn submit_rich_extrinsic(&self, Extrinsic) -> Result<Hash>;
/// Submit hex-encoded extrinsic for inclusion in block.
#[rpc(name = "author_submitExtrinsic")]
fn submit_extrinsic(&self, Bytes) -> Result<Hash>;
/// Returns all pending extrinsics, potentially grouped by sender.
#[rpc(name = "author_pendingExtrinsics")]
fn pending_extrinsics(&self) -> Result<PendingExtrinsics>;
#[pubsub(name = "author_extrinsicUpdate")] {
/// Submit an extrinsic to watch.
#[rpc(name = "author_submitAndWatchExtrinsic")]
fn watch_extrinsic(&self, Self::Metadata, pubsub::Subscriber<Status<Hash>>, Bytes);
/// Unsubscribe from extrinsic watching.
#[rpc(name = "author_unwatchExtrinsic")]
fn unwatch_extrinsic(&self, SubscriptionId) -> Result<bool>;
}
}
}
/// Authoring API
pub struct Author<B, E, Block: traits::Block, P> {
/// Substrate client
client: Arc<Client<B, E, Block>>,
/// Extrinsic pool
pool: Arc<P>,
/// Subscriptions manager
subscriptions: Subscriptions,
}
impl<B, E, Block: traits::Block, P> Author<B, E, Block, P> {
/// Create new instance of Authoring API.
pub fn new(client: Arc<Client<B, E, Block>>, pool: Arc<P>, executor: TaskExecutor) -> Self {
Author {
client,
pool,
subscriptions: Subscriptions::new(executor),
}
}
}
impl<B, E, Block, P, Ex, Hash, InPool> AuthorApi<Hash, Ex, InPool> for Author<B, E, Block, P> where
B: client::backend::Backend<Block, KeccakHasher, RlpCodec> + Send + Sync + 'static,
E: client::CallExecutor<Block, KeccakHasher, RlpCodec> + Send + Sync + 'static,
Block: traits::Block + 'static,
Hash: traits::MaybeSerializeDebug + Send + Sync + 'static,
InPool: traits::MaybeSerializeDebug + Send + Sync + 'static,
P: ExtrinsicPool<Ex, generic::BlockId<Block>, Hash, InPool=InPool>,
P::Error: 'static,
Ex: Codec,
{
type Metadata = ::metadata::Metadata;
fn submit_extrinsic(&self, xt: Bytes) -> Result<Hash> {
let dxt = Ex::decode(&mut &xt[..]).ok_or(error::Error::from(error::ErrorKind::BadFormat))?;
self.submit_rich_extrinsic(dxt)
}
fn submit_rich_extrinsic(&self, xt: Ex) -> Result<Hash> {
let best_block_hash = self.client.info()?.chain.best_hash;
self.pool
.submit(generic::BlockId::hash(best_block_hash), vec![xt])
.map(|mut res| res.pop().expect("One extrinsic passed; one result back; qed"))
.map_err(|e| e.into_pool_error()
.map(Into::into)
.unwrap_or_else(|e| error::ErrorKind::Verification(Box::new(e)).into())
)
}
fn pending_extrinsics(&self) -> Result<InPool> {
Ok(self.pool.all())
}
fn watch_extrinsic(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber<Status<Hash>>, xt: Bytes) {
let submit = || -> Result<_> {
let best_block_hash = self.client.info()?.chain.best_hash;
let dxt = Ex::decode(&mut &xt[..]).ok_or(error::Error::from(error::ErrorKind::BadFormat))?;
self.pool
.submit_and_watch(generic::BlockId::hash(best_block_hash), dxt)
.map_err(|e| e.into_pool_error()
.map(Into::into)
.unwrap_or_else(|e| error::ErrorKind::Verification(Box::new(e)).into())
)
};
let watcher = match submit() {
Ok(watcher) => watcher,
Err(err) => {
// reject the subscriber (ignore errors - we don't care if subscriber is no longer there).
let _ = subscriber.reject(err.into());
return;
},
};
self.subscriptions.add(subscriber, move |sink| {
sink
.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))
.send_all(watcher.into_stream().map(Ok))
.map(|_| ())
})
}
fn unwatch_extrinsic(&self, id: SubscriptionId) -> Result<bool> {
Ok(self.subscriptions.cancel(id))
}
}