mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 03:31:10 +00:00
contracts: Allow indeterministic instructions off-chain (#12469)
* Allow indetermistic instructions off-chain * Apply suggestions from code review Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * fmt Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
This commit is contained in:
committed by
GitHub
parent
d0dcf008ec
commit
3ae4be8662
@@ -32,65 +32,54 @@ use sp_std::{marker::PhantomData, prelude::*};
|
||||
pub struct Migration<T: Config>(PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for Migration<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let version = StorageVersion::get::<Pallet<T>>();
|
||||
let version = <Pallet<T>>::on_chain_storage_version();
|
||||
let mut weight = Weight::zero();
|
||||
|
||||
if version < 4 {
|
||||
weight = weight.saturating_add(v4::migrate::<T>());
|
||||
StorageVersion::new(4).put::<Pallet<T>>();
|
||||
v4::migrate::<T>(&mut weight);
|
||||
}
|
||||
|
||||
if version < 5 {
|
||||
weight = weight.saturating_add(v5::migrate::<T>());
|
||||
StorageVersion::new(5).put::<Pallet<T>>();
|
||||
v5::migrate::<T>(&mut weight);
|
||||
}
|
||||
|
||||
if version < 6 {
|
||||
weight = weight.saturating_add(v6::migrate::<T>());
|
||||
StorageVersion::new(6).put::<Pallet<T>>();
|
||||
v6::migrate::<T>(&mut weight);
|
||||
}
|
||||
|
||||
if version < 7 {
|
||||
weight = weight.saturating_add(v7::migrate::<T>());
|
||||
StorageVersion::new(7).put::<Pallet<T>>();
|
||||
v7::migrate::<T>(&mut weight);
|
||||
}
|
||||
|
||||
if version < 8 {
|
||||
weight = weight.saturating_add(v8::migrate::<T>());
|
||||
StorageVersion::new(8).put::<Pallet<T>>();
|
||||
v8::migrate::<T>(&mut weight);
|
||||
}
|
||||
|
||||
if version < 9 {
|
||||
v9::migrate::<T>(&mut weight);
|
||||
}
|
||||
|
||||
StorageVersion::new(9).put::<Pallet<T>>();
|
||||
weight.saturating_accrue(T::DbWeight::get().writes(1));
|
||||
|
||||
weight
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
let version = StorageVersion::get::<Pallet<T>>();
|
||||
let version = <Pallet<T>>::on_chain_storage_version();
|
||||
|
||||
if version < 7 {
|
||||
return Ok(vec![])
|
||||
}
|
||||
|
||||
if version < 8 {
|
||||
if version == 8 {
|
||||
v8::pre_upgrade::<T>()?;
|
||||
}
|
||||
|
||||
Ok(vec![])
|
||||
Ok(version.encode())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
let version = StorageVersion::get::<Pallet<T>>();
|
||||
|
||||
if version < 7 {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if version < 8 {
|
||||
v8::post_upgrade::<T>()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
let version = Decode::decode(&mut state.as_ref()).map_err(|_| "Cannot decode version")?;
|
||||
post_checks::post_upgrade::<T>(version)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,10 +87,10 @@ impl<T: Config> OnRuntimeUpgrade for Migration<T> {
|
||||
mod v4 {
|
||||
use super::*;
|
||||
|
||||
pub fn migrate<T: Config>() -> Weight {
|
||||
pub fn migrate<T: Config>(weight: &mut Weight) {
|
||||
#[allow(deprecated)]
|
||||
migration::remove_storage_prefix(<Pallet<T>>::name().as_bytes(), b"CurrentSchedule", b"");
|
||||
T::DbWeight::get().writes(1)
|
||||
weight.saturating_accrue(T::DbWeight::get().writes(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,11 +158,9 @@ mod v5 {
|
||||
#[storage_alias]
|
||||
type DeletionQueue<T: Config> = StorageValue<Pallet<T>, Vec<DeletedContract>>;
|
||||
|
||||
pub fn migrate<T: Config>() -> Weight {
|
||||
let mut weight = Weight::zero();
|
||||
|
||||
pub fn migrate<T: Config>(weight: &mut Weight) {
|
||||
<ContractInfoOf<T>>::translate(|_key, old: OldContractInfo<T>| {
|
||||
weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1));
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
|
||||
match old {
|
||||
OldContractInfo::Alive(old) => Some(ContractInfo::<T> {
|
||||
trie_id: old.trie_id,
|
||||
@@ -185,12 +172,10 @@ mod v5 {
|
||||
});
|
||||
|
||||
DeletionQueue::<T>::translate(|old: Option<Vec<OldDeletedContract>>| {
|
||||
weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1));
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
|
||||
old.map(|old| old.into_iter().map(|o| DeletedContract { trie_id: o.trie_id }).collect())
|
||||
})
|
||||
.ok();
|
||||
|
||||
weight
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,14 +199,14 @@ mod v6 {
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode)]
|
||||
struct PrefabWasmModule {
|
||||
pub struct PrefabWasmModule {
|
||||
#[codec(compact)]
|
||||
instruction_weights_version: u32,
|
||||
pub instruction_weights_version: u32,
|
||||
#[codec(compact)]
|
||||
initial: u32,
|
||||
pub initial: u32,
|
||||
#[codec(compact)]
|
||||
maximum: u32,
|
||||
code: Vec<u8>,
|
||||
pub maximum: u32,
|
||||
pub code: Vec<u8>,
|
||||
}
|
||||
|
||||
use v5::ContractInfo as OldContractInfo;
|
||||
@@ -258,11 +243,9 @@ mod v6 {
|
||||
#[storage_alias]
|
||||
type OwnerInfoOf<T: Config> = StorageMap<Pallet<T>, Identity, CodeHash<T>, OwnerInfo<T>>;
|
||||
|
||||
pub fn migrate<T: Config>() -> Weight {
|
||||
let mut weight = Weight::zero();
|
||||
|
||||
pub fn migrate<T: Config>(weight: &mut Weight) {
|
||||
<ContractInfoOf<T>>::translate(|_key, old: OldContractInfo<T>| {
|
||||
weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1));
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
|
||||
Some(ContractInfo::<T> {
|
||||
trie_id: old.trie_id,
|
||||
code_hash: old.code_hash,
|
||||
@@ -274,7 +257,7 @@ mod v6 {
|
||||
.expect("Infinite input; no dead input space; qed");
|
||||
|
||||
<CodeStorage<T>>::translate(|key, old: OldPrefabWasmModule| {
|
||||
weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 2));
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));
|
||||
<OwnerInfoOf<T>>::insert(
|
||||
key,
|
||||
OwnerInfo {
|
||||
@@ -290,8 +273,6 @@ mod v6 {
|
||||
code: old.code,
|
||||
})
|
||||
});
|
||||
|
||||
weight
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,14 +280,14 @@ mod v6 {
|
||||
mod v7 {
|
||||
use super::*;
|
||||
|
||||
pub fn migrate<T: Config>() -> Weight {
|
||||
pub fn migrate<T: Config>(weight: &mut Weight) {
|
||||
#[storage_alias]
|
||||
type AccountCounter<T: Config> = StorageValue<Pallet<T>, u64, ValueQuery>;
|
||||
#[storage_alias]
|
||||
type Nonce<T: Config> = StorageValue<Pallet<T>, u64, ValueQuery>;
|
||||
|
||||
Nonce::<T>::set(AccountCounter::<T>::take());
|
||||
T::DbWeight::get().reads_writes(1, 2)
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,23 +298,21 @@ mod v8 {
|
||||
use v6::ContractInfo as OldContractInfo;
|
||||
|
||||
#[derive(Encode, Decode)]
|
||||
struct ContractInfo<T: Config> {
|
||||
trie_id: TrieId,
|
||||
code_hash: CodeHash<T>,
|
||||
storage_bytes: u32,
|
||||
storage_items: u32,
|
||||
storage_byte_deposit: BalanceOf<T>,
|
||||
storage_item_deposit: BalanceOf<T>,
|
||||
storage_base_deposit: BalanceOf<T>,
|
||||
pub struct ContractInfo<T: Config> {
|
||||
pub trie_id: TrieId,
|
||||
pub code_hash: CodeHash<T>,
|
||||
pub storage_bytes: u32,
|
||||
pub storage_items: u32,
|
||||
pub storage_byte_deposit: BalanceOf<T>,
|
||||
pub storage_item_deposit: BalanceOf<T>,
|
||||
pub storage_base_deposit: BalanceOf<T>,
|
||||
}
|
||||
|
||||
#[storage_alias]
|
||||
type ContractInfoOf<T: Config, V> =
|
||||
StorageMap<Pallet<T>, Twox64Concat, <T as frame_system::Config>::AccountId, V>;
|
||||
|
||||
pub fn migrate<T: Config>() -> Weight {
|
||||
let mut weight = Weight::zero();
|
||||
|
||||
pub fn migrate<T: Config>(weight: &mut Weight) {
|
||||
<ContractInfoOf<T, ContractInfo<T>>>::translate_values(|old: OldContractInfo<T>| {
|
||||
// Count storage items of this contract
|
||||
let mut storage_bytes = 0u32;
|
||||
@@ -359,8 +338,9 @@ mod v8 {
|
||||
|
||||
// Reads: One read for each storage item plus the contract info itself.
|
||||
// Writes: Only the new contract info.
|
||||
weight = weight
|
||||
.saturating_add(T::DbWeight::get().reads_writes(u64::from(storage_items) + 1, 1));
|
||||
weight.saturating_accrue(
|
||||
T::DbWeight::get().reads_writes(u64::from(storage_items) + 1, 1),
|
||||
);
|
||||
|
||||
Some(ContractInfo {
|
||||
trie_id: old.trie_id,
|
||||
@@ -372,8 +352,6 @@ mod v8 {
|
||||
storage_base_deposit,
|
||||
})
|
||||
});
|
||||
|
||||
weight
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
@@ -385,9 +363,78 @@ mod v8 {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
pub fn post_upgrade<T: Config>() -> Result<(), &'static str> {
|
||||
/// Update `CodeStorage` with the new `determinism` field.
|
||||
mod v9 {
|
||||
use super::*;
|
||||
use crate::Determinism;
|
||||
use v6::PrefabWasmModule as OldPrefabWasmModule;
|
||||
|
||||
#[derive(Encode, Decode)]
|
||||
pub struct PrefabWasmModule {
|
||||
#[codec(compact)]
|
||||
pub instruction_weights_version: u32,
|
||||
#[codec(compact)]
|
||||
pub initial: u32,
|
||||
#[codec(compact)]
|
||||
pub maximum: u32,
|
||||
pub code: Vec<u8>,
|
||||
pub determinism: Determinism,
|
||||
}
|
||||
|
||||
#[storage_alias]
|
||||
type CodeStorage<T: Config> = StorageMap<Pallet<T>, Identity, CodeHash<T>, PrefabWasmModule>;
|
||||
|
||||
pub fn migrate<T: Config>(weight: &mut Weight) {
|
||||
<CodeStorage<T>>::translate_values(|old: OldPrefabWasmModule| {
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
|
||||
Some(PrefabWasmModule {
|
||||
instruction_weights_version: old.instruction_weights_version,
|
||||
initial: old.initial,
|
||||
maximum: old.maximum,
|
||||
code: old.code,
|
||||
determinism: Determinism::Deterministic,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Post checks always need to be run against the latest storage version. This is why we
|
||||
// do not scope them in the per version modules. They always need to be ported to the latest
|
||||
// version.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
mod post_checks {
|
||||
use super::*;
|
||||
use crate::Determinism;
|
||||
use sp_io::default_child_storage as child;
|
||||
use v8::ContractInfo;
|
||||
use v9::PrefabWasmModule;
|
||||
|
||||
#[storage_alias]
|
||||
type CodeStorage<T: Config> = StorageMap<Pallet<T>, Identity, CodeHash<T>, PrefabWasmModule>;
|
||||
|
||||
#[storage_alias]
|
||||
type ContractInfoOf<T: Config, V> =
|
||||
StorageMap<Pallet<T>, Twox64Concat, <T as frame_system::Config>::AccountId, V>;
|
||||
|
||||
pub fn post_upgrade<T: Config>(old_version: StorageVersion) -> Result<(), &'static str> {
|
||||
if old_version < 7 {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if old_version < 8 {
|
||||
v8::<T>()?;
|
||||
}
|
||||
|
||||
if old_version < 9 {
|
||||
v9::<T>()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn v8<T: Config>() -> Result<(), &'static str> {
|
||||
use frame_support::traits::ReservableCurrency;
|
||||
for (key, value) in ContractInfoOf::<T, ContractInfo<T>>::iter() {
|
||||
let reserved = T::Currency::reserved_balance(&key);
|
||||
@@ -413,4 +460,14 @@ mod v8 {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn v9<T: Config>() -> Result<(), &'static str> {
|
||||
for value in CodeStorage::<T>::iter_values() {
|
||||
ensure!(
|
||||
value.determinism == Determinism::Deterministic,
|
||||
"All pre-existing codes need to be deterministic."
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user