From be5ccc1d11fa262c7c99521b1b6dab879aa75839 Mon Sep 17 00:00:00 2001 From: David Craven Date: Thu, 8 Aug 2019 17:01:07 +0200 Subject: [PATCH] Get it to work. (#6) --- src/lib.rs | 18 +++-- src/metadata.rs | 12 +++- src/rpc.rs | 176 +++++++++++++++++++++++++++++------------------- 3 files changed, 127 insertions(+), 79 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7ba55479554b4..f8f9b0a82d48c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, @@ -133,11 +137,11 @@ impl Client { ) -> impl Future, Error = error::Error> where P: Pair, - P::Public: Into, + P::Public: Into<::Source>, P::Signature: Codec, E: Fn(T::Index) -> SE, { - let account_id: T::AccountId = signer.public().into(); + let account_id: ::Source = signer.public().into(); let account_nonce_key = self .metadata .module("System") @@ -169,14 +173,14 @@ pub struct XtBuilder { impl XtBuilder where P: Pair, - P::Public: Into, + P::Public: Into<::Source>, P::Signature: Codec, E: Fn(T::Index) -> SE, { - pub fn submit( + pub fn submit( &self, call: C, - ) -> impl Future, Error = error::Error> { + ) -> impl Future { let signer = self.signer.clone(); let nonce = self.nonce.clone(); let extra = (self.extra)(nonce.clone()); @@ -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 = >::key_for(&dest); diff --git a/src/metadata.rs b/src/metadata.rs index 6ae6b20b98b28..0a28dda15dd5b 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -14,6 +14,14 @@ use std::{ }; use substrate_primitives::storage::StorageKey; +pub struct Encoded(pub Vec); + +impl Encode for Encoded { + fn encode(&self) -> Vec { + self.0.to_owned() + } +} + #[derive(Clone, Debug)] pub struct Metadata { modules: HashMap, @@ -33,10 +41,10 @@ pub struct ModuleMetadata { } impl ModuleMetadata { - pub fn call(&self, call: T) -> Vec { + pub fn call(&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> { diff --git a/src/rpc.rs b/src/rpc.rs index b1a6843a27d83..ab0238d3374dc 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -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::{ @@ -44,8 +35,8 @@ use runtime_metadata::RuntimeMetadataPrefixed; use runtime_primitives::{ generic::UncheckedExtrinsic, traits::{ - Hash as _, SignedExtension, + StaticLookup, }, }; use serde::{ @@ -53,15 +44,10 @@ use serde::{ 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::{ @@ -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)] @@ -171,11 +156,92 @@ impl Rpc { } } +impl Rpc { + /// Create and submit an extrinsic and return corresponding Hash if successful + pub fn create_and_submit_extrinsic( + self, + signer: P, + call: C, + extra: SE, + account_nonce: T::Index, + genesis_hash: T::Hash, + ) -> impl Future + where + C: Encode + Send, + P: Pair, + P::Public: Into<::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( + signer: &P, + call: C, + extra: SE, + account_nonce: T::Index, + genesis_hash: T::Hash, + ) -> UncheckedExtrinsic<::Source, C, P::Signature, SE> + where + C: Encode + Send, + P: Pair, + P::Public: Into<::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 Rpc { /// Subscribe to substrate System Events fn subscribe_events( &self, - ) -> impl Future>, Error = RpcError> + ) -> impl Future>, Error = Error> { let events_key = b"System Events"; let storage_key = twox_128(events_key); @@ -183,18 +249,24 @@ impl Rpc { 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( self, - extrinsic: UncheckedExtrinsic, + extrinsic: UncheckedExtrinsic< + ::Source, + C, + P::Signature, + SE, + >, ) -> impl Future where - C: Codec + Send, + C: Encode + Send, P: Pair, - P::Public: Into, + P::Public: Into<::Source>, P::Signature: Codec, { self.author @@ -204,7 +276,8 @@ impl Rpc { 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())), @@ -223,7 +296,8 @@ impl Rpc { } /// Create and submit an extrinsic and return corresponding Event if successful - pub fn create_and_submit_extrinsic( + #[allow(unused)] + pub fn create_and_watch_extrinsic( self, signer: P, call: C, @@ -232,22 +306,21 @@ impl Rpc { genesis_hash: T::Hash, ) -> impl Future, Error = Error> where - C: Codec + Send, + C: Encode + Send, P: Pair, - P::Public: Into, + P::Public: Into<::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(); @@ -274,43 +347,6 @@ impl Rpc { }) }) } - - /// Creates and signs an Extrinsic for the supplied `Call` - fn create_and_sign_extrinsic( - index: T::Index, - function: C, - genesis_hash: T::Hash, - signer: &P, - extra: SE, - ) -> UncheckedExtrinsic - where - C: Encode + Send, - P: Pair, - P::Public: Into, - 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