1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
//! A library to **sub**mit e**xt**rinsics to a
//! [substrate](https://github.com/paritytech/substrate) node via RPC.
use crate::Config;
/// Signing transactions requires a [`Signer`]. This is responsible for
/// providing the "from" account that the transaction is being signed by,
/// as well as actually signing a SCALE encoded payload.
pub trait Signer<T: Config> {
/// Return the "from" account ID.
fn account_id(&self) -> &T::AccountId;
/// Return the "from" address.
fn address(&self) -> T::Address;
/// Takes a signer payload for an extrinsic, and returns a signature based on it.
///
/// Some signers may fail, for instance because the hardware on which the keys are located has
/// refused the operation.
fn sign(&self, signer_payload: &[u8]) -> T::Signature;
}
#[cfg(feature = "substrate-compat")]
pub use pair_signer::PairSigner;
// A signer suitable for substrate based chains. This provides compatibility with Substrate
// packages like sp_keyring and such, and so relies on sp_core and sp_runtime to be included.
#[cfg(feature = "substrate-compat")]
mod pair_signer {
use super::Signer;
use crate::Config;
use sp_core::Pair as PairT;
use sp_runtime::{
traits::{
IdentifyAccount,
Verify,
},
AccountId32 as SpAccountId32,
MultiSignature as SpMultiSignature,
};
/// A [`Signer`] implementation that can be constructed from an [`sp_core::Pair`].
#[derive(Clone, Debug)]
pub struct PairSigner<T: Config, Pair> {
account_id: T::AccountId,
signer: Pair,
}
impl<T, Pair> PairSigner<T, Pair>
where
T: Config,
Pair: PairT,
// We go via an sp_runtime::MultiSignature. We can probably generalise this
// by implementing some of these traits on our built-in MultiSignature and then
// requiring them on all T::Signatures, to avoid any go-between.
<SpMultiSignature as Verify>::Signer: From<Pair::Public>,
T::AccountId: From<SpAccountId32>,
{
/// Creates a new [`Signer`] from an [`sp_core::Pair`].
pub fn new(signer: Pair) -> Self {
let account_id = <SpMultiSignature as Verify>::Signer::from(signer.public())
.into_account();
Self {
account_id: account_id.into(),
signer,
}
}
/// Returns the [`sp_core::Pair`] implementation used to construct this.
pub fn signer(&self) -> &Pair {
&self.signer
}
/// Return the account ID.
pub fn account_id(&self) -> &T::AccountId {
&self.account_id
}
}
impl<T, Pair> Signer<T> for PairSigner<T, Pair>
where
T: Config,
Pair: PairT,
Pair::Signature: Into<T::Signature>,
{
fn account_id(&self) -> &T::AccountId {
&self.account_id
}
fn address(&self) -> T::Address {
self.account_id.clone().into()
}
fn sign(&self, signer_payload: &[u8]) -> T::Signature {
self.signer.sign(signer_payload).into()
}
}
}