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

Commit

Permalink
Move to lazy migration
Browse files Browse the repository at this point in the history
  • Loading branch information
athei authored and pgherveou committed Apr 28, 2023
1 parent 8da2fca commit a4713fc
Show file tree
Hide file tree
Showing 5 changed files with 372 additions and 406 deletions.
14 changes: 14 additions & 0 deletions frame/contracts/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ pub enum ContractAccessError {
DoesntExist,
/// Storage key cannot be decoded from the provided input data.
KeyDecodingFailed,
/// Storage is migrating. Try again later.
MigrationInProgress,
}

impl<T, B: Zero> From<DispatchError> for ContractResult<Result<T, DispatchError>, B> {
fn from(error: DispatchError) -> Self {
ContractResult {
gas_consumed: Zero::zero(),
gas_required: Zero::zero(),
storage_deposit: Default::default(),
debug_message: Vec::new(),
result: Err(error),
}
}
}

bitflags! {
Expand Down
41 changes: 40 additions & 1 deletion frame/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ use crate::{
use codec::{Codec, Encode, HasCompact};
use environmental::*;
use frame_support::{
dispatch::{Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo},
dispatch::{Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo, WithPostDispatchInfo},
ensure,
traits::{
tokens::fungible::Inspect, ConstU32, Contains, Currency, Get, Randomness,
Expand Down Expand Up @@ -314,11 +314,17 @@ pub mod pallet {
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_idle(_block: T::BlockNumber, remaining_weight: Weight) -> Weight {
// TODO: run migration here
if Migration::<T>::ensure_migrated().is_err() {
return T::DbWeight::get().reads(1)
}
ContractInfo::<T>::process_deletion_queue_batch(remaining_weight)
.saturating_add(T::WeightInfo::on_process_deletion_queue_batch())
}

fn integrity_test() {
Migration::<T>::integrity_test();

// Total runtime memory limit
let max_runtime_mem: u32 = T::Schedule::get().limits.runtime_memory;
// Memory limits for a single contract:
Expand Down Expand Up @@ -497,6 +503,7 @@ pub mod pallet {
storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
determinism: Determinism,
) -> DispatchResult {
Migration::<T>::ensure_migrated()?;
let origin = ensure_signed(origin)?;
Self::bare_upload_code(origin, code, storage_deposit_limit.map(Into::into), determinism)
.map(|_| ())
Expand All @@ -512,6 +519,7 @@ pub mod pallet {
origin: OriginFor<T>,
code_hash: CodeHash<T>,
) -> DispatchResultWithPostInfo {
Migration::<T>::ensure_migrated()?;
let origin = ensure_signed(origin)?;
<PrefabWasmModule<T>>::remove(&origin, code_hash)?;
// we waive the fee because removing unused code is beneficial
Expand All @@ -535,6 +543,7 @@ pub mod pallet {
dest: AccountIdLookupOf<T>,
code_hash: CodeHash<T>,
) -> DispatchResult {
Migration::<T>::ensure_migrated()?;
ensure_root(origin)?;
let dest = T::Lookup::lookup(dest)?;
<ContractInfoOf<T>>::try_mutate(&dest, |contract| {
Expand Down Expand Up @@ -584,6 +593,7 @@ pub mod pallet {
storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
data: Vec<u8>,
) -> DispatchResultWithPostInfo {
Migration::<T>::ensure_migrated()?;
let gas_limit: Weight = gas_limit.into();
let origin = ensure_signed(origin)?;
let dest = T::Lookup::lookup(dest)?;
Expand Down Expand Up @@ -645,6 +655,7 @@ pub mod pallet {
data: Vec<u8>,
salt: Vec<u8>,
) -> DispatchResultWithPostInfo {
Migration::<T>::ensure_migrated()?;
let origin = ensure_signed(origin)?;
let code_len = code.len() as u32;
let data_len = data.len() as u32;
Expand Down Expand Up @@ -688,6 +699,7 @@ pub mod pallet {
data: Vec<u8>,
salt: Vec<u8>,
) -> DispatchResultWithPostInfo {
Migration::<T>::ensure_migrated()?;
let origin = ensure_signed(origin)?;
let data_len = data.len() as u32;
let salt_len = salt.len() as u32;
Expand All @@ -711,6 +723,17 @@ pub mod pallet {
T::WeightInfo::instantiate(data_len, salt_len),
)
}

/// TODO: add benchmark for base weight
/// TODO: add a minimum weight limit so that people don't spam small free extrinsics
#[pallet::call_index(9)]
#[pallet::weight(*weight_limit)]
pub fn migrate(origin: OriginFor<T>, weight_limit: Weight) -> DispatchResultWithPostInfo {
ensure_signed(origin)?;
Migration::<T>::migrate(weight_limit)
.map(|weight| PostDispatchInfo { actual_weight: Some(weight), pays_fee: Pays::No })
.map_err(|(weight, error)| error.with_weight(weight))
}
}

#[pallet::event]
Expand Down Expand Up @@ -863,6 +886,8 @@ pub mod pallet {
CodeRejected,
/// An indetermistic code was used in a context where this is not permitted.
Indeterministic,
MigrationInProgress,
NoMigrationPerformed,
}

/// A mapping from an original code hash to the original code, untouched by instrumentation.
Expand Down Expand Up @@ -922,6 +947,10 @@ pub mod pallet {
#[pallet::storage]
pub(crate) type DeletionQueueCounter<T: Config> =
StorageValue<_, DeletionQueueManager<T>, ValueQuery>;

#[pallet::storage]
pub(crate) type MigrationInProgress<T: Config> =
StorageValue<_, migration::Cursor, OptionQuery>;
}

/// Context of a contract invocation.
Expand Down Expand Up @@ -1137,6 +1166,9 @@ impl<T: Config> Pallet<T> {
debug: bool,
determinism: Determinism,
) -> ContractExecResult<BalanceOf<T>> {
if let Err(err) = Migration::<T>::ensure_migrated() {
return err.into()
}
let mut debug_message = if debug { Some(DebugBufferVec::<T>::default()) } else { None };
let common = CommonInput {
origin,
Expand Down Expand Up @@ -1178,6 +1210,9 @@ impl<T: Config> Pallet<T> {
salt: Vec<u8>,
debug: bool,
) -> ContractInstantiateResult<T::AccountId, BalanceOf<T>> {
if let Err(err) = Migration::<T>::ensure_migrated() {
return err.into()
}
let mut debug_message = if debug { Some(DebugBufferVec::<T>::default()) } else { None };
let common = CommonInput {
origin,
Expand Down Expand Up @@ -1210,6 +1245,7 @@ impl<T: Config> Pallet<T> {
storage_deposit_limit: Option<BalanceOf<T>>,
determinism: Determinism,
) -> CodeUploadResult<CodeHash<T>, BalanceOf<T>> {
Migration::<T>::ensure_migrated()?;
let schedule = T::Schedule::get();
let module = PrefabWasmModule::from_code(
code,
Expand All @@ -1230,6 +1266,9 @@ impl<T: Config> Pallet<T> {

/// Query storage of a specified contract under a specified key.
pub fn get_storage(address: T::AccountId, key: Vec<u8>) -> GetStorageResult {
if let Err(_) = Migration::<T>::ensure_migrated() {
return Err(ContractAccessError::MigrationInProgress)
}
let contract_info =
ContractInfoOf::<T>::get(&address).ok_or(ContractAccessError::DoesntExist)?;

Expand Down
Loading

0 comments on commit a4713fc

Please sign in to comment.