mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
internal/ethapi: fix access list precompile overrides
AccessList previously applied state overrides with a nil precompile set. That meant MovePrecompileTo could not recognize source precompiles in this path, and AccessList generation could diverge from the behavior already used by DoCall and DoEstimateGas. Fix this by constructing a mutable precompile set from the active rules before applying state overrides, then reusing the resulting set for both access-list tracer exclusion and EVM execution. This ensures moved or overridden precompiles are handled consistently throughout access-list generation. Also add regression coverage for CreateAccessList with MovePrecompileTo so the state override path is exercised directly, in addition to the existing EstimateGas coverage. Full go run ./build/ci.go test is currently failing in github.com/ethereum/go-ethereum/tests at TestExecutionSpecTransaction, which was not part of this change and was committed per explicit user instruction.
This commit is contained in:
parent
5d0e18f775
commit
fa21201ee3
2 changed files with 52 additions and 5 deletions
|
|
@ -21,6 +21,7 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
gomath "math"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
|
@ -1275,12 +1276,15 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
|||
if db == nil || err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
isPostMerge := header.Difficulty.Sign() == 0
|
||||
rules := b.ChainConfig().Rules(header.Number, isPostMerge, header.Time)
|
||||
precompileSet := maps.Clone(vm.ActivePrecompiledContracts(rules))
|
||||
|
||||
// Apply state overrides immediately after StateAndHeaderByNumberOrHash.
|
||||
// If not applied here, there could be cases where user-specified overrides (e.g., nonce)
|
||||
// may conflict with default values from the database, leading to inconsistencies.
|
||||
if stateOverrides != nil {
|
||||
if err := stateOverrides.Apply(db, nil); err != nil {
|
||||
if err := stateOverrides.Apply(db, precompileSet); err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
}
|
||||
|
|
@ -1304,9 +1308,11 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
|||
} else {
|
||||
to = crypto.CreateAddress(args.from(), uint64(*args.Nonce))
|
||||
}
|
||||
isPostMerge := header.Difficulty.Sign() == 0
|
||||
// Retrieve the precompiles since they don't need to be added to the access list
|
||||
precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time))
|
||||
precompiles := make([]common.Address, 0, len(precompileSet))
|
||||
for addr := range precompileSet {
|
||||
precompiles = append(precompiles, addr)
|
||||
}
|
||||
|
||||
// addressesToExclude contains sender, receiver, precompiles and valid authorizations
|
||||
addressesToExclude := map[common.Address]struct{}{args.from(): {}, to: {}}
|
||||
|
|
@ -1354,6 +1360,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
|||
tracer := logger.NewAccessListTracer(accessList, addressesToExclude)
|
||||
config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
|
||||
evm := b.GetEVM(ctx, statedb, header, &config, nil)
|
||||
evm.SetPrecompiles(precompileSet)
|
||||
|
||||
// Lower the basefee to 0 to avoid breaking EVM
|
||||
// invariants (basefee < feecap).
|
||||
|
|
|
|||
|
|
@ -1014,7 +1014,7 @@ func TestCall(t *testing.T) {
|
|||
Balance: big.NewInt(params.Ether),
|
||||
Nonce: 1,
|
||||
Storage: map[common.Hash]common.Hash{
|
||||
common.Hash{}: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
|
||||
{}: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -3795,7 +3795,7 @@ func TestCreateAccessListWithStateOverrides(t *testing.T) {
|
|||
Balance: (*hexutil.Big)(big.NewInt(1000000000000000000)),
|
||||
Nonce: &nonce,
|
||||
State: map[common.Hash]common.Hash{
|
||||
common.Hash{}: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"),
|
||||
{}: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -3832,6 +3832,46 @@ func TestCreateAccessListWithStateOverrides(t *testing.T) {
|
|||
require.Equal(t, expected, result.Accesslist)
|
||||
}
|
||||
|
||||
func TestCreateAccessListWithMovePrecompile(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Initialize test accounts
|
||||
var (
|
||||
accounts = newAccounts(2)
|
||||
genesis = &core.Genesis{
|
||||
Config: params.MergedTestChainConfig,
|
||||
Alloc: types.GenesisAlloc{
|
||||
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
||||
},
|
||||
}
|
||||
)
|
||||
backend := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
|
||||
b.SetPoS()
|
||||
})
|
||||
api := NewBlockChainAPI(backend)
|
||||
|
||||
var (
|
||||
sha256Addr = common.BytesToAddress([]byte{0x2})
|
||||
newSha256Addr = common.BytesToAddress([]byte{0x10, 0})
|
||||
sha256Input = hexutil.Bytes([]byte("hello"))
|
||||
gas = hexutil.Uint64(100000)
|
||||
args = TransactionArgs{
|
||||
From: &accounts[0].addr,
|
||||
To: &newSha256Addr,
|
||||
Data: &sha256Input,
|
||||
Gas: &gas,
|
||||
}
|
||||
overrides = &override.StateOverride{
|
||||
sha256Addr: override.OverrideAccount{
|
||||
MovePrecompileTo: &newSha256Addr,
|
||||
},
|
||||
}
|
||||
)
|
||||
result, err := api.CreateAccessList(context.Background(), args, nil, overrides)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, result)
|
||||
require.NotNil(t, result.Accesslist)
|
||||
}
|
||||
|
||||
func TestEstimateGasWithMovePrecompile(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Initialize test accounts
|
||||
|
|
|
|||
Loading…
Reference in a new issue