Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

contracts: Use WeakBoundedVec for instrumented code #12186

Merged
merged 4 commits into from
Sep 19, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,6 @@ impl pallet_contracts::Config for Runtime {
type AddressGenerator = pallet_contracts::DefaultAddressGenerator;
type ContractAccessWeight = pallet_contracts::DefaultContractAccessWeight<RuntimeBlockWeights>;
type MaxCodeLen = ConstU32<{ 128 * 1024 }>;
type RelaxedMaxCodeLen = ConstU32<{ 256 * 1024 }>;
type MaxStorageKeyLen = ConstU32<128>;
}

Expand Down
13 changes: 2 additions & 11 deletions frame/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ use frame_support::{
ensure,
traits::{ConstU32, Contains, Currency, Get, Randomness, ReservableCurrency, Time},
weights::Weight,
BoundedVec,
BoundedVec, WeakBoundedVec,
};
use frame_system::{limits::BlockWeights, Pallet as System};
use pallet_contracts_primitives::{
Expand All @@ -135,7 +135,7 @@ 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>;
type RelaxedCodeVec<T> = WeakBoundedVec<u8, <T as Config>::MaxCodeLen>;
type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;

/// Used as a sentinel value when reading and writing contract memory.
Expand Down Expand Up @@ -366,15 +366,6 @@ pub mod pallet {
/// 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>;

/// The maximum allowable length in bytes for storage keys.
type MaxStorageKeyLen: Get<u32>;
}
Expand Down
1 change: 0 additions & 1 deletion frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,6 @@ impl Config for Test {
type AddressGenerator = DefaultAddressGenerator;
type ContractAccessWeight = DefaultContractAccessWeight<BlockWeights>;
type MaxCodeLen = ConstU32<{ 128 * 1024 }>;
type RelaxedMaxCodeLen = ConstU32<{ 256 * 1024 }>;
type MaxStorageKeyLen = ConstU32<128>;
}

Expand Down
14 changes: 10 additions & 4 deletions frame/contracts/src/wasm/code_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use frame_support::{
dispatch::{DispatchError, DispatchResult},
ensure,
traits::{Get, ReservableCurrency},
WeakBoundedVec,
};
use sp_core::crypto::UncheckedFrom;
use sp_runtime::traits::BadOrigin;
Expand Down Expand Up @@ -195,10 +196,15 @@ pub fn reinstrument<T: Config>(
let original_code =
<PristineCode<T>>::get(&prefab_module.code_hash).ok_or(Error::<T>::CodeNotFound)?;
let original_code_len = original_code.len();
prefab_module.code = prepare::reinstrument_contract::<T>(&original_code, schedule)
.map_err(|_| <Error<T>>::CodeRejected)?
.try_into()
.map_err(|_| <Error<T>>::CodeTooLarge)?;
// We need to allow contracts growing too big after re-instrumentation. Otherwise
// the contract can become inaccessible. The user has no influence over this size
// as the contract is already deployed and every change in size would be the result
// of changes in the instrumentation algorithm controlled by the chain authors.
prefab_module.code = WeakBoundedVec::force_from(
prepare::reinstrument_contract::<T>(&original_code, schedule)
.map_err(|_| <Error<T>>::CodeRejected)?,
Some("Contract exceeds limit after re-instrumentation."),
);
prefab_module.instruction_weights_version = schedule.instruction_weights.version;
<CodeStorage<T>>::insert(&prefab_module.code_hash, &*prefab_module);
Ok(original_code_len as u32)
Expand Down
12 changes: 1 addition & 11 deletions frame/contracts/src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ use crate::{
Schedule,
};
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{
dispatch::{DispatchError, DispatchResult},
ensure,
traits::Get,
};
use frame_support::dispatch::{DispatchError, DispatchResult};
use sp_core::crypto::UncheckedFrom;
use sp_sandbox::{SandboxEnvironmentBuilder, SandboxInstance, SandboxMemory};
use sp_std::prelude::*;
Expand Down Expand Up @@ -134,12 +130,6 @@ where
schedule,
owner,
)?;
// When instrumenting a new code we apply a stricter limit than enforced by the
// `RelaxedCodeVec` in order to leave some headroom for reinstrumentation.
ensure!(
module.code.len() as u32 <= T::MaxCodeLen::get(),
(<Error<T>>::CodeTooLarge.into(), ""),
);
Ok(module)
}

Expand Down