Skip to content

Commit

Permalink
refund pov gas based on measured proof size usage (#230)
Browse files Browse the repository at this point in the history
Co-authored-by: Agusrodri <[email protected]>
  • Loading branch information
2 people authored and TarekkMA committed Feb 17, 2025
1 parent 986eb1a commit 5d0e59b
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 19 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk
substrate-test-runtime-client = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412" }
substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412" }

# Cumulus primitives
cumulus-primitives-storage-weight-reclaim = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-stable2407", default-features = false }

# XCM
xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }

Expand Down
3 changes: 2 additions & 1 deletion frame/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,8 @@ pub mod pallet {
"pre log already exists; block is invalid",
);

Self::apply_validated_transaction(source, transaction).map(|(post_info, _)| post_info)
Self::apply_validated_transaction(source, transaction)
.map(|(post_info, _)| post_info)
}
}

Expand Down
7 changes: 7 additions & 0 deletions frame/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,18 @@ impl-trait-for-tuples = "0.2.3"
log = { workspace = true }
scale-codec = { workspace = true }
scale-info = { workspace = true }

# Cumulus
cumulus-primitives-storage-weight-reclaim = { workspace = true, default-features = false }

# Substrate
frame-benchmarking = { workspace = true, optional = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }

# Frontier
fp-account = { workspace = true }
fp-evm = { workspace = true, features = ["serde"] }
Expand All @@ -48,6 +53,8 @@ std = [
"log/std",
"scale-codec/std",
"scale-info/std",
# Cumulus
"cumulus-primitives-storage-weight-reclaim/std",
# Substrate
"frame-benchmarking?/std",
"frame-support/std",
Expand Down
27 changes: 14 additions & 13 deletions frame/evm/src/runner/meter.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This file is part of Frontier.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// Copyright (c) 2021-2022 Parity Technologies (UK) Ltd.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use alloc::collections::btree_set::BTreeSet;
use evm::{
Expand Down
87 changes: 83 additions & 4 deletions frame/evm/src/runner/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ use evm::{
gasometer::{GasCost, StorageTarget},
ExitError, ExitReason, ExternalOperation, Opcode, Transfer,
};
// Cumulus
use cumulus_primitives_storage_weight_reclaim::get_proof_size;
// Substrate
use frame_support::{
traits::{
Expand Down Expand Up @@ -79,6 +81,7 @@ where
is_transactional: bool,
weight_limit: Option<Weight>,
proof_size_base_cost: Option<u64>,
measured_proof_size_before: u64,
f: F,
) -> Result<ExecutionInfoV2<R>, RunnerError<Error<T>>>
where
Expand Down Expand Up @@ -109,6 +112,7 @@ where
weight,
weight_limit,
proof_size_base_cost,
measured_proof_size_before,
);

#[cfg(feature = "forbid-evm-reentrancy")]
Expand Down Expand Up @@ -147,6 +151,7 @@ where
weight,
weight_limit,
proof_size_base_cost,
measured_proof_size_before,
)
});

Expand All @@ -168,6 +173,7 @@ where
weight: Weight,
weight_limit: Option<Weight>,
proof_size_base_cost: Option<u64>,
measured_proof_size_before: u64,
) -> Result<ExecutionInfoV2<R>, RunnerError<Error<T>>>
where
F: FnOnce(
Expand Down Expand Up @@ -291,15 +297,20 @@ where
None => 0,
};

let pov_gas = match executor.state().weight_info() {
Some(weight_info) => weight_info
// Measure actual proof size usage (or get computed proof size)
let actual_proof_size = if let Some(measured_proof_size_after) = get_proof_size() {
measured_proof_size_after.saturating_sub(measured_proof_size_before)
} else {
executor
.state()
.weight_info()
.unwrap_or_default()
.proof_size_usage
.unwrap_or_default()
.saturating_mul(T::GasLimitPovSizeRatio::get()),
None => 0,
};

// Post execution.
let pov_gas = actual_proof_size.saturating_mul(T::GasLimitPovSizeRatio::get());
let used_gas = executor.used_gas();
let effective_gas = U256::from(core::cmp::max(
core::cmp::max(used_gas, pov_gas),
Expand Down Expand Up @@ -472,6 +483,7 @@ where
proof_size_base_cost: Option<u64>,
config: &evm::Config,
) -> Result<CallInfo, RunnerError<Self::Error>> {
let measured_proof_size_before = get_proof_size().unwrap_or_default();
if validate {
Self::validate(
source,
Expand Down Expand Up @@ -501,6 +513,7 @@ where
is_transactional,
weight_limit,
proof_size_base_cost,
measured_proof_size_before,
|executor| executor.transact_call(source, target, value, input, gas_limit, access_list),
)
}
Expand All @@ -520,6 +533,7 @@ where
proof_size_base_cost: Option<u64>,
config: &evm::Config,
) -> Result<CreateInfo, RunnerError<Self::Error>> {
let measured_proof_size_before = get_proof_size().unwrap_or_default();
if validate {
Self::validate(
source,
Expand Down Expand Up @@ -549,6 +563,7 @@ where
is_transactional,
weight_limit,
proof_size_base_cost,
measured_proof_size_before,
|executor| {
let address = executor.create_address(evm::CreateScheme::Legacy { caller: source });
T::OnCreate::on_create(source, address);
Expand All @@ -575,6 +590,7 @@ where
proof_size_base_cost: Option<u64>,
config: &evm::Config,
) -> Result<CreateInfo, RunnerError<Self::Error>> {
let measured_proof_size_before = get_proof_size().unwrap_or_default();
if validate {
Self::validate(
source,
Expand Down Expand Up @@ -605,6 +621,7 @@ where
is_transactional,
weight_limit,
proof_size_base_cost,
measured_proof_size_before,
|executor| {
let address = executor.create_address(evm::CreateScheme::Create2 {
caller: source,
Expand All @@ -618,6 +635,68 @@ where
},
)
}

fn create_force_address(
source: H160,
init: Vec<u8>,
value: U256,
gas_limit: u64,
max_fee_per_gas: Option<U256>,
max_priority_fee_per_gas: Option<U256>,
nonce: Option<U256>,
access_list: Vec<(H160, Vec<H256>)>,
is_transactional: bool,
validate: bool,
weight_limit: Option<Weight>,
proof_size_base_cost: Option<u64>,
config: &evm::Config,
contract_address: H160,
) -> Result<CreateInfo, RunnerError<Self::Error>> {
let measured_proof_size_before = get_proof_size().unwrap_or_default();
if validate {
Self::validate(
source,
None,
init.clone(),
value,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
nonce,
access_list.clone(),
is_transactional,
weight_limit,
proof_size_base_cost,
config,
)?;
}
let precompiles = T::PrecompilesValue::get();
Self::execute(
source,
value,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
config,
&precompiles,
is_transactional,
weight_limit,
proof_size_base_cost,
measured_proof_size_before,
|executor| {
T::OnCreate::on_create(source, contract_address);
let (reason, _) = executor.transact_create_force_address(
source,
value,
init,
gas_limit,
access_list,
contract_address,
);
(reason, contract_address)
},
)
}
}

struct SubstrateStackSubstate<'config> {
Expand Down
2 changes: 1 addition & 1 deletion primitives/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub enum AccessedStorage {
AccountStorages((H160, H256)),
}

#[derive(Clone, Copy, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)]
#[derive(Clone, Copy, Eq, PartialEq, Debug, Encode, Decode, Default, TypeInfo)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct WeightInfo {
pub ref_time_limit: Option<u64>,
Expand Down

0 comments on commit 5d0e59b

Please sign in to comment.