mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 00:01:09 +00:00
contracts: Use proof_size from benchmarks (#13268)
* Avoid reading contract code when it is supplied in the extrinsic * Remove custom proof size injection from schedule * Set benchmarks pov_mode to Measure * Reduce overestimation of code size on re-instrument * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Do not override proof size from benchmark * Do not charge proof size for basic block * Incrase gas limit for tests * Fix deletion queue to also use `proof_size` * Fix tests * Update frame/contracts/src/schedule.rs Co-authored-by: Cyrill Leutwiler <bigcyrill@hotmail.com> * Fix wrong schedule macro invocations * Remove stale docs * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Handle zero components * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Fix instruction weight --------- Co-authored-by: command-bot <> Co-authored-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
committed by
GitHub
parent
3c0d8fe149
commit
1c04ab0f6f
@@ -50,53 +50,61 @@ use sp_std::vec;
|
||||
/// under the specified `code_hash`.
|
||||
pub fn store<T: Config>(mut module: PrefabWasmModule<T>, instantiated: bool) -> DispatchResult {
|
||||
let code_hash = sp_std::mem::take(&mut module.code_hash);
|
||||
<CodeStorage<T>>::mutate(&code_hash, |existing| match existing {
|
||||
Some(existing) => {
|
||||
// We instrument any uploaded contract anyways. We might as well store it to save
|
||||
// a potential re-instrumentation later.
|
||||
existing.code = module.code;
|
||||
existing.instruction_weights_version = module.instruction_weights_version;
|
||||
// When the code was merely uploaded but not instantiated we can skip this.
|
||||
if instantiated {
|
||||
<OwnerInfoOf<T>>::mutate(&code_hash, |owner_info| {
|
||||
if let Some(owner_info) = owner_info {
|
||||
owner_info.refcount = owner_info.refcount.checked_add(1).expect(
|
||||
"
|
||||
refcount is 64bit. Generating this overflow would require to store
|
||||
_at least_ 18 exabyte of data assuming that a contract consumes only
|
||||
one byte of data. Any node would run out of storage space before hitting
|
||||
this overflow.
|
||||
qed
|
||||
",
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
None => {
|
||||
let orig_code = module.original_code.take().expect(
|
||||
"
|
||||
<OwnerInfoOf<T>>::mutate(&code_hash, |owner_info| {
|
||||
match owner_info {
|
||||
// Instantiate existing contract.
|
||||
//
|
||||
// No need to update the `CodeStorage` as any re-instrumentation eagerly saves
|
||||
// the re-instrumented code.
|
||||
Some(owner_info) if instantiated => {
|
||||
owner_info.refcount = owner_info.refcount.checked_add(1).expect(
|
||||
"
|
||||
refcount is 64bit. Generating this overflow would require to store
|
||||
_at least_ 18 exabyte of data assuming that a contract consumes only
|
||||
one byte of data. Any node would run out of storage space before hitting
|
||||
this overflow.
|
||||
qed
|
||||
",
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
// Re-upload existing contract without executing it.
|
||||
//
|
||||
// We are careful here to just overwrite the code to not include it into the PoV.
|
||||
// We do this because the uploaded code was instrumented with the latest schedule
|
||||
// and hence we persist those changes. Otherwise the next execution will pay again
|
||||
// for the instrumentation.
|
||||
Some(_) => {
|
||||
<CodeStorage<T>>::insert(&code_hash, module);
|
||||
Ok(())
|
||||
},
|
||||
// Upload a new contract.
|
||||
//
|
||||
// We need to write all data structures and collect the deposit.
|
||||
None => {
|
||||
let orig_code = module.original_code.take().expect(
|
||||
"
|
||||
If an executable isn't in storage it was uploaded.
|
||||
If it was uploaded the original code must exist. qed
|
||||
",
|
||||
);
|
||||
let mut owner_info = module.owner_info.take().expect(
|
||||
"If an executable isn't in storage it was uploaded.
|
||||
);
|
||||
let mut new_owner_info = module.owner_info.take().expect(
|
||||
"If an executable isn't in storage it was uploaded.
|
||||
If it was uploaded the owner info was generated and attached. qed
|
||||
",
|
||||
);
|
||||
// This `None` case happens only in freshly uploaded modules. This means that
|
||||
// the `owner` is always the origin of the current transaction.
|
||||
T::Currency::reserve(&owner_info.owner, owner_info.deposit)
|
||||
.map_err(|_| <Error<T>>::StorageDepositNotEnoughFunds)?;
|
||||
owner_info.refcount = if instantiated { 1 } else { 0 };
|
||||
<PristineCode<T>>::insert(&code_hash, orig_code);
|
||||
<OwnerInfoOf<T>>::insert(&code_hash, owner_info);
|
||||
*existing = Some(module);
|
||||
<Pallet<T>>::deposit_event(vec![code_hash], Event::CodeStored { code_hash });
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
// This `None` case happens only in freshly uploaded modules. This means that
|
||||
// the `owner` is always the origin of the current transaction.
|
||||
T::Currency::reserve(&new_owner_info.owner, new_owner_info.deposit)
|
||||
.map_err(|_| <Error<T>>::StorageDepositNotEnoughFunds)?;
|
||||
new_owner_info.refcount = if instantiated { 1 } else { 0 };
|
||||
<PristineCode<T>>::insert(&code_hash, orig_code);
|
||||
<CodeStorage<T>>::insert(&code_hash, module);
|
||||
*owner_info = Some(new_owner_info);
|
||||
<Pallet<T>>::deposit_event(vec![code_hash], Event::CodeStored { code_hash });
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -162,15 +170,16 @@ pub fn load<T: Config>(
|
||||
let charged = gas_meter.charge(CodeToken::Load(max_code_len))?;
|
||||
|
||||
let mut prefab_module = <CodeStorage<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
|
||||
gas_meter.adjust_gas(charged, CodeToken::Load(prefab_module.code.len() as u32));
|
||||
let instrumented_code_len = prefab_module.code.len() as u32;
|
||||
gas_meter.adjust_gas(charged, CodeToken::Load(instrumented_code_len));
|
||||
prefab_module.code_hash = code_hash;
|
||||
|
||||
if prefab_module.instruction_weights_version < schedule.instruction_weights.version {
|
||||
// The instruction weights have changed.
|
||||
// We need to re-instrument the code with the new instruction weights.
|
||||
let charged = gas_meter.charge(CodeToken::Reinstrument(max_code_len))?;
|
||||
let code_size = reinstrument(&mut prefab_module, schedule)?;
|
||||
gas_meter.adjust_gas(charged, CodeToken::Reinstrument(code_size));
|
||||
let charged = gas_meter.charge(CodeToken::Reinstrument(instrumented_code_len))?;
|
||||
let orig_code_len = reinstrument(&mut prefab_module, schedule)?;
|
||||
gas_meter.adjust_gas(charged, CodeToken::Reinstrument(orig_code_len));
|
||||
}
|
||||
|
||||
Ok(prefab_module)
|
||||
@@ -224,8 +233,7 @@ impl<T: Config> Token<T> for CodeToken {
|
||||
match *self {
|
||||
Reinstrument(len) => T::WeightInfo::reinstrument(len),
|
||||
Load(len) => T::WeightInfo::call_with_code_per_byte(len)
|
||||
.saturating_sub(T::WeightInfo::call_with_code_per_byte(0))
|
||||
.set_proof_size(len.into()),
|
||||
.saturating_sub(T::WeightInfo::call_with_code_per_byte(0)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ pub use crate::wasm::{
|
||||
use crate::{
|
||||
exec::{ExecResult, Executable, ExportedFunction, Ext},
|
||||
gas::GasMeter,
|
||||
AccountIdOf, BalanceOf, CodeHash, CodeStorage, CodeVec, Config, Error, RelaxedCodeVec,
|
||||
AccountIdOf, BalanceOf, CodeHash, CodeVec, Config, Error, OwnerInfoOf, RelaxedCodeVec,
|
||||
Schedule,
|
||||
};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
@@ -191,7 +191,7 @@ impl<T: Config> PrefabWasmModule<T> {
|
||||
/// Returns `0` if the module is already in storage and hence no deposit will
|
||||
/// be charged when storing it.
|
||||
pub fn open_deposit(&self) -> BalanceOf<T> {
|
||||
if <CodeStorage<T>>::contains_key(&self.code_hash) {
|
||||
if <OwnerInfoOf<T>>::contains_key(&self.code_hash) {
|
||||
0u32.into()
|
||||
} else {
|
||||
// Only already in-storage contracts have their `owner_info` set to `None`.
|
||||
|
||||
Reference in New Issue
Block a user