mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-08 01:58:00 +00:00
rework signed extensions
This commit is contained in:
Generated
-1
@@ -4531,7 +4531,6 @@ dependencies = [
|
||||
"subxt-lightclient",
|
||||
"subxt-macro",
|
||||
"subxt-metadata",
|
||||
"subxt-signer",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
|
||||
+3
-15
@@ -24,23 +24,11 @@ default = ["jsonrpsee", "native"]
|
||||
|
||||
# Enable this for native (ie non web/wasm builds).
|
||||
# Exactly 1 of "web" and "native" is expected.
|
||||
native = [
|
||||
"jsonrpsee?/async-client",
|
||||
"jsonrpsee?/client-ws-transport-native-tls",
|
||||
"subxt-lightclient?/native",
|
||||
"tokio-util"
|
||||
]
|
||||
native = ["jsonrpsee?/async-client", "jsonrpsee?/client-ws-transport-native-tls", "subxt-lightclient?/native", "tokio-util"]
|
||||
|
||||
# Enable this for web/wasm builds.
|
||||
# Exactly 1 of "web" and "native" is expected.
|
||||
web = [
|
||||
"jsonrpsee?/async-wasm-client",
|
||||
"jsonrpsee?/client-web-transport",
|
||||
"getrandom/js",
|
||||
"subxt-lightclient?/web",
|
||||
"subxt-macro/web",
|
||||
"instant/wasm-bindgen"
|
||||
]
|
||||
web = ["jsonrpsee?/async-wasm-client", "jsonrpsee?/client-web-transport", "getrandom/js", "subxt-lightclient?/web", "subxt-macro/web", "instant/wasm-bindgen"]
|
||||
|
||||
# Enable this to use the reconnecting rpc client
|
||||
unstable-reconnecting-rpc-client = ["dep:reconnecting-jsonrpsee-ws-client"]
|
||||
@@ -127,7 +115,7 @@ sp-core = { workspace = true }
|
||||
sp-keyring = { workspace = true }
|
||||
sp-runtime = { workspace = true }
|
||||
assert_matches = { workspace = true }
|
||||
subxt-signer = { path = "../signer" }
|
||||
# subxt-signer = { path = "../signer" } // todo!() revert this, but rust analyzer blows up on cyclic dep
|
||||
# Tracing subscriber is useful for light-client examples to ensure that
|
||||
# the `bootNodes` and chain spec are configured correctly. If all is fine, then
|
||||
# the light-client wlll emit INFO logs with
|
||||
|
||||
@@ -53,13 +53,13 @@ impl CustomExtrinsicParamsBuilder {
|
||||
|
||||
// Describe how to fetch and then encode the params:
|
||||
impl<T: Config> ExtrinsicParams<T> for CustomExtrinsicParams<T> {
|
||||
type OtherParams = CustomExtrinsicParamsBuilder;
|
||||
type Params = CustomExtrinsicParamsBuilder;
|
||||
|
||||
// Gather together all of the params we will need to encode:
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
_nonce: u64,
|
||||
client: Client,
|
||||
other_params: Self::OtherParams,
|
||||
other_params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
Ok(Self {
|
||||
genesis_hash: client.genesis_hash(),
|
||||
@@ -86,7 +86,7 @@ async fn main() {
|
||||
|
||||
let tx_payload = runtime::tx().system().remark(b"Hello".to_vec());
|
||||
|
||||
// Build your custom "OtherParams":
|
||||
// Build your custom "Params":
|
||||
let tx_config = CustomExtrinsicParamsBuilder::new().tip(1234).enable_foo();
|
||||
|
||||
// And provide them when submitting a transaction:
|
||||
|
||||
@@ -58,12 +58,12 @@ impl<T: Config> signed_extensions::SignedExtension<T> for CustomSignedExtension
|
||||
|
||||
// Gather together any params we need for our signed extension, here none.
|
||||
impl<T: Config> ExtrinsicParams<T> for CustomSignedExtension {
|
||||
type OtherParams = ();
|
||||
type Params = ();
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
_nonce: u64,
|
||||
_client: Client,
|
||||
_other_params: Self::OtherParams,
|
||||
_other_params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
Ok(CustomSignedExtension)
|
||||
}
|
||||
@@ -86,7 +86,7 @@ impl ExtrinsicParamsEncoder for CustomSignedExtension {
|
||||
// to construct an entirely new interface to provide the relevant `OtherParams`.
|
||||
pub fn custom(
|
||||
params: DefaultExtrinsicParamsBuilder<CustomConfig>,
|
||||
) -> <<CustomConfig as Config>::ExtrinsicParams as ExtrinsicParams<CustomConfig>>::OtherParams {
|
||||
) -> <<CustomConfig as Config>::ExtrinsicParams as ExtrinsicParams<CustomConfig>>::Params {
|
||||
let (a, b, c, d, e, f, g) = params.build();
|
||||
(a, b, c, d, e, f, g, ())
|
||||
}
|
||||
|
||||
@@ -65,6 +65,11 @@ where
|
||||
pub fn header(&self) -> &T::Header {
|
||||
&self.header
|
||||
}
|
||||
|
||||
/// Return the entire block header. Consumes the block itself
|
||||
pub fn into_header(self) -> T::Header {
|
||||
self.header
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> Block<T, C>
|
||||
|
||||
@@ -19,7 +19,45 @@ crate::macros::cfg_unstable_light_client! {
|
||||
};
|
||||
}
|
||||
|
||||
use derivative::Derivative;
|
||||
pub use offline_client::{OfflineClient, OfflineClientT};
|
||||
pub use online_client::{
|
||||
ClientRuntimeUpdater, OnlineClient, OnlineClientT, RuntimeUpdaterStream, Update, UpgradeError,
|
||||
};
|
||||
|
||||
use crate::{backend::RuntimeVersion, Config, Metadata};
|
||||
|
||||
/// The inner values, any client should contain.
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug(bound = ""), Clone(bound = ""))]
|
||||
pub struct BaseClient<T: Config> {
|
||||
genesis_hash: T::Hash,
|
||||
runtime_version: RuntimeVersion,
|
||||
metadata: Metadata,
|
||||
}
|
||||
|
||||
impl<T: Config> BaseClient<T> {
|
||||
/// Create a new [`BaseClient`].
|
||||
pub fn new(genesis_hash: T::Hash, runtime_version: RuntimeVersion, metadata: Metadata) -> Self {
|
||||
Self {
|
||||
genesis_hash,
|
||||
runtime_version,
|
||||
metadata,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the genesis hash.
|
||||
pub fn genesis_hash(&self) -> T::Hash {
|
||||
self.genesis_hash
|
||||
}
|
||||
|
||||
/// Return the runtime version.
|
||||
pub fn runtime_version(&self) -> RuntimeVersion {
|
||||
self.runtime_version.clone()
|
||||
}
|
||||
|
||||
/// Return the [`Metadata`] used in this client.
|
||||
pub fn metadata(&self) -> Metadata {
|
||||
self.metadata.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||
// see LICENSE for license details.
|
||||
|
||||
use super::BaseClient;
|
||||
use crate::custom_values::CustomValuesClient;
|
||||
use crate::{
|
||||
backend::RuntimeVersion, blocks::BlocksClient, constants::ConstantsClient,
|
||||
@@ -9,7 +10,6 @@ use crate::{
|
||||
Config, Metadata,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A trait representing a client that can perform
|
||||
@@ -21,6 +21,8 @@ pub trait OfflineClientT<T: Config>: Clone + Send + Sync + 'static {
|
||||
fn genesis_hash(&self) -> T::Hash;
|
||||
/// Return the provided [`RuntimeVersion`].
|
||||
fn runtime_version(&self) -> RuntimeVersion;
|
||||
/// Return the inner [`BaseClient`].
|
||||
fn base_client(&self) -> BaseClient<T>;
|
||||
|
||||
/// Work with transactions.
|
||||
fn tx(&self) -> TxClient<T, Self> {
|
||||
@@ -63,15 +65,7 @@ pub trait OfflineClientT<T: Config>: Clone + Send + Sync + 'static {
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug(bound = ""), Clone(bound = ""))]
|
||||
pub struct OfflineClient<T: Config> {
|
||||
inner: Arc<Inner<T>>,
|
||||
}
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug(bound = ""), Clone(bound = ""))]
|
||||
struct Inner<T: Config> {
|
||||
genesis_hash: T::Hash,
|
||||
runtime_version: RuntimeVersion,
|
||||
metadata: Metadata,
|
||||
inner: Arc<BaseClient<T>>,
|
||||
}
|
||||
|
||||
impl<T: Config> OfflineClient<T> {
|
||||
@@ -83,11 +77,11 @@ impl<T: Config> OfflineClient<T> {
|
||||
metadata: impl Into<Metadata>,
|
||||
) -> OfflineClient<T> {
|
||||
OfflineClient {
|
||||
inner: Arc::new(Inner {
|
||||
inner: Arc::new(BaseClient::new(
|
||||
genesis_hash,
|
||||
runtime_version,
|
||||
metadata: metadata.into(),
|
||||
}),
|
||||
metadata.into(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +100,12 @@ impl<T: Config> OfflineClient<T> {
|
||||
self.inner.metadata.clone()
|
||||
}
|
||||
|
||||
/// Return the inner [`BaseClient`].
|
||||
pub fn base_client(&self) -> BaseClient<T> {
|
||||
// Note: this clone should be cheap because metadata is arced up.
|
||||
(*self.inner).clone()
|
||||
}
|
||||
|
||||
// Just a copy of the most important trait methods so that people
|
||||
// don't need to import the trait for most things:
|
||||
|
||||
@@ -145,6 +145,10 @@ impl<T: Config> OfflineClientT<T> for OfflineClient<T> {
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.metadata()
|
||||
}
|
||||
|
||||
fn base_client(&self) -> BaseClient<T> {
|
||||
self.base_client()
|
||||
}
|
||||
}
|
||||
|
||||
// For ergonomics; cloning a client is deliberately fairly cheap (via Arc),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||
// see LICENSE for license details.
|
||||
|
||||
use super::{OfflineClient, OfflineClientT};
|
||||
use super::{BaseClient, OfflineClient, OfflineClientT};
|
||||
use crate::custom_values::CustomValuesClient;
|
||||
use crate::{
|
||||
backend::{
|
||||
@@ -33,18 +33,10 @@ pub trait OnlineClientT<T: Config>: OfflineClientT<T> {
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Clone(bound = ""))]
|
||||
pub struct OnlineClient<T: Config> {
|
||||
inner: Arc<RwLock<Inner<T>>>,
|
||||
inner: Arc<RwLock<BaseClient<T>>>,
|
||||
backend: Arc<dyn Backend<T>>,
|
||||
}
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug(bound = ""))]
|
||||
struct Inner<T: Config> {
|
||||
genesis_hash: T::Hash,
|
||||
runtime_version: RuntimeVersion,
|
||||
metadata: Metadata,
|
||||
}
|
||||
|
||||
impl<T: Config> std::fmt::Debug for OnlineClient<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Client")
|
||||
@@ -146,11 +138,11 @@ impl<T: Config> OnlineClient<T> {
|
||||
backend: Arc<B>,
|
||||
) -> Result<OnlineClient<T>, Error> {
|
||||
Ok(OnlineClient {
|
||||
inner: Arc::new(RwLock::new(Inner {
|
||||
inner: Arc::new(RwLock::new(BaseClient::new(
|
||||
genesis_hash,
|
||||
runtime_version,
|
||||
metadata: metadata.into(),
|
||||
})),
|
||||
metadata.into(),
|
||||
))),
|
||||
backend,
|
||||
})
|
||||
}
|
||||
@@ -268,6 +260,12 @@ impl<T: Config> OnlineClient<T> {
|
||||
inner.genesis_hash
|
||||
}
|
||||
|
||||
/// Return the inner [`BaseClient`].
|
||||
pub fn base_client(&self) -> BaseClient<T> {
|
||||
let inner = self.inner.read().expect("shouldn't be poisoned");
|
||||
inner.clone()
|
||||
}
|
||||
|
||||
/// Change the genesis hash used in this client.
|
||||
///
|
||||
/// # Warning
|
||||
@@ -360,6 +358,10 @@ impl<T: Config> OfflineClientT<T> for OnlineClient<T> {
|
||||
fn runtime_version(&self) -> RuntimeVersion {
|
||||
self.runtime_version()
|
||||
}
|
||||
|
||||
fn base_client(&self) -> BaseClient<T> {
|
||||
self.base_client()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> OnlineClientT<T> for OnlineClient<T> {
|
||||
|
||||
@@ -20,12 +20,14 @@ pub type DefaultExtrinsicParams<T> = signed_extensions::AnyOf<
|
||||
),
|
||||
>;
|
||||
|
||||
/// A builder that outputs the set of [`super::ExtrinsicParams::OtherParams`] required for
|
||||
/// A builder that outputs the set of [`super::ExtrinsicParams::Params`] required for
|
||||
/// [`DefaultExtrinsicParams`]. This may expose methods that aren't applicable to the current
|
||||
/// chain; such values will simply be ignored if so.
|
||||
pub struct DefaultExtrinsicParamsBuilder<T: Config> {
|
||||
/// `None` means the tx will be immortal.
|
||||
mortality: Option<Mortality<T::Hash>>,
|
||||
/// The account nonce has to be set explicitly when creating extrinsic params.
|
||||
nonce: Option<u64>,
|
||||
/// `None` means we'll use the native token.
|
||||
tip_of_asset_id: Option<T::AssetId>,
|
||||
tip: u128,
|
||||
@@ -36,7 +38,7 @@ struct Mortality<Hash> {
|
||||
/// Block hash that mortality starts from
|
||||
checkpoint_hash: Hash,
|
||||
/// Block number that mortality starts from (must
|
||||
// point to the same block as the hash above)
|
||||
/// point to the same block as the hash above)
|
||||
checkpoint_number: u64,
|
||||
/// How many blocks the tx is mortal for
|
||||
period: u64,
|
||||
@@ -46,6 +48,7 @@ impl<T: Config> Default for DefaultExtrinsicParamsBuilder<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mortality: None,
|
||||
nonce: None,
|
||||
tip: 0,
|
||||
tip_of: 0,
|
||||
tip_of_asset_id: None,
|
||||
@@ -111,7 +114,7 @@ impl<T: Config> DefaultExtrinsicParamsBuilder<T> {
|
||||
}
|
||||
|
||||
/// Build the extrinsic parameters.
|
||||
pub fn build(self) -> <DefaultExtrinsicParams<T> as ExtrinsicParams<T>>::OtherParams {
|
||||
pub fn build(self) -> <DefaultExtrinsicParams<T> as ExtrinsicParams<T>>::Params {
|
||||
let check_mortality_params = if let Some(mortality) = self.mortality {
|
||||
signed_extensions::CheckMortalityParams::mortal(
|
||||
mortality.period,
|
||||
@@ -128,13 +131,15 @@ impl<T: Config> DefaultExtrinsicParamsBuilder<T> {
|
||||
signed_extensions::ChargeAssetTxPaymentParams::tip(self.tip)
|
||||
};
|
||||
|
||||
let check_nonce_params = signed_extensions::CheckNonceParams(self.nonce);
|
||||
|
||||
let charge_transaction_params =
|
||||
signed_extensions::ChargeTransactionPaymentParams::tip(self.tip);
|
||||
|
||||
(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
check_nonce_params,
|
||||
(),
|
||||
check_mortality_params,
|
||||
charge_asset_tx_params,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//! [`crate::config::DefaultExtrinsicParams`] provides a general-purpose
|
||||
//! implementation of this that will work in many cases.
|
||||
|
||||
use crate::{client::OfflineClientT, Config};
|
||||
use crate::{client::BaseClient, Config};
|
||||
use core::fmt::Debug;
|
||||
|
||||
/// An error that can be emitted when trying to construct an instance of [`ExtrinsicParams`],
|
||||
@@ -53,14 +53,11 @@ pub trait ExtrinsicParams<T: Config>: ExtrinsicParamsEncoder + Sized + 'static {
|
||||
/// These parameters can be provided to the constructor along with
|
||||
/// some default parameters that `subxt` understands, in order to
|
||||
/// help construct your [`ExtrinsicParams`] object.
|
||||
type OtherParams;
|
||||
type Params: FromBaseParams<T>;
|
||||
|
||||
/// Construct a new instance of our [`ExtrinsicParams`].
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
nonce: u64,
|
||||
client: Client,
|
||||
other_params: Self::OtherParams,
|
||||
) -> Result<Self, ExtrinsicParamsError>;
|
||||
fn new(base_params: &BaseParams<T>, params: Self::Params)
|
||||
-> Result<Self, ExtrinsicParamsError>;
|
||||
}
|
||||
|
||||
/// This trait is expected to be implemented for any [`ExtrinsicParams`], and
|
||||
@@ -80,26 +77,36 @@ pub trait ExtrinsicParamsEncoder: 'static {
|
||||
fn encode_additional_to(&self, _v: &mut Vec<u8>) {}
|
||||
}
|
||||
|
||||
/// Like the `From<T>` trait, if value is Some(_), but it lets us circumvent the orphan rule, because we want to implement
|
||||
/// `DefaultOrFrom<Header>` for `()`, such that DefaultOrFrom<Header> is implemented by `((),(),(),CheckMortalityParams)`, if `CheckMortalityParams` implements `DefaultFrom<Header>`
|
||||
pub trait DefaultOrFrom<T> {
|
||||
/// If value is None, Self is constructed as some default value. Otherwise it takes the value of `T` into account.
|
||||
fn default_or_from(value: Option<&T>) -> Self;
|
||||
/// Params that always need to be known to construct the Params of an extrinsic.
|
||||
pub struct BaseParams<T: Config> {
|
||||
/// [`BaseClient`] containing the metadata, genesis hash and runtime version.
|
||||
pub client: BaseClient<T>,
|
||||
/// Latest hash of a finalized block. Not always known (None), e.g. if only a [`crate::OfflineClient`] is available.
|
||||
pub latest_block_header: Option<T::Header>,
|
||||
/// Account nonce for the account submitting the extrinsic.
|
||||
pub nonce: u64,
|
||||
}
|
||||
|
||||
impl<T> DefaultOrFrom<T> for () {
|
||||
fn default_or_from(_value: Option<&T>) {}
|
||||
/// Types implementing this trait can be constructed from a minimal set of data provided by the client.
|
||||
/// Implementing this trait is similar to implementing Default, only that we pass in some prior information here.
|
||||
pub trait FromBaseParams<T: Config> {
|
||||
/// Constructs the value from the given mandatory params.
|
||||
fn from_base_params(params: &BaseParams<T>) -> Self;
|
||||
}
|
||||
|
||||
impl<T: Config> FromBaseParams<T> for () {
|
||||
fn from_base_params(_params: &BaseParams<T>) {}
|
||||
}
|
||||
|
||||
macro_rules! impl_default_from_tuples {
|
||||
($($ident:ident),+) => {
|
||||
impl <T, $($ident),+> DefaultOrFrom<T> for ($($ident,)+)
|
||||
impl <T: Config, $($ident),+> FromBaseParams<T> for ($($ident,)+)
|
||||
where
|
||||
$($ident: DefaultOrFrom<T>,)+
|
||||
$($ident: FromBaseParams<T>,)+
|
||||
{
|
||||
fn default_or_from(value: Option<&T>) -> Self {
|
||||
fn from_base_params(params: &BaseParams<T>) -> Self {
|
||||
($(
|
||||
(<$ident as DefaultOrFrom<T>>::default_or_from(value)),
|
||||
(<$ident as FromBaseParams<T>>::from_base_params(params)),
|
||||
)+)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
pub use default_extrinsic_params::{DefaultExtrinsicParams, DefaultExtrinsicParamsBuilder};
|
||||
pub use extrinsic_params::{
|
||||
DefaultOrFrom, ExtrinsicParams, ExtrinsicParamsEncoder, ExtrinsicParamsError,
|
||||
BaseParams, ExtrinsicParams, ExtrinsicParamsEncoder, ExtrinsicParamsError, FromBaseParams,
|
||||
};
|
||||
pub use polkadot::{PolkadotConfig, PolkadotExtrinsicParams, PolkadotExtrinsicParamsBuilder};
|
||||
pub use signed_extensions::SignedExtension;
|
||||
@@ -62,7 +62,7 @@ pub trait Config: Sized + Send + Sync + 'static {
|
||||
}
|
||||
|
||||
/// given some [`Config`], this return the other params needed for its `ExtrinsicParams`.
|
||||
pub type OtherParamsFor<T> = <<T as Config>::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams;
|
||||
pub type ParamsFor<T> = <<T as Config>::ExtrinsicParams as ExtrinsicParams<T>>::Params;
|
||||
|
||||
/// Block hashes must conform to a bunch of things to be used in Subxt.
|
||||
pub trait BlockHash:
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
//! [`AnyOf`] to configure the set of signed extensions which are known about
|
||||
//! when interacting with a chain.
|
||||
|
||||
use super::extrinsic_params::{
|
||||
DefaultOrFrom, ExtrinsicParams, ExtrinsicParamsEncoder, ExtrinsicParamsError,
|
||||
};
|
||||
use super::extrinsic_params::{ExtrinsicParams, ExtrinsicParamsEncoder, ExtrinsicParamsError};
|
||||
use super::{BaseParams, FromBaseParams};
|
||||
use crate::config::Header;
|
||||
use crate::utils::Era;
|
||||
use crate::{client::OfflineClientT, Config};
|
||||
@@ -40,14 +39,15 @@ pub trait SignedExtension<T: Config>: ExtrinsicParams<T> {
|
||||
pub struct CheckSpecVersion(u32);
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for CheckSpecVersion {
|
||||
type OtherParams = ();
|
||||
type Params = ();
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
_nonce: u64,
|
||||
client: Client,
|
||||
_other_params: Self::OtherParams,
|
||||
fn new(
|
||||
base_params: &BaseParams<T>,
|
||||
params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
Ok(CheckSpecVersion(client.runtime_version().spec_version))
|
||||
Ok(CheckSpecVersion(
|
||||
base_params.client.runtime_version().spec_version,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,13 +68,13 @@ impl<T: Config> SignedExtension<T> for CheckSpecVersion {
|
||||
pub struct CheckNonce(Compact<u64>);
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for CheckNonce {
|
||||
type OtherParams = ();
|
||||
type Params = CheckNonceParams;
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
nonce: u64,
|
||||
_client: Client,
|
||||
_other_params: Self::OtherParams,
|
||||
fn new(
|
||||
base_params: &BaseParams<T>,
|
||||
params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
let nonce = params.0.unwrap_or_else(|| base_params.nonce);
|
||||
Ok(CheckNonce(Compact(nonce)))
|
||||
}
|
||||
}
|
||||
@@ -92,18 +92,29 @@ impl<T: Config> SignedExtension<T> for CheckNonce {
|
||||
}
|
||||
}
|
||||
|
||||
/// The nonce can be explicitly set to `Some(_)` or left empty with `None`. In this case it will be taken from the base params.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct CheckNonceParams(pub Option<u64>);
|
||||
|
||||
impl<T: Config> FromBaseParams<T> for CheckNonceParams {
|
||||
fn from_base_params(params: &BaseParams<T>) -> Self {
|
||||
CheckNonceParams(Some(params.nonce))
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`CheckTxVersion`] signed extension.
|
||||
pub struct CheckTxVersion(u32);
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for CheckTxVersion {
|
||||
type OtherParams = ();
|
||||
type Params = ();
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
_nonce: u64,
|
||||
client: Client,
|
||||
_other_params: Self::OtherParams,
|
||||
fn new(
|
||||
base_params: &BaseParams<T>,
|
||||
params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
Ok(CheckTxVersion(client.runtime_version().transaction_version))
|
||||
Ok(CheckTxVersion(
|
||||
base_params.client.runtime_version().transaction_version,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,14 +135,13 @@ impl<T: Config> SignedExtension<T> for CheckTxVersion {
|
||||
pub struct CheckGenesis<T: Config>(T::Hash);
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for CheckGenesis<T> {
|
||||
type OtherParams = ();
|
||||
type Params = ();
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
_nonce: u64,
|
||||
client: Client,
|
||||
_other_params: Self::OtherParams,
|
||||
fn new(
|
||||
base_params: &BaseParams<T>,
|
||||
params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
Ok(CheckGenesis(client.genesis_hash()))
|
||||
Ok(CheckGenesis(base_params.client.genesis_hash()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,9 +179,9 @@ impl<T: Config> Default for CheckMortalityParams<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> DefaultOrFrom<T::Header> for CheckMortalityParams<T> {
|
||||
fn default_or_from(value: Option<&T::Header>) -> Self {
|
||||
if let Some(header) = value {
|
||||
impl<T: Config> FromBaseParams<T> for CheckMortalityParams<T> {
|
||||
fn from_base_params(params: &BaseParams<T>) -> Self {
|
||||
if let Some(header) = ¶ms.latest_block_header {
|
||||
const FOR_N_BLOCKS: u64 = 32;
|
||||
CheckMortalityParams::mortal(FOR_N_BLOCKS, header.number().into(), header.hash())
|
||||
} else {
|
||||
@@ -201,16 +211,17 @@ impl<T: Config> CheckMortalityParams<T> {
|
||||
}
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for CheckMortality<T> {
|
||||
type OtherParams = CheckMortalityParams<T>;
|
||||
type Params = CheckMortalityParams<T>;
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
_nonce: u64,
|
||||
client: Client,
|
||||
other_params: Self::OtherParams,
|
||||
fn new(
|
||||
base_params: &BaseParams<T>,
|
||||
params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
Ok(CheckMortality {
|
||||
era: other_params.era,
|
||||
checkpoint: other_params.checkpoint.unwrap_or(client.genesis_hash()),
|
||||
era: params.era,
|
||||
checkpoint: params
|
||||
.checkpoint
|
||||
.unwrap_or(base_params.client.genesis_hash()),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -267,8 +278,8 @@ impl<T: Config> Default for ChargeAssetTxPaymentParams<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> DefaultOrFrom<T::Header> for ChargeAssetTxPaymentParams<T> {
|
||||
fn default_or_from(_value: Option<&T::Header>) -> Self {
|
||||
impl<T: Config> FromBaseParams<T> for ChargeAssetTxPaymentParams<T> {
|
||||
fn from_base_params(params: &BaseParams<T>) -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
@@ -298,16 +309,15 @@ impl<T: Config> ChargeAssetTxPaymentParams<T> {
|
||||
}
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for ChargeAssetTxPayment<T> {
|
||||
type OtherParams = ChargeAssetTxPaymentParams<T>;
|
||||
type Params = ChargeAssetTxPaymentParams<T>;
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
_nonce: u64,
|
||||
_client: Client,
|
||||
other_params: Self::OtherParams,
|
||||
fn new(
|
||||
base_params: &BaseParams<T>,
|
||||
params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
Ok(ChargeAssetTxPayment {
|
||||
tip: Compact(other_params.tip),
|
||||
asset_id: other_params.asset_id,
|
||||
tip: Compact(params.tip),
|
||||
asset_id: params.asset_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -344,8 +354,8 @@ pub struct ChargeTransactionPaymentParams {
|
||||
tip: u128,
|
||||
}
|
||||
|
||||
impl<T> DefaultOrFrom<T> for ChargeTransactionPaymentParams {
|
||||
fn default_or_from(_value: Option<&T>) -> Self {
|
||||
impl<T: Config> FromBaseParams<T> for ChargeTransactionPaymentParams {
|
||||
fn from_base_params(params: &BaseParams<T>) -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
@@ -362,15 +372,14 @@ impl ChargeTransactionPaymentParams {
|
||||
}
|
||||
|
||||
impl<T: Config> ExtrinsicParams<T> for ChargeTransactionPayment {
|
||||
type OtherParams = ChargeTransactionPaymentParams;
|
||||
type Params = ChargeTransactionPaymentParams;
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
_nonce: u64,
|
||||
_client: Client,
|
||||
other_params: Self::OtherParams,
|
||||
fn new(
|
||||
base_params: &BaseParams<T>,
|
||||
params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
Ok(ChargeTransactionPayment {
|
||||
tip: Compact(other_params.tip),
|
||||
tip: Compact(params.tip),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -406,14 +415,13 @@ macro_rules! impl_tuples {
|
||||
T: Config,
|
||||
$($ident: SignedExtension<T>,)+
|
||||
{
|
||||
type OtherParams = ($($ident::OtherParams,)+);
|
||||
type Params = ($($ident::Params,)+);
|
||||
|
||||
fn new<Client: OfflineClientT<T>>(
|
||||
nonce: u64,
|
||||
client: Client,
|
||||
other_params: Self::OtherParams,
|
||||
fn new(
|
||||
base_params: &BaseParams<T>,
|
||||
params: Self::Params,
|
||||
) -> Result<Self, ExtrinsicParamsError> {
|
||||
let metadata = client.metadata();
|
||||
let metadata = base_params.client.metadata();
|
||||
let types = metadata.types();
|
||||
|
||||
// For each signed extension in the tuple, find the matching index in the metadata, if
|
||||
@@ -427,7 +435,7 @@ macro_rules! impl_tuples {
|
||||
}
|
||||
// Break and record as soon as we find a match:
|
||||
if $ident::matches(e.identifier(), e.extra_ty(), types) {
|
||||
let ext = $ident::new(nonce, client.clone(), other_params.$index)?;
|
||||
let ext = $ident::new(base_params, params.$index)?;
|
||||
let boxed_ext: Box<dyn ExtrinsicParamsEncoder> = Box::new(ext);
|
||||
exts_by_index.insert(idx, boxed_ext);
|
||||
break
|
||||
|
||||
+39
-33
@@ -7,7 +7,7 @@ use std::borrow::Cow;
|
||||
use crate::{
|
||||
backend::{BackendExt, BlockRef, TransactionStatus},
|
||||
client::{OfflineClientT, OnlineClientT},
|
||||
config::{Config, DefaultOrFrom, ExtrinsicParams, ExtrinsicParamsEncoder, Hasher},
|
||||
config::{BaseParams, Config, ExtrinsicParams, ExtrinsicParamsEncoder, FromBaseParams, Hasher},
|
||||
error::{Error, MetadataError},
|
||||
tx::{Signer as SignerT, TxPayload, TxProgress},
|
||||
utils::{Encoded, PhantomDataSendSync},
|
||||
@@ -103,11 +103,11 @@ impl<T: Config, C: OfflineClientT<T>> TxClient<T, C> {
|
||||
}
|
||||
|
||||
/// Create a partial extrinsic.
|
||||
pub fn create_partial_signed_with_nonce<Call>(
|
||||
fn create_partial_signed_with_base_params<Call>(
|
||||
&self,
|
||||
call: &Call,
|
||||
account_nonce: u64,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams,
|
||||
base_params: BaseParams<T>,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::Params,
|
||||
) -> Result<PartialExtrinsic<T, C>, Error>
|
||||
where
|
||||
Call: TxPayload,
|
||||
@@ -120,11 +120,8 @@ impl<T: Config, C: OfflineClientT<T>> TxClient<T, C> {
|
||||
let call_data = self.call_data(call)?;
|
||||
|
||||
// 3. Construct our custom additional/extra params.
|
||||
let additional_and_extra_params = <T::ExtrinsicParams as ExtrinsicParams<T>>::new(
|
||||
account_nonce,
|
||||
self.client.clone(),
|
||||
other_params,
|
||||
)?;
|
||||
let additional_and_extra_params =
|
||||
<T::ExtrinsicParams as ExtrinsicParams<T>>::new(&base_params, other_params)?;
|
||||
|
||||
// Return these details, ready to construct a signed extrinsic from.
|
||||
Ok(PartialExtrinsic {
|
||||
@@ -135,12 +132,12 @@ impl<T: Config, C: OfflineClientT<T>> TxClient<T, C> {
|
||||
}
|
||||
|
||||
/// Creates a signed extrinsic without submitting it.
|
||||
pub fn create_signed_with_nonce<Call, Signer>(
|
||||
fn create_signed_with_base_params<Call, Signer>(
|
||||
&self,
|
||||
call: &Call,
|
||||
signer: &Signer,
|
||||
account_nonce: u64,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams,
|
||||
base_params: BaseParams<T>,
|
||||
params: <T::ExtrinsicParams as ExtrinsicParams<T>>::Params,
|
||||
) -> Result<SubmittableExtrinsic<T, C>, Error>
|
||||
where
|
||||
Call: TxPayload,
|
||||
@@ -153,7 +150,7 @@ impl<T: Config, C: OfflineClientT<T>> TxClient<T, C> {
|
||||
// 2. Gather the "additional" and "extra" params along with the encoded call data,
|
||||
// ready to be signed.
|
||||
let partial_signed =
|
||||
self.create_partial_signed_with_nonce(call, account_nonce, other_params)?;
|
||||
self.create_partial_signed_with_base_params(call, base_params, params)?;
|
||||
|
||||
// 3. Sign and construct an extrinsic from these details.
|
||||
Ok(partial_signed.sign(signer))
|
||||
@@ -171,18 +168,30 @@ where
|
||||
crate::blocks::get_account_nonce(&self.client, account_id, block_ref.hash()).await
|
||||
}
|
||||
|
||||
async fn base_params(&self, account_id: &T::AccountId) -> Result<BaseParams<T>, Error> {
|
||||
let nonce = self.account_nonce(account_id).await?;
|
||||
let latest_block = self.client.blocks().at_latest().await.ok();
|
||||
let latest_block_header = latest_block.map(|b| b.into_header());
|
||||
let base_params = BaseParams::<T> {
|
||||
client: self.client.base_client(),
|
||||
latest_block_header,
|
||||
nonce,
|
||||
};
|
||||
Ok(base_params)
|
||||
}
|
||||
|
||||
/// Creates a partial signed extrinsic, without submitting it.
|
||||
pub async fn create_partial_signed<Call>(
|
||||
&self,
|
||||
call: &Call,
|
||||
account_id: &T::AccountId,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::Params,
|
||||
) -> Result<PartialExtrinsic<T, C>, Error>
|
||||
where
|
||||
Call: TxPayload,
|
||||
{
|
||||
let account_nonce = self.account_nonce(account_id).await?;
|
||||
self.create_partial_signed_with_nonce(call, account_nonce, other_params)
|
||||
let base_params = self.base_params(account_id).await?;
|
||||
self.create_partial_signed_with_base_params(call, base_params, other_params)
|
||||
}
|
||||
|
||||
/// Creates a signed extrinsic, without submitting it.
|
||||
@@ -190,14 +199,14 @@ where
|
||||
&self,
|
||||
call: &Call,
|
||||
signer: &Signer,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::Params,
|
||||
) -> Result<SubmittableExtrinsic<T, C>, Error>
|
||||
where
|
||||
Call: TxPayload,
|
||||
Signer: SignerT<T>,
|
||||
{
|
||||
let account_nonce = self.account_nonce(&signer.account_id()).await?;
|
||||
self.create_signed_with_nonce(call, signer, account_nonce, other_params)
|
||||
let base_params = self.base_params(&signer.account_id()).await?;
|
||||
self.create_signed_with_base_params(call, signer, base_params, other_params)
|
||||
}
|
||||
|
||||
/// Creates and signs an extrinsic and submits it to the chain. Passes default parameters
|
||||
@@ -213,13 +222,12 @@ where
|
||||
where
|
||||
Call: TxPayload,
|
||||
Signer: SignerT<T>,
|
||||
<T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams: DefaultOrFrom<T::Header>,
|
||||
{
|
||||
let latest_block = self.client.blocks().at_latest().await.ok();
|
||||
let latest_header = latest_block.as_ref().map(|b| b.header());
|
||||
let other_params =
|
||||
<T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams::default_or_from(latest_header);
|
||||
self.sign_and_submit_then_watch(call, signer, other_params)
|
||||
let base_params = self.base_params(&signer.account_id()).await?;
|
||||
let params =
|
||||
<T::ExtrinsicParams as ExtrinsicParams<T>>::Params::from_base_params(&base_params);
|
||||
self.create_signed_with_base_params(call, signer, base_params, params)?
|
||||
.submit_and_watch()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -231,14 +239,14 @@ where
|
||||
&self,
|
||||
call: &Call,
|
||||
signer: &Signer,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::Params,
|
||||
) -> Result<TxProgress<T, C>, Error>
|
||||
where
|
||||
Call: TxPayload,
|
||||
Signer: SignerT<T>,
|
||||
{
|
||||
self.create_signed(call, signer, other_params)
|
||||
.await?
|
||||
let base_params = self.base_params(&signer.account_id()).await?;
|
||||
self.create_signed_with_base_params(call, signer, base_params, other_params)?
|
||||
.submit_and_watch()
|
||||
.await
|
||||
}
|
||||
@@ -261,12 +269,10 @@ where
|
||||
where
|
||||
Call: TxPayload,
|
||||
Signer: SignerT<T>,
|
||||
<T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams: DefaultOrFrom<T::Header>,
|
||||
{
|
||||
let latest_block = self.client.blocks().at_latest().await.ok();
|
||||
let latest_header = latest_block.as_ref().map(|b| b.header());
|
||||
let base_params = self.base_params(&signer.account_id()).await?;
|
||||
let other_params =
|
||||
<T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams::default_or_from(latest_header);
|
||||
<T::ExtrinsicParams as ExtrinsicParams<T>>::Params::from_base_params(&base_params);
|
||||
self.sign_and_submit(call, signer, other_params).await
|
||||
}
|
||||
|
||||
@@ -282,7 +288,7 @@ where
|
||||
&self,
|
||||
call: &Call,
|
||||
signer: &Signer,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::OtherParams,
|
||||
other_params: <T::ExtrinsicParams as ExtrinsicParams<T>>::Params,
|
||||
) -> Result<T::Hash, Error>
|
||||
where
|
||||
Call: TxPayload,
|
||||
|
||||
Reference in New Issue
Block a user