mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-18 07:11:03 +00:00
Adapt pallet-contracts to WeightV2 (#12421)
* Replace contract access weight by proper PoV component * Return the whole weight struct from dry-runs * Fixup `seal_call` and `seal_instantiate` * Fix duplicate extrinsics * Remove ContractAccessWeight from runtime * Fix doc link * Remove leftover debugging output
This commit is contained in:
committed by
GitHub
parent
8f048cf522
commit
b135a0fae4
@@ -107,7 +107,7 @@ use crate::{
|
||||
};
|
||||
use codec::{Encode, HasCompact};
|
||||
use frame_support::{
|
||||
dispatch::{DispatchClass, Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo},
|
||||
dispatch::{Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo},
|
||||
ensure,
|
||||
traits::{
|
||||
tokens::fungible::Inspect, ConstU32, Contains, Currency, Get, Randomness,
|
||||
@@ -116,7 +116,7 @@ use frame_support::{
|
||||
weights::{OldWeight, Weight},
|
||||
BoundedVec, WeakBoundedVec,
|
||||
};
|
||||
use frame_system::{limits::BlockWeights, Pallet as System};
|
||||
use frame_system::Pallet as System;
|
||||
use pallet_contracts_primitives::{
|
||||
Code, CodeUploadResult, CodeUploadReturnValue, ContractAccessError, ContractExecResult,
|
||||
ContractInstantiateResult, ExecReturnValue, GetStorageResult, InstantiateReturnValue,
|
||||
@@ -199,29 +199,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A conservative implementation to be used for [`pallet::Config::ContractAccessWeight`].
|
||||
///
|
||||
/// This derives the weight from the [`BlockWeights`] passed as `B` and the `maxPovSize` passed
|
||||
/// as `P`. The default value for `P` is the `maxPovSize` used by Polkadot and Kusama.
|
||||
///
|
||||
/// It simply charges from the weight meter pro rata: If loading the contract code would consume
|
||||
/// 50% of the max storage proof then this charges 50% of the max block weight.
|
||||
pub struct DefaultContractAccessWeight<B: Get<BlockWeights>, const P: u32 = 5_242_880>(
|
||||
PhantomData<B>,
|
||||
);
|
||||
|
||||
impl<B: Get<BlockWeights>, const P: u32> Get<Weight> for DefaultContractAccessWeight<B, P> {
|
||||
fn get() -> Weight {
|
||||
let block_weights = B::get();
|
||||
block_weights
|
||||
.per_class
|
||||
.get(DispatchClass::Normal)
|
||||
.max_total
|
||||
.unwrap_or(block_weights.max_block) /
|
||||
u64::from(P)
|
||||
}
|
||||
}
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
@@ -334,27 +311,6 @@ pub mod pallet {
|
||||
#[pallet::constant]
|
||||
type DepositPerByte: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The weight per byte of code that is charged when loading a contract from storage.
|
||||
///
|
||||
/// Currently, FRAME only charges fees for computation incurred but not for PoV
|
||||
/// consumption caused for storage access. This is usually not exploitable because
|
||||
/// accessing storage carries some substantial weight costs, too. However in case
|
||||
/// of contract code very much PoV consumption can be caused while consuming very little
|
||||
/// computation. This could be used to keep the chain busy without paying the
|
||||
/// proper fee for it. Until this is resolved we charge from the weight meter for
|
||||
/// contract access.
|
||||
///
|
||||
/// For more information check out: <https://github.com/paritytech/substrate/issues/10301>
|
||||
///
|
||||
/// [`DefaultContractAccessWeight`] is a safe default to be used for Polkadot or Kusama
|
||||
/// parachains.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This is only relevant for parachains. Set to zero in case of a standalone chain.
|
||||
#[pallet::constant]
|
||||
type ContractAccessWeight: Get<Weight>;
|
||||
|
||||
/// The amount of balance a caller has to pay for each storage item.
|
||||
///
|
||||
/// # Note
|
||||
@@ -413,23 +369,8 @@ pub mod pallet {
|
||||
T::AccountId: AsRef<[u8]>,
|
||||
<BalanceOf<T> as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode,
|
||||
{
|
||||
/// Makes a call to an account, optionally transferring some balance.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `dest`: Address of the contract to call.
|
||||
/// * `value`: The balance to transfer from the `origin` to `dest`.
|
||||
/// * `gas_limit`: The gas limit enforced when executing the constructor.
|
||||
/// * `storage_deposit_limit`: The maximum amount of balance that can be charged from the
|
||||
/// caller to pay for the storage consumed.
|
||||
/// * `data`: The input data to pass to the contract.
|
||||
///
|
||||
/// * If the account is a smart-contract account, the associated code will be
|
||||
/// executed and any value will be transferred.
|
||||
/// * If the account is a regular account, any value will be transferred.
|
||||
/// * If no account exists and the call value is not less than `existential_deposit`,
|
||||
/// a regular account will be created and any value will be transferred.
|
||||
#[pallet::weight(T::WeightInfo::call().saturating_add((*gas_limit).into()))]
|
||||
/// Deprecated version if [`Self::call`] for use in an in-storage `Call`.
|
||||
#[pallet::weight(T::WeightInfo::call().saturating_add(<Pallet<T>>::compat_weight(*gas_limit)))]
|
||||
#[allow(deprecated)]
|
||||
#[deprecated(note = "1D weight is used in this extrinsic, please migrate to `call`")]
|
||||
pub fn call_old_weight(
|
||||
@@ -440,55 +381,20 @@ pub mod pallet {
|
||||
storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
|
||||
data: Vec<u8>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let gas_limit: Weight = gas_limit.into();
|
||||
let origin = ensure_signed(origin)?;
|
||||
let dest = T::Lookup::lookup(dest)?;
|
||||
let mut output = Self::internal_call(
|
||||
Self::call(
|
||||
origin,
|
||||
dest,
|
||||
value,
|
||||
gas_limit,
|
||||
storage_deposit_limit.map(Into::into),
|
||||
<Pallet<T>>::compat_weight(gas_limit),
|
||||
storage_deposit_limit,
|
||||
data,
|
||||
None,
|
||||
);
|
||||
if let Ok(retval) = &output.result {
|
||||
if retval.did_revert() {
|
||||
output.result = Err(<Error<T>>::ContractReverted.into());
|
||||
}
|
||||
}
|
||||
output.gas_meter.into_dispatch_result(output.result, T::WeightInfo::call())
|
||||
)
|
||||
}
|
||||
|
||||
/// Instantiates a new contract from the supplied `code` optionally transferring
|
||||
/// some balance.
|
||||
///
|
||||
/// This dispatchable has the same effect as calling [`Self::upload_code`] +
|
||||
/// [`Self::instantiate`]. Bundling them together provides efficiency gains. Please
|
||||
/// also check the documentation of [`Self::upload_code`].
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `value`: The balance to transfer from the `origin` to the newly created contract.
|
||||
/// * `gas_limit`: The gas limit enforced when executing the constructor.
|
||||
/// * `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved
|
||||
/// from the caller to pay for the storage consumed.
|
||||
/// * `code`: The contract code to deploy in raw bytes.
|
||||
/// * `data`: The input data to pass to the contract constructor.
|
||||
/// * `salt`: Used for the address derivation. See [`Pallet::contract_address`].
|
||||
///
|
||||
/// Instantiation is executed as follows:
|
||||
///
|
||||
/// - The supplied `code` is instrumented, deployed, and a `code_hash` is created for that
|
||||
/// code.
|
||||
/// - If the `code_hash` already exists on the chain the underlying `code` will be shared.
|
||||
/// - The destination address is computed based on the sender, code_hash and the salt.
|
||||
/// - The smart-contract account is created at the computed address.
|
||||
/// - The `value` is transferred to the new account.
|
||||
/// - The `deploy` function is executed in the context of the newly-created account.
|
||||
/// Deprecated version if [`Self::instantiate_with_code`] for use in an in-storage `Call`.
|
||||
#[pallet::weight(
|
||||
T::WeightInfo::instantiate_with_code(code.len() as u32, salt.len() as u32)
|
||||
.saturating_add((*gas_limit).into())
|
||||
.saturating_add(<Pallet<T>>::compat_weight(*gas_limit))
|
||||
)]
|
||||
#[allow(deprecated)]
|
||||
#[deprecated(
|
||||
@@ -503,38 +409,20 @@ pub mod pallet {
|
||||
data: Vec<u8>,
|
||||
salt: Vec<u8>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let gas_limit: Weight = gas_limit.into();
|
||||
let origin = ensure_signed(origin)?;
|
||||
let code_len = code.len() as u32;
|
||||
let salt_len = salt.len() as u32;
|
||||
let mut output = Self::internal_instantiate(
|
||||
Self::instantiate_with_code(
|
||||
origin,
|
||||
value,
|
||||
gas_limit,
|
||||
storage_deposit_limit.map(Into::into),
|
||||
Code::Upload(code),
|
||||
<Pallet<T>>::compat_weight(gas_limit),
|
||||
storage_deposit_limit,
|
||||
code,
|
||||
data,
|
||||
salt,
|
||||
None,
|
||||
);
|
||||
if let Ok(retval) = &output.result {
|
||||
if retval.1.did_revert() {
|
||||
output.result = Err(<Error<T>>::ContractReverted.into());
|
||||
}
|
||||
}
|
||||
output.gas_meter.into_dispatch_result(
|
||||
output.result.map(|(_address, result)| result),
|
||||
T::WeightInfo::instantiate_with_code(code_len, salt_len),
|
||||
)
|
||||
}
|
||||
|
||||
/// Instantiates a contract from a previously deployed wasm binary.
|
||||
///
|
||||
/// This function is identical to [`Self::instantiate_with_code`] but without the
|
||||
/// code deployment step. Instead, the `code_hash` of an on-chain deployed wasm binary
|
||||
/// must be supplied.
|
||||
/// Deprecated version if [`Self::instantiate`] for use in an in-storage `Call`.
|
||||
#[pallet::weight(
|
||||
T::WeightInfo::instantiate(salt.len() as u32).saturating_add((*gas_limit).into())
|
||||
T::WeightInfo::instantiate(salt.len() as u32).saturating_add(<Pallet<T>>::compat_weight(*gas_limit))
|
||||
)]
|
||||
#[allow(deprecated)]
|
||||
#[deprecated(note = "1D weight is used in this extrinsic, please migrate to `instantiate`")]
|
||||
@@ -547,27 +435,14 @@ pub mod pallet {
|
||||
data: Vec<u8>,
|
||||
salt: Vec<u8>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let gas_limit: Weight = gas_limit.into();
|
||||
let origin = ensure_signed(origin)?;
|
||||
let salt_len = salt.len() as u32;
|
||||
let mut output = Self::internal_instantiate(
|
||||
Self::instantiate(
|
||||
origin,
|
||||
value,
|
||||
gas_limit,
|
||||
storage_deposit_limit.map(Into::into),
|
||||
Code::Existing(code_hash),
|
||||
<Pallet<T>>::compat_weight(gas_limit),
|
||||
storage_deposit_limit,
|
||||
code_hash,
|
||||
data,
|
||||
salt,
|
||||
None,
|
||||
);
|
||||
if let Ok(retval) = &output.result {
|
||||
if retval.1.did_revert() {
|
||||
output.result = Err(<Error<T>>::ContractReverted.into());
|
||||
}
|
||||
}
|
||||
output.gas_meter.into_dispatch_result(
|
||||
output.result.map(|(_address, output)| output),
|
||||
T::WeightInfo::instantiate(salt_len),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1059,8 +934,8 @@ where
|
||||
);
|
||||
ContractExecResult {
|
||||
result: output.result.map_err(|r| r.error),
|
||||
gas_consumed: output.gas_meter.gas_consumed().ref_time(),
|
||||
gas_required: output.gas_meter.gas_required().ref_time(),
|
||||
gas_consumed: output.gas_meter.gas_consumed(),
|
||||
gas_required: output.gas_meter.gas_required(),
|
||||
storage_deposit: output.storage_deposit,
|
||||
debug_message: debug_message.unwrap_or_default(),
|
||||
}
|
||||
@@ -1104,8 +979,8 @@ where
|
||||
.result
|
||||
.map(|(account_id, result)| InstantiateReturnValue { result, account_id })
|
||||
.map_err(|e| e.error),
|
||||
gas_consumed: output.gas_meter.gas_consumed().ref_time(),
|
||||
gas_required: output.gas_meter.gas_required().ref_time(),
|
||||
gas_consumed: output.gas_meter.gas_consumed(),
|
||||
gas_required: output.gas_meter.gas_required(),
|
||||
storage_deposit: output.storage_deposit,
|
||||
debug_message: debug_message.unwrap_or_default(),
|
||||
}
|
||||
@@ -1287,4 +1162,12 @@ where
|
||||
fn min_balance() -> BalanceOf<T> {
|
||||
<T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
|
||||
}
|
||||
|
||||
/// Convert a 1D Weight to a 2D weight.
|
||||
///
|
||||
/// Used by backwards compatible extrinsics. We cannot just set the proof to zero
|
||||
/// or an old `Call` will just fail.
|
||||
fn compat_weight(gas_limit: OldWeight) -> Weight {
|
||||
Weight::from(gas_limit).set_proof_size(u64::from(T::MaxCodeLen::get()) * 2)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user