blockchain - 我们可以从作为参数传递给基板中函数的调用(类型)中获取托盘和函数数据吗?
问题描述
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize
) -> Result<Self::Pre, TransactionValidityError> {
let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
Ok((self.0, who.clone(), imbalance))
}
(上面的代码是从 txn-payment-pallet 复制的)
这里我们可以从调用中获取函数名和参数(参数之一),并且根据用户传递的函数名,pallet,参数,我想计算费用。
例如,如果它是从pallet-staking::bond(x : amount_of_tokens_to_be_bonded)调用的,我想根据x 为txn 设置费用。那可能吗??同样,我想根据用户输入的函数调用参数设置费用。
解决方案
你可以,但它需要一些类型的杂耍才能做到这一点。
首先,您需要type Call = T::Call;
在ChargeTransactionPayment
. 往里看trait Config
,那里看pallet_transaction_payment
不到type Call
。相反,这种类型来自frame_system::Config
(这是所有托盘的超级特征)。
对顶层运行时聚合器文件的简要介绍可以发现,这种Call
类型本质上是运行时的外部调用,一个封装了所有托盘调用的枚举。
话虽这么说,这里的重点是,从内部pallet_transaction_payment
,我们无法知道这个外部调用是否包含这个来自质押的特定调用。为此,您需要通过一个新的 trait bound 来强制执行这个假设,即IsSubType
. 此特征专门用于从包装类型(如外部调用)转换为其内部变体。请参阅为's类型实现的这种类型的示例。node_runtime
Call
将以下差异应用于基板主控应该完全符合您的要求。
diff --git a/Cargo.lock b/Cargo.lock
index ea54adf99e..df66185163 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6074,6 +6074,7 @@ dependencies = [
"frame-support",
"frame-system",
"pallet-balances",
+ "pallet-staking",
"parity-scale-codec",
"scale-info",
"serde",
diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml
index 1d3066e39f..0e705514bb 100644
--- a/frame/transaction-payment/Cargo.toml
+++ b/frame/transaction-payment/Cargo.toml
@@ -27,6 +27,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primit
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
+pallet-staking = { version = "4.0.0-dev", default-features = false, path = "../staking" }
[dev-dependencies]
serde_json = "1.0.68"
@@ -44,5 +45,6 @@ std = [
"sp-std/std",
"frame-support/std",
"frame-system/std",
+ "pallet-staking/std",
]
try-runtime = ["frame-support/try-runtime"]
diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs
index 59d94a8237..3b0803663d 100644
--- a/frame/transaction-payment/src/lib.rs
+++ b/frame/transaction-payment/src/lib.rs
@@ -251,7 +251,7 @@ pub mod pallet {
pub struct Pallet<T>(_);
#[pallet::config]
- pub trait Config: frame_system::Config {
+ pub trait Config: frame_system::Config + pallet_staking::Config {
/// Handler for withdrawing, refunding and depositing the transaction fee.
/// Transaction fees are withdrawn before the transaction is executed.
/// After the transaction was executed the transaction weight can be
@@ -696,7 +696,8 @@ impl<T: Config> sp_std::fmt::Debug for ChargeTransactionPayment<T> {
impl<T: Config> SignedExtension for ChargeTransactionPayment<T>
where
BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,
- T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
+ T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>
+ + frame_support::traits::IsSubType<pallet_staking::Call<T>>,
{
const IDENTIFIER: &'static str = "ChargeTransactionPayment";
type AccountId = T::AccountId;
@@ -736,8 +737,15 @@ where
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
- let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
- Ok((self.0, who.clone(), imbalance))
+ use frame_support::traits::IsSubType;
+ if let Some(pallet_staking::Call::bond_extra { .. }) = call.is_sub_type() {
+ // skip
+ todo!()
+ } else {
+ // default impl
+ let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
+ Ok((self.0, who.clone(), imbalance))
+ }
}
fn post_dispatch(
请注意,这种方法意味着pallet_staking::Config
存在于运行时中,这与 Frame 的模块化不相符,并且没有实现 ergo。如果你想拥有这个功能,到目前为止,唯一的方法是pallet_transaction_payment
为你的运行时分叉和定制它。
推荐阅读
- python - 在大量方面上绘图
- sql-server - 插入 ... 选择输出子句,同时获取 INSERTED.ID 和 SELECTED.ID
- typescript - RXJS 主题 - 阻止错误传播
- python - Python - MQTT 多订阅:消息来自哪个主题
- linux - 如何通过混合连接将 Azure Web App 连接到 Oracle Linux
- angular - 简单计算的打字稿“不舍入”数字
- c# - Visual Studio的clickonce更新不起作用
- android - 本地化 - 在 Android 应用程序中执行本地化时,只有少数字符串会转换为印地语
- c++ - 通过指向 base、static_cast、crtp、删除模板的指针派生的成员
- python - Pandas 为单元格赋值,为什么这不起作用?