go-ethereum/core/vm/evm.libevm.go
Arran Schlosberg e7035f19ee
feat!: disambiguate EVM-semantic and raw caller/self addresses for precompiles (#211)
## Why this should be merged

Provides precompiles with unambiguous access to contextual addresses,
without the consumer needing to understand how they change under
different call types.

## How this works

The `libevm.AddressContext` type, which used to carry 3 addresses, now
provides different versions of `Caller` and `Self`. The EVM-semantic
versions are as defined by the rules of the EVM (and available before
this change). The raw versions are the unmodified caller and self.

## How this was tested

Extension of existing UTs to include raw addresses in addition to
existing, EVM-semantic ones.
2025-08-07 23:48:32 +01:00

71 lines
2.6 KiB
Go

// Copyright 2025 the libevm authors.
//
// The libevm additions to go-ethereum are free software: you can redistribute
// them and/or modify them 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 libevm additions are distributed in the hope that they 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 (
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/libevm"
"github.com/ava-labs/libevm/log"
)
// canCreateContract is a convenience wrapper for calling the
// [params.RulesHooks.CanCreateContract] hook.
func (evm *EVM) canCreateContract(caller ContractRef, contractToCreate common.Address, gas uint64) (remainingGas uint64, _ error) {
addrs := &libevm.AddressContext{
Origin: evm.Origin,
EVMSemantic: libevm.CallerAndSelf{
Caller: caller.Address(),
Self: contractToCreate,
},
// The "raw" caller isn't guaranteed to be known if the caller is a
// delegate so the `Raw` field is documented as always being nil.
}
gas, err := evm.chainRules.Hooks().CanCreateContract(addrs, gas, evm.StateDB)
// NOTE that this block only performs logging and that all paths propagate
// `(gas, err)` unmodified.
if err != nil {
log.Debug(
"Contract creation blocked by libevm hook",
"origin", addrs.Origin,
"caller", addrs.EVMSemantic.Caller,
"contract", addrs.EVMSemantic.Self,
"hooks", log.TypeOf(evm.chainRules.Hooks()),
"reason", err,
)
}
return gas, err
}
// InvalidateExecution sets the error that will be returned by
// [EVM.ExecutionInvalidated] for the length of the current transaction; i.e.
// until [EVM.Reset] is called. This is honoured by state-transition logic to
// render the execution itself void (as against reverted).
//
// This method MUST NOT be exposed in a manner that allows contracts to set
// the error; it MAY be exposed to precompiles.
func (evm *EVM) InvalidateExecution(err error) {
evm.executionInvalidated = err
}
// ExecutionInvalidated returns the last value passed to
// [EVM.InvalidateExecution] or nil if no such call has occurred or if
// [EVM.Reset] has been called.
func (evm *EVM) ExecutionInvalidated() error {
return evm.executionInvalidated
}