diff --git a/Cargo.toml b/Cargo.toml index 808ed57b16..30582f1570 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ substrate-subxt-proc-macro = { version = "0.9.0", path = "proc-macro" } async-std = { version = "=1.5.0", features = ["attributes"] } env_logger = "0.7.1" wabt = "0.9.2" +wabt-sys = "=0.7.1" # pinned because 0.7.2 fails to compile frame-system = { version = "2.0.0-rc4", package = "frame-system" } pallet-balances = { version = "2.0.0-rc4", package = "pallet-balances" } sp-keyring = { version = "2.0.0-rc4", package = "sp-keyring" } diff --git a/src/extra.rs b/src/extrinsic/extra.rs similarity index 97% rename from src/extra.rs rename to src/extrinsic/extra.rs index fa7ff54a55..f31cec25b8 100644 --- a/src/extra.rs +++ b/src/extrinsic/extra.rs @@ -28,11 +28,17 @@ use sp_runtime::{ transaction_validity::TransactionValidityError, }; -use crate::frame::{ - balances::Balances, - system::System, +use crate::{ + frame::{ + balances::Balances, + system::System, + }, + runtimes::Runtime, }; +/// Extra type. +pub type Extra = <::Extra as SignedExtra>::Extra; + /// SignedExtra checks copied from substrate, in order to remove requirement to implement /// substrate's `frame_system::Trait` diff --git a/src/extrinsic/mod.rs b/src/extrinsic/mod.rs new file mode 100644 index 0000000000..70b50c9a11 --- /dev/null +++ b/src/extrinsic/mod.rs @@ -0,0 +1,82 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of substrate-subxt. +// +// subxt 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. +// +// subxt 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-subxt. If not, see . + +//! Create signed or unsigned extrinsics. + +mod extra; +mod signer; + +pub use self::{ + extra::{ + DefaultExtra, + Extra, + SignedExtra, + }, + signer::{ + PairSigner, + Signer, + }, +}; + +use sp_runtime::traits::SignedExtension; +use sp_version::RuntimeVersion; + +use crate::{ + frame::system::System, + runtimes::Runtime, + Encoded, + Error, +}; + +/// UncheckedExtrinsic type. +pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic< + ::Address, + Encoded, + ::Signature, + Extra, +>; + +/// SignedPayload type. +pub type SignedPayload = sp_runtime::generic::SignedPayload>; + +/// Creates a signed extrinsic +pub async fn create_signed( + runtime_version: &RuntimeVersion, + genesis_hash: T::Hash, + nonce: T::Index, + call: Encoded, + signer: &(dyn Signer + Send + Sync), +) -> Result, Error> +where + T: Runtime, + <>::Extra as SignedExtension>::AdditionalSigned: + Send + Sync, +{ + let spec_version = runtime_version.spec_version; + let tx_version = runtime_version.transaction_version; + let extra: T::Extra = T::Extra::new(spec_version, tx_version, nonce, genesis_hash); + let payload = SignedPayload::::new(call, extra.extra())?; + let signed = signer.sign(payload).await?; + Ok(signed) +} + +/// Creates an unsigned extrinsic +pub fn create_unsigned(call: Encoded) -> UncheckedExtrinsic +where + T: Runtime, +{ + UncheckedExtrinsic::::new_unsigned(call) +} diff --git a/src/signer.rs b/src/extrinsic/signer.rs similarity index 96% rename from src/signer.rs rename to src/extrinsic/signer.rs index ebbcd41654..13ff50a366 100644 --- a/src/signer.rs +++ b/src/extrinsic/signer.rs @@ -17,14 +17,12 @@ //! A library to **sub**mit e**xt**rinsics to a //! [substrate](https://github.com/paritytech/substrate) node via RPC. -use crate::{ - extra::SignedExtra, - runtimes::{ - Runtime, - SignedPayload, - UncheckedExtrinsic, - }, +use super::{ + SignedExtra, + SignedPayload, + UncheckedExtrinsic, }; +use crate::runtimes::Runtime; use codec::Encode; use sp_core::Pair; use sp_runtime::traits::{ diff --git a/src/frame/balances.rs b/src/frame/balances.rs index bb1bdad498..4c210ce748 100644 --- a/src/frame/balances.rs +++ b/src/frame/balances.rs @@ -115,7 +115,7 @@ mod tests { RuntimeError, }, events::EventsDecoder, - signer::{ + extrinsic::{ PairSigner, Signer, }, diff --git a/src/frame/sudo.rs b/src/frame/sudo.rs index 541a923bfc..8efb336b7d 100644 --- a/src/frame/sudo.rs +++ b/src/frame/sudo.rs @@ -44,8 +44,8 @@ mod tests { use super::*; use crate::{ error::Error, + extrinsic::PairSigner, frame::balances::TransferCall, - signer::PairSigner, tests::{ test_client, TestRuntime, diff --git a/src/lib.rs b/src/lib.rs index 23927e7df3..c833c93228 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,17 +60,16 @@ use sp_core::{ Bytes, }; pub use sp_runtime::traits::SignedExtension; -use sp_version::RuntimeVersion; +pub use sp_version::RuntimeVersion; use std::marker::PhantomData; mod error; mod events; -mod extra; +pub mod extrinsic; mod frame; mod metadata; mod rpc; mod runtimes; -mod signer; mod subscription; pub use crate::{ @@ -79,7 +78,12 @@ pub use crate::{ EventsDecoder, RawEvent, }, - extra::*, + extrinsic::{ + PairSigner, + SignedExtra, + Signer, + UncheckedExtrinsic, + }, frame::*, metadata::{ Metadata, @@ -90,7 +94,6 @@ pub use crate::{ ExtrinsicSuccess, }, runtimes::*, - signer::*, subscription::*, substrate_subxt_proc_macro::*, }; @@ -311,49 +314,13 @@ impl Client { .and_then(|module| module.call(C::FUNCTION, call))?) } - /// Creates an payload for an extrinsic. - /// - /// If `nonce` is `None` the nonce will be fetched from the chain. - pub async fn create_payload>( - &self, - call: C, - account_id: &::AccountId, - nonce: Option, - ) -> Result, Error> - where - <>::Extra as SignedExtension>::AdditionalSigned: - Send + Sync, - { - let account_nonce = if let Some(nonce) = nonce { - nonce - } else { - self.account(account_id, None).await?.nonce - }; - let spec_version = self.runtime_version.spec_version; - let tx_version = self.runtime_version.transaction_version; - let genesis_hash = self.genesis_hash; - let call = self.encode(call)?; - let extra: T::Extra = - T::Extra::new(spec_version, tx_version, account_nonce, genesis_hash); - let raw_payload = SignedPayload::::new(call, extra.extra())?; - Ok(raw_payload) - } - /// Creates an unsigned extrinsic. - pub async fn create_unsigned + Send + Sync>( + pub fn create_unsigned + Send + Sync>( &self, call: C, - account_id: &::AccountId, - nonce: Option, - ) -> Result, Error> - where - <>::Extra as SignedExtension>::AdditionalSigned: - Send + Sync, - { - let payload = self.create_payload(call, account_id, nonce).await?; - let (call, _, _) = payload.deconstruct(); - let unsigned = UncheckedExtrinsic::::new_unsigned(call); - Ok(unsigned) + ) -> Result, Error> { + let call = self.encode(call)?; + Ok(extrinsic::create_unsigned::(call)) } /// Creates a signed extrinsic. @@ -366,10 +333,20 @@ impl Client { <>::Extra as SignedExtension>::AdditionalSigned: Send + Sync, { - let payload = self - .create_payload(call, signer.account_id(), signer.nonce()) - .await?; - let signed = signer.sign(payload).await?; + let account_nonce = if let Some(nonce) = signer.nonce() { + nonce + } else { + self.account(signer.account_id(), None).await?.nonce + }; + let call = self.encode(call)?; + let signed = extrinsic::create_signed( + &self.runtime_version, + self.genesis_hash, + account_nonce, + call, + signer, + ) + .await?; Ok(signed) } @@ -479,19 +456,11 @@ impl codec::Encode for Encoded { #[cfg(test)] mod tests { use super::*; - use codec::Encode; - use sp_core::{ - storage::{ - well_known_keys, - StorageKey, - }, - Pair, - }; - use sp_keyring::{ - AccountKeyring, - Ed25519Keyring, + use sp_core::storage::{ + well_known_keys, + StorageKey, }; - use sp_runtime::MultiSignature; + use sp_keyring::AccountKeyring; use substrate_subxt_client::{ DatabaseConfig, KeystoreConfig, @@ -640,47 +609,4 @@ mod tests { let mut blocks = client.subscribe_finalized_blocks().await.unwrap(); blocks.next().await; } - - #[async_std::test] - async fn test_create_raw_payload() { - let signer_pair = Ed25519Keyring::Alice.pair(); - let signer_account_id = Ed25519Keyring::Alice.to_account_id(); - let dest = AccountKeyring::Bob.to_account_id().into(); - - let (client, _) = test_client().await; - - // create raw payload with AccoundId and sign it - let raw_payload = client - .create_payload( - balances::TransferCall { - to: &dest, - amount: 10_000, - }, - &signer_account_id, - None, - ) - .await - .unwrap(); - let raw_signature = signer_pair.sign(raw_payload.encode().as_slice()); - let raw_multisig = MultiSignature::from(raw_signature); - - // create signature with Xtbuilder - let signer = PairSigner::new(Ed25519Keyring::Alice.pair()); - let xt_multi_sig = client - .create_signed( - balances::TransferCall { - to: &dest, - amount: 10_000, - }, - &signer, - ) - .await - .unwrap() - .signature - .unwrap() - .1; - - // compare signatures - assert_eq!(raw_multisig, xt_multi_sig); - } } diff --git a/src/runtimes.rs b/src/runtimes.rs index 0f23635158..13779d71b8 100644 --- a/src/runtimes.rs +++ b/src/runtimes.rs @@ -27,7 +27,7 @@ use sp_runtime::{ }; use crate::{ - extra::{ + extrinsic::{ DefaultExtra, SignedExtra, }, @@ -40,7 +40,6 @@ use crate::{ sudo::Sudo, system::System, }, - Encoded, }; /// Runtime trait. @@ -51,20 +50,6 @@ pub trait Runtime: System + Sized + Send + Sync + 'static { type Extra: SignedExtra + Send + Sync + 'static; } -/// Extra type. -pub type Extra = <::Extra as SignedExtra>::Extra; - -/// UncheckedExtrinsic type. -pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic< - ::Address, - Encoded, - ::Signature, - Extra, ->; - -/// SignedPayload type. -pub type SignedPayload = sp_runtime::generic::SignedPayload>; - /// Concrete type definitions compatible with those in the default substrate `node_runtime` /// /// # Note