Cleanup macro magic (#5270)

* Cleanup macro magic

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make sign_call infallible

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix build

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* cargo update -p sp-io

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

Co-authored-by: parity-processbot <>
This commit is contained in:
Oliver Tale-Yazdi
2022-06-01 12:28:14 +02:00
committed by GitHub
parent 31bff68f94
commit 4206f8f45a
2 changed files with 421 additions and 336 deletions
+171 -171
View File
File diff suppressed because it is too large Load Diff
+251 -166
View File
@@ -28,7 +28,7 @@ use sc_executor::NativeElseWasmExecutor;
use sp_api::{CallApiAt, Encode, NumberFor, ProvideRuntimeApi}; use sp_api::{CallApiAt, Encode, NumberFor, ProvideRuntimeApi};
use sp_blockchain::{HeaderBackend, HeaderMetadata}; use sp_blockchain::{HeaderBackend, HeaderMetadata};
use sp_consensus::BlockStatus; use sp_consensus::BlockStatus;
use sp_core::Pair; use sp_core::{Pair, H256};
use sp_keyring::Sr25519Keyring; use sp_keyring::Sr25519Keyring;
use sp_runtime::{ use sp_runtime::{
generic::{BlockId, SignedBlock}, generic::{BlockId, SignedBlock},
@@ -239,23 +239,44 @@ pub trait ClientHandle {
fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output; fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output;
} }
/// Unwraps a [`Client`] into the concrete client type and
/// provides the concrete runtime as `runtime`.
macro_rules! with_client { macro_rules! with_client {
{ {
$self:ident, $self:ident,
$client:ident, $client:ident,
{ // NOTE: Using an expression here is fine since blocks are also expressions.
$( $code:tt )* $code:expr
}
} => { } => {
match $self { match $self {
#[cfg(feature = "polkadot")] #[cfg(feature = "polkadot")]
Self::Polkadot($client) => { $( $code )* }, Self::Polkadot($client) => {
#[allow(unused_imports)]
use polkadot_runtime as runtime;
$code
},
#[cfg(feature = "westend")] #[cfg(feature = "westend")]
Self::Westend($client) => { $( $code )* }, Self::Westend($client) => {
#[allow(unused_imports)]
use westend_runtime as runtime;
$code
},
#[cfg(feature = "kusama")] #[cfg(feature = "kusama")]
Self::Kusama($client) => { $( $code )* }, Self::Kusama($client) => {
#[allow(unused_imports)]
use kusama_runtime as runtime;
$code
},
#[cfg(feature = "rococo")] #[cfg(feature = "rococo")]
Self::Rococo($client) => { $( $code )* }, Self::Rococo($client) => {
#[allow(unused_imports)]
use rococo_runtime as runtime;
$code
},
} }
} }
} }
@@ -583,195 +604,259 @@ impl sp_blockchain::HeaderBackend<Block> for Client {
} }
} }
/// Provides a `SignedPayload` for any runtime. impl frame_benchmarking_cli::ExtrinsicBuilder for Client {
/// fn remark(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
/// Should only be used for benchmarking as it is not tested for regular usage. with_client! {
/// self, client, {
/// The first code block should set up all variables that are needed to create the use runtime::{Call, SystemCall};
/// `SignedPayload`. The second block can make use of the `SignedPayload`.
/// let call = Call::System(SystemCall::remark { remark: vec![] });
/// This is not done as a trait function since the return type depends on the runtime. let signer = Sr25519Keyring::Bob.pair();
/// This macro therefore uses the same approach as [`with_client!`].
macro_rules! with_signed_payload { let period = polkadot_runtime_common::BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
{ let genesis = self.usage_info().chain.best_hash;
$self:ident,
{ Ok(client.sign_call(call, nonce, 0, period, genesis, signer))
$extra:ident,
$client:ident,
$raw_payload:ident
},
{
$( $setup:tt )*
},
(
$period:expr,
$current_block:expr,
$nonce:expr,
$tip:expr,
$call:expr,
$genesis:expr
),
{
$( $usage:tt )*
} }
} => {
match $self {
#[cfg(feature = "polkadot")]
Self::Polkadot($client) => {
use polkadot_runtime as runtime;
$( $setup )*
let $extra: runtime::SignedExtra = (
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
frame_system::CheckTxVersion::<runtime::Runtime>::new(),
frame_system::CheckGenesis::<runtime::Runtime>::new(),
frame_system::CheckMortality::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
$period,
$current_block,
)),
frame_system::CheckNonce::<runtime::Runtime>::from($nonce),
frame_system::CheckWeight::<runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from($tip),
polkadot_runtime_common::claims::PrevalidateAttests::<runtime::Runtime>::new(),
);
let $raw_payload = runtime::SignedPayload::from_raw(
$call.clone(),
$extra.clone(),
(
(),
runtime::VERSION.spec_version,
runtime::VERSION.transaction_version,
$genesis.clone(),
$genesis,
(),
(),
(),
(),
),
);
$( $usage )*
},
#[cfg(feature = "westend")]
Self::Westend($client) => {
use westend_runtime as runtime;
$( $setup )*
signed_payload!($extra, $raw_payload,
($period, $current_block, $nonce, $tip, $call, $genesis));
$( $usage )*
},
#[cfg(feature = "kusama")]
Self::Kusama($client) => {
use kusama_runtime as runtime;
$( $setup )*
signed_payload!($extra, $raw_payload,
($period, $current_block, $nonce, $tip, $call, $genesis));
$( $usage )*
},
#[cfg(feature = "rococo")]
Self::Rococo($client) => {
use rococo_runtime as runtime;
$( $setup )*
signed_payload!($extra, $raw_payload,
($period, $current_block, $nonce, $tip, $call, $genesis));
$( $usage )*
},
} }
} }
} }
/// Generates a `SignedPayload` for the Kusama, Westend and Rococo runtime. /// Helper trait to implement [`frame_benchmarking_cli::ExtrinsicBuilder`].
/// ///
/// Should only be used for benchmarking as it is not tested for regular usage. /// Should only be used for benchmarking since it makes strong assumptions
#[allow(unused_macros)] /// about the chain state that these calls will be valid for.
macro_rules! signed_payload { trait BenchmarkCallSigner<Call: Encode + Clone, Signer: Pair> {
( /// Signs a call together with the signed extensions of the specific runtime.
$extra:ident, $raw_payload:ident, ///
( /// Only works if the current block is the genesis block since the
$period:expr, /// `CheckMortality` check is mocked by using the genesis block.
$current_block:expr, fn sign_call(
$nonce:expr, &self,
$tip:expr, call: Call,
$call:expr, nonce: u32,
$genesis:expr current_block: u64,
) period: u64,
) => { genesis: H256,
let $extra: runtime::SignedExtra = ( acc: Signer,
) -> OpaqueExtrinsic;
}
#[cfg(feature = "polkadot")]
impl BenchmarkCallSigner<polkadot_runtime::Call, sp_core::sr25519::Pair>
for FullClient<polkadot_runtime::RuntimeApi, PolkadotExecutorDispatch>
{
fn sign_call(
&self,
call: polkadot_runtime::Call,
nonce: u32,
current_block: u64,
period: u64,
genesis: H256,
acc: sp_core::sr25519::Pair,
) -> OpaqueExtrinsic {
use polkadot_runtime as runtime;
let extra: runtime::SignedExtra = (
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(), frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<runtime::Runtime>::new(), frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
frame_system::CheckTxVersion::<runtime::Runtime>::new(), frame_system::CheckTxVersion::<runtime::Runtime>::new(),
frame_system::CheckGenesis::<runtime::Runtime>::new(), frame_system::CheckGenesis::<runtime::Runtime>::new(),
frame_system::CheckMortality::<runtime::Runtime>::from( frame_system::CheckMortality::<runtime::Runtime>::from(
sp_runtime::generic::Era::mortal($period, $current_block), sp_runtime::generic::Era::mortal(period, current_block),
), ),
frame_system::CheckNonce::<runtime::Runtime>::from($nonce), frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
frame_system::CheckWeight::<runtime::Runtime>::new(), frame_system::CheckWeight::<runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from($tip), pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
polkadot_runtime_common::claims::PrevalidateAttests::<runtime::Runtime>::new(),
); );
let $raw_payload = runtime::SignedPayload::from_raw( let payload = runtime::SignedPayload::from_raw(
$call.clone(), call.clone(),
$extra.clone(), extra.clone(),
( (
(), (),
runtime::VERSION.spec_version, runtime::VERSION.spec_version,
runtime::VERSION.transaction_version, runtime::VERSION.transaction_version,
$genesis.clone(), genesis.clone(),
$genesis, genesis,
(),
(), (),
(), (),
(), (),
), ),
); );
};
}
impl frame_benchmarking_cli::ExtrinsicBuilder for Client { let signature = payload.using_encoded(|p| acc.sign(p));
fn remark(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> { runtime::UncheckedExtrinsic::new_signed(
with_signed_payload! {
self,
{extra, client, raw_payload},
{
// First the setup code to init all the variables that are needed
// to build the signed extras.
use runtime::{Call, SystemCall};
let call = Call::System(SystemCall::remark { remark: vec![] });
let bob = Sr25519Keyring::Bob.pair();
let period = polkadot_runtime_common::BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
let current_block = 0;
let tip = 0;
let genesis = client.usage_info().chain.best_hash;
},
(period, current_block, nonce, tip, call, genesis),
/* The SignedPayload is generated here */
{
// Use the payload to generate a signature.
let signature = raw_payload.using_encoded(|payload| bob.sign(payload));
let ext = runtime::UncheckedExtrinsic::new_signed(
call, call,
sp_runtime::AccountId32::from(bob.public()).into(), sp_runtime::AccountId32::from(acc.public()).into(),
polkadot_core_primitives::Signature::Sr25519(signature.clone()), polkadot_core_primitives::Signature::Sr25519(signature.clone()),
extra, extra,
)
.into()
}
}
#[cfg(feature = "westend")]
impl BenchmarkCallSigner<westend_runtime::Call, sp_core::sr25519::Pair>
for FullClient<westend_runtime::RuntimeApi, WestendExecutorDispatch>
{
fn sign_call(
&self,
call: westend_runtime::Call,
nonce: u32,
current_block: u64,
period: u64,
genesis: H256,
acc: sp_core::sr25519::Pair,
) -> OpaqueExtrinsic {
use westend_runtime as runtime;
let extra: runtime::SignedExtra = (
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
frame_system::CheckTxVersion::<runtime::Runtime>::new(),
frame_system::CheckGenesis::<runtime::Runtime>::new(),
frame_system::CheckMortality::<runtime::Runtime>::from(
sp_runtime::generic::Era::mortal(period, current_block),
),
frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
frame_system::CheckWeight::<runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
); );
Ok(ext.into())
let payload = runtime::SignedPayload::from_raw(
call.clone(),
extra.clone(),
(
(),
runtime::VERSION.spec_version,
runtime::VERSION.transaction_version,
genesis.clone(),
genesis,
(),
(),
(),
),
);
let signature = payload.using_encoded(|p| acc.sign(p));
runtime::UncheckedExtrinsic::new_signed(
call,
sp_runtime::AccountId32::from(acc.public()).into(),
polkadot_core_primitives::Signature::Sr25519(signature.clone()),
extra,
)
.into()
} }
}
#[cfg(feature = "kusama")]
impl BenchmarkCallSigner<kusama_runtime::Call, sp_core::sr25519::Pair>
for FullClient<kusama_runtime::RuntimeApi, KusamaExecutorDispatch>
{
fn sign_call(
&self,
call: kusama_runtime::Call,
nonce: u32,
current_block: u64,
period: u64,
genesis: H256,
acc: sp_core::sr25519::Pair,
) -> OpaqueExtrinsic {
use kusama_runtime as runtime;
let extra: runtime::SignedExtra = (
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
frame_system::CheckTxVersion::<runtime::Runtime>::new(),
frame_system::CheckGenesis::<runtime::Runtime>::new(),
frame_system::CheckMortality::<runtime::Runtime>::from(
sp_runtime::generic::Era::mortal(period, current_block),
),
frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
frame_system::CheckWeight::<runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
);
let payload = runtime::SignedPayload::from_raw(
call.clone(),
extra.clone(),
(
(),
runtime::VERSION.spec_version,
runtime::VERSION.transaction_version,
genesis.clone(),
genesis,
(),
(),
(),
),
);
let signature = payload.using_encoded(|p| acc.sign(p));
runtime::UncheckedExtrinsic::new_signed(
call,
sp_runtime::AccountId32::from(acc.public()).into(),
polkadot_core_primitives::Signature::Sr25519(signature.clone()),
extra,
)
.into()
} }
}
#[cfg(feature = "rococo")]
impl BenchmarkCallSigner<rococo_runtime::Call, sp_core::sr25519::Pair>
for FullClient<rococo_runtime::RuntimeApi, RococoExecutorDispatch>
{
fn sign_call(
&self,
call: rococo_runtime::Call,
nonce: u32,
current_block: u64,
period: u64,
genesis: H256,
acc: sp_core::sr25519::Pair,
) -> OpaqueExtrinsic {
use rococo_runtime as runtime;
let extra: runtime::SignedExtra = (
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
frame_system::CheckTxVersion::<runtime::Runtime>::new(),
frame_system::CheckGenesis::<runtime::Runtime>::new(),
frame_system::CheckMortality::<runtime::Runtime>::from(
sp_runtime::generic::Era::mortal(period, current_block),
),
frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
frame_system::CheckWeight::<runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
);
let payload = runtime::SignedPayload::from_raw(
call.clone(),
extra.clone(),
(
(),
runtime::VERSION.spec_version,
runtime::VERSION.transaction_version,
genesis.clone(),
genesis,
(),
(),
(),
),
);
let signature = payload.using_encoded(|p| acc.sign(p));
runtime::UncheckedExtrinsic::new_signed(
call,
sp_runtime::AccountId32::from(acc.public()).into(),
polkadot_core_primitives::Signature::Sr25519(signature.clone()),
extra,
)
.into()
} }
} }