go-ethereum/core/vm/interface.go
Arran Schlosberg 9021836d7d
feat: vm.Hooks.PreprocessingGasCharge() (#235)
## Why this should be merged

In lieu of modifications to `core.IntrinsicGas()`, required for support
of Warp in SAE.

If we were to introduce variadic `options.Option`s to `IntrinsicGas()`,
it's impossible to guarantee that they would always be passed. The
`types.Transaction` itself isn't actually passed to `IntrinsicGas()`
either, so we can't rely on it to carry payloads/hooks.

## How this works

`vm.Hooks` are extended to include `PreprocessingGasCharge(tx
common.Hash) (uint64, error)`, which returns the amount of gas to be
charged between `core.IntrinsicGas` and `vm.EVM` execution charges. The
two entry points to execution, `vm.EVM.Call()` and `vm.EVM.Create()` are
modified to first spend said charge before running upstream logic.

The new hook is defined on a separate interface definition, embedded in
`vm.Hooks`, to allow types to implement just that method and enforce it
with the `var _ vm.Preprocessor = (*impl)(nil)` pattern.

## How this was tested

Integration tests via both `core.ApplyTransaction()` and
`core.ApplyMessage()`. The former is more comprehensive, while the
latter allows for inspection of interim error values.

---------

Signed-off-by: Arran Schlosberg <519948+ARR4N@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Austin Larson <78000745+alarso16@users.noreply.github.com>
2025-12-15 20:49:13 +00:00

100 lines
4 KiB
Go

// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package vm
import (
"math/big"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/types"
"github.com/ava-labs/libevm/params"
"github.com/holiman/uint256"
// libevm extra imports
"github.com/ava-labs/libevm/libevm/stateconf"
)
// StateDB is an EVM database for full state querying.
type StateDB interface {
CreateAccount(common.Address)
SubBalance(common.Address, *uint256.Int)
AddBalance(common.Address, *uint256.Int)
GetBalance(common.Address) *uint256.Int
GetNonce(common.Address) uint64
SetNonce(common.Address, uint64)
GetCodeHash(common.Address) common.Hash
GetCode(common.Address) []byte
SetCode(common.Address, []byte)
GetCodeSize(common.Address) int
AddRefund(uint64)
SubRefund(uint64)
GetRefund() uint64
GetCommittedState(common.Address, common.Hash, ...stateconf.StateDBStateOption) common.Hash
GetState(common.Address, common.Hash, ...stateconf.StateDBStateOption) common.Hash
SetState(common.Address, common.Hash, common.Hash, ...stateconf.StateDBStateOption)
GetTransientState(addr common.Address, key common.Hash) common.Hash
SetTransientState(addr common.Address, key, value common.Hash)
SelfDestruct(common.Address)
HasSelfDestructed(common.Address) bool
Selfdestruct6780(common.Address)
// Exist reports whether the given account exists in state.
// Notably this should also return true for self-destructed accounts.
Exist(common.Address) bool
// Empty returns whether the given account is empty. Empty
// is defined according to EIP161 (balance = nonce = code = 0).
Empty(common.Address) bool
AddressInAccessList(addr common.Address) bool
SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool)
// AddAddressToAccessList adds the given address to the access list. This operation is safe to perform
// even if the feature/fork is not active yet
AddAddressToAccessList(addr common.Address)
// AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform
// even if the feature/fork is not active yet
AddSlotToAccessList(addr common.Address, slot common.Hash)
Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList)
RevertToSnapshot(int)
Snapshot() int
AddLog(*types.Log)
AddPreimage(common.Hash, []byte)
StateDBRemainder
}
// CallContext provides a basic interface for the EVM calling conventions. The EVM
// depends on this context being implemented for doing subcalls and initialising new EVM contracts.
type CallContext interface {
// Call calls another contract.
Call(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
// CallCode takes another contracts code and execute within our own context
CallCode(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
// DelegateCall is same as CallCode except sender and value is propagated from parent to child scope
DelegateCall(env *EVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error)
// Create creates a new contract
Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
}