mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-16 23:41:02 +00:00
Contracts: Refactor API to use WeightMeter (#2943)
Update the Contracts API to use `WeightMeter`, as it simplifies the code and makes it easier to reason about, rather than taking a mutable weight or returning a tuple with the weight consumed --------- Co-authored-by: Alexander Theißen <alex.theissen@me.com>
This commit is contained in:
@@ -28,7 +28,7 @@ use crate::{
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::{
|
||||
storage::child::{self, ChildInfo},
|
||||
weights::Weight,
|
||||
weights::{Weight, WeightMeter},
|
||||
CloneNoBound, DefaultNoBound,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
@@ -279,14 +279,15 @@ impl<T: Config> ContractInfo<T> {
|
||||
|
||||
/// Calculates the weight that is necessary to remove one key from the trie and how many
|
||||
/// of those keys can be deleted from the deletion queue given the supplied weight limit.
|
||||
pub fn deletion_budget(weight_limit: Weight) -> (Weight, u32) {
|
||||
pub fn deletion_budget(meter: &WeightMeter) -> (Weight, u32) {
|
||||
let base_weight = T::WeightInfo::on_process_deletion_queue_batch();
|
||||
let weight_per_key = T::WeightInfo::on_initialize_per_trie_key(1) -
|
||||
T::WeightInfo::on_initialize_per_trie_key(0);
|
||||
|
||||
// `weight_per_key` being zero makes no sense and would constitute a failure to
|
||||
// benchmark properly. We opt for not removing any keys at all in this case.
|
||||
let key_budget = weight_limit
|
||||
let key_budget = meter
|
||||
.limit()
|
||||
.saturating_sub(base_weight)
|
||||
.checked_div_per_component(&weight_per_key)
|
||||
.unwrap_or(0) as u32;
|
||||
@@ -295,24 +296,18 @@ impl<T: Config> ContractInfo<T> {
|
||||
}
|
||||
|
||||
/// Delete as many items from the deletion queue possible within the supplied weight limit.
|
||||
///
|
||||
/// It returns the amount of weight used for that task.
|
||||
pub fn process_deletion_queue_batch(weight_limit: Weight) -> Weight {
|
||||
pub fn process_deletion_queue_batch(meter: &mut WeightMeter) {
|
||||
if meter.try_consume(T::WeightInfo::on_process_deletion_queue_batch()).is_err() {
|
||||
return
|
||||
};
|
||||
|
||||
let mut queue = <DeletionQueueManager<T>>::load();
|
||||
|
||||
if queue.is_empty() {
|
||||
return Weight::zero()
|
||||
}
|
||||
|
||||
let (weight_per_key, mut remaining_key_budget) = Self::deletion_budget(weight_limit);
|
||||
|
||||
// We want to check whether we have enough weight to decode the queue before
|
||||
// proceeding. Too little weight for decoding might happen during runtime upgrades
|
||||
// which consume the whole block before the other `on_initialize` blocks are called.
|
||||
if remaining_key_budget == 0 {
|
||||
return weight_limit
|
||||
return;
|
||||
}
|
||||
|
||||
let (weight_per_key, budget) = Self::deletion_budget(&meter);
|
||||
let mut remaining_key_budget = budget;
|
||||
while remaining_key_budget > 0 {
|
||||
let Some(entry) = queue.next() else { break };
|
||||
|
||||
@@ -324,7 +319,10 @@ impl<T: Config> ContractInfo<T> {
|
||||
|
||||
match outcome {
|
||||
// This happens when our budget wasn't large enough to remove all keys.
|
||||
KillStorageResult::SomeRemaining(_) => return weight_limit,
|
||||
KillStorageResult::SomeRemaining(keys_removed) => {
|
||||
remaining_key_budget.saturating_reduce(keys_removed);
|
||||
break
|
||||
},
|
||||
KillStorageResult::AllRemoved(keys_removed) => {
|
||||
entry.remove();
|
||||
// charge at least one key even if none were removed.
|
||||
@@ -333,7 +331,7 @@ impl<T: Config> ContractInfo<T> {
|
||||
};
|
||||
}
|
||||
|
||||
weight_limit.saturating_sub(weight_per_key.saturating_mul(u64::from(remaining_key_budget)))
|
||||
meter.consume(weight_per_key.saturating_mul(u64::from(budget - remaining_key_budget)))
|
||||
}
|
||||
|
||||
/// Returns the code hash of the contract specified by `account` ID.
|
||||
|
||||
Reference in New Issue
Block a user