// Copyright 2019-2023 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::macros::cfg_substrate_compat; 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 { /// 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_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 { account_id: T::AccountId, signer: Pair, } impl PairSigner 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. ::Signer: From, T::AccountId: From, { /// Creates a new [`Signer`] from an [`sp_core::Pair`]. pub fn new(signer: Pair) -> Self { let account_id = ::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 Signer for PairSigner where T: Config, Pair: PairT, Pair::Signature: Into, { fn account_id(&self) -> T::AccountId { self.account_id.clone() } fn address(&self) -> T::Address { self.account_id.clone().into() } fn sign(&self, signer_payload: &[u8]) -> T::Signature { self.signer.sign(signer_payload).into() } } }