This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
contracts: Multi block migrations #14045
Merged
Merged
Changes from all commits
Commits
Show all changes
83 commits
Select commit
Hold shift + click to select a range
b878662
Frame Add translate_next
pgherveou 7ab5774
Move to lazy migration
athei e49f0ce
Updates
pgherveou 758902a
simplify MockMigration
pgherveou 3a9c925
wip
pgherveou c7aa478
wip
pgherveou c5d33ce
add bench
pgherveou a27b8bc
add bench
pgherveou d4eee87
fmt
pgherveou f5d9638
fix bench
pgherveou dc501ce
add .
pgherveou e6cd691
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
5db9beb
Apply suggestions from code review
pgherveou 1bd551e
Scalfold v10 / v11 fix tests
pgherveou d718995
PR comment
pgherveou 131cc45
tweak pub use
pgherveou 1f22230
wip
pgherveou f3f69c8
wip
pgherveou 1b07693
wip
pgherveou d8500b7
Merge branch 'master' into at/migration
pgherveou e561a69
misc merge master
pgherveou 2a57bff
Merge branch 'at/migration' into pg/migration
pgherveou 4e7a1f7
misc merge master
pgherveou b1dd6a1
Merge branch 'at/migration' into pg/migration
pgherveou db7b4e9
wip
pgherveou 3c08a37
rm tmp stuff
pgherveou e966c87
wip
pgherveou f1134c6
wip
pgherveou a85ff26
wip
pgherveou 87a8f3b
wip
pgherveou 193c788
wip
pgherveou aafaa03
fixes
pgherveou 0d84f28
add state
pgherveou be9bc81
wip
pgherveou 59bd209
wip
pgherveou 92ddfa0
wip
pgherveou 1221345
wip
pgherveou 8445ae7
wip
pgherveou 42e5b5b
wip
pgherveou 82ed2d1
wip
pgherveou dee4889
wip
pgherveou 6aff1bd
wip
pgherveou 4a7ec2e
wip
pgherveou f21b524
wip
pgherveou 42cf92c
wip
pgherveou 68ff246
wip
pgherveou bcd404b
wip
pgherveou 0a321db
fix
pgherveou 4b771b2
fixed compilation
pgherveou 7864d6c
clean up logs
pgherveou 2af1523
wip
pgherveou 4c4758b
Revert "Frame Add translate_next"
pgherveou 7f9b013
Merge branch 'master' into pg/migration
pgherveou 1194ad3
Fix v10 logic
pgherveou 657ac6e
Apply suggestions from code review
pgherveou 69734ae
wip
pgherveou 98f5df5
fixes
pgherveou 14b7102
exercise del_queue
pgherveou 59acab8
bump sample size
pgherveou 4a142bc
fmt
pgherveou 48cf78a
wip
pgherveou 14f078c
blank line
pgherveou 79b36b9
fix lint
pgherveou d954437
fix rustdoc job lint
pgherveou 9782bd9
PR comment do not use dangerous into()
pgherveou 82adfd8
Ad macros for updating mod visibility
pgherveou 25b2ec6
Add doc
pgherveou 453489f
Add max_weight to integrity_test
pgherveou 1ceb5e0
fix compilation
pgherveou 883f54f
Merge branch 'master' into pg/migration
pgherveou ab44573
Add no migration tests
pgherveou c87e1d7
Merge branch 'master' of https://github.com/paritytech/substrate into…
b8ee019
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
2081eae
fix clippy
pgherveou aaac768
PR review
pgherveou c2e587d
Update frame/contracts/src/lib.rs
pgherveou 0b690e9
Merge branch 'master' into pg/migration
pgherveou 1fc4035
Fix master merge
pgherveou c6ea2eb
Merge branch 'master' into pg/migration
pgherveou 0b9c16c
fix merge 2
pgherveou 25ada0f
fix tryruntime
pgherveou 7d5e934
fix lint
pgherveou de10f33
Merge branch 'master' into pg/migration
pgherveou File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -107,7 +107,10 @@ use crate::{ | |
| use codec::{Codec, Decode, Encode, HasCompact}; | ||
| use environmental::*; | ||
| use frame_support::{ | ||
| dispatch::{DispatchError, Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo, RawOrigin}, | ||
| dispatch::{ | ||
| DispatchError, Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo, RawOrigin, | ||
| WithPostDispatchInfo, | ||
| }, | ||
| ensure, | ||
| error::BadOrigin, | ||
| traits::{ | ||
|
|
@@ -120,18 +123,18 @@ use frame_support::{ | |
| use frame_system::{ensure_signed, pallet_prelude::OriginFor, EventRecord, Pallet as System}; | ||
| use pallet_contracts_primitives::{ | ||
| Code, CodeUploadResult, CodeUploadReturnValue, ContractAccessError, ContractExecResult, | ||
| ContractInstantiateResult, ExecReturnValue, GetStorageResult, InstantiateReturnValue, | ||
| StorageDeposit, | ||
| ContractInstantiateResult, ContractResult, ExecReturnValue, GetStorageResult, | ||
| InstantiateReturnValue, StorageDeposit, | ||
| }; | ||
| use scale_info::TypeInfo; | ||
| use smallvec::Array; | ||
| use sp_runtime::traits::{Convert, Hash, Saturating, StaticLookup}; | ||
| use sp_runtime::traits::{Convert, Hash, Saturating, StaticLookup, Zero}; | ||
| use sp_std::{fmt::Debug, marker::PhantomData, prelude::*}; | ||
|
|
||
| pub use crate::{ | ||
| address::{AddressGenerator, DefaultAddressGenerator}, | ||
| exec::Frame, | ||
| migration::Migration, | ||
| migration::{MigrateSequence, Migration, NoopMigration}, | ||
| pallet::*, | ||
| schedule::{HostFnWeights, InstructionWeights, Limits, Schedule}, | ||
| wasm::Determinism, | ||
|
|
@@ -179,7 +182,12 @@ pub mod pallet { | |
| use frame_system::pallet_prelude::*; | ||
|
|
||
| /// The current storage version. | ||
| const STORAGE_VERSION: StorageVersion = StorageVersion::new(9); | ||
| #[cfg(not(any(test, feature = "runtime-benchmarks")))] | ||
| const STORAGE_VERSION: StorageVersion = StorageVersion::new(11); | ||
|
|
||
| /// Hard coded storage version for running tests that depend on the current storage version. | ||
| #[cfg(any(test, feature = "runtime-benchmarks"))] | ||
| const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); | ||
|
|
||
| #[pallet::pallet] | ||
| #[pallet::storage_version(STORAGE_VERSION)] | ||
|
|
@@ -316,11 +324,22 @@ pub mod pallet { | |
| #[pallet::hooks] | ||
| impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> { | ||
| fn on_idle(_block: T::BlockNumber, remaining_weight: Weight) -> Weight { | ||
| use migration::MigrateResult::*; | ||
|
|
||
| let (result, weight) = Migration::<T>::migrate(remaining_weight); | ||
| let remaining_weight = remaining_weight.saturating_sub(weight); | ||
|
|
||
| if !matches!(result, Completed | NoMigrationInProgress) { | ||
| return weight | ||
| } | ||
|
|
||
| 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: | ||
|
|
@@ -499,6 +518,7 @@ pub mod pallet { | |
| storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>, | ||
| determinism: Determinism, | ||
| ) -> DispatchResult { | ||
| Migration::<T>::ensure_migrated()?; | ||
agryaznov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| let origin = ensure_signed(origin)?; | ||
| Self::bare_upload_code(origin, code, storage_deposit_limit.map(Into::into), determinism) | ||
| .map(|_| ()) | ||
|
|
@@ -514,6 +534,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 | ||
|
|
@@ -537,6 +558,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| { | ||
|
|
@@ -586,6 +608,7 @@ pub mod pallet { | |
| storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>, | ||
| data: Vec<u8>, | ||
| ) -> DispatchResultWithPostInfo { | ||
| Migration::<T>::ensure_migrated()?; | ||
| let common = CommonInput { | ||
| origin: Origin::from_runtime_origin(origin)?, | ||
| value, | ||
|
|
@@ -645,6 +668,7 @@ pub mod pallet { | |
| data: Vec<u8>, | ||
| salt: Vec<u8>, | ||
| ) -> DispatchResultWithPostInfo { | ||
| Migration::<T>::ensure_migrated()?; | ||
| let code_len = code.len() as u32; | ||
| let data_len = data.len() as u32; | ||
| let salt_len = salt.len() as u32; | ||
|
|
@@ -687,6 +711,7 @@ pub mod pallet { | |
| data: Vec<u8>, | ||
| salt: Vec<u8>, | ||
| ) -> DispatchResultWithPostInfo { | ||
| Migration::<T>::ensure_migrated()?; | ||
| let data_len = data.len() as u32; | ||
| let salt_len = salt.len() as u32; | ||
| let common = CommonInput { | ||
|
|
@@ -709,6 +734,33 @@ pub mod pallet { | |
| T::WeightInfo::instantiate(data_len, salt_len), | ||
| ) | ||
| } | ||
|
|
||
pgherveou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /// When a migration is in progress, this dispatchable can be used to run migration steps. | ||
| /// Calls that contribute to advancing the migration have their fees waived, as it's helpful | ||
| /// for the chain. Note that while the migration is in progress, the pallet will also | ||
| /// leverage the `on_idle` hooks to run migration steps. | ||
| #[pallet::call_index(9)] | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note from talk with Sasha: should we give a different DispatchClass to this call? |
||
| #[pallet::weight(T::WeightInfo::migrate().saturating_add(*weight_limit))] | ||
| pub fn migrate(origin: OriginFor<T>, weight_limit: Weight) -> DispatchResultWithPostInfo { | ||
| use migration::MigrateResult::*; | ||
| ensure_signed(origin)?; | ||
|
|
||
| let weight_limit = weight_limit.saturating_add(T::WeightInfo::migrate()); | ||
| let (result, weight) = Migration::<T>::migrate(weight_limit); | ||
|
|
||
| match result { | ||
| Completed => | ||
| Ok(PostDispatchInfo { actual_weight: Some(weight), pays_fee: Pays::No }), | ||
| InProgress { steps_done, .. } if steps_done > 0 => | ||
| Ok(PostDispatchInfo { actual_weight: Some(weight), pays_fee: Pays::No }), | ||
| InProgress { .. } => | ||
| Ok(PostDispatchInfo { actual_weight: Some(weight), pays_fee: Pays::Yes }), | ||
agryaznov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| NoMigrationInProgress | NoMigrationPerformed => { | ||
| let err: DispatchError = <Error<T>>::NoMigrationPerformed.into(); | ||
| Err(err.with_weight(T::WeightInfo::migrate())) | ||
| }, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[pallet::event] | ||
|
|
@@ -861,6 +913,10 @@ pub mod pallet { | |
| CodeRejected, | ||
| /// An indetermistic code was used in a context where this is not permitted. | ||
| Indeterministic, | ||
| /// A pending migration needs to complete before the extrinsic can be called. | ||
| MigrationInProgress, | ||
| /// Migrate dispatch call was attempted but no migration was performed. | ||
| NoMigrationPerformed, | ||
| } | ||
|
|
||
| /// A mapping from an original code hash to the original code, untouched by instrumentation. | ||
|
|
@@ -920,6 +976,10 @@ pub mod pallet { | |
| #[pallet::storage] | ||
| pub(crate) type DeletionQueueCounter<T: Config> = | ||
| StorageValue<_, DeletionQueueManager<T>, ValueQuery>; | ||
|
|
||
pgherveou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| #[pallet::storage] | ||
| pub(crate) type MigrationInProgress<T: Config> = | ||
| StorageValue<_, migration::Cursor, OptionQuery>; | ||
| } | ||
|
|
||
| /// The type of origins supported by the contracts pallet. | ||
|
|
@@ -1210,6 +1270,21 @@ impl<T: Config> Invokable<T> for InstantiateInput<T> { | |
| } | ||
| } | ||
|
|
||
| macro_rules! ensure_no_migration_in_progress { | ||
agryaznov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| () => { | ||
| if Migration::<T>::in_progress() { | ||
| return ContractResult { | ||
| gas_consumed: Zero::zero(), | ||
| gas_required: Zero::zero(), | ||
| storage_deposit: Default::default(), | ||
| debug_message: Vec::new(), | ||
| result: Err(Error::<T>::MigrationInProgress.into()), | ||
| events: None, | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| impl<T: Config> Pallet<T> { | ||
| /// Perform a call to a specified contract. | ||
| /// | ||
|
|
@@ -1234,6 +1309,8 @@ impl<T: Config> Pallet<T> { | |
| collect_events: CollectEvents, | ||
| determinism: Determinism, | ||
| ) -> ContractExecResult<BalanceOf<T>, EventRecordOf<T>> { | ||
| ensure_no_migration_in_progress!(); | ||
agryaznov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| let mut debug_message = if matches!(debug, DebugInfo::UnsafeDebug) { | ||
| Some(DebugBufferVec::<T>::default()) | ||
| } else { | ||
|
|
@@ -1290,6 +1367,8 @@ impl<T: Config> Pallet<T> { | |
| debug: DebugInfo, | ||
| collect_events: CollectEvents, | ||
| ) -> ContractInstantiateResult<T::AccountId, BalanceOf<T>, EventRecordOf<T>> { | ||
| ensure_no_migration_in_progress!(); | ||
|
|
||
| let mut debug_message = if debug == DebugInfo::UnsafeDebug { | ||
| Some(DebugBufferVec::<T>::default()) | ||
| } else { | ||
|
|
@@ -1333,6 +1412,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, | ||
|
|
@@ -1353,6 +1433,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 Migration::<T>::in_progress() { | ||
| return Err(ContractAccessError::MigrationInProgress) | ||
| } | ||
| let contract_info = | ||
| ContractInfoOf::<T>::get(&address).ok_or(ContractAccessError::DoesntExist)?; | ||
|
|
||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.