go-ethereum/libevm/libevm.go
Arran Schlosberg 98a792673a
feat: parallel package for precompile pre-processing (#228)
## Why this should be merged

EVM parallel co-processors that interface with the regular transaction
path via precompiles.

## How this works

Introduces the `parallel.Processor`, which orchestrates a set of
`parallel.Handler`s. Each `Handler` performs arbitrary, strongly typed
processing of any sub-set of transactions in a block and makes its
results available to a precompile and/or a post-block method for
persisting state. Although stateful, `Handler`s can only read the
pre-block and post-block state, which isolates them from conflicts with
the regular transaction path.

There is deliberately no support for a precompile to "write" to a
`Handler`, only to "read". This is because the transaction might still
revert, which would also have to be communicated to the `Handler`,
resulting in unnecessary complexity. Logs/events are the recommended
approach for precompile -> `Handler` communication, to be read from the
`types.Receipts` at the end of the block.

## How this was tested

Integration tests covering:

1. Selection of transactions to process + end-to-end plumbing of data
through a `Handler`.
2. Registration as a precompile, exercised with actual transaction
processing, and demonstrating log + return-data correctness.

---------

Signed-off-by: Arran Schlosberg <519948+ARR4N@users.noreply.github.com>
2026-02-18 12:02:13 +00:00

93 lines
3.4 KiB
Go

// Copyright 2024 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 libevm
import (
"github.com/holiman/uint256"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/libevm/stateconf"
)
// PrecompiledContract is an exact copy of vm.PrecompiledContract, mirrored here
// for instances where importing that package would result in a circular
// dependency.
type PrecompiledContract interface {
RequiredGas(input []byte) uint64
Run(input []byte) ([]byte, error)
}
// StateReader is a subset of vm.StateDB, exposing only methods that read from
// but do not modify state. See method comments in vm.StateDB, which aren't
// copied here as they risk becoming outdated.
type StateReader interface {
GetBalance(common.Address) *uint256.Int
GetNonce(common.Address) uint64
GetCodeHash(common.Address) common.Hash
GetCode(common.Address) []byte
GetCodeSize(common.Address) int
GetRefund() uint64
GetCommittedState(common.Address, common.Hash, ...stateconf.StateDBStateOption) common.Hash
GetState(common.Address, common.Hash, ...stateconf.StateDBStateOption) common.Hash
GetTransientState(addr common.Address, key common.Hash) common.Hash
HasSelfDestructed(common.Address) bool
Exist(common.Address) bool
Empty(common.Address) bool
AddressInAccessList(addr common.Address) bool
SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool)
TxHash() common.Hash
TxIndex() int
}
// AddressContext carries addresses available to contexts such as calls and
// contract creation.
//
// With respect to contract creation, the EVMSemantic.Self address MAY be the
// predicted address of the contract about to be deployed, which might not exist
// yet.
type AddressContext struct {
Origin common.Address // equivalent to vm.ORIGIN op code
// EVMSemantic addresses are those defined by the rules of the EVM, based on
// the type of call made to a contract; i.e. the addresses pushed to the
// stack by the vm.CALLER and vm.SELF op codes, respectively.
EVMSemantic CallerAndSelf
// Raw addresses are those that would be available to a contract under a
// standard CALL; i.e. not interpreted according EVM rules. They are the
// "intuitive" addresses such that the `Caller` is the account that called
// `Self` even if it did so via DELEGATECALL or CALLCODE (in which cases
// `Raw` and `EVMSemantic` would differ).
//
// Raw MUST NOT be nil when returned to a precompile implementation but MAY
// be nil in other situations (e.g. hooks), which MUST document behaviour on
// a case-by-case basis.
Raw *CallerAndSelf
}
// CallerAndSelf carries said addresses for use in an [AddressContext], where
// the definitions of `Caller` and `Self` are defined based on context.
type CallerAndSelf struct {
Caller common.Address
Self common.Address
}