From 918d46b942b9d9f2a13c02cf12a651ba9ccae879 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Wed, 20 May 2026 21:12:13 +0800 Subject: [PATCH] core, cmd, internal: rework BAL json marshalling to adhere EELS (#34972) It's a change to BAL json marshalling and t8n tooling to adhere the EELS definition. --- cmd/evm/internal/t8ntool/block.go | 44 ++-- cmd/evm/internal/t8ntool/execution.go | 30 ++- cmd/evm/internal/t8ntool/gen_execresult.go | 13 ++ cmd/evm/internal/t8ntool/gen_header.go | 12 + core/bal_test.go | 48 ++-- core/types/bal/bal_encoding.go | 218 ++++++++++-------- core/types/bal/bal_encoding_rlp_generated.go | 71 +++--- core/types/bal/bal_test.go | 52 ++--- core/types/bal/gen_account_access_json.go | 76 ++++++ .../bal/gen_encoding_account_nonce_json.go | 42 ++++ .../bal/gen_encoding_balance_change_json.go | 43 ++++ .../bal/gen_encoding_code_change_json.go | 42 ++++ .../bal/gen_encoding_slot_changes_json.go | 43 ++++ .../bal/gen_encoding_storage_write_json.go | 43 ++++ core/types/block.go | 2 +- core/types/gen_header_json.go | 4 +- internal/ethapi/api.go | 2 +- 17 files changed, 581 insertions(+), 204 deletions(-) create mode 100644 core/types/bal/gen_account_access_json.go create mode 100644 core/types/bal/gen_encoding_account_nonce_json.go create mode 100644 core/types/bal/gen_encoding_balance_change_json.go create mode 100644 core/types/bal/gen_encoding_code_change_json.go create mode 100644 core/types/bal/gen_encoding_slot_changes_json.go create mode 100644 core/types/bal/gen_encoding_storage_write_json.go diff --git a/cmd/evm/internal/t8ntool/block.go b/cmd/evm/internal/t8ntool/block.go index 6148e9e248..396900d5fd 100644 --- a/cmd/evm/internal/t8ntool/block.go +++ b/cmd/evm/internal/t8ntool/block.go @@ -56,6 +56,8 @@ type header struct { BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` ExcessBlobGas *uint64 `json:"excessBlobGas" 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"` } @@ -119,26 +121,28 @@ func (c *cliqueInput) UnmarshalJSON(input []byte) error { // ToBlock converts i into a *types.Block func (i *bbInput) ToBlock() *types.Block { header := &types.Header{ - ParentHash: i.Header.ParentHash, - UncleHash: types.EmptyUncleHash, - Coinbase: common.Address{}, - Root: i.Header.Root, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - Bloom: i.Header.Bloom, - Difficulty: common.Big0, - Number: i.Header.Number, - GasLimit: i.Header.GasLimit, - GasUsed: i.Header.GasUsed, - Time: i.Header.Time, - Extra: i.Header.Extra, - MixDigest: i.Header.MixDigest, - BaseFee: i.Header.BaseFee, - WithdrawalsHash: i.Header.WithdrawalsHash, - BlobGasUsed: i.Header.BlobGasUsed, - ExcessBlobGas: i.Header.ExcessBlobGas, - ParentBeaconRoot: i.Header.ParentBeaconBlockRoot, - SlotNumber: i.Header.SlotNumber, + ParentHash: i.Header.ParentHash, + UncleHash: types.EmptyUncleHash, + Coinbase: common.Address{}, + Root: i.Header.Root, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, + Bloom: i.Header.Bloom, + Difficulty: common.Big0, + Number: i.Header.Number, + GasLimit: i.Header.GasLimit, + GasUsed: i.Header.GasUsed, + Time: i.Header.Time, + Extra: i.Header.Extra, + MixDigest: i.Header.MixDigest, + BaseFee: i.Header.BaseFee, + WithdrawalsHash: i.Header.WithdrawalsHash, + BlobGasUsed: i.Header.BlobGasUsed, + ExcessBlobGas: i.Header.ExcessBlobGas, + ParentBeaconRoot: i.Header.ParentBeaconBlockRoot, + RequestsHash: i.Header.RequestsHash, + BlockAccessListHash: i.Header.BlockAccessListHash, + SlotNumber: i.Header.SlotNumber, } // Fill optional values. diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 043e675494..bd089c9f55 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -76,6 +76,9 @@ type ExecutionResult struct { CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` RequestsHash *common.Hash `json:"requestsHash,omitempty"` Requests [][]byte `json:"requests"` + + BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"` + BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` } type executionResultMarshaling struct { @@ -153,8 +156,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, return h } 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 != "" { var err error @@ -299,9 +304,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, receipts = append(receipts, receipt) blockAccessList.Merge(bal) } - statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber)) + // TODO(rjl493456442) call engine.Finalize() instead // Add mining reward? (-1 means rewards are disabled) if miningReward >= 0 { // 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 { // Amount is in gwei, turn into wei 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 { 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. @@ -379,6 +395,12 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, execRs.RequestsHash = &h 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 statedb, err = state.New(root, statedb.Database()) diff --git a/cmd/evm/internal/t8ntool/gen_execresult.go b/cmd/evm/internal/t8ntool/gen_execresult.go index 38310b9f2b..f678c65de2 100644 --- a/cmd/evm/internal/t8ntool/gen_execresult.go +++ b/cmd/evm/internal/t8ntool/gen_execresult.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/types/bal" ) var _ = (*executionResultMarshaling)(nil) @@ -32,6 +33,8 @@ func (e ExecutionResult) MarshalJSON() ([]byte, error) { CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` RequestsHash *common.Hash `json:"requestsHash,omitempty"` Requests []hexutil.Bytes `json:"requests"` + BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"` + BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` } var enc ExecutionResult enc.StateRoot = e.StateRoot @@ -54,6 +57,8 @@ func (e ExecutionResult) MarshalJSON() ([]byte, error) { enc.Requests[k] = v } } + enc.BlockAccessList = e.BlockAccessList + enc.BlockAccessListHash = e.BlockAccessListHash return json.Marshal(&enc) } @@ -75,6 +80,8 @@ func (e *ExecutionResult) UnmarshalJSON(input []byte) error { CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` RequestsHash *common.Hash `json:"requestsHash,omitempty"` Requests []hexutil.Bytes `json:"requests"` + BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"` + BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` } var dec ExecutionResult if err := json.Unmarshal(input, &dec); err != nil { @@ -130,5 +137,11 @@ func (e *ExecutionResult) UnmarshalJSON(input []byte) error { e.Requests[k] = v } } + if dec.BlockAccessList != nil { + e.BlockAccessList = dec.BlockAccessList + } + if dec.BlockAccessListHash != nil { + e.BlockAccessListHash = dec.BlockAccessListHash + } return nil } diff --git a/cmd/evm/internal/t8ntool/gen_header.go b/cmd/evm/internal/t8ntool/gen_header.go index f430feb6d2..1c5e0065e1 100644 --- a/cmd/evm/internal/t8ntool/gen_header.go +++ b/cmd/evm/internal/t8ntool/gen_header.go @@ -38,6 +38,8 @@ func (h header) MarshalJSON() ([]byte, error) { BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"` ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" 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"` } var enc header @@ -61,6 +63,8 @@ func (h header) MarshalJSON() ([]byte, error) { enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed) enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas) enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot + enc.RequestsHash = h.RequestsHash + enc.BlockAccessListHash = h.BlockAccessListHash enc.SlotNumber = (*math.HexOrDecimal64)(h.SlotNumber) return json.Marshal(&enc) } @@ -88,6 +92,8 @@ func (h *header) UnmarshalJSON(input []byte) error { BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"` ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" 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"` } var dec header @@ -158,6 +164,12 @@ func (h *header) UnmarshalJSON(input []byte) error { if dec.ParentBeaconBlockRoot != nil { h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot } + if dec.RequestsHash != nil { + h.RequestsHash = dec.RequestsHash + } + if dec.BlockAccessListHash != nil { + h.BlockAccessListHash = dec.BlockAccessListHash + } if dec.SlotNumber != nil { h.SlotNumber = (*uint64)(dec.SlotNumber) } diff --git a/core/bal_test.go b/core/bal_test.go index f0b9dc6443..d20108b96c 100644 --- a/core/bal_test.go +++ b/core/bal_test.go @@ -121,7 +121,7 @@ func hasStorageWrite(b *bal.BlockAccessList, addr common.Address, key common.Has return false } want := new(uint256.Int).SetBytes(key[:]) - for _, w := range aa.StorageWrites { + for _, w := range aa.StorageChanges { if w.Slot.Cmp(want) == 0 { 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) { 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 { 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) - 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) } if len(sender.BalanceChanges) == 0 { t.Fatalf("sender missing balance change") } 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) } } @@ -236,7 +236,7 @@ func TestBALCoinbaseTipCapturesBalance(t *testing.T) { }) 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) } } @@ -264,7 +264,7 @@ func TestBALSystemAddressIncludedWhenTouched(t *testing.T) { }) 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) } } @@ -319,7 +319,7 @@ func TestBALPrecompileValueTransferRecordsBalance(t *testing.T) { }) 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) } } @@ -537,7 +537,7 @@ func TestBALSenderRecordedOnRevert(t *testing.T) { }) 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) } if len(sender.BalanceChanges) == 0 { @@ -667,10 +667,10 @@ func TestBALStorageWriteZeroIsAWrite(t *testing.T) { if !hasStorageWrite(b, contract, slot) { 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 len(w.Accesses) != 1 || !w.Accesses[0].ValueAfter.IsZero() { - t.Fatalf("expected post-value 0 for slot 0x03, got %+v", w.Accesses) + if len(w.SlotChanges) != 1 || !w.SlotChanges[0].PostValue.IsZero() { + 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 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) } - 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) } - 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) } } @@ -716,7 +716,7 @@ func TestBALCreateEmptyRuntimeNoCodeEntry(t *testing.T) { created := receipts[0].ContractAddress 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) } if len(aa.CodeChanges) != 0 { @@ -849,7 +849,7 @@ func TestBALInEVMCreateDeploysContract(t *testing.T) { // which is the factory's genesis nonce (1). deployed := crypto.CreateAddress(factory, 1) 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) } } @@ -900,7 +900,7 @@ func TestBALSelfDestructBeneficiaryWithValueTransfer(t *testing.T) { }) 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) } } @@ -925,11 +925,11 @@ func TestBALSelfDestructPreExistingContract(t *testing.T) { }) 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) } 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) } } @@ -1041,7 +1041,7 @@ func TestBALWithdrawalNonZeroAmountRecordsBalance(t *testing.T) { }) 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) } } @@ -1266,7 +1266,7 @@ func TestBALAuthCodeRoundTripNoCodeEntry(t *testing.T) { }) 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) } 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) } want := types.AddressToDelegation(delegateB) - if !bytes.Equal(aa.CodeChanges[0].Code, want) { - t.Fatalf("final code mismatch: want %x, got %x", want, aa.CodeChanges[0].Code) + if !bytes.Equal(aa.CodeChanges[0].NewCode, want) { + 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) } } diff --git a/core/types/bal/bal_encoding.go b/core/types/bal/bal_encoding.go index 128e8dea2c..612d2f8777 100644 --- a/core/types/bal/bal_encoding.go +++ b/core/types/bal/bal_encoding.go @@ -27,6 +27,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -99,7 +100,7 @@ func (e *BlockAccessList) Validate(blockGasLimit uint64, blockTxCount int) error func (e *BlockAccessList) itemCount() uint64 { count := uint64(len(*e)) // distinct addresses 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 } @@ -130,28 +131,38 @@ func (e *BlockAccessList) Hash() common.Hash { return crypto.Keccak256Hash(enc.Bytes()) } -// encodingBalanceChange is the encoding format of BalanceChange. -type encodingBalanceChange struct { - TxIdx uint32 - Balance *uint256.Int -} +// EIP-7928 encoding types. Field names and JSON keys mirror the +// execution-spec-tests Pydantic models in +// `src/ethereum_test_types/block_access_list/account_changes.py`. Hex +// formatting on JSON output is supplied via the gencodec overrides +// below. -// encodingAccountNonce is the encoding format of NonceChange. -type encodingAccountNonce struct { - TxIdx uint32 - Nonce uint64 -} +//go:generate go run github.com/fjl/gencodec -type encodingStorageWrite -field-override encodingStorageWriteMarshaling -out gen_encoding_storage_write_json.go +//go:generate go run github.com/fjl/gencodec -type encodingSlotChanges -field-override encodingSlotChangesMarshaling -out gen_encoding_slot_changes_json.go +//go:generate go run github.com/fjl/gencodec -type encodingBalanceChange -field-override encodingBalanceChangeMarshaling -out gen_encoding_balance_change_json.go +//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 { - TxIdx uint32 - ValueAfter *uint256.Int + BlockAccessIndex uint32 `json:"blockAccessIndex"` + PostValue *uint256.Int `json:"postValue"` } -// encodingStorageWrite is the encoding format of SlotWrites. -type encodingSlotWrites struct { - Slot *uint256.Int - Accesses []encodingStorageWrite +type encodingStorageWriteMarshaling struct { + BlockAccessIndex hexutil.Uint64 + PostValue *hexutil.U256 +} + +// 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 { @@ -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 // which are ordered ascending by transaction index and contain no duplicate // modifications for a given index. -func (e *encodingSlotWrites) validate(maxBALIndex int) error { - if !isStrictlySortedFunc(e.Accesses, func(a, b encodingStorageWrite) int { - return cmp.Compare(a.TxIdx, b.TxIdx) +func (e *encodingSlotChanges) validate(maxBALIndex int) error { + if !isStrictlySortedFunc(e.SlotChanges, func(a, b encodingStorageWrite) int { + return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex) }) { 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 { - return fmt.Errorf("storage write index exceeds limit, index: %d, limit: %d", 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.SlotChanges[len(e.SlotChanges)-1].BlockAccessIndex, maxBALIndex) } return nil } -// encodingCodeChange contains the runtime bytecode deployed at an address -// and the transaction index where the deployment took place. +// encodingBalanceChange is one transaction's post-state balance for an account. +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 { - TxIndex uint32 - Code []byte + BlockAccessIndex uint32 `json:"blockAccessIndex"` + NewCode []byte `json:"newCode"` +} + +type encodingCodeChangeMarshaling struct { + BlockAccessIndex hexutil.Uint64 + NewCode hexutil.Bytes } // AccountAccess is the encoding format of ConstructionAccountAccess. type AccountAccess struct { - Address [20]byte // 20-byte Ethereum address - StorageWrites []encodingSlotWrites // Storage changes (slot -> [tx_index -> new_value]) - StorageReads []*uint256.Int // Read-only storage keys - BalanceChanges []encodingBalanceChange // Balance changes ([tx_index -> post_balance]) - NonceChanges []encodingAccountNonce // Nonce changes ([tx_index -> new_nonce]) - CodeChanges []encodingCodeChange // Code changes ([tx_index -> new_code]) + Address common.Address `json:"address"` + StorageChanges []encodingSlotChanges `json:"storageChanges"` + StorageReads []*uint256.Int `json:"storageReads"` + BalanceChanges []encodingBalanceChange `json:"balanceChanges"` + NonceChanges []encodingAccountNonce `json:"nonceChanges"` + CodeChanges []encodingCodeChange `json:"codeChanges"` +} + +type accountAccessMarshaling struct { + StorageReads []*hexutil.U256 } // validate converts the account accesses out of encoding format. @@ -200,13 +241,13 @@ type AccountAccess struct { // spec, an error is returned. func (e *AccountAccess) validate(maxBALIndex int) error { // 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 errors.New("storage write slots must be unique and sorted") } // 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 { return err } @@ -223,13 +264,13 @@ func (e *AccountAccess) validate(maxBALIndex int) error { // set of read slots. var ( 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 { readKey := common.BytesToHash(rk.Bytes()) readKeys[readKey] = struct{}{} } - for _, write := range e.StorageWrites { + for _, write := range e.StorageChanges { writeKey := common.BytesToHash(write.Slot.Bytes()) 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 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") } // 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 { - return fmt.Errorf("balance change index exceeds limit, index: %d, limit: %d", 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].BlockAccessIndex, maxBALIndex) } // Check the nonce changes are sorted in order, and unique by tx index 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") } // check that the tx index of the highest nonce change is not greater than // the max allowed for the block - if len(e.NonceChanges) > 0 && int(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].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].BlockAccessIndex, maxBALIndex) } // Check the code changes are sorted in order, and unique by tx index 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") } // check that the tx index of the highest code changeis not greater than the // max allowed for the block - if len(e.CodeChanges) > 0 && int(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].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].BlockAccessIndex, maxBALIndex) } // Check that none of the code changes report a new code which is larger // than the max allowed by the protocol 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") } } @@ -290,7 +331,7 @@ func (e *AccountAccess) Copy() AccountAccess { StorageReads: make([]*uint256.Int, 0, len(e.StorageReads)), BalanceChanges: make([]encodingBalanceChange, 0, len(e.BalanceChanges)), 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)), } for _, slot := range e.StorageReads { @@ -298,27 +339,27 @@ func (e *AccountAccess) Copy() AccountAccess { } for _, change := range e.BalanceChanges { res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{ - TxIdx: change.TxIdx, - Balance: change.Balance.Clone(), + BlockAccessIndex: change.BlockAccessIndex, + PostBalance: change.PostBalance.Clone(), }) } - for _, storageWrite := range e.StorageWrites { - accesses := make([]encodingStorageWrite, 0, len(storageWrite.Accesses)) - for _, w := range storageWrite.Accesses { - accesses = append(accesses, encodingStorageWrite{ - TxIdx: w.TxIdx, - ValueAfter: w.ValueAfter.Clone(), + for _, slot := range e.StorageChanges { + writes := make([]encodingStorageWrite, 0, len(slot.SlotChanges)) + for _, w := range slot.SlotChanges { + writes = append(writes, encodingStorageWrite{ + BlockAccessIndex: w.BlockAccessIndex, + PostValue: w.PostValue.Clone(), }) } - res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{ - Slot: storageWrite.Slot.Clone(), - Accesses: accesses, + res.StorageChanges = append(res.StorageChanges, encodingSlotChanges{ + Slot: slot.Slot.Clone(), + SlotChanges: writes, }) } for _, codeChange := range e.CodeChanges { res.CodeChanges = append(res.CodeChanges, encodingCodeChange{ - TxIndex: codeChange.TxIndex, - Code: bytes.Clone(codeChange.Code), + BlockAccessIndex: codeChange.BlockAccessIndex, + NewCode: bytes.Clone(codeChange.NewCode), }) } return res @@ -336,7 +377,7 @@ var _ rlp.Encoder = &ConstructionBlockAccessList{} func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAccess { res := AccountAccess{ Address: addr, - StorageWrites: make([]encodingSlotWrites, 0, len(a.StorageWrites)), + StorageChanges: make([]encodingSlotChanges, 0, len(a.StorageWrites)), StorageReads: make([]*uint256.Int, 0, len(a.StorageReads)), BalanceChanges: make([]encodingBalanceChange, 0, len(a.BalanceChanges)), 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)) slices.SortFunc(writeSlots, common.Hash.Cmp) for _, slot := range writeSlots { - obj := encodingSlotWrites{ + obj := encodingSlotChanges{ Slot: new(uint256.Int).SetBytes(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)) - slices.SortFunc(indices, cmp.Compare[uint32]) + slices.SortFunc(indices, cmp.Compare) for _, index := range indices { val := slotWrites[index] - obj.Accesses = append(obj.Accesses, encodingStorageWrite{ - TxIdx: index, - ValueAfter: new(uint256.Int).SetBytes(val[:]), + obj.SlotChanges = append(obj.SlotChanges, encodingStorageWrite{ + BlockAccessIndex: index, + PostValue: new(uint256.Int).SetBytes(val[:]), }) } - res.StorageWrites = append(res.StorageWrites, obj) + res.StorageChanges = append(res.StorageChanges, obj) } // Convert read slots @@ -374,36 +415,36 @@ func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAc // Convert balance changes balanceIndices := slices.Collect(maps.Keys(a.BalanceChanges)) - slices.SortFunc(balanceIndices, cmp.Compare[uint32]) + slices.SortFunc(balanceIndices, cmp.Compare) for _, idx := range balanceIndices { res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{ - TxIdx: idx, - Balance: a.BalanceChanges[idx].Clone(), + BlockAccessIndex: idx, + PostBalance: a.BalanceChanges[idx].Clone(), }) } // Convert nonce changes nonceIndices := slices.Collect(maps.Keys(a.NonceChanges)) - slices.SortFunc(nonceIndices, cmp.Compare[uint32]) + slices.SortFunc(nonceIndices, cmp.Compare) for _, idx := range nonceIndices { res.NonceChanges = append(res.NonceChanges, encodingAccountNonce{ - TxIdx: idx, - Nonce: a.NonceChanges[idx], + BlockAccessIndex: idx, + PostNonce: a.NonceChanges[idx], }) } // Convert code change codeIndices := slices.Collect(maps.Keys(a.CodeChange)) - slices.SortFunc(codeIndices, cmp.Compare[uint32]) + slices.SortFunc(codeIndices, cmp.Compare) for _, idx := range codeIndices { res.CodeChanges = append(res.CodeChanges, encodingCodeChange{ - TxIndex: idx, + BlockAccessIndex: idx, // TODO(rjl493456442) the contract code is not deep-copied. // In theory the deep-copy is unnecessary, the semantics of // the function should be probably changed that the returned // AccessList is unsafe for modification. - Code: a.CodeChange[idx], + NewCode: a.CodeChange[idx], }) } return res @@ -432,33 +473,28 @@ func (e *BlockAccessList) PrettyPrint() string { } for _, accountDiff := range *e { printWithIndent(0, fmt.Sprintf("%x:", accountDiff.Address)) - - printWithIndent(1, "storage writes:") - for _, sWrite := range accountDiff.StorageWrites { - printWithIndent(2, fmt.Sprintf("%s:", sWrite.Slot.Hex())) - for _, access := range sWrite.Accesses { - printWithIndent(3, fmt.Sprintf("%d: %s", access.TxIdx, access.ValueAfter.Hex())) + printWithIndent(1, "storage changes:") + for _, slot := range accountDiff.StorageChanges { + printWithIndent(2, fmt.Sprintf("%s:", slot.Slot.Hex())) + for _, access := range slot.SlotChanges { + printWithIndent(3, fmt.Sprintf("%d: %s", access.BlockAccessIndex, access.PostValue.Hex())) } } - printWithIndent(1, "storage reads:") for _, slot := range accountDiff.StorageReads { printWithIndent(2, slot.Hex()) } - printWithIndent(1, "balance changes:") 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:") 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:") 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() diff --git a/core/types/bal/bal_encoding_rlp_generated.go b/core/types/bal/bal_encoding_rlp_generated.go index 540987c076..49f53197cf 100644 --- a/core/types/bal/bal_encoding_rlp_generated.go +++ b/core/types/bal/bal_encoding_rlp_generated.go @@ -2,6 +2,7 @@ package bal +import "github.com/ethereum/go-ethereum/common" import "github.com/ethereum/go-ethereum/rlp" import "github.com/holiman/uint256" import "io" @@ -11,7 +12,7 @@ func (obj *AccountAccess) EncodeRLP(_w io.Writer) error { _tmp0 := w.List() w.WriteBytes(obj.Address[:]) _tmp1 := w.List() - for _, _tmp2 := range obj.StorageWrites { + for _, _tmp2 := range obj.StorageChanges { _tmp3 := w.List() if _tmp2.Slot == nil { w.Write(rlp.EmptyString) @@ -19,13 +20,13 @@ func (obj *AccountAccess) EncodeRLP(_w io.Writer) error { w.WriteUint256(_tmp2.Slot) } _tmp4 := w.List() - for _, _tmp5 := range _tmp2.Accesses { + for _, _tmp5 := range _tmp2.SlotChanges { _tmp6 := w.List() - w.WriteUint64(uint64(_tmp5.TxIdx)) - if _tmp5.ValueAfter == nil { + w.WriteUint64(uint64(_tmp5.BlockAccessIndex)) + if _tmp5.PostValue == nil { w.Write(rlp.EmptyString) } else { - w.WriteUint256(_tmp5.ValueAfter) + w.WriteUint256(_tmp5.PostValue) } w.ListEnd(_tmp6) } @@ -45,11 +46,11 @@ func (obj *AccountAccess) EncodeRLP(_w io.Writer) error { _tmp9 := w.List() for _, _tmp10 := range obj.BalanceChanges { _tmp11 := w.List() - w.WriteUint64(uint64(_tmp10.TxIdx)) - if _tmp10.Balance == nil { + w.WriteUint64(uint64(_tmp10.BlockAccessIndex)) + if _tmp10.PostBalance == nil { w.Write(rlp.EmptyString) } else { - w.WriteUint256(_tmp10.Balance) + w.WriteUint256(_tmp10.PostBalance) } w.ListEnd(_tmp11) } @@ -57,16 +58,16 @@ func (obj *AccountAccess) EncodeRLP(_w io.Writer) error { _tmp12 := w.List() for _, _tmp13 := range obj.NonceChanges { _tmp14 := w.List() - w.WriteUint64(uint64(_tmp13.TxIdx)) - w.WriteUint64(_tmp13.Nonce) + w.WriteUint64(uint64(_tmp13.BlockAccessIndex)) + w.WriteUint64(_tmp13.PostNonce) w.ListEnd(_tmp14) } w.ListEnd(_tmp12) _tmp15 := w.List() for _, _tmp16 := range obj.CodeChanges { _tmp17 := w.List() - w.WriteUint64(uint64(_tmp16.TxIndex)) - w.WriteBytes(_tmp16.Code) + w.WriteUint64(uint64(_tmp16.BlockAccessIndex)) + w.WriteBytes(_tmp16.NewCode) w.ListEnd(_tmp17) } w.ListEnd(_tmp15) @@ -81,18 +82,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error { return err } // Address: - var _tmp1 [20]byte + var _tmp1 common.Address if err := dec.ReadBytes(_tmp1[:]); err != nil { return err } _tmp0.Address = _tmp1 - // StorageWrites: - var _tmp2 []encodingSlotWrites + // StorageChanges: + var _tmp2 []encodingSlotChanges if _, err := dec.List(); err != nil { return err } for dec.MoreDataInList() { - var _tmp3 encodingSlotWrites + var _tmp3 encodingSlotChanges { if _, err := dec.List(); err != nil { return err @@ -103,7 +104,7 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error { return err } _tmp3.Slot = &_tmp4 - // Accesses: + // SlotChanges: var _tmp5 []encodingStorageWrite if _, err := dec.List(); err != nil { return err @@ -114,18 +115,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error { if _, err := dec.List(); err != nil { return err } - // TxIdx: + // BlockAccessIndex: _tmp7, err := dec.Uint32() if err != nil { return err } - _tmp6.TxIdx = _tmp7 - // ValueAfter: + _tmp6.BlockAccessIndex = _tmp7 + // PostValue: var _tmp8 uint256.Int if err := dec.ReadUint256(&_tmp8); err != nil { return err } - _tmp6.ValueAfter = &_tmp8 + _tmp6.PostValue = &_tmp8 if err := dec.ListEnd(); err != nil { return err } @@ -135,7 +136,7 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error { if err := dec.ListEnd(); err != nil { return err } - _tmp3.Accesses = _tmp5 + _tmp3.SlotChanges = _tmp5 if err := dec.ListEnd(); err != nil { return err } @@ -145,7 +146,7 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error { if err := dec.ListEnd(); err != nil { return err } - _tmp0.StorageWrites = _tmp2 + _tmp0.StorageChanges = _tmp2 // StorageReads: var _tmp9 []*uint256.Int if _, err := dec.List(); err != nil { @@ -173,18 +174,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error { if _, err := dec.List(); err != nil { return err } - // TxIdx: + // BlockAccessIndex: _tmp13, err := dec.Uint32() if err != nil { return err } - _tmp12.TxIdx = _tmp13 - // Balance: + _tmp12.BlockAccessIndex = _tmp13 + // PostBalance: var _tmp14 uint256.Int if err := dec.ReadUint256(&_tmp14); err != nil { return err } - _tmp12.Balance = &_tmp14 + _tmp12.PostBalance = &_tmp14 if err := dec.ListEnd(); err != nil { return err } @@ -206,18 +207,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error { if _, err := dec.List(); err != nil { return err } - // TxIdx: + // BlockAccessIndex: _tmp17, err := dec.Uint32() if err != nil { return err } - _tmp16.TxIdx = _tmp17 - // Nonce: + _tmp16.BlockAccessIndex = _tmp17 + // PostNonce: _tmp18, err := dec.Uint64() if err != nil { return err } - _tmp16.Nonce = _tmp18 + _tmp16.PostNonce = _tmp18 if err := dec.ListEnd(); err != nil { return err } @@ -239,18 +240,18 @@ func (obj *AccountAccess) DecodeRLP(dec *rlp.Stream) error { if _, err := dec.List(); err != nil { return err } - // TxIndex: + // BlockAccessIndex: _tmp21, err := dec.Uint32() if err != nil { return err } - _tmp20.TxIndex = _tmp21 - // Code: + _tmp20.BlockAccessIndex = _tmp21 + // NewCode: _tmp22, err := dec.Bytes() if err != nil { return err } - _tmp20.Code = _tmp22 + _tmp20.NewCode = _tmp22 if err := dec.ListEnd(); err != nil { return err } diff --git a/core/types/bal/bal_test.go b/core/types/bal/bal_test.go index fae4856ac6..a798337c19 100644 --- a/core/types/bal/bal_test.go +++ b/core/types/bal/bal_test.go @@ -160,7 +160,7 @@ func TestConstructionBALMerge(t *testing.T) { func makeTestAccountAccess(sort bool) AccountAccess { var ( - storageWrites []encodingSlotWrites + storageWrites []encodingSlotChanges storageReads []*uint256.Int balances []encodingBalanceChange nonces []encodingAccountNonce @@ -170,24 +170,24 @@ func makeTestAccountAccess(sort bool) AccountAccess { return new(uint256.Int).SetBytes(testrand.Bytes(32)) } for i := 0; i < 5; i++ { - slot := encodingSlotWrites{ + slot := encodingSlotChanges{ Slot: randSlot(), } for j := 0; j < 3; j++ { - slot.Accesses = append(slot.Accesses, encodingStorageWrite{ - TxIdx: uint32(2 * j), - ValueAfter: randSlot(), + slot.SlotChanges = append(slot.SlotChanges, encodingStorageWrite{ + BlockAccessIndex: uint32(2 * j), + PostValue: randSlot(), }) } if sort { - slices.SortFunc(slot.Accesses, func(a, b encodingStorageWrite) int { - return cmp.Compare[uint32](a.TxIdx, b.TxIdx) + slices.SortFunc(slot.SlotChanges, func(a, b encodingStorageWrite) int { + return cmp.Compare(a.BlockAccessIndex, b.BlockAccessIndex) }) } storageWrites = append(storageWrites, slot) } if sort { - slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int { + slices.SortFunc(storageWrites, func(a, b encodingSlotChanges) int { return a.Slot.Cmp(b.Slot) }) } @@ -203,43 +203,43 @@ func makeTestAccountAccess(sort bool) AccountAccess { for i := 0; i < 5; i++ { balances = append(balances, encodingBalanceChange{ - TxIdx: uint32(2 * i), - Balance: new(uint256.Int).SetBytes(testrand.Bytes(16)), + BlockAccessIndex: uint32(2 * i), + PostBalance: new(uint256.Int).SetBytes(testrand.Bytes(16)), }) } if sort { 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++ { nonces = append(nonces, encodingAccountNonce{ - TxIdx: uint32(2 * i), - Nonce: uint64(i + 100), + BlockAccessIndex: uint32(2 * i), + PostNonce: uint64(i + 100), }) } if sort { 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++ { codes = append(codes, encodingCodeChange{ - TxIndex: uint32(2 * i), - Code: testrand.Bytes(256), + BlockAccessIndex: uint32(2 * i), + NewCode: testrand.Bytes(256), }) } if sort { 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{ - Address: [20]byte(testrand.Bytes(20)), - StorageWrites: storageWrites, + Address: common.Address(testrand.Bytes(20)), + StorageChanges: storageWrites, StorageReads: storageReads, BalanceChanges: balances, NonceChanges: nonces, @@ -289,14 +289,14 @@ func TestBlockAccessListItemCount(t *testing.T) { t.Fatalf("empty BAL item count: got %d, want 0", got) } - addr1 := [20]byte(testrand.Bytes(20)) - addr2 := [20]byte(testrand.Bytes(20)) + addr1 := common.Address(testrand.Bytes(20)) + addr2 := common.Address(testrand.Bytes(20)) one := func() *uint256.Int { return new(uint256.Int).SetBytes(testrand.Bytes(32)) } bal := &BlockAccessList{ AccountAccess{ Address: addr1, - StorageWrites: []encodingSlotWrites{ - {Slot: one(), Accesses: []encodingStorageWrite{{TxIdx: 0, ValueAfter: one()}, {TxIdx: 1, ValueAfter: one()}}}, + StorageChanges: []encodingSlotChanges{ + {Slot: one(), SlotChanges: []encodingStorageWrite{{BlockAccessIndex: 0, PostValue: one()}, {BlockAccessIndex: 1, PostValue: one()}}}, {Slot: 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)) } bal := make(BlockAccessList, 3) 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++ { - bal[i].StorageWrites = append(bal[i].StorageWrites, encodingSlotWrites{ - Slot: one(), Accesses: []encodingStorageWrite{{TxIdx: 0, ValueAfter: one()}}, + bal[i].StorageChanges = append(bal[i].StorageChanges, encodingSlotChanges{ + Slot: one(), SlotChanges: []encodingStorageWrite{{BlockAccessIndex: 0, PostValue: one()}}, }) } for j := 0; j < 4; j++ { diff --git a/core/types/bal/gen_account_access_json.go b/core/types/bal/gen_account_access_json.go new file mode 100644 index 0000000000..754a875e39 --- /dev/null +++ b/core/types/bal/gen_account_access_json.go @@ -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 +} diff --git a/core/types/bal/gen_encoding_account_nonce_json.go b/core/types/bal/gen_encoding_account_nonce_json.go new file mode 100644 index 0000000000..62087b3d8a --- /dev/null +++ b/core/types/bal/gen_encoding_account_nonce_json.go @@ -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 +} diff --git a/core/types/bal/gen_encoding_balance_change_json.go b/core/types/bal/gen_encoding_balance_change_json.go new file mode 100644 index 0000000000..630f81496c --- /dev/null +++ b/core/types/bal/gen_encoding_balance_change_json.go @@ -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 +} diff --git a/core/types/bal/gen_encoding_code_change_json.go b/core/types/bal/gen_encoding_code_change_json.go new file mode 100644 index 0000000000..c725a47da4 --- /dev/null +++ b/core/types/bal/gen_encoding_code_change_json.go @@ -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 +} diff --git a/core/types/bal/gen_encoding_slot_changes_json.go b/core/types/bal/gen_encoding_slot_changes_json.go new file mode 100644 index 0000000000..0cc318f3d6 --- /dev/null +++ b/core/types/bal/gen_encoding_slot_changes_json.go @@ -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 +} diff --git a/core/types/bal/gen_encoding_storage_write_json.go b/core/types/bal/gen_encoding_storage_write_json.go new file mode 100644 index 0000000000..c5075c1336 --- /dev/null +++ b/core/types/bal/gen_encoding_storage_write_json.go @@ -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 +} diff --git a/core/types/block.go b/core/types/block.go index 0856845a4e..eab458e88a 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -101,7 +101,7 @@ type Header struct { RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"` // 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 *uint64 `json:"slotNumber" rlp:"optional"` diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go index 2e2f1cdca5..6856562215 100644 --- a/core/types/gen_header_json.go +++ b/core/types/gen_header_json.go @@ -37,7 +37,7 @@ func (h Header) MarshalJSON() ([]byte, error) { ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" 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"` Hash common.Hash `json:"hash"` } @@ -93,7 +93,7 @@ func (h *Header) UnmarshalJSON(input []byte) error { ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" 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"` } var dec Header diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 109169e0b0..6452fcf37c 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1002,7 +1002,7 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} { result["requestsHash"] = head.RequestsHash } if head.BlockAccessListHash != nil { - result["balHash"] = head.BlockAccessListHash + result["blockAccessListHash"] = head.BlockAccessListHash } if head.SlotNumber != nil { result["slotNumber"] = hexutil.Uint64(*head.SlotNumber)