From e41b90910e31a8a39e0b89914f2f465959233c12 Mon Sep 17 00:00:00 2001 From: Muharem Ismailov <ismailov.m.h@gmail.com> Date: Wed, 10 Aug 2022 12:36:16 +0200 Subject: [PATCH] Transaction payment runtime api: query call info and fee details (#11819) * Transaction payment RPC calls: query call info * transaction payment pallet - runtime api - add query_call info and fee_details * remove unused deps * separate call runtime api * undo fmt for unchanged code * system config call bounded to GetDispatchInfo, drop Call generic for query call info/fee * impl GetDispatchInfo for Extrinsics within runtime test-utils * introduced runtime api methods accept encoded Call instead of Call type * replace Bytes by Vec, docs for for new api, drop len argument, drop GetDispatchInfo bound from system_Config::Call * clean up toml and extra impl for dropped bound * panic if Call can not be decoded * revert to d43ba2f * fmt and docs * rustfmt --- .../bin/node-template/runtime/src/lib.rs | 17 +++++ substrate/bin/node/runtime/src/lib.rs | 11 ++++ .../rpc/runtime-api/src/lib.rs | 12 ++++ .../frame/transaction-payment/src/lib.rs | 63 +++++++++++++++++++ 4 files changed, 103 insertions(+) diff --git a/substrate/bin/node-template/runtime/src/lib.rs b/substrate/bin/node-template/runtime/src/lib.rs index 88fc86db02e..b43fbde52dc 100644 --- a/substrate/bin/node-template/runtime/src/lib.rs +++ b/substrate/bin/node-template/runtime/src/lib.rs @@ -467,6 +467,23 @@ impl_runtime_apis! { } } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, Call> + for Runtime + { + fn query_call_info( + call: Call, + len: u32, + ) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> { + TransactionPayment::query_call_info(call, len) + } + fn query_call_fee_details( + call: Call, + len: u32, + ) -> pallet_transaction_payment::FeeDetails<Balance> { + TransactionPayment::query_call_fee_details(call, len) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark<Block> for Runtime { fn benchmark_metadata(extra: bool) -> ( diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 2ac1e6444f1..6bfbe341305 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1965,6 +1965,17 @@ impl_runtime_apis! { } } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, Call> + for Runtime + { + fn query_call_info(call: Call, len: u32) -> RuntimeDispatchInfo<Balance> { + TransactionPayment::query_call_info(call, len) + } + fn query_call_fee_details(call: Call, len: u32) -> FeeDetails<Balance> { + TransactionPayment::query_call_fee_details(call, len) + } + } + impl pallet_mmr::primitives::MmrApi< Block, mmr::Hash, diff --git a/substrate/frame/transaction-payment/rpc/runtime-api/src/lib.rs b/substrate/frame/transaction-payment/rpc/runtime-api/src/lib.rs index 5a0c70138db..6944593daa5 100644 --- a/substrate/frame/transaction-payment/rpc/runtime-api/src/lib.rs +++ b/substrate/frame/transaction-payment/rpc/runtime-api/src/lib.rs @@ -31,4 +31,16 @@ sp_api::decl_runtime_apis! { fn query_info(uxt: Block::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance>; fn query_fee_details(uxt: Block::Extrinsic, len: u32) -> FeeDetails<Balance>; } + + pub trait TransactionPaymentCallApi<Balance, Call> + where + Balance: Codec + MaybeDisplay, + Call: Codec, + { + /// Query information of a dispatch class, weight, and fee of a given encoded `Call`. + fn query_call_info(call: Call, len: u32) -> RuntimeDispatchInfo<Balance>; + + /// Query fee details of a given encoded `Call`. + fn query_call_fee_details(call: Call, len: u32) -> FeeDetails<Balance>; + } } diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs index fe37acb2144..ff65c0d2735 100644 --- a/substrate/frame/transaction-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/src/lib.rs @@ -445,6 +445,32 @@ where } } + /// Query information of a dispatch class, weight, and fee of a given encoded `Call`. + pub fn query_call_info(call: T::Call, len: u32) -> RuntimeDispatchInfo<BalanceOf<T>> + where + T::Call: Dispatchable<Info = DispatchInfo> + GetDispatchInfo, + { + let dispatch_info = <T::Call as GetDispatchInfo>::get_dispatch_info(&call); + let DispatchInfo { weight, class, .. } = dispatch_info; + + RuntimeDispatchInfo { + weight, + class, + partial_fee: Self::compute_fee(len, &dispatch_info, 0u32.into()), + } + } + + /// Query fee details of a given encoded `Call`. + pub fn query_call_fee_details(call: T::Call, len: u32) -> FeeDetails<BalanceOf<T>> + where + T::Call: Dispatchable<Info = DispatchInfo> + GetDispatchInfo, + { + let dispatch_info = <T::Call as GetDispatchInfo>::get_dispatch_info(&call); + let tip = 0u32.into(); + + Self::compute_fee_details(len, &dispatch_info, tip) + } + /// Compute the final fee value for a particular transaction. pub fn compute_fee(len: u32, info: &DispatchInfoOf<T::Call>, tip: BalanceOf<T>) -> BalanceOf<T> where @@ -1206,6 +1232,43 @@ mod tests { }); } + #[test] + fn query_call_info_and_fee_details_works() { + let call = Call::Balances(BalancesCall::transfer { dest: 2, value: 69 }); + let info = call.get_dispatch_info(); + let encoded_call = call.encode(); + let len = encoded_call.len() as u32; + + ExtBuilder::default().base_weight(5).weight_fee(2).build().execute_with(|| { + // all fees should be x1.5 + <NextFeeMultiplier<Runtime>>::put(Multiplier::saturating_from_rational(3, 2)); + + assert_eq!( + TransactionPayment::query_call_info(call.clone(), len), + RuntimeDispatchInfo { + weight: info.weight, + class: info.class, + partial_fee: 5 * 2 /* base * weight_fee */ + + len as u64 /* len * 1 */ + + info.weight.min(BlockWeights::get().max_block) as u64 * 2 * 3 / 2 /* weight */ + }, + ); + + assert_eq!( + TransactionPayment::query_call_fee_details(call, len), + FeeDetails { + inclusion_fee: Some(InclusionFee { + base_fee: 5 * 2, /* base * weight_fee */ + len_fee: len as u64, /* len * 1 */ + adjusted_weight_fee: info.weight.min(BlockWeights::get().max_block) as u64 * + 2 * 3 / 2 /* weight * weight_fee * multipler */ + }), + tip: 0, + }, + ); + }); + } + #[test] fn compute_fee_works_without_multiplier() { ExtBuilder::default() -- GitLab