Skip to content

Commit

Permalink
Add ProofSizeMeter to WeightInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmadkaouk committed Aug 3, 2023
1 parent ce75d15 commit 26a85ad
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 59 deletions.
4 changes: 2 additions & 2 deletions frame/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,8 +690,8 @@ impl<T: Config> Pallet<T> {
true,
);
if let Some(weight_info) = weight_info {
if let Some(proof_size_usage) = weight_info.proof_size_usage {
*gas_to_weight.proof_size_mut() = proof_size_usage;
if let Some(proof_size_meter) = weight_info.proof_size_meter {
*gas_to_weight.proof_size_mut() = proof_size_meter.usage();
}
}
Some(gas_to_weight)
Expand Down
12 changes: 6 additions & 6 deletions frame/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,8 @@ pub mod pallet {
true,
);
if let Some(weight_info) = info.weight_info {
if let Some(proof_size_usage) = weight_info.proof_size_usage {
*gas_to_weight.proof_size_mut() = proof_size_usage;
if let Some(proof_size_meter) = weight_info.proof_size_meter {
*gas_to_weight.proof_size_mut() = proof_size_meter.usage();
}
}
Some(gas_to_weight)
Expand Down Expand Up @@ -355,8 +355,8 @@ pub mod pallet {
true,
);
if let Some(weight_info) = info.weight_info {
if let Some(proof_size_usage) = weight_info.proof_size_usage {
*gas_to_weight.proof_size_mut() = proof_size_usage;
if let Some(proof_size_meter) = weight_info.proof_size_meter {
*gas_to_weight.proof_size_mut() = proof_size_meter.usage();
}
}
Some(gas_to_weight)
Expand Down Expand Up @@ -443,8 +443,8 @@ pub mod pallet {
true,
);
if let Some(weight_info) = info.weight_info {
if let Some(proof_size_usage) = weight_info.proof_size_usage {
*gas_to_weight.proof_size_mut() = proof_size_usage;
if let Some(proof_size_meter) = weight_info.proof_size_meter {
*gas_to_weight.proof_size_mut() = proof_size_meter.usage();
}
}
Some(gas_to_weight)
Expand Down
7 changes: 3 additions & 4 deletions frame/evm/src/runner/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,7 @@ where
Some(weight_info) => U256::from(sp_std::cmp::max(
used_gas,
weight_info
.proof_size_usage
.unwrap_or_default()
.proof_size_usage()
.saturating_mul(T::GasLimitPovSizeRatio::get()),
)),
_ => used_gas.into(),
Expand Down Expand Up @@ -1057,8 +1056,8 @@ where

// Record proof_size
// Return if proof size recording is disabled
let proof_size_limit = if let Some(proof_size_limit) = weight_info.proof_size_limit {
proof_size_limit
let proof_size_limit = if let Some(proof_size_meter) = weight_info.proof_size_meter {
proof_size_meter.limit()
} else {
return Ok(());
};
Expand Down
25 changes: 8 additions & 17 deletions frame/evm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ mod proof_size_test {
let actual_proof_size = result
.weight_info
.expect("weight info")
.proof_size_usage
.expect("proof size usage");
.proof_size_usage();

assert_eq!(expected_proof_size, actual_proof_size);
});
Expand Down Expand Up @@ -245,8 +244,7 @@ mod proof_size_test {
let actual_proof_size = result
.weight_info
.expect("weight info")
.proof_size_usage
.expect("proof size usage");
.proof_size_usage();

assert_eq!(expected_proof_size, actual_proof_size);
});
Expand Down Expand Up @@ -302,8 +300,7 @@ mod proof_size_test {
let actual_proof_size = result
.weight_info
.expect("weight info")
.proof_size_usage
.expect("proof size usage");
.proof_size_usage();

assert_eq!(expected_proof_size, actual_proof_size);
});
Expand Down Expand Up @@ -351,8 +348,7 @@ mod proof_size_test {
let actual_proof_size = result
.weight_info
.expect("weight info")
.proof_size_usage
.expect("proof size usage");
.proof_size_usage();

assert_eq!(expected_proof_size, actual_proof_size);
});
Expand Down Expand Up @@ -401,8 +397,7 @@ mod proof_size_test {
let actual_proof_size = result
.weight_info
.expect("weight info")
.proof_size_usage
.expect("proof size usage");
.proof_size_usage();

assert_eq!(expected_proof_size, actual_proof_size);
});
Expand Down Expand Up @@ -458,9 +453,7 @@ mod proof_size_test {
let actual_proof_size = result
.weight_info
.expect("weight info")
.proof_size_usage
.expect("proof size usage");

.proof_size_usage();
assert_eq!(expected_proof_size, actual_proof_size);
});
}
Expand Down Expand Up @@ -528,8 +521,7 @@ mod proof_size_test {
let actual_proof_size = result
.weight_info
.expect("weight info")
.proof_size_usage
.expect("proof size usage");
.proof_size_usage();

assert_eq!(expected_proof_size, actual_proof_size);
});
Expand Down Expand Up @@ -615,8 +607,7 @@ mod proof_size_test {
let actual_proof_size = result
.weight_info
.expect("weight info")
.proof_size_usage
.expect("proof size usage");
.proof_size_usage();

assert_eq!(used_gas.standard, U256::from(21_000));
assert_eq!(used_gas.effective, U256::from(actual_proof_size * ratio));
Expand Down
40 changes: 21 additions & 19 deletions primitives/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(unused_crate_dependencies)]

mod metric;
mod precompile;
mod validation;
mod metric;

use frame_support::weights::{constants::WEIGHT_REF_TIME_PER_MILLIS, Weight};
use metric::ProofSizeMeter;
use scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
#[cfg(feature = "serde")]
Expand Down Expand Up @@ -78,9 +79,8 @@ pub enum AccessedStorage {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct WeightInfo {
pub ref_time_limit: Option<u64>,
pub proof_size_limit: Option<u64>,
pub ref_time_usage: Option<u64>,
pub proof_size_usage: Option<u64>,
pub proof_size_meter: Option<ProofSizeMeter>,
}

impl WeightInfo {
Expand All @@ -95,16 +95,17 @@ impl WeightInfo {
{
Some(WeightInfo {
ref_time_limit: Some(weight_limit.ref_time()),
proof_size_limit: Some(weight_limit.proof_size()),
ref_time_usage: Some(0u64),
proof_size_usage: Some(proof_size_base_cost),
proof_size_meter: Some(
ProofSizeMeter::new(proof_size_base_cost, weight_limit.proof_size())
.map_err(|_| "invalid proof size base cost")?,
),
})
}
(Some(weight_limit), None) => Some(WeightInfo {
ref_time_limit: Some(weight_limit.ref_time()),
proof_size_limit: None,
ref_time_usage: Some(0u64),
proof_size_usage: None,
proof_size_meter: None,
}),
_ => return Err("must provide Some valid weight limit or None"),
})
Expand All @@ -129,22 +130,23 @@ impl WeightInfo {
Ok(())
}
pub fn try_record_proof_size_or_fail(&mut self, cost: u64) -> Result<(), ExitError> {
if let (Some(proof_size_usage), Some(proof_size_limit)) =
(self.proof_size_usage, self.proof_size_limit)
{
let proof_size_usage = self.try_consume(cost, proof_size_limit, proof_size_usage)?;
if proof_size_usage > proof_size_limit {
return Err(ExitError::OutOfGas);
}
self.proof_size_usage = Some(proof_size_usage);
if let Some(proof_size_meter) = self.proof_size_meter.as_mut() {
proof_size_meter
.record_proof_size(cost)
.map_err(|_| ExitError::OutOfGas)?;
}

Ok(())
}
pub fn refund_proof_size(&mut self, amount: u64) {
if let Some(proof_size_usage) = self.proof_size_usage {
let proof_size_usage = proof_size_usage.saturating_sub(amount);
self.proof_size_usage = Some(proof_size_usage);
}
self.proof_size_meter.as_mut().map(|proof_size_meter| {
proof_size_meter.refund(amount);
});
}

pub fn proof_size_usage(&self) -> u64 {
self.proof_size_meter
.map_or(0, |proof_size_meter| proof_size_meter.usage())
}
pub fn refund_ref_time(&mut self, amount: u64) {
if let Some(ref_time_usage) = self.ref_time_usage {
Expand Down
52 changes: 41 additions & 11 deletions primitives/evm/src/metric.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
use evm::{gasometer::GasCost, ExitError, Opcode};
use evm::{gasometer::GasCost, Opcode};
use scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use sp_core::U256;
use sp_runtime::{traits::CheckedAdd, Saturating};

use crate::AccessedStorage;

#[derive(Debug, PartialEq)]
/// Metric error.
pub enum MetricError {
Expand All @@ -10,14 +17,8 @@ pub enum MetricError {
InvalidBaseCost,
}

impl Into<ExitError> for MetricError {
fn into(self) -> ExitError {
match self {
MetricError::LimitExceeded | MetricError::InvalidBaseCost => ExitError::OutOfGas,
}
}
}

#[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, Debug, TypeInfo)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
/// A struct that keeps track of metric usage and limit.
pub struct Metric<T> {
limit: T,
Expand Down Expand Up @@ -65,12 +66,26 @@ where
fn refund(&mut self, amount: T) {
self.usage = self.usage.saturating_sub(amount);
}

/// Returns the usage.
fn usage(&self) -> T {
self.usage
}
}

/// A struct that keeps track of the size of the proof.
#[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, Debug, TypeInfo)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
/// A struct that keeps track of the proof size and limit.
pub struct ProofSizeMeter(Metric<u64>);

impl ProofSizeMeter {
/// `System::Account` 16(hash) + 20 (key) + 60 (AccountInfo::max_encoded_len)
pub const ACCOUNT_BASIC_PROOF_SIZE: u64 = 96;
/// `AccountCodesMetadata` read, temptatively 16 (hash) + 20 (key) + 40 (CodeMetadata).
pub const ACCOUNT_CODES_METADATA_PROOF_SIZE: u64 = 76;
/// Account basic proof size + 5 bytes max of `decode_len` call.
pub const IS_EMPTY_CHECK_PROOF_SIZE: u64 = 93;

/// Creates a new `ProofSizeMetric` instance with the given limit.
pub fn new(base_cost: u64, limit: u64) -> Result<Self, MetricError> {
Ok(Self(Metric::new(base_cost, limit)?))
Expand All @@ -81,9 +96,24 @@ impl ProofSizeMeter {
/// # Errors
///
/// Returns `MetricError::LimitExceeded` if the proof size exceeds the limit.
fn record_proof_size(&mut self, size: u64) -> Result<(), MetricError> {
pub fn record_proof_size(&mut self, size: u64) -> Result<(), MetricError> {
self.0.record_cost(size)
}

/// Refunds the given amount of proof size.
pub fn refund(&mut self, amount: u64) {
self.0.refund(amount)
}

/// Returns the proof size usage.
pub fn usage(&self) -> u64 {
self.0.usage()
}

/// Returns the proof size limit.
pub fn limit(&self) -> u64 {
self.0.limit
}
}

/// A struct that keeps track of storage usage (newly created storage) and limit.
Expand Down

0 comments on commit 26a85ad

Please sign in to comment.