mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
core: extend TxContext to have all data related to TXPARAM* family
This commit is contained in:
parent
c051a69bfb
commit
4e1fc9bc25
5 changed files with 143 additions and 23 deletions
44
core/evm.go
44
core/evm.go
|
|
@ -25,6 +25,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -82,13 +84,55 @@ func NewEVMTxContext(msg *Message) vm.TxContext {
|
||||||
Origin: msg.From,
|
Origin: msg.From,
|
||||||
GasPrice: new(big.Int).Set(msg.GasPrice),
|
GasPrice: new(big.Int).Set(msg.GasPrice),
|
||||||
BlobHashes: msg.BlobHashes,
|
BlobHashes: msg.BlobHashes,
|
||||||
|
|
||||||
|
// EIP-7701 fields
|
||||||
|
TxType: msg.TxType,
|
||||||
|
Nonce: msg.Nonce,
|
||||||
|
Sender: msg.Sender,
|
||||||
|
Deployer: msg.Deployer,
|
||||||
|
Paymaster: msg.Paymaster,
|
||||||
|
SenderExecutionData: msg.Data,
|
||||||
|
SenderExecutionGas: msg.GasLimit,
|
||||||
}
|
}
|
||||||
if msg.BlobGasFeeCap != nil {
|
if msg.BlobGasFeeCap != nil {
|
||||||
ctx.BlobFeeCap = new(big.Int).Set(msg.BlobGasFeeCap)
|
ctx.BlobFeeCap = new(big.Int).Set(msg.BlobGasFeeCap)
|
||||||
}
|
}
|
||||||
|
if msg.GasTipCap != nil {
|
||||||
|
ctx.MaxPriorityFeePerGas = new(big.Int).Set(msg.GasTipCap)
|
||||||
|
}
|
||||||
|
if msg.GasFeeCap != nil {
|
||||||
|
ctx.MaxFeePerGas = new(big.Int).Set(msg.GasFeeCap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute AccessListHash
|
||||||
|
if len(msg.AccessList) > 0 {
|
||||||
|
ctx.AccessListHash = rlpHash(msg.AccessList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute AuthorizationListHash
|
||||||
|
if len(msg.SetCodeAuthorizations) > 0 {
|
||||||
|
ctx.AuthorizationListHash = rlpHash(msg.SetCodeAuthorizations)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxHashForSignature is nil for AA transactions
|
||||||
|
// For non-AA transactions, we leave it nil as we don't have access to the
|
||||||
|
// original transaction here. If needed, this should be set by the caller.
|
||||||
|
if !msg.Abstract {
|
||||||
|
// TODO: compute TxHashForSignature for non-AA transactions if needed
|
||||||
|
}
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rlpHash computes the keccak256 hash of the RLP encoding of x.
|
||||||
|
func rlpHash(x interface{}) common.Hash {
|
||||||
|
encoded, err := rlp.EncodeToBytes(x)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}
|
||||||
|
}
|
||||||
|
return crypto.Keccak256Hash(encoded)
|
||||||
|
}
|
||||||
|
|
||||||
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
|
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
|
||||||
func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash {
|
func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash {
|
||||||
// Cache will initially contain [refHash.parent],
|
// Cache will initially contain [refHash.parent],
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,7 @@ func toWordSize(size uint64) uint64 {
|
||||||
// A Message contains the data derived from a single transaction that is relevant to state
|
// A Message contains the data derived from a single transaction that is relevant to state
|
||||||
// processing.
|
// processing.
|
||||||
type Message struct {
|
type Message struct {
|
||||||
|
TxType uint8
|
||||||
To *common.Address
|
To *common.Address
|
||||||
From common.Address
|
From common.Address
|
||||||
Nonce uint64
|
Nonce uint64
|
||||||
|
|
@ -187,6 +188,7 @@ type Message struct {
|
||||||
// TransactionToMessage converts a transaction into a Message.
|
// TransactionToMessage converts a transaction into a Message.
|
||||||
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) {
|
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) {
|
||||||
msg := &Message{
|
msg := &Message{
|
||||||
|
TxType: tx.Type(),
|
||||||
Nonce: tx.Nonce(),
|
Nonce: tx.Nonce(),
|
||||||
GasLimit: tx.Gas(),
|
GasLimit: tx.Gas(),
|
||||||
GasPrice: new(big.Int).Set(tx.GasPrice()),
|
GasPrice: new(big.Int).Set(tx.GasPrice()),
|
||||||
|
|
|
||||||
|
|
@ -599,82 +599,128 @@ func opAcceptRole(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||||
|
|
||||||
type paramLoader func(*EVM, uint64) []byte
|
type paramLoader func(*EVM, uint64) []byte
|
||||||
|
|
||||||
|
// uint64ToBytes32 converts a uint64 to a 32-byte big-endian slice.
|
||||||
|
func uint64ToBytes32(v uint64) []byte {
|
||||||
|
return common.LeftPadBytes(new(uint256.Int).SetUint64(v).Bytes(), 32)
|
||||||
|
}
|
||||||
|
|
||||||
func loadType(evm *EVM, id uint64) []byte {
|
func loadType(evm *EVM, id uint64) []byte {
|
||||||
// TODO: plumb in type to TxContext
|
return uint64ToBytes32(uint64(evm.TxContext.TxType))
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadNonce(evm *EVM, id uint64) []byte {
|
func loadNonce(evm *EVM, id uint64) []byte {
|
||||||
// TODO: plumb in nonce to TxContext
|
return uint64ToBytes32(evm.TxContext.Nonce)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSender(evm *EVM, id uint64) []byte {
|
func loadSender(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
return common.LeftPadBytes(evm.TxContext.Origin.Bytes(), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSenderValidationData(evm *EVM, id uint64) []byte {
|
func loadSenderValidationData(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
if evm.TxContext.Sender == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return evm.TxContext.Sender.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDeployer(evm *EVM, id uint64) []byte {
|
func loadDeployer(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
// 0 or 32 bytes: return nil when not set
|
||||||
|
if evm.TxContext.Deployer == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return common.LeftPadBytes(evm.TxContext.Deployer.Target.Bytes(), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDeployerData(evm *EVM, id uint64) []byte {
|
func loadDeployerData(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
// dynamic, default empty array
|
||||||
|
if evm.TxContext.Deployer == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return evm.TxContext.Deployer.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPaymaster(evm *EVM, id uint64) []byte {
|
func loadPaymaster(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
// 0 or 32 bytes: return nil when not set
|
||||||
|
if evm.TxContext.Paymaster == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return common.LeftPadBytes(evm.TxContext.Paymaster.Target.Bytes(), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPaymasterData(evm *EVM, id uint64) []byte {
|
func loadPaymasterData(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
// dynamic, default empty array
|
||||||
|
if evm.TxContext.Paymaster == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return evm.TxContext.Paymaster.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSenderExecutionData(evm *EVM, id uint64) []byte {
|
func loadSenderExecutionData(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
return evm.TxContext.SenderExecutionData
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMaxPriorityFeePerGas(evm *EVM, id uint64) []byte {
|
func loadMaxPriorityFeePerGas(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
if evm.TxContext.MaxPriorityFeePerGas == nil {
|
||||||
|
return make([]byte, 32)
|
||||||
|
}
|
||||||
|
return common.LeftPadBytes(evm.TxContext.MaxPriorityFeePerGas.Bytes(), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMaxFeePerGas(evm *EVM, id uint64) []byte {
|
func loadMaxFeePerGas(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
if evm.TxContext.MaxFeePerGas == nil {
|
||||||
|
return make([]byte, 32)
|
||||||
|
}
|
||||||
|
return common.LeftPadBytes(evm.TxContext.MaxFeePerGas.Bytes(), 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSenderValidationGas(evm *EVM, id uint64) []byte {
|
||||||
|
if evm.TxContext.Sender == nil {
|
||||||
|
return uint64ToBytes32(0)
|
||||||
|
}
|
||||||
|
return uint64ToBytes32(evm.TxContext.Sender.Gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPaymasterValidationGas(evm *EVM, id uint64) []byte {
|
func loadPaymasterValidationGas(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
// 32 bytes, default 0
|
||||||
|
if evm.TxContext.Paymaster == nil {
|
||||||
|
return uint64ToBytes32(0)
|
||||||
|
}
|
||||||
|
return uint64ToBytes32(evm.TxContext.Paymaster.Gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSenderExecutionGas(evm *EVM, id uint64) []byte {
|
func loadSenderExecutionGas(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
return uint64ToBytes32(evm.TxContext.SenderExecutionGas)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPaymasterPostOpGas(evm *EVM, id uint64) []byte {
|
func loadPaymasterPostOpGas(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
// 32 bytes, default 0
|
||||||
|
if evm.TxContext.Paymaster == nil {
|
||||||
|
return uint64ToBytes32(0)
|
||||||
|
}
|
||||||
|
return uint64ToBytes32(evm.TxContext.Paymaster.PostOpGas)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAccessListHash(evm *EVM, id uint64) []byte {
|
func loadAccessListHash(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
return evm.TxContext.AccessListHash[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAuthorizationListHash(evm *EVM, id uint64) []byte {
|
func loadAuthorizationListHash(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
return evm.TxContext.AuthorizationListHash[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadExecutionStatus(evm *EVM, id uint64) []byte {
|
func loadExecutionStatus(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
return uint64ToBytes32(evm.TxContext.ExecutionStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadExecutionGasUsed(evm *EVM, id uint64) []byte {
|
func loadExecutionGasUsed(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
return uint64ToBytes32(evm.TxContext.ExecutionGasUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadTxHashForSignature(evm *EVM, id uint64) []byte {
|
func loadTxHashForSignature(evm *EVM, id uint64) []byte {
|
||||||
return nil
|
if evm.TxContext.TxHashForSignature == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return evm.TxContext.TxHashForSignature[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// idToParam is a map of identifier to transaction parameter loader.
|
// idToParam is a map of identifier to transaction parameter loader.
|
||||||
|
|
@ -690,7 +736,7 @@ var idToParam = map[uint64]paramLoader{
|
||||||
0x08: loadSenderExecutionData,
|
0x08: loadSenderExecutionData,
|
||||||
0x0B: loadMaxPriorityFeePerGas,
|
0x0B: loadMaxPriorityFeePerGas,
|
||||||
0x0C: loadMaxFeePerGas,
|
0x0C: loadMaxFeePerGas,
|
||||||
0x0D: loadSenderValidationData,
|
0x0D: loadSenderValidationGas,
|
||||||
0x0E: loadPaymasterValidationGas,
|
0x0E: loadPaymasterValidationGas,
|
||||||
0x0F: loadSenderExecutionGas,
|
0x0F: loadSenderExecutionGas,
|
||||||
0x10: loadPaymasterPostOpGas,
|
0x10: loadPaymasterPostOpGas,
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,29 @@ type TxContext struct {
|
||||||
BlobFeeCap *big.Int // Is used to zero the blobbasefee if NoBaseFee is set
|
BlobFeeCap *big.Int // Is used to zero the blobbasefee if NoBaseFee is set
|
||||||
AccessEvents *state.AccessEvents // Capture all state accesses for this tx
|
AccessEvents *state.AccessEvents // Capture all state accesses for this tx
|
||||||
|
|
||||||
// TODO: add EIP-7701 fields
|
// EIP-7701: Transaction parameters for TXPARAM* opcodes
|
||||||
|
TxType uint8 // 0x00: transaction type
|
||||||
|
Nonce uint64 // 0x01: transaction nonce
|
||||||
|
// Origin is sender (0x02)
|
||||||
|
|
||||||
|
// AA authorization structs (nil for non-AA txs)
|
||||||
|
Sender *types.AbstractAuthorization // 0x03: Data, 0x0D: Gas
|
||||||
|
Deployer *types.AbstractAuthorization // 0x04: Target, 0x05: Data
|
||||||
|
Paymaster *types.PaymasterAuthorization // 0x06: Target, 0x07: Data, 0x0E: Gas, 0x10: PostOpGas
|
||||||
|
|
||||||
|
SenderExecutionData []byte // 0x08: execution calldata
|
||||||
|
SenderExecutionGas uint64 // 0x0F: execution gas limit
|
||||||
|
MaxPriorityFeePerGas *big.Int // 0x0B: max priority fee per gas
|
||||||
|
MaxFeePerGas *big.Int // 0x0C: max fee per gas
|
||||||
|
|
||||||
|
// Hashes (computed when creating TxContext)
|
||||||
|
AccessListHash common.Hash // 0x11: hash of access list
|
||||||
|
AuthorizationListHash common.Hash // 0x12: hash of authorization list
|
||||||
|
TxHashForSignature *common.Hash // 0xff: hash for signature (nil for AA txs)
|
||||||
|
|
||||||
|
// Mutable execution state (set during AA tx processing)
|
||||||
|
ExecutionStatus uint64 // 0xf1: execution result status
|
||||||
|
ExecutionGasUsed uint64 // 0xf2: gas used during execution
|
||||||
}
|
}
|
||||||
|
|
||||||
// EVM is the Ethereum Virtual Machine base object and provides
|
// EVM is the Ethereum Virtual Machine base object and provides
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,12 @@ func NewEnv(cfg *Config) *vm.EVM {
|
||||||
GasPrice: cfg.GasPrice,
|
GasPrice: cfg.GasPrice,
|
||||||
BlobHashes: cfg.BlobHashes,
|
BlobHashes: cfg.BlobHashes,
|
||||||
BlobFeeCap: cfg.BlobFeeCap,
|
BlobFeeCap: cfg.BlobFeeCap,
|
||||||
|
|
||||||
|
// EIP-7701: Set basic fields for non-AA transactions
|
||||||
|
// AA-specific fields (Sender, Deployer, Paymaster) remain nil
|
||||||
|
MaxPriorityFeePerGas: cfg.GasPrice,
|
||||||
|
MaxFeePerGas: cfg.GasPrice,
|
||||||
|
SenderExecutionGas: cfg.GasLimit,
|
||||||
}
|
}
|
||||||
blockContext := vm.BlockContext{
|
blockContext := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue