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 all 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 @@ -1162,7 +1162,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