mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
eth/tracers/logger, internal/ethapi: reimplement excluding authorizations
This commit is contained in:
parent
f449561d95
commit
cbe68b3ac2
4 changed files with 24 additions and 111 deletions
|
|
@ -44,46 +44,6 @@ func (al AccessList) StorageKeys() int {
|
||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithoutAuthorizations removes authorities of valid authorizations from the resulting array,
|
|
||||||
// because such addresses will be added to the access list automatically, so there is no reason to return them
|
|
||||||
// (exception if they have not empty storage keys list).
|
|
||||||
func (al AccessList) WithoutAuthorizations(chainID *big.Int, authorizations []SetCodeAuthorization) AccessList {
|
|
||||||
validAuthorities := make(map[common.Address]struct{}, len(authorizations))
|
|
||||||
|
|
||||||
for _, auth := range authorizations {
|
|
||||||
// According to stateTransition.applyAuthorization(),
|
|
||||||
// authority address will be added to the access list if the next three conditions are satisfied.
|
|
||||||
if !auth.ChainID.IsZero() && auth.ChainID.CmpBig(chainID) != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if auth.Nonce+1 < auth.Nonce {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
authority, err := auth.Authority()
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
validAuthorities[authority] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(validAuthorities) == 0 {
|
|
||||||
return al
|
|
||||||
}
|
|
||||||
|
|
||||||
output := make(AccessList, 0, len(validAuthorities))
|
|
||||||
for _, accessTuple := range al {
|
|
||||||
// Keep this address if it is not present in valid authorities map, or if it contains not empty storage keys.
|
|
||||||
if _, ok := validAuthorities[accessTuple.Address]; !ok || len(accessTuple.StorageKeys) != 0 {
|
|
||||||
output = append(output, accessTuple)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessListTx is the data of EIP-2930 access list transactions.
|
// AccessListTx is the data of EIP-2930 access list transactions.
|
||||||
type AccessListTx struct {
|
type AccessListTx struct {
|
||||||
ChainID *big.Int // destination chain ID
|
ChainID *big.Int // destination chain ID
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"math"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/holiman/uint256"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAccessListWithoutAuthorizations(t *testing.T) {
|
|
||||||
generateKey := func(t *testing.T) *ecdsa.PrivateKey {
|
|
||||||
key, err := crypto.GenerateKey()
|
|
||||||
require.NoError(t, err)
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareAuth := func(t *testing.T, auth SetCodeAuthorization, key *ecdsa.PrivateKey) SetCodeAuthorization {
|
|
||||||
signature, err := crypto.Sign(auth.sigHash().Bytes(), key)
|
|
||||||
require.NoError(t, err)
|
|
||||||
auth.R.SetBytes(signature[0:32])
|
|
||||||
auth.S.SetBytes(signature[32:64])
|
|
||||||
auth.V = signature[64]
|
|
||||||
return auth
|
|
||||||
}
|
|
||||||
|
|
||||||
targetChainID := uint256.NewInt(1)
|
|
||||||
key1, key2, key3, key4, key5 := generateKey(t), generateKey(t), generateKey(t), generateKey(t), generateKey(t)
|
|
||||||
|
|
||||||
authorizationWithInvalidSignature := SetCodeAuthorization{ChainID: *targetChainID}
|
|
||||||
authorizationWithInvalidChainID := prepareAuth(t, SetCodeAuthorization{ChainID: *uint256.NewInt(2)}, key1)
|
|
||||||
authorizationWithNonceOverflow := prepareAuth(t, SetCodeAuthorization{ChainID: *targetChainID, Nonce: math.MaxUint64}, key2)
|
|
||||||
validAuthorizationForAddressWithStorage := prepareAuth(t, SetCodeAuthorization{ChainID: *targetChainID}, key3)
|
|
||||||
validAuthorizationForAddressWithoutStorage1 := prepareAuth(t, SetCodeAuthorization{}, key4)
|
|
||||||
validAuthorizationForAddressWithoutStorage2 := prepareAuth(t, SetCodeAuthorization{ChainID: *targetChainID}, key5)
|
|
||||||
|
|
||||||
accessTuple1 := AccessTuple{Address: crypto.PubkeyToAddress(key1.PublicKey)}
|
|
||||||
accessTuple2 := AccessTuple{Address: crypto.PubkeyToAddress(key2.PublicKey)}
|
|
||||||
accessTuple3 := AccessTuple{Address: crypto.PubkeyToAddress(key3.PublicKey), StorageKeys: []common.Hash{{}}}
|
|
||||||
accessTuple4 := AccessTuple{Address: crypto.PubkeyToAddress(key4.PublicKey), StorageKeys: []common.Hash{}} // should be deleted
|
|
||||||
accessTuple5 := AccessTuple{Address: crypto.PubkeyToAddress(key5.PublicKey)} // should be deleted
|
|
||||||
accessTuple6 := AccessTuple{Address: common.Address{1}}
|
|
||||||
|
|
||||||
al := AccessList{accessTuple1, accessTuple2, accessTuple3, accessTuple4, accessTuple5, accessTuple6}
|
|
||||||
|
|
||||||
require.Equal(t, al, al.WithoutAuthorizations(targetChainID.ToBig(), nil), "AccessList should not be modified without authorizations")
|
|
||||||
require.Equal(t, AccessList{accessTuple1, accessTuple2, accessTuple3, accessTuple6}, al.WithoutAuthorizations(targetChainID.ToBig(), []SetCodeAuthorization{
|
|
||||||
authorizationWithInvalidSignature,
|
|
||||||
authorizationWithInvalidChainID,
|
|
||||||
authorizationWithNonceOverflow,
|
|
||||||
validAuthorizationForAddressWithStorage,
|
|
||||||
validAuthorizationForAddressWithoutStorage1,
|
|
||||||
validAuthorizationForAddressWithoutStorage2,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
@ -103,16 +103,10 @@ type AccessListTracer struct {
|
||||||
// NewAccessListTracer creates a new tracer that can generate AccessLists.
|
// NewAccessListTracer creates a new tracer that can generate AccessLists.
|
||||||
// An optional AccessList can be specified to occupy slots and addresses in
|
// An optional AccessList can be specified to occupy slots and addresses in
|
||||||
// the resulting accesslist.
|
// the resulting accesslist.
|
||||||
func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompiles []common.Address) *AccessListTracer {
|
func NewAccessListTracer(acl types.AccessList, addressesToExclude map[common.Address]struct{}) *AccessListTracer {
|
||||||
excl := map[common.Address]struct{}{
|
|
||||||
from: {}, to: {},
|
|
||||||
}
|
|
||||||
for _, addr := range precompiles {
|
|
||||||
excl[addr] = struct{}{}
|
|
||||||
}
|
|
||||||
list := newAccessList()
|
list := newAccessList()
|
||||||
for _, al := range acl {
|
for _, al := range acl {
|
||||||
if _, ok := excl[al.Address]; !ok {
|
if _, ok := addressesToExclude[al.Address]; !ok {
|
||||||
list.addAddress(al.Address)
|
list.addAddress(al.Address)
|
||||||
}
|
}
|
||||||
for _, slot := range al.StorageKeys {
|
for _, slot := range al.StorageKeys {
|
||||||
|
|
@ -120,7 +114,7 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &AccessListTracer{
|
return &AccessListTracer{
|
||||||
excl: excl,
|
excl: addressesToExclude,
|
||||||
list: list,
|
list: list,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1165,10 +1165,27 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
||||||
// Retrieve the precompiles since they don't need to be added to the access list
|
// 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 := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time))
|
||||||
|
|
||||||
|
// addressesToExclude contains sender, receiver, precompiles and valid authorizations
|
||||||
|
addressesToExclude := map[common.Address]struct{}{args.from(): {}, to: {}}
|
||||||
|
for _, addr := range precompiles {
|
||||||
|
addressesToExclude[addr] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, auth := range args.AuthorizationList {
|
||||||
|
// Duplicating stateTransition.validateAuthorization() logic
|
||||||
|
if (!auth.ChainID.IsZero() && auth.ChainID.CmpBig(b.ChainConfig().ChainID) != 0) || auth.Nonce+1 < auth.Nonce {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if authority, err := auth.Authority(); err == nil {
|
||||||
|
addressesToExclude[authority] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create an initial tracer
|
// Create an initial tracer
|
||||||
prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles)
|
prevTracer := logger.NewAccessListTracer(nil, addressesToExclude)
|
||||||
if args.AccessList != nil {
|
if args.AccessList != nil {
|
||||||
prevTracer = logger.NewAccessListTracer(*args.AccessList, args.from(), to, precompiles)
|
prevTracer = logger.NewAccessListTracer(*args.AccessList, addressesToExclude)
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
|
|
@ -1185,7 +1202,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
||||||
msg := args.ToMessage(header.BaseFee, true, true)
|
msg := args.ToMessage(header.BaseFee, true, true)
|
||||||
|
|
||||||
// Apply the transaction with the access list tracer
|
// Apply the transaction with the access list tracer
|
||||||
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
tracer := logger.NewAccessListTracer(accessList, addressesToExclude)
|
||||||
config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
|
config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
|
||||||
evm := b.GetEVM(ctx, statedb, header, &config, nil)
|
evm := b.GetEVM(ctx, statedb, header, &config, nil)
|
||||||
|
|
||||||
|
|
@ -1202,7 +1219,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
||||||
return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.ToTransaction(types.LegacyTxType).Hash(), err)
|
return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.ToTransaction(types.LegacyTxType).Hash(), err)
|
||||||
}
|
}
|
||||||
if tracer.Equal(prevTracer) {
|
if tracer.Equal(prevTracer) {
|
||||||
return accessList.WithoutAuthorizations(b.ChainConfig().ChainID, msg.SetCodeAuthorizations), res.UsedGas, res.Err, nil
|
return accessList, res.UsedGas, res.Err, nil
|
||||||
}
|
}
|
||||||
prevTracer = tracer
|
prevTracer = tracer
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue