contracts: Get rid of #[pallet::without_storage_info] (#11414)

* Implement `MaxEncodeLen` for pallet-contracts storage

* Remove redundant debug println

* Move code len check to PrefabWasmModule::from_code
This commit is contained in:
Alexander Theißen
2022-05-18 09:40:53 +02:00
committed by GitHub
parent fe4acb7924
commit ef46d84aed
9 changed files with 99 additions and 67 deletions
+26 -17
View File
@@ -114,8 +114,9 @@ use codec::{Encode, HasCompact};
use frame_support::{
dispatch::Dispatchable,
ensure,
traits::{Contains, Currency, Get, Randomness, ReservableCurrency, Time},
traits::{ConstU32, Contains, Currency, Get, Randomness, ReservableCurrency, Time},
weights::{DispatchClass, GetDispatchInfo, Pays, PostDispatchInfo, Weight},
BoundedVec,
};
use frame_system::{limits::BlockWeights, Pallet as System};
use pallet_contracts_primitives::{
@@ -129,9 +130,11 @@ use sp_runtime::traits::{Convert, Hash, Saturating, StaticLookup};
use sp_std::{fmt::Debug, marker::PhantomData, prelude::*};
type CodeHash<T> = <T as frame_system::Config>::Hash;
type TrieId = Vec<u8>;
type TrieId = BoundedVec<u8, ConstU32<128>>;
type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
type CodeVec<T> = BoundedVec<u8, <T as Config>::MaxCodeLen>;
type RelaxedCodeVec<T> = BoundedVec<u8, <T as Config>::RelaxedMaxCodeLen>;
/// Used as a sentinel value when reading and writing contract memory.
///
@@ -224,7 +227,6 @@ pub mod pallet {
#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
#[pallet::without_storage_info]
pub struct Pallet<T>(PhantomData<T>);
#[pallet::config]
@@ -356,6 +358,20 @@ pub mod pallet {
/// The address generator used to generate the addresses of contracts.
type AddressGenerator: AddressGenerator<Self>;
/// The maximum length of a contract code in bytes. This limit applies to the instrumented
/// version of the code. Therefore `instantiate_with_code` can fail even when supplying
/// a wasm binary below this maximum size.
type MaxCodeLen: Get<u32>;
/// The maximum length of a contract code after reinstrumentation.
///
/// When uploading a new contract the size defined by [`Self::MaxCodeLen`] is used for both
/// the pristine **and** the instrumented version. When a existing contract needs to be
/// reinstrumented after a runtime upgrade we apply this bound. The reason is that if the
/// new instrumentation increases the size beyond the limit it would make that contract
/// inaccessible until rectified by another runtime upgrade.
type RelaxedMaxCodeLen: Get<u32>;
}
#[pallet::hooks]
@@ -698,7 +714,7 @@ pub mod pallet {
/// A mapping from an original code hash to the original code, untouched by instrumentation.
#[pallet::storage]
pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, CodeHash<T>, Vec<u8>>;
pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, CodeHash<T>, CodeVec<T>>;
/// A mapping between an original code hash and instrumented wasm code, ready for execution.
#[pallet::storage]
@@ -746,7 +762,8 @@ pub mod pallet {
/// Child trie deletion is a heavy operation depending on the amount of storage items
/// stored in said trie. Therefore this operation is performed lazily in `on_initialize`.
#[pallet::storage]
pub(crate) type DeletionQueue<T: Config> = StorageValue<_, Vec<DeletedContract>, ValueQuery>;
pub(crate) type DeletionQueue<T: Config> =
StorageValue<_, BoundedVec<DeletedContract, T::DeletionQueueDepth>, ValueQuery>;
}
/// Return type of the private [`Pallet::internal_call`] function.
@@ -864,8 +881,8 @@ where
storage_deposit_limit: Option<BalanceOf<T>>,
) -> CodeUploadResult<CodeHash<T>, BalanceOf<T>> {
let schedule = T::Schedule::get();
let module = PrefabWasmModule::from_code(code, &schedule, origin)
.map_err(|_| <Error<T>>::CodeRejected)?;
let module =
PrefabWasmModule::from_code(code, &schedule, origin).map_err(|(err, _)| err)?;
let deposit = module.open_deposit();
if let Some(storage_deposit_limit) = storage_deposit_limit {
ensure!(storage_deposit_limit >= deposit, <Error<T>>::StorageDepositLimitExhausted);
@@ -971,19 +988,11 @@ where
let schedule = T::Schedule::get();
let (extra_deposit, executable) = match code {
Code::Upload(Bytes(binary)) => {
ensure!(
binary.len() as u32 <= schedule.limits.code_len,
<Error<T>>::CodeTooLarge
);
let executable = PrefabWasmModule::from_code(binary, &schedule, origin.clone())
.map_err(|msg| {
.map_err(|(err, msg)| {
debug_message.as_mut().map(|buffer| buffer.extend(msg.as_bytes()));
<Error<T>>::CodeRejected
err
})?;
ensure!(
executable.code_len() <= schedule.limits.code_len,
<Error<T>>::CodeTooLarge
);
// The open deposit will be charged during execution when the
// uploaded module does not already exist. This deposit is not part of the
// storage meter because it is not transfered to the contract but