Skip to content

Commit

Permalink
Get it to work. (paritytech#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
dvc94ch authored and ascjones committed Aug 8, 2019
1 parent 19604e8 commit be5ccc1
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 79 deletions.
18 changes: 11 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ use metadata::Metadata;
use parity_scale_codec::{
Codec,
Decode,
Encode,
};
use runtime_primitives::traits::{
SignedExtension,
StaticLookup,
};
use runtime_primitives::traits::SignedExtension;
use substrate_primitives::{
storage::StorageKey,
Pair,
Expand Down Expand Up @@ -133,11 +137,11 @@ impl<T: srml_system::Trait, SE: SignedExtension> Client<T, SE> {
) -> impl Future<Item = XtBuilder<T, SE, P, E>, Error = error::Error>
where
P: Pair,
P::Public: Into<T::AccountId>,
P::Public: Into<<T::Lookup as StaticLookup>::Source>,
P::Signature: Codec,
E: Fn(T::Index) -> SE,
{
let account_id: T::AccountId = signer.public().into();
let account_id: <T::Lookup as StaticLookup>::Source = signer.public().into();
let account_nonce_key = self
.metadata
.module("System")
Expand Down Expand Up @@ -169,14 +173,14 @@ pub struct XtBuilder<T: srml_system::Trait, SE: SignedExtension, P, E> {
impl<T: srml_system::Trait, SE: SignedExtension, P, E> XtBuilder<T, SE, P, E>
where
P: Pair,
P::Public: Into<T::AccountId>,
P::Public: Into<<T::Lookup as StaticLookup>::Source>,
P::Signature: Codec,
E: Fn(T::Index) -> SE,
{
pub fn submit<C: Codec + Send>(
pub fn submit<C: Encode + Send>(
&self,
call: C,
) -> impl Future<Item = ExtrinsicSuccess<T>, Error = error::Error> {
) -> impl Future<Item = T::Hash, Error = error::Error> {
let signer = self.signer.clone();
let nonce = self.nonce.clone();
let extra = (self.extra)(nonce.clone());
Expand Down Expand Up @@ -323,7 +327,7 @@ mod tests {
let call = node_runtime::Call::Balances(transfer.clone())
.encode()
.to_vec();
let call2 = balances.call(transfer);
let call2 = balances.call(transfer).0;
assert_eq!(call, call2);

let free_balance = <srml_balances::FreeBalance<Runtime>>::key_for(&dest);
Expand Down
12 changes: 10 additions & 2 deletions src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ use std::{
};
use substrate_primitives::storage::StorageKey;

pub struct Encoded(pub Vec<u8>);

impl Encode for Encoded {
fn encode(&self) -> Vec<u8> {
self.0.to_owned()
}
}

#[derive(Clone, Debug)]
pub struct Metadata {
modules: HashMap<String, ModuleMetadata>,
Expand All @@ -33,10 +41,10 @@ pub struct ModuleMetadata {
}

impl ModuleMetadata {
pub fn call<T: Encode>(&self, call: T) -> Vec<u8> {
pub fn call<T: Encode>(&self, call: T) -> Encoded {
let mut bytes = vec![self.index];
bytes.extend(call.encode());
bytes
Encoded(bytes)
}

pub fn storage(&self, key: &str) -> Option<&StorageMetadata> {
Expand Down
176 changes: 106 additions & 70 deletions src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,12 @@
use crate::{
error::Error,
metadata::Metadata,
ExtrinsicSuccess,
};
use futures::{
future::{
self,
Future,
IntoFuture,
},
stream::Stream,
};
use jsonrpc_core_client::{
RpcChannel,
RpcError,
TypedSubscriptionStream,
use futures::future::{
self,
Future,
};
use jsonrpc_core_client::RpcChannel;
use log;
use num_traits::bounds::Bounded;
use parity_scale_codec::{
Expand All @@ -44,24 +35,19 @@ use runtime_metadata::RuntimeMetadataPrefixed;
use runtime_primitives::{
generic::UncheckedExtrinsic,
traits::{
Hash as _,
SignedExtension,
StaticLookup,
},
};
use serde::{
self,
de::Error as DeError,
Deserialize,
};
use srml_system::EventRecord;
use std::convert::TryInto;
use substrate_primitives::{
blake2_256,
storage::{
StorageChangeSet,
StorageKey,
},
twox_128,
storage::StorageKey,
Pair,
};
use substrate_rpc::{
Expand All @@ -72,7 +58,6 @@ use substrate_rpc::{
},
state::StateClient,
};
use transaction_pool::txpool::watcher::Status;

/// Copy of runtime_primitives::OpaqueExtrinsic to allow a local Deserialize impl
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
Expand Down Expand Up @@ -171,30 +156,117 @@ impl<T: srml_system::Trait, SE: SignedExtension> Rpc<T, SE> {
}
}

impl<T: srml_system::Trait, SE: SignedExtension> Rpc<T, SE> {
/// Create and submit an extrinsic and return corresponding Hash if successful
pub fn create_and_submit_extrinsic<C, P>(
self,
signer: P,
call: C,
extra: SE,
account_nonce: T::Index,
genesis_hash: T::Hash,
) -> impl Future<Item = T::Hash, Error = Error>
where
C: Encode + Send,
P: Pair,
P::Public: Into<<T::Lookup as StaticLookup>::Source>,
P::Signature: Codec,
{
let extrinsic = Self::create_and_sign_extrinsic(
&signer,
call,
extra,
account_nonce,
genesis_hash,
);

self.author
.submit_extrinsic(extrinsic.encode().into())
.map_err(Into::into)
}

/// Creates and signs an Extrinsic for the supplied `Call`
fn create_and_sign_extrinsic<C, P>(
signer: &P,
call: C,
extra: SE,
account_nonce: T::Index,
genesis_hash: T::Hash,
) -> UncheckedExtrinsic<<T::Lookup as StaticLookup>::Source, C, P::Signature, SE>
where
C: Encode + Send,
P: Pair,
P::Public: Into<<T::Lookup as StaticLookup>::Source>,
P::Signature: Codec,
{
log::info!(
"Creating Extrinsic with genesis hash {:?} and account nonce {:?}",
genesis_hash,
account_nonce
);

let raw_payload = (call, extra.clone(), (&genesis_hash, &genesis_hash));
let signature = raw_payload.using_encoded(|payload| {
if payload.len() > 256 {
signer.sign(&blake2_256(payload)[..])
} else {
signer.sign(payload)
}
});

UncheckedExtrinsic::new_signed(
raw_payload.0,
signer.public().into(),
signature.into(),
extra,
)
}
}

use crate::ExtrinsicSuccess;
use futures::{
future::IntoFuture,
stream::Stream,
};
use jsonrpc_core_client::TypedSubscriptionStream;
use runtime_primitives::traits::Hash;
use srml_system::EventRecord;
use substrate_primitives::{
storage::StorageChangeSet,
twox_128,
};
use transaction_pool::txpool::watcher::Status;

impl<T: srml_system::Trait, SE: SignedExtension> Rpc<T, SE> {
/// Subscribe to substrate System Events
fn subscribe_events(
&self,
) -> impl Future<Item = TypedSubscriptionStream<StorageChangeSet<T::Hash>>, Error = RpcError>
) -> impl Future<Item = TypedSubscriptionStream<StorageChangeSet<T::Hash>>, Error = Error>
{
let events_key = b"System Events";
let storage_key = twox_128(events_key);
log::debug!("Events storage key {:?}", storage_key);

self.state
.subscribe_storage(Some(vec![StorageKey(storage_key.to_vec())]))
.map_err(Into::into)
}

/// Submit an extrinsic, waiting for it to be finalized.
/// If successful, returns the block hash.
fn submit_and_watch<C, P>(
self,
extrinsic: UncheckedExtrinsic<T::AccountId, C, P::Signature, SE>,
extrinsic: UncheckedExtrinsic<
<T::Lookup as StaticLookup>::Source,
C,
P::Signature,
SE,
>,
) -> impl Future<Item = T::Hash, Error = Error>
where
C: Codec + Send,
C: Encode + Send,
P: Pair,
P::Public: Into<T::AccountId>,
P::Public: Into<<T::Lookup as StaticLookup>::Source>,
P::Signature: Codec,
{
self.author
Expand All @@ -204,7 +276,8 @@ impl<T: srml_system::Trait, SE: SignedExtension> Rpc<T, SE> {
stream
.filter_map(|status| {
match status {
Status::Future | Status::Ready | Status::Broadcast(_) => None, // ignore in progress extrinsic for now
// ignore in progress extrinsic for now
Status::Future | Status::Ready | Status::Broadcast(_) => None,
Status::Finalized(block_hash) => Some(Ok(block_hash)),
Status::Usurped(_) => Some(Err("Extrinsic Usurped".into())),
Status::Dropped => Some(Err("Extrinsic Dropped".into())),
Expand All @@ -223,7 +296,8 @@ impl<T: srml_system::Trait, SE: SignedExtension> Rpc<T, SE> {
}

/// Create and submit an extrinsic and return corresponding Event if successful
pub fn create_and_submit_extrinsic<C, P>(
#[allow(unused)]
pub fn create_and_watch_extrinsic<C, P>(
self,
signer: P,
call: C,
Expand All @@ -232,22 +306,21 @@ impl<T: srml_system::Trait, SE: SignedExtension> Rpc<T, SE> {
genesis_hash: T::Hash,
) -> impl Future<Item = ExtrinsicSuccess<T>, Error = Error>
where
C: Codec + Send,
C: Encode + Send,
P: Pair,
P::Public: Into<T::AccountId>,
P::Public: Into<<T::Lookup as StaticLookup>::Source>,
P::Signature: Codec,
{
let events = self.subscribe_events().map_err(Into::into);
events.and_then(move |events| {
let extrinsic = Self::create_and_sign_extrinsic(
account_nonce,
call,
genesis_hash,
&signer,
call,
extra,
account_nonce,
genesis_hash,
);
let ext_hash = T::Hashing::hash_of(&extrinsic);

log::info!("Submitting Extrinsic `{:?}`", ext_hash);

let chain = self.chain.clone();
Expand All @@ -274,43 +347,6 @@ impl<T: srml_system::Trait, SE: SignedExtension> Rpc<T, SE> {
})
})
}

/// Creates and signs an Extrinsic for the supplied `Call`
fn create_and_sign_extrinsic<C, P>(
index: T::Index,
function: C,
genesis_hash: T::Hash,
signer: &P,
extra: SE,
) -> UncheckedExtrinsic<T::AccountId, C, P::Signature, SE>
where
C: Encode + Send,
P: Pair,
P::Public: Into<T::AccountId>,
P::Signature: Codec,
{
log::info!(
"Creating Extrinsic with genesis hash {:?} and account nonce {:?}",
genesis_hash,
index
);

let raw_payload = (function, extra.clone(), genesis_hash);
let signature = raw_payload.using_encoded(|payload| {
if payload.len() > 256 {
signer.sign(&blake2_256(payload)[..])
} else {
signer.sign(payload)
}
});

UncheckedExtrinsic::new_signed(
raw_payload.0,
signer.public().into(),
signature.into(),
extra,
)
}
}

/// Waits for events for the block triggered by the extrinsic
Expand Down

0 comments on commit be5ccc1

Please sign in to comment.