Skip to content

Commit

Permalink
Refactor: extract functions and types for creating extrinsics (#138)
Browse files Browse the repository at this point in the history
* Extract extrinsic

* Extract extrinsic types to own module

* Fix compiler errors

* Fix warnings

* Fmt

* Pin wabt-sys to 0.7.1, it fails (on my machine) with 0.7.2

* Fix up tests

* Fmt

* Reexport RuntimeVersion
  • Loading branch information
ascjones authored Jul 20, 2020
1 parent 015a819 commit cd6b8f4
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 132 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
12 changes: 9 additions & 3 deletions src/extra.rs → src/extrinsic/extra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = <<T as Runtime>::Extra as SignedExtra<T>>::Extra;

/// SignedExtra checks copied from substrate, in order to remove requirement to implement
/// substrate's `frame_system::Trait`
Expand Down
82 changes: 82 additions & 0 deletions src/extrinsic/mod.rs
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

//! 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<T> = sp_runtime::generic::UncheckedExtrinsic<
<T as System>::Address,
Encoded,
<T as Runtime>::Signature,
Extra<T>,
>;

/// SignedPayload type.
pub type SignedPayload<T> = sp_runtime::generic::SignedPayload<Encoded, Extra<T>>;

/// Creates a signed extrinsic
pub async fn create_signed<T>(
runtime_version: &RuntimeVersion,
genesis_hash: T::Hash,
nonce: T::Index,
call: Encoded,
signer: &(dyn Signer<T> + Send + Sync),
) -> Result<UncheckedExtrinsic<T>, Error>
where
T: Runtime,
<<T::Extra as SignedExtra<T>>::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::<T>::new(call, extra.extra())?;
let signed = signer.sign(payload).await?;
Ok(signed)
}

/// Creates an unsigned extrinsic
pub fn create_unsigned<T>(call: Encoded) -> UncheckedExtrinsic<T>
where
T: Runtime,
{
UncheckedExtrinsic::<T>::new_unsigned(call)
}
12 changes: 5 additions & 7 deletions src/signer.rs → src/extrinsic/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down
2 changes: 1 addition & 1 deletion src/frame/balances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ mod tests {
RuntimeError,
},
events::EventsDecoder,
signer::{
extrinsic::{
PairSigner,
Signer,
},
Expand Down
2 changes: 1 addition & 1 deletion src/frame/sudo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ mod tests {
use super::*;
use crate::{
error::Error,
extrinsic::PairSigner,
frame::balances::TransferCall,
signer::PairSigner,
tests::{
test_client,
TestRuntime,
Expand Down
134 changes: 30 additions & 104 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -79,7 +78,12 @@ pub use crate::{
EventsDecoder,
RawEvent,
},
extra::*,
extrinsic::{
PairSigner,
SignedExtra,
Signer,
UncheckedExtrinsic,
},
frame::*,
metadata::{
Metadata,
Expand All @@ -90,7 +94,6 @@ pub use crate::{
ExtrinsicSuccess,
},
runtimes::*,
signer::*,
subscription::*,
substrate_subxt_proc_macro::*,
};
Expand Down Expand Up @@ -311,49 +314,13 @@ impl<T: Runtime> Client<T> {
.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<C: Call<T>>(
&self,
call: C,
account_id: &<T as System>::AccountId,
nonce: Option<T::Index>,
) -> Result<SignedPayload<T>, Error>
where
<<T::Extra as SignedExtra<T>>::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::<T>::new(call, extra.extra())?;
Ok(raw_payload)
}

/// Creates an unsigned extrinsic.
pub async fn create_unsigned<C: Call<T> + Send + Sync>(
pub fn create_unsigned<C: Call<T> + Send + Sync>(
&self,
call: C,
account_id: &<T as System>::AccountId,
nonce: Option<T::Index>,
) -> Result<UncheckedExtrinsic<T>, Error>
where
<<T::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
Send + Sync,
{
let payload = self.create_payload(call, account_id, nonce).await?;
let (call, _, _) = payload.deconstruct();
let unsigned = UncheckedExtrinsic::<T>::new_unsigned(call);
Ok(unsigned)
) -> Result<UncheckedExtrinsic<T>, Error> {
let call = self.encode(call)?;
Ok(extrinsic::create_unsigned::<T>(call))
}

/// Creates a signed extrinsic.
Expand All @@ -366,10 +333,20 @@ impl<T: Runtime> Client<T> {
<<T::Extra as SignedExtra<T>>::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)
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
}
17 changes: 1 addition & 16 deletions src/runtimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use sp_runtime::{
};

use crate::{
extra::{
extrinsic::{
DefaultExtra,
SignedExtra,
},
Expand All @@ -40,7 +40,6 @@ use crate::{
sudo::Sudo,
system::System,
},
Encoded,
};

/// Runtime trait.
Expand All @@ -51,20 +50,6 @@ pub trait Runtime: System + Sized + Send + Sync + 'static {
type Extra: SignedExtra<Self> + Send + Sync + 'static;
}

/// Extra type.
pub type Extra<T> = <<T as Runtime>::Extra as SignedExtra<T>>::Extra;

/// UncheckedExtrinsic type.
pub type UncheckedExtrinsic<T> = sp_runtime::generic::UncheckedExtrinsic<
<T as System>::Address,
Encoded,
<T as Runtime>::Signature,
Extra<T>,
>;

/// SignedPayload type.
pub type SignedPayload<T> = sp_runtime::generic::SignedPayload<Encoded, Extra<T>>;

/// Concrete type definitions compatible with those in the default substrate `node_runtime`
///
/// # Note
Expand Down

0 comments on commit cd6b8f4

Please sign in to comment.