core, cmd, internal: rework BAL json marshalling to adhere EELS (#34972)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
/ Linux Build (push) Waiting to run

It's a change to BAL json marshalling and t8n tooling to adhere the EELS
definition.
This commit is contained in:
rjl493456442 2026-05-20 21:12:13 +08:00 committed by GitHub
parent 50ae34c1d8
commit 918d46b942
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 581 additions and 204 deletions

View file

@ -56,6 +56,8 @@ type header struct {
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"blockAccessListHash" rlp:"optional"`
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"` SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`
} }
@ -119,26 +121,28 @@ func (c *cliqueInput) UnmarshalJSON(input []byte) error {
// ToBlock converts i into a *types.Block // ToBlock converts i into a *types.Block
func (i *bbInput) ToBlock() *types.Block { func (i *bbInput) ToBlock() *types.Block {
header := &types.Header{ header := &types.Header{
ParentHash: i.Header.ParentHash, ParentHash: i.Header.ParentHash,
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
Coinbase: common.Address{}, Coinbase: common.Address{},
Root: i.Header.Root, Root: i.Header.Root,
TxHash: types.EmptyTxsHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyReceiptsHash, ReceiptHash: types.EmptyReceiptsHash,
Bloom: i.Header.Bloom, Bloom: i.Header.Bloom,
Difficulty: common.Big0, Difficulty: common.Big0,
Number: i.Header.Number, Number: i.Header.Number,
GasLimit: i.Header.GasLimit, GasLimit: i.Header.GasLimit,
GasUsed: i.Header.GasUsed, GasUsed: i.Header.GasUsed,
Time: i.Header.Time, Time: i.Header.Time,
Extra: i.Header.Extra, Extra: i.Header.Extra,
MixDigest: i.Header.MixDigest, MixDigest: i.Header.MixDigest,
BaseFee: i.Header.BaseFee, BaseFee: i.Header.BaseFee,
WithdrawalsHash: i.Header.WithdrawalsHash, WithdrawalsHash: i.Header.WithdrawalsHash,
BlobGasUsed: i.Header.BlobGasUsed, BlobGasUsed: i.Header.BlobGasUsed,
ExcessBlobGas: i.Header.ExcessBlobGas, ExcessBlobGas: i.Header.ExcessBlobGas,
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot, ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
SlotNumber: i.Header.SlotNumber, RequestsHash: i.Header.RequestsHash,
BlockAccessListHash: i.Header.BlockAccessListHash,
SlotNumber: i.Header.SlotNumber,
} }
// Fill optional values. // Fill optional values.

View file

@ -76,6 +76,9 @@ type ExecutionResult struct {
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
RequestsHash *common.Hash `json:"requestsHash,omitempty"` RequestsHash *common.Hash `json:"requestsHash,omitempty"`
Requests [][]byte `json:"requests"` Requests [][]byte `json:"requests"`
BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"`
BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"`
} }
type executionResultMarshaling struct { type executionResultMarshaling struct {
@ -153,8 +156,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return h return h
} }
var ( var (
isEIP4762 = chainConfig.IsUBT(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp) statedb *state.StateDB
statedb *state.StateDB
isEIP4762 = chainConfig.IsUBT(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp)
isAmsterdam = chainConfig.IsAmsterdam(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp)
) )
if pre.AllocPath != "" { if pre.AllocPath != "" {
var err error var err error
@ -299,9 +304,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
receipts = append(receipts, receipt) receipts = append(receipts, receipt)
blockAccessList.Merge(bal) blockAccessList.Merge(bal)
} }
statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber)) statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber))
// TODO(rjl493456442) call engine.Finalize() instead
// Add mining reward? (-1 means rewards are disabled) // Add mining reward? (-1 means rewards are disabled)
if miningReward >= 0 { if miningReward >= 0 {
// Add mining reward. The mining reward may be `0`, which only makes a difference in the cases // Add mining reward. The mining reward may be `0`, which only makes a difference in the cases
@ -330,11 +335,22 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
for _, w := range pre.Env.Withdrawals { for _, w := range pre.Env.Withdrawals {
// Amount is in gwei, turn into wei // Amount is in gwei, turn into wei
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei)) amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal) prev := statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
if isEIP4762 { if isEIP4762 {
statedb.AccessEvents().AddAccount(w.Address, true, stdmath.MaxUint64) statedb.AccessEvents().AddAccount(w.Address, true, stdmath.MaxUint64)
} }
if isAmsterdam {
if w.Amount == 0 {
// Zero amount withdrawal, account is accessed potential
// without state changes.
blockAccessList.AccountRead(w.Address)
} else {
// Non-zero amount withdrawal, account is accessed with
// a balance change.
blockAccessList.BalanceChange(uint32(len(receipts)+1), w.Address, new(uint256.Int).Add(&prev, uint256.MustFromBig(amount)))
}
}
} }
// Gather the execution-layer triggered requests. // Gather the execution-layer triggered requests.
@ -379,6 +395,12 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
execRs.RequestsHash = &h execRs.RequestsHash = &h
execRs.Requests = requests execRs.Requests = requests
} }
if isAmsterdam {
bal := blockAccessList.ToEncodingObj()
balHash := bal.Hash()
execRs.BlockAccessListHash = &balHash
execRs.BlockAccessList = bal
}
// Re-create statedb instance with new root for MPT mode // Re-create statedb instance with new root for MPT mode
statedb, err = state.New(root, statedb.Database()) statedb, err = state.New(root, statedb.Database())

View file

@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types/bal"
) )
var _ = (*executionResultMarshaling)(nil) var _ = (*executionResultMarshaling)(nil)
@ -32,6 +33,8 @@ func (e ExecutionResult) MarshalJSON() ([]byte, error) {
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
RequestsHash *common.Hash `json:"requestsHash,omitempty"` RequestsHash *common.Hash `json:"requestsHash,omitempty"`
Requests []hexutil.Bytes `json:"requests"` Requests []hexutil.Bytes `json:"requests"`
BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"`
BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"`
} }
var enc ExecutionResult var enc ExecutionResult
enc.StateRoot = e.StateRoot enc.StateRoot = e.StateRoot
@ -54,6 +57,8 @@ func (e ExecutionResult) MarshalJSON() ([]byte, error) {
enc.Requests[k] = v enc.Requests[k] = v
} }
} }
enc.BlockAccessList = e.BlockAccessList
enc.BlockAccessListHash = e.BlockAccessListHash
return json.Marshal(&enc) return json.Marshal(&enc)
} }
@ -75,6 +80,8 @@ func (e *ExecutionResult) UnmarshalJSON(input []byte) error {
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
RequestsHash *common.Hash `json:"requestsHash,omitempty"` RequestsHash *common.Hash `json:"requestsHash,omitempty"`
Requests []hexutil.Bytes `json:"requests"` Requests []hexutil.Bytes `json:"requests"`
BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"`
BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"`
} }
var dec ExecutionResult var dec ExecutionResult
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
@ -130,5 +137,11 @@ func (e *ExecutionResult) UnmarshalJSON(input []byte) error {
e.Requests[k] = v e.Requests[k] = v
} }
} }
if dec.BlockAccessList != nil {
e.BlockAccessList = dec.BlockAccessList
}
if dec.BlockAccessListHash != nil {
e.BlockAccessListHash = dec.BlockAccessListHash
}
return nil return nil
} }

View file

@ -38,6 +38,8 @@ func (h header) MarshalJSON() ([]byte, error) {
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"` BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"` ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"blockAccessListHash" rlp:"optional"`
SlotNumber *math.HexOrDecimal64 `json:"slotNumber" rlp:"optional"` SlotNumber *math.HexOrDecimal64 `json:"slotNumber" rlp:"optional"`
} }
var enc header var enc header
@ -61,6 +63,8 @@ func (h header) MarshalJSON() ([]byte, error) {
enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed) enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed)
enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas) enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas)
enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot
enc.RequestsHash = h.RequestsHash
enc.BlockAccessListHash = h.BlockAccessListHash
enc.SlotNumber = (*math.HexOrDecimal64)(h.SlotNumber) enc.SlotNumber = (*math.HexOrDecimal64)(h.SlotNumber)
return json.Marshal(&enc) return json.Marshal(&enc)
} }
@ -88,6 +92,8 @@ func (h *header) UnmarshalJSON(input []byte) error {
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"` BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"` ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"blockAccessListHash" rlp:"optional"`
SlotNumber *math.HexOrDecimal64 `json:"slotNumber" rlp:"optional"` SlotNumber *math.HexOrDecimal64 `json:"slotNumber" rlp:"optional"`
} }
var dec header var dec header
@ -158,6 +164,12 @@ func (h *header) UnmarshalJSON(input []byte) error {
if dec.ParentBeaconBlockRoot != nil { if dec.ParentBeaconBlockRoot != nil {
h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
} }
if dec.RequestsHash != nil {
h.RequestsHash = dec.RequestsHash
}
if dec.BlockAccessListHash != nil {
h.BlockAccessListHash = dec.BlockAccessListHash
}
if dec.SlotNumber != nil { if dec.SlotNumber != nil {
h.SlotNumber = (*uint64)(dec.SlotNumber) h.SlotNumber = (*uint64)(dec.SlotNumber)
} }

View file

@ -121,7 +121,7 @@ func hasStorageWrite(b *bal.BlockAccessList, addr common.Address, key common.Has
return false return false
} }
want := new(uint256.Int).SetBytes(key[:]) want := new(uint256.Int).SetBytes(key[:])
for _, w := range aa.StorageWrites { for _, w := range aa.StorageChanges {
if w.Slot.Cmp(want) == 0 { if w.Slot.Cmp(want) == 0 {
return true return true
} }
@ -147,7 +147,7 @@ func assertAbsent(t *testing.T, b *bal.BlockAccessList, addr common.Address) {
func assertEmpty(t *testing.T, aa *bal.AccountAccess) { func assertEmpty(t *testing.T, aa *bal.AccountAccess) {
t.Helper() t.Helper()
if len(aa.StorageWrites) != 0 || len(aa.StorageReads) != 0 || if len(aa.StorageChanges) != 0 || len(aa.StorageReads) != 0 ||
len(aa.BalanceChanges) != 0 || len(aa.NonceChanges) != 0 || len(aa.CodeChanges) != 0 { len(aa.BalanceChanges) != 0 || len(aa.NonceChanges) != 0 || len(aa.CodeChanges) != 0 {
t.Fatalf("expected empty change set for %x, got %+v", aa.Address, aa) t.Fatalf("expected empty change set for %x, got %+v", aa.Address, aa)
} }
@ -181,14 +181,14 @@ func TestBALTxSenderAndRecipient(t *testing.T) {
}) })
sender := assertPresent(t, b, env.from) sender := assertPresent(t, b, env.from)
if len(sender.NonceChanges) == 0 || sender.NonceChanges[0].Nonce != 1 { if len(sender.NonceChanges) == 0 || sender.NonceChanges[0].PostNonce != 1 {
t.Fatalf("sender nonce not bumped: %+v", sender.NonceChanges) t.Fatalf("sender nonce not bumped: %+v", sender.NonceChanges)
} }
if len(sender.BalanceChanges) == 0 { if len(sender.BalanceChanges) == 0 {
t.Fatalf("sender missing balance change") t.Fatalf("sender missing balance change")
} }
recipient := assertPresent(t, b, to) recipient := assertPresent(t, b, to)
if len(recipient.BalanceChanges) != 1 || recipient.BalanceChanges[0].Balance.Uint64() != 1000 { if len(recipient.BalanceChanges) != 1 || recipient.BalanceChanges[0].PostBalance.Uint64() != 1000 {
t.Fatalf("recipient balance: %+v", recipient.BalanceChanges) t.Fatalf("recipient balance: %+v", recipient.BalanceChanges)
} }
} }
@ -236,7 +236,7 @@ func TestBALCoinbaseTipCapturesBalance(t *testing.T) {
}) })
cb := assertPresent(t, b, coinbase) cb := assertPresent(t, b, coinbase)
if len(cb.BalanceChanges) == 0 || cb.BalanceChanges[0].Balance.Sign() == 0 { if len(cb.BalanceChanges) == 0 || cb.BalanceChanges[0].PostBalance.Sign() == 0 {
t.Fatalf("coinbase missing positive balance change: %+v", cb.BalanceChanges) t.Fatalf("coinbase missing positive balance change: %+v", cb.BalanceChanges)
} }
} }
@ -264,7 +264,7 @@ func TestBALSystemAddressIncludedWhenTouched(t *testing.T) {
}) })
aa := assertPresent(t, b, sys) aa := assertPresent(t, b, sys)
if len(aa.BalanceChanges) != 1 || aa.BalanceChanges[0].Balance.Uint64() != 1000 { if len(aa.BalanceChanges) != 1 || aa.BalanceChanges[0].PostBalance.Uint64() != 1000 {
t.Fatalf("system-address balance change missing: %+v", aa.BalanceChanges) t.Fatalf("system-address balance change missing: %+v", aa.BalanceChanges)
} }
} }
@ -319,7 +319,7 @@ func TestBALPrecompileValueTransferRecordsBalance(t *testing.T) {
}) })
aa := assertPresent(t, b, identity) aa := assertPresent(t, b, identity)
if len(aa.BalanceChanges) != 1 || aa.BalanceChanges[0].Balance.Uint64() != 5 { if len(aa.BalanceChanges) != 1 || aa.BalanceChanges[0].PostBalance.Uint64() != 5 {
t.Fatalf("precompile balance change wrong: %+v", aa.BalanceChanges) t.Fatalf("precompile balance change wrong: %+v", aa.BalanceChanges)
} }
} }
@ -537,7 +537,7 @@ func TestBALSenderRecordedOnRevert(t *testing.T) {
}) })
sender := assertPresent(t, b, env.from) sender := assertPresent(t, b, env.from)
if len(sender.NonceChanges) == 0 || sender.NonceChanges[0].Nonce != 1 { if len(sender.NonceChanges) == 0 || sender.NonceChanges[0].PostNonce != 1 {
t.Fatalf("sender nonce must be bumped even on revert: %+v", sender.NonceChanges) t.Fatalf("sender nonce must be bumped even on revert: %+v", sender.NonceChanges)
} }
if len(sender.BalanceChanges) == 0 { if len(sender.BalanceChanges) == 0 {
@ -667,10 +667,10 @@ func TestBALStorageWriteZeroIsAWrite(t *testing.T) {
if !hasStorageWrite(b, contract, slot) { if !hasStorageWrite(b, contract, slot) {
t.Fatalf("SSTORE to zero must record a write\n%s", b.PrettyPrint()) t.Fatalf("SSTORE to zero must record a write\n%s", b.PrettyPrint())
} }
for _, w := range aa.StorageWrites { for _, w := range aa.StorageChanges {
if w.Slot.Uint64() == 0x03 { if w.Slot.Uint64() == 0x03 {
if len(w.Accesses) != 1 || !w.Accesses[0].ValueAfter.IsZero() { if len(w.SlotChanges) != 1 || !w.SlotChanges[0].PostValue.IsZero() {
t.Fatalf("expected post-value 0 for slot 0x03, got %+v", w.Accesses) t.Fatalf("expected post-value 0 for slot 0x03, got %+v", w.SlotChanges)
} }
} }
} }
@ -692,13 +692,13 @@ func TestBALCreateDeploysCode(t *testing.T) {
created := receipts[0].ContractAddress created := receipts[0].ContractAddress
aa := assertPresent(t, b, created) aa := assertPresent(t, b, created)
if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].Nonce != 1 { if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].PostNonce != 1 {
t.Fatalf("expected nonce 0→1, got %+v", aa.NonceChanges) t.Fatalf("expected nonce 0→1, got %+v", aa.NonceChanges)
} }
if len(aa.CodeChanges) != 1 || !bytes.Equal(aa.CodeChanges[0].Code, []byte{0x00}) { if len(aa.CodeChanges) != 1 || !bytes.Equal(aa.CodeChanges[0].NewCode, []byte{0x00}) {
t.Fatalf("expected code [0x00], got %+v", aa.CodeChanges) t.Fatalf("expected code [0x00], got %+v", aa.CodeChanges)
} }
if len(aa.BalanceChanges) != 1 || aa.BalanceChanges[0].Balance.Uint64() != 7 { if len(aa.BalanceChanges) != 1 || aa.BalanceChanges[0].PostBalance.Uint64() != 7 {
t.Fatalf("expected balance 7, got %+v", aa.BalanceChanges) t.Fatalf("expected balance 7, got %+v", aa.BalanceChanges)
} }
} }
@ -716,7 +716,7 @@ func TestBALCreateEmptyRuntimeNoCodeEntry(t *testing.T) {
created := receipts[0].ContractAddress created := receipts[0].ContractAddress
aa := assertPresent(t, b, created) aa := assertPresent(t, b, created)
if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].Nonce != 1 { if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].PostNonce != 1 {
t.Fatalf("expected nonce 0→1, got %+v", aa.NonceChanges) t.Fatalf("expected nonce 0→1, got %+v", aa.NonceChanges)
} }
if len(aa.CodeChanges) != 0 { if len(aa.CodeChanges) != 0 {
@ -849,7 +849,7 @@ func TestBALInEVMCreateDeploysContract(t *testing.T) {
// which is the factory's genesis nonce (1). // which is the factory's genesis nonce (1).
deployed := crypto.CreateAddress(factory, 1) deployed := crypto.CreateAddress(factory, 1)
aa := assertPresent(t, b, deployed) aa := assertPresent(t, b, deployed)
if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].Nonce != 1 { if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].PostNonce != 1 {
t.Fatalf("deployed contract nonce: %+v", aa.NonceChanges) t.Fatalf("deployed contract nonce: %+v", aa.NonceChanges)
} }
} }
@ -900,7 +900,7 @@ func TestBALSelfDestructBeneficiaryWithValueTransfer(t *testing.T) {
}) })
ben := assertPresent(t, b, beneficiary) ben := assertPresent(t, b, beneficiary)
if len(ben.BalanceChanges) != 1 || ben.BalanceChanges[0].Balance.Uint64() != 100 { if len(ben.BalanceChanges) != 1 || ben.BalanceChanges[0].PostBalance.Uint64() != 100 {
t.Fatalf("beneficiary balance must be credited with 100: %+v", ben.BalanceChanges) t.Fatalf("beneficiary balance must be credited with 100: %+v", ben.BalanceChanges)
} }
} }
@ -925,11 +925,11 @@ func TestBALSelfDestructPreExistingContract(t *testing.T) {
}) })
aa := assertPresent(t, b, suicidal) aa := assertPresent(t, b, suicidal)
if len(aa.BalanceChanges) != 1 || !aa.BalanceChanges[0].Balance.IsZero() { if len(aa.BalanceChanges) != 1 || !aa.BalanceChanges[0].PostBalance.IsZero() {
t.Fatalf("suicidal contract balance should drop to 0: %+v", aa.BalanceChanges) t.Fatalf("suicidal contract balance should drop to 0: %+v", aa.BalanceChanges)
} }
ben := assertPresent(t, b, beneficiary) ben := assertPresent(t, b, beneficiary)
if len(ben.BalanceChanges) != 1 || ben.BalanceChanges[0].Balance.Uint64() != 50 { if len(ben.BalanceChanges) != 1 || ben.BalanceChanges[0].PostBalance.Uint64() != 50 {
t.Fatalf("beneficiary should receive 50: %+v", ben.BalanceChanges) t.Fatalf("beneficiary should receive 50: %+v", ben.BalanceChanges)
} }
} }
@ -1041,7 +1041,7 @@ func TestBALWithdrawalNonZeroAmountRecordsBalance(t *testing.T) {
}) })
r := assertPresent(t, b, recipient) r := assertPresent(t, b, recipient)
if len(r.BalanceChanges) != 1 || r.BalanceChanges[0].Balance.Sign() == 0 { if len(r.BalanceChanges) != 1 || r.BalanceChanges[0].PostBalance.Sign() == 0 {
t.Fatalf("withdrawal balance change missing: %+v", r.BalanceChanges) t.Fatalf("withdrawal balance change missing: %+v", r.BalanceChanges)
} }
} }
@ -1266,7 +1266,7 @@ func TestBALAuthCodeRoundTripNoCodeEntry(t *testing.T) {
}) })
aa := assertPresent(t, b, authority) aa := assertPresent(t, b, authority)
if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].Nonce != 2 { if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].PostNonce != 2 {
t.Fatalf("expected final nonce 2, got %+v", aa.NonceChanges) t.Fatalf("expected final nonce 2, got %+v", aa.NonceChanges)
} }
if len(aa.CodeChanges) != 0 { if len(aa.CodeChanges) != 0 {
@ -1310,10 +1310,10 @@ func TestBALAuthCodeOverwrittenFinalRecorded(t *testing.T) {
t.Fatalf("expected exactly 1 code change (final), got %+v", aa.CodeChanges) t.Fatalf("expected exactly 1 code change (final), got %+v", aa.CodeChanges)
} }
want := types.AddressToDelegation(delegateB) want := types.AddressToDelegation(delegateB)
if !bytes.Equal(aa.CodeChanges[0].Code, want) { if !bytes.Equal(aa.CodeChanges[0].NewCode, want) {
t.Fatalf("final code mismatch: want %x, got %x", want, aa.CodeChanges[0].Code) t.Fatalf("final code mismatch: want %x, got %x", want, aa.CodeChanges[0].NewCode)
} }
if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].Nonce != 2 { if len(aa.NonceChanges) != 1 || aa.NonceChanges[0].PostNonce != 2 {
t.Fatalf("expected final nonce 2, got %+v", aa.NonceChanges) t.Fatalf("expected final nonce 2, got %+v", aa.NonceChanges)
} }
} }

View file

@ -27,6 +27,7 @@ import (
"strings" "strings"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -99,7 +100,7 @@ func (e *BlockAccessList) Validate(blockGasLimit uint64, blockTxCount int) error
func (e *BlockAccessList) itemCount() uint64 { func (e *BlockAccessList) itemCount() uint64 {
count := uint64(len(*e)) // distinct addresses count := uint64(len(*e)) // distinct addresses
for i := range *e { for i := range *e {
count += uint64(len((*e)[i].StorageWrites)) + uint64(len((*e)[i].StorageReads)) count += uint64(len((*e)[i].StorageChanges)) + uint64(len((*e)[i].StorageReads))
} }
return count return count
} }
@ -130,28 +131,38 @@ func (e *BlockAccessList) Hash() common.Hash {
return crypto.Keccak256Hash(enc.Bytes()) return crypto.Keccak256Hash(enc.Bytes())
} }
// encodingBalanceChange is the encoding format of BalanceChange. // EIP-7928 encoding types. Field names and JSON keys mirror the
type encodingBalanceChange struct { // execution-spec-tests Pydantic models in
TxIdx uint32 // `src/ethereum_test_types/block_access_list/account_changes.py`. Hex
Balance *uint256.Int // formatting on JSON output is supplied via the gencodec overrides
} // below.
// encodingAccountNonce is the encoding format of NonceChange. //go:generate go run github.com/fjl/gencodec -type encodingStorageWrite -field-override encodingStorageWriteMarshaling -out gen_encoding_storage_write_json.go
type encodingAccountNonce struct { //go:generate go run github.com/fjl/gencodec -type encodingSlotChanges -field-override encodingSlotChangesMarshaling -out gen_encoding_slot_changes_json.go
TxIdx uint32 //go:generate go run github.com/fjl/gencodec -type encodingBalanceChange -field-override encodingBalanceChangeMarshaling -out gen_encoding_balance_change_json.go
Nonce uint64 //go:generate go run github.com/fjl/gencodec -type encodingAccountNonce -field-override encodingAccountNonceMarshaling -out gen_encoding_account_nonce_json.go
} //go:generate go run github.com/fjl/gencodec -type encodingCodeChange -field-override encodingCodeChangeMarshaling -out gen_encoding_code_change_json.go
//go:generate go run github.com/fjl/gencodec -type AccountAccess -field-override accountAccessMarshaling -out gen_account_access_json.go
// encodingStorageWrite is the encoding format of StorageWrites. // encodingStorageWrite is one transaction's write to a storage slot.
type encodingStorageWrite struct { type encodingStorageWrite struct {
TxIdx uint32 BlockAccessIndex uint32 `json:"blockAccessIndex"`
ValueAfter *uint256.Int PostValue *uint256.Int `json:"postValue"`
} }
// encodingStorageWrite is the encoding format of SlotWrites. type encodingStorageWriteMarshaling struct {
type encodingSlotWrites struct { BlockAccessIndex hexutil.Uint64
Slot *uint256.Int PostValue *hexutil.U256
Accesses []encodingStorageWrite }
// encodingSlotChanges aggregates all per-tx writes to a single storage slot.
type encodingSlotChanges struct {
Slot *uint256.Int `json:"slot"`
SlotChanges []encodingStorageWrite `json:"slotChanges"`
}
type encodingSlotChangesMarshaling struct {
Slot *hexutil.U256
} }
func isStrictlySortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool { func isStrictlySortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
@ -166,33 +177,63 @@ func isStrictlySortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
// validate asserts that the encodingSlotWrites contain storage modfications // validate asserts that the encodingSlotWrites contain storage modfications
// which are ordered ascending by transaction index and contain no duplicate // which are ordered ascending by transaction index and contain no duplicate
// modifications for a given index. // modifications for a given index.
func (e *encodingSlotWrites) validate(maxBALIndex int) error { func (e *encodingSlotChanges) validate(maxBALIndex int) error {
if !isStrictlySortedFunc(e.Accesses, func(a, b encodingStorageWrite) int { if !isStrictlySortedFunc(e.SlotChanges, func(a, b encodingStorageWrite) int {
return cmp.Compare(a.TxIdx, b.TxIdx) return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex)
}) { }) {
return errors.New("storage write indexes must be unique and sorted") return errors.New("storage write indexes must be unique and sorted")
} }
if len(e.Accesses) > 0 && int(e.Accesses[len(e.Accesses)-1].TxIdx) > maxBALIndex { if len(e.SlotChanges) > 0 && int(e.SlotChanges[len(e.SlotChanges)-1].BlockAccessIndex) > maxBALIndex {
return fmt.Errorf("storage write index exceeds limit, index: %d, limit: %d", e.Accesses[len(e.Accesses)-1].TxIdx, maxBALIndex) return fmt.Errorf("storage write index exceeds limit, index: %d, limit: %d", e.SlotChanges[len(e.SlotChanges)-1].BlockAccessIndex, maxBALIndex)
} }
return nil return nil
} }
// encodingCodeChange contains the runtime bytecode deployed at an address // encodingBalanceChange is one transaction's post-state balance for an account.
// and the transaction index where the deployment took place. type encodingBalanceChange struct {
BlockAccessIndex uint32 `json:"blockAccessIndex"`
PostBalance *uint256.Int `json:"postBalance"`
}
type encodingBalanceChangeMarshaling struct {
BlockAccessIndex hexutil.Uint64
PostBalance *hexutil.U256
}
// encodingAccountNonce is one transaction's post-state nonce for an account.
type encodingAccountNonce struct {
BlockAccessIndex uint32 `json:"blockAccessIndex"`
PostNonce uint64 `json:"postNonce"`
}
type encodingAccountNonceMarshaling struct {
BlockAccessIndex hexutil.Uint64
PostNonce hexutil.Uint64
}
// encodingCodeChange is one transaction's deployed runtime bytecode for an account.
type encodingCodeChange struct { type encodingCodeChange struct {
TxIndex uint32 BlockAccessIndex uint32 `json:"blockAccessIndex"`
Code []byte NewCode []byte `json:"newCode"`
}
type encodingCodeChangeMarshaling struct {
BlockAccessIndex hexutil.Uint64
NewCode hexutil.Bytes
} }
// AccountAccess is the encoding format of ConstructionAccountAccess. // AccountAccess is the encoding format of ConstructionAccountAccess.
type AccountAccess struct { type AccountAccess struct {
Address [20]byte // 20-byte Ethereum address Address common.Address `json:"address"`
StorageWrites []encodingSlotWrites // Storage changes (slot -> [tx_index -> new_value]) StorageChanges []encodingSlotChanges `json:"storageChanges"`
StorageReads []*uint256.Int // Read-only storage keys StorageReads []*uint256.Int `json:"storageReads"`
BalanceChanges []encodingBalanceChange // Balance changes ([tx_index -> post_balance]) BalanceChanges []encodingBalanceChange `json:"balanceChanges"`
NonceChanges []encodingAccountNonce // Nonce changes ([tx_index -> new_nonce]) NonceChanges []encodingAccountNonce `json:"nonceChanges"`
CodeChanges []encodingCodeChange // Code changes ([tx_index -> new_code]) CodeChanges []encodingCodeChange `json:"codeChanges"`
}
type accountAccessMarshaling struct {
StorageReads []*hexutil.U256
} }
// validate converts the account accesses out of encoding format. // validate converts the account accesses out of encoding format.
@ -200,13 +241,13 @@ type AccountAccess struct {
// spec, an error is returned. // spec, an error is returned.
func (e *AccountAccess) validate(maxBALIndex int) error { func (e *AccountAccess) validate(maxBALIndex int) error {
// Check the storage writes are sorted in order, and unique by slot // Check the storage writes are sorted in order, and unique by slot
if !isStrictlySortedFunc(e.StorageWrites, func(a, b encodingSlotWrites) int { if !isStrictlySortedFunc(e.StorageChanges, func(a, b encodingSlotChanges) int {
return a.Slot.Cmp(b.Slot) return a.Slot.Cmp(b.Slot)
}) { }) {
return errors.New("storage write slots must be unique and sorted") return errors.New("storage write slots must be unique and sorted")
} }
// Check the validity of each storage slot's mutations // Check the validity of each storage slot's mutations
for _, slotWrites := range e.StorageWrites { for _, slotWrites := range e.StorageChanges {
if err := slotWrites.validate(maxBALIndex); err != nil { if err := slotWrites.validate(maxBALIndex); err != nil {
return err return err
} }
@ -223,13 +264,13 @@ func (e *AccountAccess) validate(maxBALIndex int) error {
// set of read slots. // set of read slots.
var ( var (
readKeys = make(map[common.Hash]struct{}, len(e.StorageReads)) readKeys = make(map[common.Hash]struct{}, len(e.StorageReads))
writeKeys = make(map[common.Hash]struct{}, len(e.StorageWrites)) writeKeys = make(map[common.Hash]struct{}, len(e.StorageChanges))
) )
for _, rk := range e.StorageReads { for _, rk := range e.StorageReads {
readKey := common.BytesToHash(rk.Bytes()) readKey := common.BytesToHash(rk.Bytes())
readKeys[readKey] = struct{}{} readKeys[readKey] = struct{}{}
} }
for _, write := range e.StorageWrites { for _, write := range e.StorageChanges {
writeKey := common.BytesToHash(write.Slot.Bytes()) writeKey := common.BytesToHash(write.Slot.Bytes())
writeKeys[writeKey] = struct{}{} writeKeys[writeKey] = struct{}{}
} }
@ -241,42 +282,42 @@ func (e *AccountAccess) validate(maxBALIndex int) error {
// Check the balance changes are sorted in order, and unique by tx index // Check the balance changes are sorted in order, and unique by tx index
if !isStrictlySortedFunc(e.BalanceChanges, func(a, b encodingBalanceChange) int { if !isStrictlySortedFunc(e.BalanceChanges, func(a, b encodingBalanceChange) int {
return cmp.Compare(a.TxIdx, b.TxIdx) return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex)
}) { }) {
return errors.New("balance changes must be unique and sorted") return errors.New("balance changes must be unique and sorted")
} }
// check that the tx index is not greater than the max allowed for the block // check that the tx index is not greater than the max allowed for the block
if len(e.BalanceChanges) > 0 && int(e.BalanceChanges[len(e.BalanceChanges)-1].TxIdx) > maxBALIndex { if len(e.BalanceChanges) > 0 && int(e.BalanceChanges[len(e.BalanceChanges)-1].BlockAccessIndex) > maxBALIndex {
return fmt.Errorf("balance change index exceeds limit, index: %d, limit: %d", e.BalanceChanges[len(e.BalanceChanges)-1].TxIdx, maxBALIndex) return fmt.Errorf("balance change index exceeds limit, index: %d, limit: %d", e.BalanceChanges[len(e.BalanceChanges)-1].BlockAccessIndex, maxBALIndex)
} }
// Check the nonce changes are sorted in order, and unique by tx index // Check the nonce changes are sorted in order, and unique by tx index
if !isStrictlySortedFunc(e.NonceChanges, func(a, b encodingAccountNonce) int { if !isStrictlySortedFunc(e.NonceChanges, func(a, b encodingAccountNonce) int {
return cmp.Compare(a.TxIdx, b.TxIdx) return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex)
}) { }) {
return errors.New("nonce changes must be unique and sorted") return errors.New("nonce changes must be unique and sorted")
} }
// check that the tx index of the highest nonce change is not greater than // check that the tx index of the highest nonce change is not greater than
// the max allowed for the block // the max allowed for the block
if len(e.NonceChanges) > 0 && int(e.NonceChanges[len(e.NonceChanges)-1].TxIdx) > maxBALIndex { if len(e.NonceChanges) > 0 && int(e.NonceChanges[len(e.NonceChanges)-1].BlockAccessIndex) > maxBALIndex {
return fmt.Errorf("nonce change index exceeds limit, index: %d, limit: %d", e.NonceChanges[len(e.NonceChanges)-1].TxIdx, maxBALIndex) return fmt.Errorf("nonce change index exceeds limit, index: %d, limit: %d", e.NonceChanges[len(e.NonceChanges)-1].BlockAccessIndex, maxBALIndex)
} }
// Check the code changes are sorted in order, and unique by tx index // Check the code changes are sorted in order, and unique by tx index
if !isStrictlySortedFunc(e.CodeChanges, func(a, b encodingCodeChange) int { if !isStrictlySortedFunc(e.CodeChanges, func(a, b encodingCodeChange) int {
return cmp.Compare(a.TxIndex, b.TxIndex) return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex)
}) { }) {
return errors.New("code changes must be unique and sorted") return errors.New("code changes must be unique and sorted")
} }
// check that the tx index of the highest code changeis not greater than the // check that the tx index of the highest code changeis not greater than the
// max allowed for the block // max allowed for the block
if len(e.CodeChanges) > 0 && int(e.CodeChanges[len(e.CodeChanges)-1].TxIndex) > maxBALIndex { if len(e.CodeChanges) > 0 && int(e.CodeChanges[len(e.CodeChanges)-1].BlockAccessIndex) > maxBALIndex {
return fmt.Errorf("code change index exceeds limit, index: %d, limit: %d", e.CodeChanges[len(e.CodeChanges)-1].TxIndex, maxBALIndex) return fmt.Errorf("code change index exceeds limit, index: %d, limit: %d", e.CodeChanges[len(e.CodeChanges)-1].BlockAccessIndex, maxBALIndex)
} }
// Check that none of the code changes report a new code which is larger // Check that none of the code changes report a new code which is larger
// than the max allowed by the protocol // than the max allowed by the protocol
for _, change := range e.CodeChanges { for _, change := range e.CodeChanges {
if len(change.Code) > params.MaxCodeSizeAmsterdam { if len(change.NewCode) > params.MaxCodeSizeAmsterdam {
return errors.New("code change contained oversized code") return errors.New("code change contained oversized code")
} }
} }
@ -290,7 +331,7 @@ func (e *AccountAccess) Copy() AccountAccess {
StorageReads: make([]*uint256.Int, 0, len(e.StorageReads)), StorageReads: make([]*uint256.Int, 0, len(e.StorageReads)),
BalanceChanges: make([]encodingBalanceChange, 0, len(e.BalanceChanges)), BalanceChanges: make([]encodingBalanceChange, 0, len(e.BalanceChanges)),
NonceChanges: slices.Clone(e.NonceChanges), NonceChanges: slices.Clone(e.NonceChanges),
StorageWrites: make([]encodingSlotWrites, 0, len(e.StorageWrites)), StorageChanges: make([]encodingSlotChanges, 0, len(e.StorageChanges)),
CodeChanges: make([]encodingCodeChange, 0, len(e.CodeChanges)), CodeChanges: make([]encodingCodeChange, 0, len(e.CodeChanges)),
} }
for _, slot := range e.StorageReads { for _, slot := range e.StorageReads {
@ -298,27 +339,27 @@ func (e *AccountAccess) Copy() AccountAccess {
} }
for _, change := range e.BalanceChanges { for _, change := range e.BalanceChanges {
res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{ res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{
TxIdx: change.TxIdx, BlockAccessIndex: change.BlockAccessIndex,
Balance: change.Balance.Clone(), PostBalance: change.PostBalance.Clone(),
}) })
} }
for _, storageWrite := range e.StorageWrites { for _, slot := range e.StorageChanges {
accesses := make([]encodingStorageWrite, 0, len(storageWrite.Accesses)) writes := make([]encodingStorageWrite, 0, len(slot.SlotChanges))
for _, w := range storageWrite.Accesses { for _, w := range slot.SlotChanges {
accesses = append(accesses, encodingStorageWrite{ writes = append(writes, encodingStorageWrite{
TxIdx: w.TxIdx, BlockAccessIndex: w.BlockAccessIndex,
ValueAfter: w.ValueAfter.Clone(), PostValue: w.PostValue.Clone(),
}) })
} }
res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{ res.StorageChanges = append(res.StorageChanges, encodingSlotChanges{
Slot: storageWrite.Slot.Clone(), Slot: slot.Slot.Clone(),
Accesses: accesses, SlotChanges: writes,
}) })
} }
for _, codeChange := range e.CodeChanges { for _, codeChange := range e.CodeChanges {
res.CodeChanges = append(res.CodeChanges, encodingCodeChange{ res.CodeChanges = append(res.CodeChanges, encodingCodeChange{
TxIndex: codeChange.TxIndex, BlockAccessIndex: codeChange.BlockAccessIndex,
Code: bytes.Clone(codeChange.Code), NewCode: bytes.Clone(codeChange.NewCode),
}) })
} }
return res return res
@ -336,7 +377,7 @@ var _ rlp.Encoder = &ConstructionBlockAccessList{}
func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAccess { func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAccess {
res := AccountAccess{ res := AccountAccess{
Address: addr, Address: addr,
StorageWrites: make([]encodingSlotWrites, 0, len(a.StorageWrites)), StorageChanges: make([]encodingSlotChanges, 0, len(a.StorageWrites)),
StorageReads: make([]*uint256.Int, 0, len(a.StorageReads)), StorageReads: make([]*uint256.Int, 0, len(a.StorageReads)),
BalanceChanges: make([]encodingBalanceChange, 0, len(a.BalanceChanges)), BalanceChanges: make([]encodingBalanceChange, 0, len(a.BalanceChanges)),
NonceChanges: make([]encodingAccountNonce, 0, len(a.NonceChanges)), NonceChanges: make([]encodingAccountNonce, 0, len(a.NonceChanges)),
@ -347,22 +388,22 @@ func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAc
writeSlots := slices.Collect(maps.Keys(a.StorageWrites)) writeSlots := slices.Collect(maps.Keys(a.StorageWrites))
slices.SortFunc(writeSlots, common.Hash.Cmp) slices.SortFunc(writeSlots, common.Hash.Cmp)
for _, slot := range writeSlots { for _, slot := range writeSlots {
obj := encodingSlotWrites{ obj := encodingSlotChanges{
Slot: new(uint256.Int).SetBytes(slot[:]), Slot: new(uint256.Int).SetBytes(slot[:]),
} }
slotWrites := a.StorageWrites[slot] slotWrites := a.StorageWrites[slot]
obj.Accesses = make([]encodingStorageWrite, 0, len(slotWrites)) obj.SlotChanges = make([]encodingStorageWrite, 0, len(slotWrites))
indices := slices.Collect(maps.Keys(slotWrites)) indices := slices.Collect(maps.Keys(slotWrites))
slices.SortFunc(indices, cmp.Compare[uint32]) slices.SortFunc(indices, cmp.Compare)
for _, index := range indices { for _, index := range indices {
val := slotWrites[index] val := slotWrites[index]
obj.Accesses = append(obj.Accesses, encodingStorageWrite{ obj.SlotChanges = append(obj.SlotChanges, encodingStorageWrite{
TxIdx: index, BlockAccessIndex: index,
ValueAfter: new(uint256.Int).SetBytes(val[:]), PostValue: new(uint256.Int).SetBytes(val[:]),
}) })
} }
res.StorageWrites = append(res.StorageWrites, obj) res.StorageChanges = append(res.StorageChanges, obj)
} }
// Convert read slots // Convert read slots
@ -374,36 +415,36 @@ func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAc
// Convert balance changes // Convert balance changes
balanceIndices := slices.Collect(maps.Keys(a.BalanceChanges)) balanceIndices := slices.Collect(maps.Keys(a.BalanceChanges))
slices.SortFunc(balanceIndices, cmp.Compare[uint32]) slices.SortFunc(balanceIndices, cmp.Compare)
for _, idx := range balanceIndices { for _, idx := range balanceIndices {
res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{ res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{
TxIdx: idx, BlockAccessIndex: idx,
Balance: a.BalanceChanges[idx].Clone(), PostBalance: a.BalanceChanges[idx].Clone(),
}) })
} }
// Convert nonce changes // Convert nonce changes
nonceIndices := slices.Collect(maps.Keys(a.NonceChanges)) nonceIndices := slices.Collect(maps.Keys(a.NonceChanges))
slices.SortFunc(nonceIndices, cmp.Compare[uint32]) slices.SortFunc(nonceIndices, cmp.Compare)
for _, idx := range nonceIndices { for _, idx := range nonceIndices {
res.NonceChanges = append(res.NonceChanges, encodingAccountNonce{ res.NonceChanges = append(res.NonceChanges, encodingAccountNonce{
TxIdx: idx, BlockAccessIndex: idx,
Nonce: a.NonceChanges[idx], PostNonce: a.NonceChanges[idx],
}) })
} }
// Convert code change // Convert code change
codeIndices := slices.Collect(maps.Keys(a.CodeChange)) codeIndices := slices.Collect(maps.Keys(a.CodeChange))
slices.SortFunc(codeIndices, cmp.Compare[uint32]) slices.SortFunc(codeIndices, cmp.Compare)
for _, idx := range codeIndices { for _, idx := range codeIndices {
res.CodeChanges = append(res.CodeChanges, encodingCodeChange{ res.CodeChanges = append(res.CodeChanges, encodingCodeChange{
TxIndex: idx, BlockAccessIndex: idx,
// TODO(rjl493456442) the contract code is not deep-copied. // TODO(rjl493456442) the contract code is not deep-copied.
// In theory the deep-copy is unnecessary, the semantics of // In theory the deep-copy is unnecessary, the semantics of
// the function should be probably changed that the returned // the function should be probably changed that the returned
// AccessList is unsafe for modification. // AccessList is unsafe for modification.
Code: a.CodeChange[idx], NewCode: a.CodeChange[idx],
}) })
} }
return res return res
@ -432,33 +473,28 @@ func (e *BlockAccessList) PrettyPrint() string {
} }
for _, accountDiff := range *e { for _, accountDiff := range *e {
printWithIndent(0, fmt.Sprintf("%x:", accountDiff.Address)) printWithIndent(0, fmt.Sprintf("%x:", accountDiff.Address))
printWithIndent(1, "storage changes:")
printWithIndent(1, "storage writes:") for _, slot := range accountDiff.StorageChanges {
for _, sWrite := range accountDiff.StorageWrites { printWithIndent(2, fmt.Sprintf("%s:", slot.Slot.Hex()))
printWithIndent(2, fmt.Sprintf("%s:", sWrite.Slot.Hex())) for _, access := range slot.SlotChanges {
for _, access := range sWrite.Accesses { printWithIndent(3, fmt.Sprintf("%d: %s", access.BlockAccessIndex, access.PostValue.Hex()))
printWithIndent(3, fmt.Sprintf("%d: %s", access.TxIdx, access.ValueAfter.Hex()))
} }
} }
printWithIndent(1, "storage reads:") printWithIndent(1, "storage reads:")
for _, slot := range accountDiff.StorageReads { for _, slot := range accountDiff.StorageReads {
printWithIndent(2, slot.Hex()) printWithIndent(2, slot.Hex())
} }
printWithIndent(1, "balance changes:") printWithIndent(1, "balance changes:")
for _, change := range accountDiff.BalanceChanges { for _, change := range accountDiff.BalanceChanges {
printWithIndent(2, fmt.Sprintf("%d: %s", change.TxIdx, change.Balance)) printWithIndent(2, fmt.Sprintf("%d: %s", change.BlockAccessIndex, change.PostBalance))
} }
printWithIndent(1, "nonce changes:") printWithIndent(1, "nonce changes:")
for _, change := range accountDiff.NonceChanges { for _, change := range accountDiff.NonceChanges {
printWithIndent(2, fmt.Sprintf("%d: %d", change.TxIdx, change.Nonce)) printWithIndent(2, fmt.Sprintf("%d: %d", change.BlockAccessIndex, change.PostNonce))
} }
printWithIndent(1, "code changes:") printWithIndent(1, "code changes:")
for _, change := range accountDiff.CodeChanges { for _, change := range accountDiff.CodeChanges {
printWithIndent(2, fmt.Sprintf("%d: %x", change.TxIndex, change.Code)) printWithIndent(2, fmt.Sprintf("%d: %x", change.BlockAccessIndex, change.NewCode))
} }
} }
return res.String() return res.String()

View file

@ -2,6 +2,7 @@
package bal package bal
import "github.com/ethereum/go-ethereum/common"
import "github.com/ethereum/go-ethereum/rlp" import "github.com/ethereum/go-ethereum/rlp"
import "github.com/holiman/uint256" import "github.com/holiman/uint256"
import "io" import "io"
@ -11,7 +12,7 @@ func (obj *AccountAccess) EncodeRLP(_w io.Writer) error {
_tmp0 := w.List() _tmp0 := w.List()
w.WriteBytes(obj.Address[:]) w.WriteBytes(obj.Address[:])
_tmp1 := w.List() _tmp1 := w.List()
for _, _tmp2 := range obj.StorageWrites { for _, _tmp2 := range obj.StorageChanges {
_tmp3 := w.List() _tmp3 := w.List()
if _tmp2.Slot == nil { if _tmp2.Slot == nil {
w.Write(rlp.EmptyString) w.Write(rlp.EmptyString)
@ -19,13 +20,13 @@ func (obj *AccountAccess) EncodeRLP(_w io.Writer) error {
w.WriteUint256(_tmp2.Slot) w.WriteUint256(_tmp2.Slot)
} }
_tmp4 := w.List() _tmp4 := w.List()
for _, _tmp5 := range _tmp2.Accesses { for _, _tmp5 := range _tmp2.SlotChanges {
_tmp6 := w.List() _tmp6 := w.List()
w.WriteUint64(uint64(_tmp5.TxIdx)) w.WriteUint64(uint64(_tmp5.BlockAccessIndex))
if _tmp5.ValueAfter == nil { if _tmp5.PostValue == nil {
w.Write(rlp.EmptyString) w.Write(rlp.EmptyString)
} else { } else {
w.WriteUint256(_tmp5.ValueAfter) w.WriteUint256(_tmp5.PostValue)
} }
w.ListEnd(_tmp6) w.ListEnd(_tmp6)
} }
@ -45,11 +46,11 @@ func (obj *AccountAccess) EncodeRLP(_w io.Writer) error {
_tmp9 := w.List() _tmp9 := w.List()
for _, _tmp10 := range obj.BalanceChanges { for _, _tmp10 := range obj.BalanceChanges {
_tmp11 := w.List() _tmp11 := w.List()
w.WriteUint64(uint64(_tmp10.TxIdx)) w.WriteUint64(uint64(_tmp10.BlockAccessIndex))
if _tmp10.Balance == nil { if _tmp10.PostBalance == nil {
w.Write(rlp.EmptyString) w.Write(rlp.EmptyString)
} else { } else {
w.WriteUint256(_tmp10.Balance) w.WriteUint256(_tmp10.PostBalance)
} }
w.ListEnd(_tmp11) w.ListEnd(_tmp11)
} }
@ -57,16 +58,16 @@ func (obj *AccountAccess) EncodeRLP(_w io.Writer) error {
_tmp12 := w.List() _tmp12 := w.List()
for _, _tmp13 := range obj.NonceChanges { for _, _tmp13 := range obj.NonceChanges {
_tmp14 := w.List() _tmp14 := w.List()
w.WriteUint64(uint64(_tmp13.TxIdx)) w.WriteUint64(uint64(_tmp13.BlockAccessIndex))
w.WriteUint64(_tmp13.Nonce) w.WriteUint64(_tmp13.PostNonce)
w.ListEnd(_tmp14) w.ListEnd(_tmp14)
} }
w.ListEnd(_tmp12) w.ListEnd(_tmp12)
_tmp15 := w.List() _tmp15 := w.List()
for _, _tmp16 := range obj.CodeChanges { for _, _tmp16 := range obj.CodeChanges {
_tmp17 := w.List() _tmp17 := w.List()
w.WriteUint64(uint64(_tmp16.TxIndex)) w.WriteUint64(uint64(_tmp16.BlockAccessIndex))
w.WriteBytes(_tmp16.Code) w.WriteBytes(_tmp16.NewCode)
w.ListEnd(_tmp17) w.ListEnd(_tmp17)
} }
w.ListEnd(_tmp15) w.ListEnd(_tmp15)
@ -81,18 +82,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error {
return err return err
} }
// Address: // Address:
var _tmp1 [20]byte var _tmp1 common.Address
if err := dec.ReadBytes(_tmp1[:]); err != nil { if err := dec.ReadBytes(_tmp1[:]); err != nil {
return err return err
} }
_tmp0.Address = _tmp1 _tmp0.Address = _tmp1
// StorageWrites: // StorageChanges:
var _tmp2 []encodingSlotWrites var _tmp2 []encodingSlotChanges
if _, err := dec.List(); err != nil { if _, err := dec.List(); err != nil {
return err return err
} }
for dec.MoreDataInList() { for dec.MoreDataInList() {
var _tmp3 encodingSlotWrites var _tmp3 encodingSlotChanges
{ {
if _, err := dec.List(); err != nil { if _, err := dec.List(); err != nil {
return err return err
@ -103,7 +104,7 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error {
return err return err
} }
_tmp3.Slot = &_tmp4 _tmp3.Slot = &_tmp4
// Accesses: // SlotChanges:
var _tmp5 []encodingStorageWrite var _tmp5 []encodingStorageWrite
if _, err := dec.List(); err != nil { if _, err := dec.List(); err != nil {
return err return err
@ -114,18 +115,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error {
if _, err := dec.List(); err != nil { if _, err := dec.List(); err != nil {
return err return err
} }
// TxIdx: // BlockAccessIndex:
_tmp7, err := dec.Uint32() _tmp7, err := dec.Uint32()
if err != nil { if err != nil {
return err return err
} }
_tmp6.TxIdx = _tmp7 _tmp6.BlockAccessIndex = _tmp7
// ValueAfter: // PostValue:
var _tmp8 uint256.Int var _tmp8 uint256.Int
if err := dec.ReadUint256(&_tmp8); err != nil { if err := dec.ReadUint256(&_tmp8); err != nil {
return err return err
} }
_tmp6.ValueAfter = &_tmp8 _tmp6.PostValue = &_tmp8
if err := dec.ListEnd(); err != nil { if err := dec.ListEnd(); err != nil {
return err return err
} }
@ -135,7 +136,7 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error {
if err := dec.ListEnd(); err != nil { if err := dec.ListEnd(); err != nil {
return err return err
} }
_tmp3.Accesses = _tmp5 _tmp3.SlotChanges = _tmp5
if err := dec.ListEnd(); err != nil { if err := dec.ListEnd(); err != nil {
return err return err
} }
@ -145,7 +146,7 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error {
if err := dec.ListEnd(); err != nil { if err := dec.ListEnd(); err != nil {
return err return err
} }
_tmp0.StorageWrites = _tmp2 _tmp0.StorageChanges = _tmp2
// StorageReads: // StorageReads:
var _tmp9 []*uint256.Int var _tmp9 []*uint256.Int
if _, err := dec.List(); err != nil { if _, err := dec.List(); err != nil {
@ -173,18 +174,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error {
if _, err := dec.List(); err != nil { if _, err := dec.List(); err != nil {
return err return err
} }
// TxIdx: // BlockAccessIndex:
_tmp13, err := dec.Uint32() _tmp13, err := dec.Uint32()
if err != nil { if err != nil {
return err return err
} }
_tmp12.TxIdx = _tmp13 _tmp12.BlockAccessIndex = _tmp13
// Balance: // PostBalance:
var _tmp14 uint256.Int var _tmp14 uint256.Int
if err := dec.ReadUint256(&_tmp14); err != nil { if err := dec.ReadUint256(&_tmp14); err != nil {
return err return err
} }
_tmp12.Balance = &_tmp14 _tmp12.PostBalance = &_tmp14
if err := dec.ListEnd(); err != nil { if err := dec.ListEnd(); err != nil {
return err return err
} }
@ -206,18 +207,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error {
if _, err := dec.List(); err != nil { if _, err := dec.List(); err != nil {
return err return err
} }
// TxIdx: // BlockAccessIndex:
_tmp17, err := dec.Uint32() _tmp17, err := dec.Uint32()
if err != nil { if err != nil {
return err return err
} }
_tmp16.TxIdx = _tmp17 _tmp16.BlockAccessIndex = _tmp17
// Nonce: // PostNonce:
_tmp18, err := dec.Uint64() _tmp18, err := dec.Uint64()
if err != nil { if err != nil {
return err return err
} }
_tmp16.Nonce = _tmp18 _tmp16.PostNonce = _tmp18
if err := dec.ListEnd(); err != nil { if err := dec.ListEnd(); err != nil {
return err return err
} }
@ -239,18 +240,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error {
if _, err := dec.List(); err != nil { if _, err := dec.List(); err != nil {
return err return err
} }
// TxIndex: // BlockAccessIndex:
_tmp21, err := dec.Uint32() _tmp21, err := dec.Uint32()
if err != nil { if err != nil {
return err return err
} }
_tmp20.TxIndex = _tmp21 _tmp20.BlockAccessIndex = _tmp21
// Code: // NewCode:
_tmp22, err := dec.Bytes() _tmp22, err := dec.Bytes()
if err != nil { if err != nil {
return err return err
} }
_tmp20.Code = _tmp22 _tmp20.NewCode = _tmp22
if err := dec.ListEnd(); err != nil { if err := dec.ListEnd(); err != nil {
return err return err
} }

View file

@ -160,7 +160,7 @@ func TestConstructionBALMerge(t *testing.T) {
func makeTestAccountAccess(sort bool) AccountAccess { func makeTestAccountAccess(sort bool) AccountAccess {
var ( var (
storageWrites []encodingSlotWrites storageWrites []encodingSlotChanges
storageReads []*uint256.Int storageReads []*uint256.Int
balances []encodingBalanceChange balances []encodingBalanceChange
nonces []encodingAccountNonce nonces []encodingAccountNonce
@ -170,24 +170,24 @@ func makeTestAccountAccess(sort bool) AccountAccess {
return new(uint256.Int).SetBytes(testrand.Bytes(32)) return new(uint256.Int).SetBytes(testrand.Bytes(32))
} }
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
slot := encodingSlotWrites{ slot := encodingSlotChanges{
Slot: randSlot(), Slot: randSlot(),
} }
for j := 0; j < 3; j++ { for j := 0; j < 3; j++ {
slot.Accesses = append(slot.Accesses, encodingStorageWrite{ slot.SlotChanges = append(slot.SlotChanges, encodingStorageWrite{
TxIdx: uint32(2 * j), BlockAccessIndex: uint32(2 * j),
ValueAfter: randSlot(), PostValue: randSlot(),
}) })
} }
if sort { if sort {
slices.SortFunc(slot.Accesses, func(a, b encodingStorageWrite) int { slices.SortFunc(slot.SlotChanges, func(a, b encodingStorageWrite) int {
return cmp.Compare[uint32](a.TxIdx, b.TxIdx) return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex)
}) })
} }
storageWrites = append(storageWrites, slot) storageWrites = append(storageWrites, slot)
} }
if sort { if sort {
slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int { slices.SortFunc(storageWrites, func(a, b encodingSlotChanges) int {
return a.Slot.Cmp(b.Slot) return a.Slot.Cmp(b.Slot)
}) })
} }
@ -203,43 +203,43 @@ func makeTestAccountAccess(sort bool) AccountAccess {
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
balances = append(balances, encodingBalanceChange{ balances = append(balances, encodingBalanceChange{
TxIdx: uint32(2 * i), BlockAccessIndex: uint32(2 * i),
Balance: new(uint256.Int).SetBytes(testrand.Bytes(16)), PostBalance: new(uint256.Int).SetBytes(testrand.Bytes(16)),
}) })
} }
if sort { if sort {
slices.SortFunc(balances, func(a, b encodingBalanceChange) int { slices.SortFunc(balances, func(a, b encodingBalanceChange) int {
return cmp.Compare[uint32](a.TxIdx, b.TxIdx) return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex)
}) })
} }
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
nonces = append(nonces, encodingAccountNonce{ nonces = append(nonces, encodingAccountNonce{
TxIdx: uint32(2 * i), BlockAccessIndex: uint32(2 * i),
Nonce: uint64(i + 100), PostNonce: uint64(i + 100),
}) })
} }
if sort { if sort {
slices.SortFunc(nonces, func(a, b encodingAccountNonce) int { slices.SortFunc(nonces, func(a, b encodingAccountNonce) int {
return cmp.Compare[uint32](a.TxIdx, b.TxIdx) return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex)
}) })
} }
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
codes = append(codes, encodingCodeChange{ codes = append(codes, encodingCodeChange{
TxIndex: uint32(2 * i), BlockAccessIndex: uint32(2 * i),
Code: testrand.Bytes(256), NewCode: testrand.Bytes(256),
}) })
} }
if sort { if sort {
slices.SortFunc(codes, func(a, b encodingCodeChange) int { slices.SortFunc(codes, func(a, b encodingCodeChange) int {
return cmp.Compare[uint32](a.TxIndex, b.TxIndex) return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex)
}) })
} }
return AccountAccess{ return AccountAccess{
Address: [20]byte(testrand.Bytes(20)), Address: common.Address(testrand.Bytes(20)),
StorageWrites: storageWrites, StorageChanges: storageWrites,
StorageReads: storageReads, StorageReads: storageReads,
BalanceChanges: balances, BalanceChanges: balances,
NonceChanges: nonces, NonceChanges: nonces,
@ -289,14 +289,14 @@ func TestBlockAccessListItemCount(t *testing.T) {
t.Fatalf("empty BAL item count: got %d, want 0", got) t.Fatalf("empty BAL item count: got %d, want 0", got)
} }
addr1 := [20]byte(testrand.Bytes(20)) addr1 := common.Address(testrand.Bytes(20))
addr2 := [20]byte(testrand.Bytes(20)) addr2 := common.Address(testrand.Bytes(20))
one := func() *uint256.Int { return new(uint256.Int).SetBytes(testrand.Bytes(32)) } one := func() *uint256.Int { return new(uint256.Int).SetBytes(testrand.Bytes(32)) }
bal := &BlockAccessList{ bal := &BlockAccessList{
AccountAccess{ AccountAccess{
Address: addr1, Address: addr1,
StorageWrites: []encodingSlotWrites{ StorageChanges: []encodingSlotChanges{
{Slot: one(), Accesses: []encodingStorageWrite{{TxIdx: 0, ValueAfter: one()}, {TxIdx: 1, ValueAfter: one()}}}, {Slot: one(), SlotChanges: []encodingStorageWrite{{BlockAccessIndex: 0, PostValue: one()}, {BlockAccessIndex: 1, PostValue: one()}}},
{Slot: one()}, {Slot: one()},
}, },
StorageReads: []*uint256.Int{one()}, StorageReads: []*uint256.Int{one()},
@ -316,10 +316,10 @@ func TestBlockAccessListValidateSize(t *testing.T) {
one := func() *uint256.Int { return new(uint256.Int).SetBytes(testrand.Bytes(32)) } one := func() *uint256.Int { return new(uint256.Int).SetBytes(testrand.Bytes(32)) }
bal := make(BlockAccessList, 3) bal := make(BlockAccessList, 3)
for i := range bal { for i := range bal {
bal[i].Address = [20]byte(testrand.Bytes(20)) bal[i].Address = common.Address(testrand.Bytes(20))
for j := 0; j < 5; j++ { for j := 0; j < 5; j++ {
bal[i].StorageWrites = append(bal[i].StorageWrites, encodingSlotWrites{ bal[i].StorageChanges = append(bal[i].StorageChanges, encodingSlotChanges{
Slot: one(), Accesses: []encodingStorageWrite{{TxIdx: 0, ValueAfter: one()}}, Slot: one(), SlotChanges: []encodingStorageWrite{{BlockAccessIndex: 0, PostValue: one()}},
}) })
} }
for j := 0; j < 4; j++ { for j := 0; j < 4; j++ {

View file

@ -0,0 +1,76 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package bal
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/holiman/uint256"
)
var _ = (*accountAccessMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (a AccountAccess) MarshalJSON() ([]byte, error) {
type AccountAccess struct {
Address common.Address `json:"address"`
StorageChanges []encodingSlotChanges `json:"storageChanges"`
StorageReads []*hexutil.U256 `json:"storageReads"`
BalanceChanges []encodingBalanceChange `json:"balanceChanges"`
NonceChanges []encodingAccountNonce `json:"nonceChanges"`
CodeChanges []encodingCodeChange `json:"codeChanges"`
}
var enc AccountAccess
enc.Address = a.Address
enc.StorageChanges = a.StorageChanges
if a.StorageReads != nil {
enc.StorageReads = make([]*hexutil.U256, len(a.StorageReads))
for k, v := range a.StorageReads {
enc.StorageReads[k] = (*hexutil.U256)(v)
}
}
enc.BalanceChanges = a.BalanceChanges
enc.NonceChanges = a.NonceChanges
enc.CodeChanges = a.CodeChanges
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (a *AccountAccess) UnmarshalJSON(input []byte) error {
type AccountAccess struct {
Address *common.Address `json:"address"`
StorageChanges []encodingSlotChanges `json:"storageChanges"`
StorageReads []*hexutil.U256 `json:"storageReads"`
BalanceChanges []encodingBalanceChange `json:"balanceChanges"`
NonceChanges []encodingAccountNonce `json:"nonceChanges"`
CodeChanges []encodingCodeChange `json:"codeChanges"`
}
var dec AccountAccess
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Address != nil {
a.Address = *dec.Address
}
if dec.StorageChanges != nil {
a.StorageChanges = dec.StorageChanges
}
if dec.StorageReads != nil {
a.StorageReads = make([]*uint256.Int, len(dec.StorageReads))
for k, v := range dec.StorageReads {
a.StorageReads[k] = (*uint256.Int)(v)
}
}
if dec.BalanceChanges != nil {
a.BalanceChanges = dec.BalanceChanges
}
if dec.NonceChanges != nil {
a.NonceChanges = dec.NonceChanges
}
if dec.CodeChanges != nil {
a.CodeChanges = dec.CodeChanges
}
return nil
}

View file

@ -0,0 +1,42 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package bal
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var _ = (*encodingAccountNonceMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (e encodingAccountNonce) MarshalJSON() ([]byte, error) {
type encodingAccountNonce struct {
BlockAccessIndex hexutil.Uint64 `json:"blockAccessIndex"`
PostNonce hexutil.Uint64 `json:"postNonce"`
}
var enc encodingAccountNonce
enc.BlockAccessIndex = hexutil.Uint64(e.BlockAccessIndex)
enc.PostNonce = hexutil.Uint64(e.PostNonce)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (e *encodingAccountNonce) UnmarshalJSON(input []byte) error {
type encodingAccountNonce struct {
BlockAccessIndex *hexutil.Uint64 `json:"blockAccessIndex"`
PostNonce *hexutil.Uint64 `json:"postNonce"`
}
var dec encodingAccountNonce
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.BlockAccessIndex != nil {
e.BlockAccessIndex = uint32(*dec.BlockAccessIndex)
}
if dec.PostNonce != nil {
e.PostNonce = uint64(*dec.PostNonce)
}
return nil
}

View file

@ -0,0 +1,43 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package bal
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/holiman/uint256"
)
var _ = (*encodingBalanceChangeMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (e encodingBalanceChange) MarshalJSON() ([]byte, error) {
type encodingBalanceChange struct {
BlockAccessIndex hexutil.Uint64 `json:"blockAccessIndex"`
PostBalance *hexutil.U256 `json:"postBalance"`
}
var enc encodingBalanceChange
enc.BlockAccessIndex = hexutil.Uint64(e.BlockAccessIndex)
enc.PostBalance = (*hexutil.U256)(e.PostBalance)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (e *encodingBalanceChange) UnmarshalJSON(input []byte) error {
type encodingBalanceChange struct {
BlockAccessIndex *hexutil.Uint64 `json:"blockAccessIndex"`
PostBalance *hexutil.U256 `json:"postBalance"`
}
var dec encodingBalanceChange
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.BlockAccessIndex != nil {
e.BlockAccessIndex = uint32(*dec.BlockAccessIndex)
}
if dec.PostBalance != nil {
e.PostBalance = (*uint256.Int)(dec.PostBalance)
}
return nil
}

View file

@ -0,0 +1,42 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package bal
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var _ = (*encodingCodeChangeMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (e encodingCodeChange) MarshalJSON() ([]byte, error) {
type encodingCodeChange struct {
BlockAccessIndex hexutil.Uint64 `json:"blockAccessIndex"`
NewCode hexutil.Bytes `json:"newCode"`
}
var enc encodingCodeChange
enc.BlockAccessIndex = hexutil.Uint64(e.BlockAccessIndex)
enc.NewCode = e.NewCode
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (e *encodingCodeChange) UnmarshalJSON(input []byte) error {
type encodingCodeChange struct {
BlockAccessIndex *hexutil.Uint64 `json:"blockAccessIndex"`
NewCode *hexutil.Bytes `json:"newCode"`
}
var dec encodingCodeChange
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.BlockAccessIndex != nil {
e.BlockAccessIndex = uint32(*dec.BlockAccessIndex)
}
if dec.NewCode != nil {
e.NewCode = *dec.NewCode
}
return nil
}

View file

@ -0,0 +1,43 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package bal
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/holiman/uint256"
)
var _ = (*encodingSlotChangesMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (e encodingSlotChanges) MarshalJSON() ([]byte, error) {
type encodingSlotChanges struct {
Slot *hexutil.U256 `json:"slot"`
SlotChanges []encodingStorageWrite `json:"slotChanges"`
}
var enc encodingSlotChanges
enc.Slot = (*hexutil.U256)(e.Slot)
enc.SlotChanges = e.SlotChanges
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (e *encodingSlotChanges) UnmarshalJSON(input []byte) error {
type encodingSlotChanges struct {
Slot *hexutil.U256 `json:"slot"`
SlotChanges []encodingStorageWrite `json:"slotChanges"`
}
var dec encodingSlotChanges
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Slot != nil {
e.Slot = (*uint256.Int)(dec.Slot)
}
if dec.SlotChanges != nil {
e.SlotChanges = dec.SlotChanges
}
return nil
}

View file

@ -0,0 +1,43 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package bal
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/holiman/uint256"
)
var _ = (*encodingStorageWriteMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (e encodingStorageWrite) MarshalJSON() ([]byte, error) {
type encodingStorageWrite struct {
BlockAccessIndex hexutil.Uint64 `json:"blockAccessIndex"`
PostValue *hexutil.U256 `json:"postValue"`
}
var enc encodingStorageWrite
enc.BlockAccessIndex = hexutil.Uint64(e.BlockAccessIndex)
enc.PostValue = (*hexutil.U256)(e.PostValue)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (e *encodingStorageWrite) UnmarshalJSON(input []byte) error {
type encodingStorageWrite struct {
BlockAccessIndex *hexutil.Uint64 `json:"blockAccessIndex"`
PostValue *hexutil.U256 `json:"postValue"`
}
var dec encodingStorageWrite
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.BlockAccessIndex != nil {
e.BlockAccessIndex = uint32(*dec.BlockAccessIndex)
}
if dec.PostValue != nil {
e.PostValue = (*uint256.Int)(dec.PostValue)
}
return nil
}

View file

@ -101,7 +101,7 @@ type Header struct {
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"` RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
// BlockAccessListHash was added by EIP-7928 and is ignored in legacy headers. // BlockAccessListHash was added by EIP-7928 and is ignored in legacy headers.
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"` BlockAccessListHash *common.Hash `json:"blockAccessListHash" rlp:"optional"`
// SlotNumber was added by EIP-7843 and is ignored in legacy headers. // SlotNumber was added by EIP-7843 and is ignored in legacy headers.
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"` SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`

View file

@ -37,7 +37,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"` RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"` BlockAccessListHash *common.Hash `json:"blockAccessListHash" rlp:"optional"`
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"` SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
Hash common.Hash `json:"hash"` Hash common.Hash `json:"hash"`
} }
@ -93,7 +93,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"` RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"` BlockAccessListHash *common.Hash `json:"blockAccessListHash" rlp:"optional"`
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"` SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
} }
var dec Header var dec Header

View file

@ -1002,7 +1002,7 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
result["requestsHash"] = head.RequestsHash result["requestsHash"] = head.RequestsHash
} }
if head.BlockAccessListHash != nil { if head.BlockAccessListHash != nil {
result["balHash"] = head.BlockAccessListHash result["blockAccessListHash"] = head.BlockAccessListHash
} }
if head.SlotNumber != nil { if head.SlotNumber != nil {
result["slotNumber"] = hexutil.Uint64(*head.SlotNumber) result["slotNumber"] = hexutil.Uint64(*head.SlotNumber)