diff --git a/core/types/bal/bal.go b/core/types/bal/bal.go index 3acef119ea55..711f15b857e5 100644 --- a/core/types/bal/bal.go +++ b/core/types/bal/bal.go @@ -1,104 +1,146 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package bal import ( "bytes" - "fmt" "maps" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" ) +// CodeChange contains the runtime bytecode deployed at an address and the +// transaction index where the deployment took place. +type CodeChange struct { + TxIndex uint16 + Code []byte `json:"code,omitempty"` +} + +// AccountAccess contains post-block account state for mutations as well as +// all storage keys that were read during execution. +type AccountAccess struct { + // StorageWrites is the post-state values of an account's storage slots + // that were modified in a block, keyed by the slot key and the tx index + // where the modification occurred. + StorageWrites map[common.Hash]map[uint16]common.Hash `json:"storageWrites,omitempty"` + + // StorageReads is the set of slot keys that were accessed during block + // execution. + // + // Storage slots which are both read and written (with changed values) + // appear only in StorageWrites. + StorageReads map[common.Hash]struct{} `json:"storageReads,omitempty"` + + // BalanceChanges contains the post-transaction balances of an account, + // keyed by transaction indices where it was changed. + BalanceChanges map[uint16]*uint256.Int `json:"balanceChanges,omitempty"` + + // NonceChanges contains the post-state nonce values of an account keyed + // by tx index. + NonceChanges map[uint16]uint64 `json:"nonceChanges,omitempty"` + + // CodeChange is only set for contract accounts which were deployed in + // the block. + CodeChange *CodeChange `json:"codeChange,omitempty"` +} + +// NewAccountAccess initializes the account access object. +func NewAccountAccess() *AccountAccess { + return &AccountAccess{ + StorageWrites: make(map[common.Hash]map[uint16]common.Hash), + StorageReads: make(map[common.Hash]struct{}), + BalanceChanges: make(map[uint16]*uint256.Int), + NonceChanges: make(map[uint16]uint64), + } +} + // BlockAccessList contains post-block modified state and some state accessed // in execution (account addresses and storage keys). type BlockAccessList struct { - accounts map[common.Address]*accountAccess + Accounts map[common.Address]*AccountAccess } // NewBlockAccessList instantiates an empty access list. func NewBlockAccessList() BlockAccessList { return BlockAccessList{ - accounts: make(map[common.Address]*accountAccess), + Accounts: make(map[common.Address]*AccountAccess), } } // AccountRead records the address of an account that has been read during execution. func (b *BlockAccessList) AccountRead(addr common.Address) { - if _, ok := b.accounts[addr]; !ok { - b.accounts[addr] = newAccountAccess() + if _, ok := b.Accounts[addr]; !ok { + b.Accounts[addr] = NewAccountAccess() } } // StorageRead records a storage key read during execution. func (b *BlockAccessList) StorageRead(address common.Address, key common.Hash) { - if _, ok := b.accounts[address]; !ok { - b.accounts[address] = newAccountAccess() + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewAccountAccess() } - - if _, ok := b.accounts[address].StorageWrites[key]; ok { + if _, ok := b.Accounts[address].StorageWrites[key]; ok { return } - - b.accounts[address].StorageReads[key] = struct{}{} + b.Accounts[address].StorageReads[key] = struct{}{} } // StorageWrite records the post-transaction value of a mutated storage slot. // The storage slot is removed from the list of read slots. func (b *BlockAccessList) StorageWrite(txIdx uint16, address common.Address, key, value common.Hash) { - if _, ok := b.accounts[address]; !ok { - b.accounts[address] = newAccountAccess() + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewAccountAccess() } - - if _, ok := b.accounts[address].StorageWrites[key]; !ok { - b.accounts[address].StorageWrites[key] = make(slotWrites) + if _, ok := b.Accounts[address].StorageWrites[key]; !ok { + b.Accounts[address].StorageWrites[key] = make(map[uint16]common.Hash) } - b.accounts[address].StorageWrites[key][txIdx] = value - delete(b.accounts[address].StorageReads, key) + b.Accounts[address].StorageWrites[key][txIdx] = value + + delete(b.Accounts[address].StorageReads, key) } // CodeChange records the code of a newly-created contract. func (b *BlockAccessList) CodeChange(address common.Address, txIndex uint16, code []byte) { - if _, ok := b.accounts[address]; !ok { - b.accounts[address] = newAccountAccess() + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewAccountAccess() } - - b.accounts[address].CodeChange = &codeChange{ + b.Accounts[address].CodeChange = &CodeChange{ TxIndex: txIndex, Code: bytes.Clone(code), } } -// NonceDiff records tx post-state nonce of any contract-like accounts whose nonce was incremented -func (b *BlockAccessList) NonceDiff(address common.Address, txIdx uint16, postNonce uint64) { - if _, ok := b.accounts[address]; !ok { - b.accounts[address] = newAccountAccess() +// NonceChange records tx post-state nonce of any contract-like accounts whose +// nonce was incremented. +func (b *BlockAccessList) NonceChange(address common.Address, txIdx uint16, postNonce uint64) { + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewAccountAccess() } - - b.accounts[address].NonceChanges[txIdx] = postNonce + b.Accounts[address].NonceChanges[txIdx] = postNonce } // BalanceChange records the post-transaction balance of an account whose // balance changed. func (b *BlockAccessList) BalanceChange(txIdx uint16, address common.Address, balance *uint256.Int) { - if _, ok := b.accounts[address]; !ok { - b.accounts[address] = newAccountAccess() + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewAccountAccess() } - - b.accounts[address].BalanceChanges[txIdx] = balance.Clone() -} - -// contains the post-transaction balances of an account, keyed by transaction indices -// where it was changed. -type balanceDiff map[uint16]*uint256.Int - -// copy returns a deep copy of the object -func (b balanceDiff) copy() balanceDiff { - res := make(balanceDiff) - for idx, balance := range b { - res[idx] = balance.Clone() - } - return res + b.Accounts[address].BalanceChanges[txIdx] = balance.Clone() } // PrettyPrint returns a human-readable representation of the access list @@ -112,116 +154,40 @@ func (b *BlockAccessList) Hash() common.Hash { hash, err := b.toEncodingObj().HashTreeRoot() if err != nil { // errors here are related to BAL values exceeding maximum size defined - // by the spec. Hard-fail because these cases are not expected to be hit + // by the spec. Hard-fail because these cases are not expected to be hit // under reasonable conditions. panic(err) } return hash } -// codeChange contains the code deployed at an address and the transaction -// index where the deployment took place. -type codeChange struct { - TxIndex uint16 - Code []byte `json:"code,omitempty"` -} - -// post-state values of an account's storage slots modified in a block, keyed -// by slot key -type storageWrites map[common.Hash]slotWrites - -func (s storageWrites) copy() storageWrites { - res := make(storageWrites) - for slot, writes := range s { - res[slot] = maps.Clone(writes) - } - return res -} - -// accountAccess contains post-block account state for mutations as well as -// all storage keys that were read during execution. -type accountAccess struct { - StorageWrites storageWrites `json:"storageWrites,omitempty"` - StorageReads map[common.Hash]struct{} `json:"storageReads,omitempty"` - BalanceChanges balanceDiff `json:"balanceChanges,omitempty"` - NonceChanges accountNonceDiffs `json:"nonceChanges,omitempty"` - - // only set for contract accounts which were deployed in the block - CodeChange *codeChange `json:"codeChange,omitempty"` -} - -func newAccountAccess() *accountAccess { - return &accountAccess{ - StorageWrites: make(map[common.Hash]slotWrites), - StorageReads: make(map[common.Hash]struct{}), - BalanceChanges: make(balanceDiff), - NonceChanges: make(accountNonceDiffs), - } -} - -// the post-state nonce values of a contract account keyed by tx index -type accountNonceDiffs map[uint16]uint64 - -// the post-state values of a storage slot, keyed by tx index -type slotWrites map[uint16]common.Hash - // Copy returns a deep copy of the access list. func (b *BlockAccessList) Copy() *BlockAccessList { res := NewBlockAccessList() - for addr, aa := range b.accounts { - var aaCopy accountAccess - aaCopy.StorageWrites = aa.StorageWrites.copy() + for addr, aa := range b.Accounts { + var aaCopy AccountAccess + + slotWrites := make(map[common.Hash]map[uint16]common.Hash, len(aa.StorageWrites)) + for key, m := range aa.StorageWrites { + slotWrites[key] = maps.Clone(m) + } + aaCopy.StorageWrites = slotWrites aaCopy.StorageReads = maps.Clone(aa.StorageReads) - aaCopy.BalanceChanges = aa.BalanceChanges.copy() + + balances := make(map[uint16]*uint256.Int, len(aa.BalanceChanges)) + for index, balance := range aa.BalanceChanges { + balances[index] = balance.Clone() + } + aaCopy.BalanceChanges = balances aaCopy.NonceChanges = maps.Clone(aa.NonceChanges) + if aa.CodeChange != nil { - aaCopy.CodeChange = &codeChange{ + aaCopy.CodeChange = &CodeChange{ TxIndex: aa.CodeChange.TxIndex, Code: bytes.Clone(aa.CodeChange.Code), } } - res.accounts[addr] = &aaCopy + res.Accounts[addr] = &aaCopy } return &res } - -func (e *encodingBlockAccessList) prettyPrint() string { - var res bytes.Buffer - printWithIndent := func(indent int, text string) { - fmt.Fprintf(&res, "%s%s\n", strings.Repeat(" ", indent), text) - } - for _, accountDiff := range e.Accesses { - printWithIndent(0, fmt.Sprintf("%x:", accountDiff.Address)) - - printWithIndent(1, "storage writes:") - for _, sWrite := range accountDiff.StorageWrites { - printWithIndent(2, fmt.Sprintf("%x:", sWrite.Slot)) - for _, access := range sWrite.Accesses { - printWithIndent(3, fmt.Sprintf("%d: %x", access.TxIdx, access.ValueAfter)) - } - } - - printWithIndent(1, "storage reads:") - for _, slot := range accountDiff.StorageReads { - printWithIndent(2, fmt.Sprintf("%x", slot)) - } - - printWithIndent(1, "balance changes:") - for _, change := range accountDiff.BalanceChanges { - balance := new(uint256.Int).SetBytes(change.Balance[:]).String() - printWithIndent(2, fmt.Sprintf("%d: %s", change.TxIdx, balance)) - } - - printWithIndent(1, "nonce changes:") - for _, change := range accountDiff.NonceChanges { - printWithIndent(2, fmt.Sprintf("%d: %d", change.TxIdx, change.Nonce)) - } - - if len(accountDiff.Code) > 0 { - printWithIndent(1, "code:") - printWithIndent(2, fmt.Sprintf("%d: %x", accountDiff.Code[0].TxIndex, accountDiff.Code[0].Code)) - } - } - - return res.String() -} diff --git a/core/types/bal/bal_encoding.go b/core/types/bal/bal_encoding.go index 5fde0c74b9dc..c5e32dc1c366 100644 --- a/core/types/bal/bal_encoding.go +++ b/core/types/bal/bal_encoding.go @@ -1,10 +1,29 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package bal import ( "bytes" + "cmp" "fmt" "io" - "sort" + "maps" + "slices" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" @@ -12,17 +31,12 @@ import ( ) //go:generate go run github.com/ferranbt/fastssz/sszgen --output bal_encoding_ssz_generated.go --path . --objs encodingStorageWrite,encodingCodeChange,encodingBalanceChange,encodingAccountNonce,encodingAccountAccess,encodingBlockAccessList - -//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_storagewrite_generated.go -type encodingStorageWrite -decoder -//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_codechange_generated.go -type encodingCodeChange -decoder -//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_balancechange_generated.go -type encodingBalanceChange -decoder -//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_accountnonce_generated.go -type encodingAccountNonce -decoder -//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_accountaccess_generated.go -type encodingAccountAccess -decoder -//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_blockaccesslist_generated.go -type encodingBlockAccessList -decoder +//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_generated.go -type encodingBlockAccessList -decoder // These are objects used as input for the access list encoding. They mirror // the spec format. +// encodingBlockAccessList is the encoding format of BlockAccessList. type encodingBlockAccessList struct { Accesses []encodingAccountAccess `ssz-max:"300000"` } @@ -30,137 +44,173 @@ type encodingBlockAccessList struct { // toBlockAccessList converts out of the encoding format, returning an error if // values in the encoder object are not properly ordered according to the spec. func (e *encodingBlockAccessList) toBlockAccessList() (*BlockAccessList, error) { - res := NewBlockAccessList() - var prevAccount *common.Address - for _, encAccountAccess := range e.Accesses { - if prevAccount != nil { - if bytes.Compare(encAccountAccess.Address[:], (*prevAccount)[:]) <= 0 { + var ( + obj = NewBlockAccessList() + prev *[20]byte + ) + for _, entry := range e.Accesses { + if prev != nil { + if bytes.Compare(entry.Address[:], (*prev)[:]) <= 0 { return nil, fmt.Errorf("block access list accounts not in lexicographic order") } } - aa, err := encAccountAccess.toAccountAccess() + prev = &entry.Address + + aa, err := entry.toAccountAccess() if err != nil { return nil, err } - res.accounts[encAccountAccess.Address] = aa + obj.Accounts[entry.Address] = aa } - return &res, nil + return &obj, nil } +// encodingCodeChange is the encoding format of CodeChange. type encodingCodeChange struct { TxIndex uint16 Code []byte `ssz-max:"24576"` } +// encodeBalance encodes the provided balance into 16-bytes. +func encodeBalance(val *uint256.Int) [16]byte { + valBytes := val.Bytes() + if len(valBytes) > 16 { + panic("can't encode value that is greater than 16 bytes in size") + } + var enc [16]byte + copy(enc[16-len(valBytes):], valBytes[:]) + return enc +} + +// encodingBalanceChange is the encoding format of BalanceChange. +type encodingBalanceChange struct { + TxIdx uint16 `ssz-size:"2"` + Balance [16]byte `ssz-size:"16"` +} + +// encodingAccountNonce is the encoding format of NonceChange. +type encodingAccountNonce struct { + TxIdx uint16 `ssz-size:"2"` + Nonce uint64 `ssz-size:"8"` +} + +// encodingStorageWrite is the encoding format of StorageWrites. +type encodingStorageWrite struct { + TxIdx uint16 + ValueAfter [32]byte `ssz-size:"32"` +} + +// encodingStorageWrite is the encoding format of SlotWrites. +type encodingSlotWrites struct { + Slot [32]byte `ssz-size:"32"` + Accesses []encodingStorageWrite `ssz-max:"300000"` +} + +// toSlotWrites returns an instance of the encoding-representation slot writes in +// working representation. +func (e *encodingSlotWrites) toSlotWrites() (map[uint16]common.Hash, error) { + var ( + prev *uint16 + obj = make(map[uint16]common.Hash) + ) + for _, write := range e.Accesses { + if prev != nil { + if *prev >= write.TxIdx { + return nil, fmt.Errorf("storage write tx indices not in order") + } + } + prev = &write.TxIdx + obj[write.TxIdx] = write.ValueAfter + } + return obj, nil +} + +// encodingAccountAccess is the encoding format of AccountAccess. type encodingAccountAccess struct { - Address [20]byte `ssz-size:"20"` - StorageWrites []encodingSlotWrites `ssz-max:"300000"` - StorageReads [][32]byte `ssz-max:"300000"` - BalanceChanges []encodingBalanceChange `ssz-max:"300000"` - NonceChanges []encodingAccountNonce `ssz-max:"300000"` - Code []encodingCodeChange `ssz-max:"1"` + Address [20]byte `ssz-size:"20"` // 20-byte Ethereum address + StorageWrites []encodingSlotWrites `ssz-max:"300000"` // Storage changes (slot -> [tx_index -> new_value]) + StorageReads [][32]byte `ssz-max:"300000"` // Read-only storage keys + BalanceChanges []encodingBalanceChange `ssz-max:"300000"` // Balance changes ([tx_index -> post_balance]) + NonceChanges []encodingAccountNonce `ssz-max:"300000"` // Nonce changes ([tx_index -> new_nonce]) + Code []encodingCodeChange `ssz-max:"1"` // Code changes ([tx_index -> new_code]) } // toAccountAccess converts the account accesses out of encoding format. // If any of the keys in the encoding object are not ordered according to the // spec, an error is returned. -func (e *encodingAccountAccess) toAccountAccess() (*accountAccess, error) { - res := accountAccess{ - StorageWrites: make(map[common.Hash]slotWrites), +func (e *encodingAccountAccess) toAccountAccess() (*AccountAccess, error) { + res := AccountAccess{ + StorageWrites: make(map[common.Hash]map[uint16]common.Hash), StorageReads: make(map[common.Hash]struct{}), - BalanceChanges: make(balanceDiff), - NonceChanges: make(accountNonceDiffs), + BalanceChanges: make(map[uint16]*uint256.Int), + NonceChanges: make(map[uint16]uint64), CodeChange: nil, } - { - var prevWriteSlot *[32]byte - for _, write := range e.StorageWrites { - if prevWriteSlot != nil { - if bytes.Compare((*prevWriteSlot)[:], write.Slot[:]) >= 0 { - return nil, fmt.Errorf("storage writes slots lexicographic order") - } - } - wr, err := write.toSlotWrites() - if err != nil { - return nil, err + // Convert slot writes + var prevSlotWrite *[32]byte + for _, write := range e.StorageWrites { + if prevSlotWrite != nil { + if bytes.Compare((*prevSlotWrite)[:], write.Slot[:]) >= 0 { + return nil, fmt.Errorf("storage writes slots not in lexicographic order") } + } + prevSlotWrite = &write.Slot - res.StorageWrites[write.Slot] = wr - prevWriteSlot = &write.Slot + wr, err := write.toSlotWrites() + if err != nil { + return nil, err } + res.StorageWrites[write.Slot] = wr } - { - var prevReadSlot *[32]byte - for _, read := range e.StorageReads { - if prevReadSlot != nil { - if bytes.Compare((*prevReadSlot)[:], read[:]) >= 0 { - return nil, fmt.Errorf("storage read slots not in lexicographic order") - } + // Convert slot reads + var prevSlotRead *[32]byte + for _, read := range e.StorageReads { + if prevSlotRead != nil { + if bytes.Compare((*prevSlotRead)[:], read[:]) >= 0 { + return nil, fmt.Errorf("storage read slots not in lexicographic order") } - res.StorageReads[read] = struct{}{} - prevReadSlot = &read } + prevSlotRead = &read + res.StorageReads[read] = struct{}{} } - { - var prevBalanceChangeIdx *uint16 - for _, balanceChange := range e.BalanceChanges { - if prevBalanceChangeIdx != nil { - if *prevBalanceChangeIdx >= balanceChange.TxIdx { - return nil, fmt.Errorf("balance changes not in ascending order by tx index") - } + // Convert balance changes + var prevBalanceIndex *uint16 + for _, balanceChange := range e.BalanceChanges { + if prevBalanceIndex != nil { + if *prevBalanceIndex >= balanceChange.TxIdx { + return nil, fmt.Errorf("balance changes not in ascending order by tx index") } - res.BalanceChanges[balanceChange.TxIdx] = new(uint256.Int).SetBytes(balanceChange.Balance[:]) - prevBalanceChangeIdx = &balanceChange.TxIdx } + prevBalanceIndex = &balanceChange.TxIdx + res.BalanceChanges[balanceChange.TxIdx] = new(uint256.Int).SetBytes(balanceChange.Balance[:]) } - { - var prevNonceDiffIdx *uint16 - for _, nonceDiff := range e.NonceChanges { - if prevNonceDiffIdx != nil { - if *prevNonceDiffIdx >= nonceDiff.TxIdx { - return nil, fmt.Errorf("nonce diffs not in ascending order by tx index") - } + // Convert nonce changes + var prevNonceIndex *uint16 + for _, nonceChange := range e.NonceChanges { + if prevNonceIndex != nil { + if *prevNonceIndex >= nonceChange.TxIdx { + return nil, fmt.Errorf("nonce diffs not in ascending order by tx index") } - res.NonceChanges[nonceDiff.TxIdx] = nonceDiff.Nonce - prevNonceDiffIdx = &nonceDiff.TxIdx } + prevNonceIndex = &nonceChange.TxIdx + res.NonceChanges[nonceChange.TxIdx] = nonceChange.Nonce } - { - if len(e.Code) == 1 { - codeChange := codeChange{e.Code[0].TxIndex, bytes.Clone(e.Code[0].Code)} - res.CodeChange = &codeChange + // Convert code change + if len(e.Code) == 1 { + res.CodeChange = &CodeChange{ + TxIndex: e.Code[0].TxIndex, + Code: bytes.Clone(e.Code[0].Code), } } return &res, nil } -type encodingBalance [16]byte - -func (b *encodingBalance) set(val *uint256.Int) *encodingBalance { - valBytes := val.Bytes() - if len(valBytes) > 16 { - panic("can't encode value that is greater than 16 bytes in size") - } - copy(b[16-len(valBytes):], valBytes[:]) - return b -} - -type encodingBalanceChange struct { - TxIdx uint16 `ssz-size:"2"` - Balance encodingBalance -} - -type encodingAccountNonce struct { - TxIdx uint16 `ssz-size:"2"` - Nonce uint64 `ssz-size:"8"` -} - -// EncodeRLP returns the SSZ-encoded access list wrapped into RLP bytes +// EncodeRLP returns the SSZ-encoded access list wrapped into RLP bytes. func (b *BlockAccessList) EncodeRLP(wr io.Writer) error { w := rlp.NewEncoderBuffer(wr) buf, err := b.encodeSSZ() @@ -183,34 +233,9 @@ func (b *BlockAccessList) DecodeRLP(s *rlp.Stream) error { var _ rlp.Encoder = &BlockAccessList{} var _ rlp.Decoder = &BlockAccessList{} -// toEncoderObj returns an instance of the slot writes which will be used as -// the input for encoding. -func (s slotWrites) toEncoderObj(slot common.Hash) encodingSlotWrites { - res := encodingSlotWrites{ - Slot: slot, - } - - var storageWriteIdxs []uint16 - for idx := range s { - storageWriteIdxs = append(storageWriteIdxs, idx) - } - sort.Slice(storageWriteIdxs, func(i, j int) bool { - return storageWriteIdxs[i] < storageWriteIdxs[j] - }) - - for _, idx := range storageWriteIdxs { - res.Accesses = append(res.Accesses, encodingStorageWrite{ - TxIdx: idx, - ValueAfter: s[idx], - }) - } - - return res -} - -// toEncodingObj creates an instance of the accountAccess of the type that is +// toEncodingObj creates an instance of the AccountAccess of the type that is // used as input for the encoding. -func (a *accountAccess) toEncodingObj(addr common.Address) encodingAccountAccess { +func (a *AccountAccess) toEncodingObj(addr common.Address) encodingAccountAccess { res := encodingAccountAccess{ Address: addr, StorageWrites: make([]encodingSlotWrites, 0), @@ -220,69 +245,55 @@ func (a *accountAccess) toEncodingObj(addr common.Address) encodingAccountAccess Code: nil, } - { - var writeSlots []common.Hash - - for slot := range a.StorageWrites { - writeSlots = append(writeSlots, slot) - } - sort.Slice(writeSlots, func(i, j int) bool { - return bytes.Compare(writeSlots[i][:], writeSlots[j][:]) < 0 - }) - - for _, slot := range writeSlots { - res.StorageWrites = append(res.StorageWrites, a.StorageWrites[slot].toEncoderObj(slot)) + // Convert write slots + writeSlots := slices.Collect(maps.Keys(a.StorageWrites)) + slices.SortFunc(writeSlots, common.Hash.Cmp) + for _, slot := range writeSlots { + var obj encodingSlotWrites + obj.Slot = slot + + slotWrites := a.StorageWrites[slot] + obj.Accesses = make([]encodingStorageWrite, 0, len(slotWrites)) + + indices := slices.Collect(maps.Keys(slotWrites)) + slices.SortFunc(indices, cmp.Compare[uint16]) + for _, index := range indices { + obj.Accesses = append(obj.Accesses, encodingStorageWrite{ + TxIdx: index, + ValueAfter: slotWrites[index], + }) } + res.StorageWrites = append(res.StorageWrites, obj) } - { - var readSlots []common.Hash - for slot := range a.StorageReads { - readSlots = append(readSlots, slot) - } - sort.Slice(readSlots, func(i, j int) bool { - return bytes.Compare(readSlots[i][:], readSlots[j][:]) < 0 - }) - for _, slot := range readSlots { - res.StorageReads = append(res.StorageReads, slot) - } + // Convert read slots + readSlots := slices.Collect(maps.Keys(a.StorageReads)) + slices.SortFunc(readSlots, common.Hash.Cmp) + for _, slot := range readSlots { + res.StorageReads = append(res.StorageReads, slot) } - { - var balanceChangeIdxs []uint16 - for idx := range a.BalanceChanges { - balanceChangeIdxs = append(balanceChangeIdxs, idx) - } - - sort.Slice(balanceChangeIdxs, func(i, j int) bool { - return balanceChangeIdxs[i] < balanceChangeIdxs[j] + // Convert balance changes + balanceIndices := slices.Collect(maps.Keys(a.BalanceChanges)) + slices.SortFunc(balanceIndices, cmp.Compare[uint16]) + for _, idx := range balanceIndices { + res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{ + TxIdx: idx, + Balance: encodeBalance(a.BalanceChanges[idx]), }) - - for _, idx := range balanceChangeIdxs { - res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{ - TxIdx: idx, - Balance: *new(encodingBalance).set(a.BalanceChanges[idx]), - }) - } } - { - var nonceChangeIdxs []uint16 - for idx := range a.NonceChanges { - nonceChangeIdxs = append(nonceChangeIdxs, idx) - } - sort.Slice(nonceChangeIdxs, func(i, j int) bool { - return nonceChangeIdxs[i] < nonceChangeIdxs[j] + // Convert nonce changes + nonceIndices := slices.Collect(maps.Keys(a.NonceChanges)) + slices.SortFunc(nonceIndices, cmp.Compare[uint16]) + for _, idx := range nonceIndices { + res.NonceChanges = append(res.NonceChanges, encodingAccountNonce{ + TxIdx: idx, + Nonce: a.NonceChanges[idx], }) - - for _, idx := range nonceChangeIdxs { - res.NonceChanges = append(res.NonceChanges, encodingAccountNonce{ - TxIdx: idx, - Nonce: a.NonceChanges[idx], - }) - } } + // Convert code change if a.CodeChange != nil { res.Code = []encodingCodeChange{ { @@ -291,24 +302,21 @@ func (a *accountAccess) toEncodingObj(addr common.Address) encodingAccountAccess }, } } - return res } // toEncodingObj returns an instance of the access list expressed as the type -// which is used as input for the decoding. +// which is used as input for the encoding/decoding. func (b *BlockAccessList) toEncodingObj() *encodingBlockAccessList { - var res encodingBlockAccessList - var addrs []common.Address - for addr := range b.accounts { - addrs = append(addrs, addr) + var addresses []common.Address + for addr := range b.Accounts { + addresses = append(addresses, addr) } - sort.Slice(addrs, func(i, j int) bool { - return bytes.Compare(addrs[i][:], addrs[j][:]) < 0 - }) + slices.SortFunc(addresses, common.Address.Cmp) - for _, addr := range addrs { - res.Accesses = append(res.Accesses, b.accounts[addr].toEncodingObj(addr)) + var res encodingBlockAccessList + for _, addr := range addresses { + res.Accesses = append(res.Accesses, b.Accounts[addr].toEncodingObj(addr)) } return &res } @@ -335,34 +343,42 @@ func (b *BlockAccessList) decodeSSZ(buf []byte) error { return nil } -// used as input for encoding. -type encodingStorageWrite struct { - TxIdx uint16 - ValueAfter [32]byte `ssz-size:"32"` -} +func (e *encodingBlockAccessList) prettyPrint() string { + var res bytes.Buffer + printWithIndent := func(indent int, text string) { + fmt.Fprintf(&res, "%s%s\n", strings.Repeat(" ", indent), text) + } + for _, accountDiff := range e.Accesses { + printWithIndent(0, fmt.Sprintf("%x:", accountDiff.Address)) + + printWithIndent(1, "storage writes:") + for _, sWrite := range accountDiff.StorageWrites { + printWithIndent(2, fmt.Sprintf("%x:", sWrite.Slot)) + for _, access := range sWrite.Accesses { + printWithIndent(3, fmt.Sprintf("%d: %x", access.TxIdx, access.ValueAfter)) + } + } -// used as input for encoding. Storage writes are expected to be sorted -// lexicographically by their storage key. -type encodingSlotWrites struct { - Slot [32]byte `ssz-size:"32"` - Accesses []encodingStorageWrite `ssz-max:"300000"` -} + printWithIndent(1, "storage reads:") + for _, slot := range accountDiff.StorageReads { + printWithIndent(2, fmt.Sprintf("%x", slot)) + } -// toSlotWrites returns an instance of the encoding-representation slot writes in -// working representation. -func (e *encodingSlotWrites) toSlotWrites() (slotWrites, error) { - var prev *uint16 + printWithIndent(1, "balance changes:") + for _, change := range accountDiff.BalanceChanges { + balance := new(uint256.Int).SetBytes(change.Balance[:]).String() + printWithIndent(2, fmt.Sprintf("%d: %s", change.TxIdx, balance)) + } - res := make(slotWrites) + printWithIndent(1, "nonce changes:") + for _, change := range accountDiff.NonceChanges { + printWithIndent(2, fmt.Sprintf("%d: %d", change.TxIdx, change.Nonce)) + } - for _, write := range e.Accesses { - if prev != nil { - if *prev >= write.TxIdx { - return nil, fmt.Errorf("storage write tx indices not in order") - } + if len(accountDiff.Code) > 0 { + printWithIndent(1, "code:") + printWithIndent(2, fmt.Sprintf("%d: %x", accountDiff.Code[0].TxIndex, accountDiff.Code[0].Code)) } - res[write.TxIdx] = write.ValueAfter - prev = &write.TxIdx } - return res, nil + return res.String() } diff --git a/core/types/bal/bal_encoding_rlp_accountaccess_generated.go b/core/types/bal/bal_encoding_rlp_accountaccess_generated.go deleted file mode 100644 index 320f7c9d9048..000000000000 --- a/core/types/bal/bal_encoding_rlp_accountaccess_generated.go +++ /dev/null @@ -1,253 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package bal - -import "github.com/ethereum/go-ethereum/rlp" -import "io" - -func (obj *encodingAccountAccess) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteBytes(obj.Address[:]) - _tmp1 := w.List() - for _, _tmp2 := range obj.StorageWrites { - _tmp3 := w.List() - w.WriteBytes(_tmp2.Slot[:]) - _tmp4 := w.List() - for _, _tmp5 := range _tmp2.Accesses { - _tmp6 := w.List() - w.WriteUint64(uint64(_tmp5.TxIdx)) - w.WriteBytes(_tmp5.ValueAfter[:]) - w.ListEnd(_tmp6) - } - w.ListEnd(_tmp4) - w.ListEnd(_tmp3) - } - w.ListEnd(_tmp1) - _tmp7 := w.List() - for _, _tmp8 := range obj.StorageReads { - w.WriteBytes(_tmp8[:]) - } - w.ListEnd(_tmp7) - _tmp9 := w.List() - for _, _tmp10 := range obj.BalanceChanges { - _tmp11 := w.List() - w.WriteUint64(uint64(_tmp10.TxIdx)) - w.WriteBytes(_tmp10.Balance[:]) - w.ListEnd(_tmp11) - } - w.ListEnd(_tmp9) - _tmp12 := w.List() - for _, _tmp13 := range obj.NonceChanges { - _tmp14 := w.List() - w.WriteUint64(uint64(_tmp13.TxIdx)) - w.WriteUint64(_tmp13.Nonce) - w.ListEnd(_tmp14) - } - w.ListEnd(_tmp12) - _tmp15 := w.List() - for _, _tmp16 := range obj.Code { - _tmp17 := w.List() - w.WriteUint64(uint64(_tmp16.TxIndex)) - w.WriteBytes(_tmp16.Code) - w.ListEnd(_tmp17) - } - w.ListEnd(_tmp15) - w.ListEnd(_tmp0) - return w.Flush() -} - -func (obj *encodingAccountAccess) DecodeRLP(dec *rlp.Stream) error { - var _tmp0 encodingAccountAccess - { - if _, err := dec.List(); err != nil { - return err - } - // Address: - var _tmp1 [20]byte - if err := dec.ReadBytes(_tmp1[:]); err != nil { - return err - } - _tmp0.Address = _tmp1 - // StorageWrites: - var _tmp2 []encodingSlotWrites - if _, err := dec.List(); err != nil { - return err - } - for dec.MoreDataInList() { - var _tmp3 encodingSlotWrites - { - if _, err := dec.List(); err != nil { - return err - } - // Slot: - var _tmp4 [32]byte - if err := dec.ReadBytes(_tmp4[:]); err != nil { - return err - } - _tmp3.Slot = _tmp4 - // Accesses: - var _tmp5 []encodingStorageWrite - if _, err := dec.List(); err != nil { - return err - } - for dec.MoreDataInList() { - var _tmp6 encodingStorageWrite - { - if _, err := dec.List(); err != nil { - return err - } - // TxIdx: - _tmp7, err := dec.Uint16() - if err != nil { - return err - } - _tmp6.TxIdx = _tmp7 - // ValueAfter: - var _tmp8 [32]byte - if err := dec.ReadBytes(_tmp8[:]); err != nil { - return err - } - _tmp6.ValueAfter = _tmp8 - if err := dec.ListEnd(); err != nil { - return err - } - } - _tmp5 = append(_tmp5, _tmp6) - } - if err := dec.ListEnd(); err != nil { - return err - } - _tmp3.Accesses = _tmp5 - if err := dec.ListEnd(); err != nil { - return err - } - } - _tmp2 = append(_tmp2, _tmp3) - } - if err := dec.ListEnd(); err != nil { - return err - } - _tmp0.StorageWrites = _tmp2 - // StorageReads: - var _tmp9 [][32]byte - if _, err := dec.List(); err != nil { - return err - } - for dec.MoreDataInList() { - var _tmp10 [32]byte - if err := dec.ReadBytes(_tmp10[:]); err != nil { - return err - } - _tmp9 = append(_tmp9, _tmp10) - } - if err := dec.ListEnd(); err != nil { - return err - } - _tmp0.StorageReads = _tmp9 - // BalanceChanges: - var _tmp11 []encodingBalanceChange - if _, err := dec.List(); err != nil { - return err - } - for dec.MoreDataInList() { - var _tmp12 encodingBalanceChange - { - if _, err := dec.List(); err != nil { - return err - } - // TxIdx: - _tmp13, err := dec.Uint16() - if err != nil { - return err - } - _tmp12.TxIdx = _tmp13 - // Balance: - var _tmp14 encodingBalance - if err := dec.ReadBytes(_tmp14[:]); err != nil { - return err - } - _tmp12.Balance = _tmp14 - if err := dec.ListEnd(); err != nil { - return err - } - } - _tmp11 = append(_tmp11, _tmp12) - } - if err := dec.ListEnd(); err != nil { - return err - } - _tmp0.BalanceChanges = _tmp11 - // NonceChanges: - var _tmp15 []encodingAccountNonce - if _, err := dec.List(); err != nil { - return err - } - for dec.MoreDataInList() { - var _tmp16 encodingAccountNonce - { - if _, err := dec.List(); err != nil { - return err - } - // TxIdx: - _tmp17, err := dec.Uint16() - if err != nil { - return err - } - _tmp16.TxIdx = _tmp17 - // Nonce: - _tmp18, err := dec.Uint64() - if err != nil { - return err - } - _tmp16.Nonce = _tmp18 - if err := dec.ListEnd(); err != nil { - return err - } - } - _tmp15 = append(_tmp15, _tmp16) - } - if err := dec.ListEnd(); err != nil { - return err - } - _tmp0.NonceChanges = _tmp15 - // Code: - var _tmp19 []encodingCodeChange - if _, err := dec.List(); err != nil { - return err - } - for dec.MoreDataInList() { - var _tmp20 encodingCodeChange - { - if _, err := dec.List(); err != nil { - return err - } - // TxIndex: - _tmp21, err := dec.Uint16() - if err != nil { - return err - } - _tmp20.TxIndex = _tmp21 - // Code: - _tmp22, err := dec.Bytes() - if err != nil { - return err - } - _tmp20.Code = _tmp22 - if err := dec.ListEnd(); err != nil { - return err - } - } - _tmp19 = append(_tmp19, _tmp20) - } - if err := dec.ListEnd(); err != nil { - return err - } - _tmp0.Code = _tmp19 - if err := dec.ListEnd(); err != nil { - return err - } - } - *obj = _tmp0 - return nil -} diff --git a/core/types/bal/bal_encoding_rlp_accountnonce_generated.go b/core/types/bal/bal_encoding_rlp_accountnonce_generated.go deleted file mode 100644 index 605ba1dd9195..000000000000 --- a/core/types/bal/bal_encoding_rlp_accountnonce_generated.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package bal - -import "github.com/ethereum/go-ethereum/rlp" -import "io" - -func (obj *encodingAccountNonce) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteUint64(uint64(obj.TxIdx)) - w.WriteUint64(obj.Nonce) - w.ListEnd(_tmp0) - return w.Flush() -} - -func (obj *encodingAccountNonce) DecodeRLP(dec *rlp.Stream) error { - var _tmp0 encodingAccountNonce - { - if _, err := dec.List(); err != nil { - return err - } - // TxIdx: - _tmp1, err := dec.Uint16() - if err != nil { - return err - } - _tmp0.TxIdx = _tmp1 - // Nonce: - _tmp2, err := dec.Uint64() - if err != nil { - return err - } - _tmp0.Nonce = _tmp2 - if err := dec.ListEnd(); err != nil { - return err - } - } - *obj = _tmp0 - return nil -} diff --git a/core/types/bal/bal_encoding_rlp_balancechange_generated.go b/core/types/bal/bal_encoding_rlp_balancechange_generated.go deleted file mode 100644 index 75014a00f205..000000000000 --- a/core/types/bal/bal_encoding_rlp_balancechange_generated.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package bal - -import "github.com/ethereum/go-ethereum/rlp" -import "io" - -func (obj *encodingBalanceChange) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteUint64(uint64(obj.TxIdx)) - w.WriteBytes(obj.Balance[:]) - w.ListEnd(_tmp0) - return w.Flush() -} - -func (obj *encodingBalanceChange) DecodeRLP(dec *rlp.Stream) error { - var _tmp0 encodingBalanceChange - { - if _, err := dec.List(); err != nil { - return err - } - // TxIdx: - _tmp1, err := dec.Uint16() - if err != nil { - return err - } - _tmp0.TxIdx = _tmp1 - // Balance: - var _tmp2 encodingBalance - if err := dec.ReadBytes(_tmp2[:]); err != nil { - return err - } - _tmp0.Balance = _tmp2 - if err := dec.ListEnd(); err != nil { - return err - } - } - *obj = _tmp0 - return nil -} diff --git a/core/types/bal/bal_encoding_rlp_codechange_generated.go b/core/types/bal/bal_encoding_rlp_codechange_generated.go deleted file mode 100644 index aafeb591cf33..000000000000 --- a/core/types/bal/bal_encoding_rlp_codechange_generated.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package bal - -import "github.com/ethereum/go-ethereum/rlp" -import "io" - -func (obj *encodingCodeChange) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteUint64(uint64(obj.TxIndex)) - w.WriteBytes(obj.Code) - w.ListEnd(_tmp0) - return w.Flush() -} - -func (obj *encodingCodeChange) DecodeRLP(dec *rlp.Stream) error { - var _tmp0 encodingCodeChange - { - if _, err := dec.List(); err != nil { - return err - } - // TxIndex: - _tmp1, err := dec.Uint16() - if err != nil { - return err - } - _tmp0.TxIndex = _tmp1 - // Code: - _tmp2, err := dec.Bytes() - if err != nil { - return err - } - _tmp0.Code = _tmp2 - if err := dec.ListEnd(); err != nil { - return err - } - } - *obj = _tmp0 - return nil -} diff --git a/core/types/bal/bal_encoding_rlp_blockaccesslist_generated.go b/core/types/bal/bal_encoding_rlp_generated.go similarity index 99% rename from core/types/bal/bal_encoding_rlp_blockaccesslist_generated.go rename to core/types/bal/bal_encoding_rlp_generated.go index aacb940eca41..e59553280173 100644 --- a/core/types/bal/bal_encoding_rlp_blockaccesslist_generated.go +++ b/core/types/bal/bal_encoding_rlp_generated.go @@ -180,7 +180,7 @@ func (obj *encodingBlockAccessList) DecodeRLP(dec *rlp.Stream) error { } _tmp14.TxIdx = _tmp15 // Balance: - var _tmp16 encodingBalance + var _tmp16 [16]byte if err := dec.ReadBytes(_tmp16[:]); err != nil { return err } diff --git a/core/types/bal/bal_encoding_rlp_storagewrite_generated.go b/core/types/bal/bal_encoding_rlp_storagewrite_generated.go deleted file mode 100644 index a5f851bfe79f..000000000000 --- a/core/types/bal/bal_encoding_rlp_storagewrite_generated.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package bal - -import "github.com/ethereum/go-ethereum/rlp" -import "io" - -func (obj *encodingStorageWrite) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteUint64(uint64(obj.TxIdx)) - w.WriteBytes(obj.ValueAfter[:]) - w.ListEnd(_tmp0) - return w.Flush() -} - -func (obj *encodingStorageWrite) DecodeRLP(dec *rlp.Stream) error { - var _tmp0 encodingStorageWrite - { - if _, err := dec.List(); err != nil { - return err - } - // TxIdx: - _tmp1, err := dec.Uint16() - if err != nil { - return err - } - _tmp0.TxIdx = _tmp1 - // ValueAfter: - var _tmp2 [32]byte - if err := dec.ReadBytes(_tmp2[:]); err != nil { - return err - } - _tmp0.ValueAfter = _tmp2 - if err := dec.ListEnd(); err != nil { - return err - } - } - *obj = _tmp0 - return nil -} diff --git a/core/types/bal/bal_encoding_ssz_generated.go b/core/types/bal/bal_encoding_ssz_generated.go index fdea76b3278e..b74075244bea 100644 --- a/core/types/bal/bal_encoding_ssz_generated.go +++ b/core/types/bal/bal_encoding_ssz_generated.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 5a611ca283f63103b9044df57fda81526194a110bef4d5f1b2035335dfeb3ad6 +// Hash: 52e68d5f470c3c68962d9d1adb13fcc3828c2efcd43c4c592c091935bb9f35f6 // Version: 0.1.3 package bal @@ -235,364 +235,6 @@ func (e *encodingCodeChange) GetTree() (*ssz.Node, error) { return ssz.ProofTree(e) } -// MarshalSSZ ssz marshals the encodingAccountAccess object -func (e *encodingAccountAccess) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(e) -} - -// MarshalSSZTo ssz marshals the encodingAccountAccess object to a target array -func (e *encodingAccountAccess) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(40) - - // Field (0) 'Address' - dst = append(dst, e.Address[:]...) - - // Offset (1) 'StorageWrites' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(e.StorageWrites); ii++ { - offset += 4 - offset += e.StorageWrites[ii].SizeSSZ() - } - - // Offset (2) 'StorageReads' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.StorageReads) * 32 - - // Offset (3) 'BalanceChanges' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.BalanceChanges) * 18 - - // Offset (4) 'NonceChanges' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.NonceChanges) * 10 - - // Offset (5) 'Code' - dst = ssz.WriteOffset(dst, offset) - - // Field (1) 'StorageWrites' - if size := len(e.StorageWrites); size > 300000 { - err = ssz.ErrListTooBigFn("encodingAccountAccess.StorageWrites", size, 300000) - return - } - { - offset = 4 * len(e.StorageWrites) - for ii := 0; ii < len(e.StorageWrites); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += e.StorageWrites[ii].SizeSSZ() - } - } - for ii := 0; ii < len(e.StorageWrites); ii++ { - if dst, err = e.StorageWrites[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (2) 'StorageReads' - if size := len(e.StorageReads); size > 300000 { - err = ssz.ErrListTooBigFn("encodingAccountAccess.StorageReads", size, 300000) - return - } - for ii := 0; ii < len(e.StorageReads); ii++ { - dst = append(dst, e.StorageReads[ii][:]...) - } - - // Field (3) 'BalanceChanges' - if size := len(e.BalanceChanges); size > 300000 { - err = ssz.ErrListTooBigFn("encodingAccountAccess.BalanceChanges", size, 300000) - return - } - for ii := 0; ii < len(e.BalanceChanges); ii++ { - if dst, err = e.BalanceChanges[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (4) 'NonceChanges' - if size := len(e.NonceChanges); size > 300000 { - err = ssz.ErrListTooBigFn("encodingAccountAccess.NonceChanges", size, 300000) - return - } - for ii := 0; ii < len(e.NonceChanges); ii++ { - if dst, err = e.NonceChanges[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (5) 'Code' - if size := len(e.Code); size > 1 { - err = ssz.ErrListTooBigFn("encodingAccountAccess.Code", size, 1) - return - } - { - offset = 4 * len(e.Code) - for ii := 0; ii < len(e.Code); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += e.Code[ii].SizeSSZ() - } - } - for ii := 0; ii < len(e.Code); ii++ { - if dst, err = e.Code[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - return -} - -// UnmarshalSSZ ssz unmarshals the encodingAccountAccess object -func (e *encodingAccountAccess) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 40 { - return ssz.ErrSize - } - - tail := buf - var o1, o2, o3, o4, o5 uint64 - - // Field (0) 'Address' - copy(e.Address[:], buf[0:20]) - - // Offset (1) 'StorageWrites' - if o1 = ssz.ReadOffset(buf[20:24]); o1 > size { - return ssz.ErrOffset - } - - if o1 != 40 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (2) 'StorageReads' - if o2 = ssz.ReadOffset(buf[24:28]); o2 > size || o1 > o2 { - return ssz.ErrOffset - } - - // Offset (3) 'BalanceChanges' - if o3 = ssz.ReadOffset(buf[28:32]); o3 > size || o2 > o3 { - return ssz.ErrOffset - } - - // Offset (4) 'NonceChanges' - if o4 = ssz.ReadOffset(buf[32:36]); o4 > size || o3 > o4 { - return ssz.ErrOffset - } - - // Offset (5) 'Code' - if o5 = ssz.ReadOffset(buf[36:40]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } - - // Field (1) 'StorageWrites' - { - buf = tail[o1:o2] - num, err := ssz.DecodeDynamicLength(buf, 300000) - if err != nil { - return err - } - e.StorageWrites = make([]encodingSlotWrites, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if err = e.StorageWrites[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (2) 'StorageReads' - { - buf = tail[o2:o3] - num, err := ssz.DivideInt2(len(buf), 32, 300000) - if err != nil { - return err - } - e.StorageReads = make([][32]byte, num) - for ii := 0; ii < num; ii++ { - copy(e.StorageReads[ii][:], buf[ii*32:(ii+1)*32]) - } - } - - // Field (3) 'BalanceChanges' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 18, 300000) - if err != nil { - return err - } - e.BalanceChanges = make([]encodingBalanceChange, num) - for ii := 0; ii < num; ii++ { - if err = e.BalanceChanges[ii].UnmarshalSSZ(buf[ii*18 : (ii+1)*18]); err != nil { - return err - } - } - } - - // Field (4) 'NonceChanges' - { - buf = tail[o4:o5] - num, err := ssz.DivideInt2(len(buf), 10, 300000) - if err != nil { - return err - } - e.NonceChanges = make([]encodingAccountNonce, num) - for ii := 0; ii < num; ii++ { - if err = e.NonceChanges[ii].UnmarshalSSZ(buf[ii*10 : (ii+1)*10]); err != nil { - return err - } - } - } - - // Field (5) 'Code' - { - buf = tail[o5:] - num, err := ssz.DecodeDynamicLength(buf, 1) - if err != nil { - return err - } - e.Code = make([]encodingCodeChange, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if err = e.Code[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the encodingAccountAccess object -func (e *encodingAccountAccess) SizeSSZ() (size int) { - size = 40 - - // Field (1) 'StorageWrites' - for ii := 0; ii < len(e.StorageWrites); ii++ { - size += 4 - size += e.StorageWrites[ii].SizeSSZ() - } - - // Field (2) 'StorageReads' - size += len(e.StorageReads) * 32 - - // Field (3) 'BalanceChanges' - size += len(e.BalanceChanges) * 18 - - // Field (4) 'NonceChanges' - size += len(e.NonceChanges) * 10 - - // Field (5) 'Code' - for ii := 0; ii < len(e.Code); ii++ { - size += 4 - size += e.Code[ii].SizeSSZ() - } - - return -} - -// HashTreeRoot ssz hashes the encodingAccountAccess object -func (e *encodingAccountAccess) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(e) -} - -// HashTreeRootWith ssz hashes the encodingAccountAccess object with a hasher -func (e *encodingAccountAccess) HashTreeRootWith(hh ssz.HashWalker) (err error) { - indx := hh.Index() - - // Field (0) 'Address' - hh.PutBytes(e.Address[:]) - - // Field (1) 'StorageWrites' - { - subIndx := hh.Index() - num := uint64(len(e.StorageWrites)) - if num > 300000 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.StorageWrites { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 300000) - } - - // Field (2) 'StorageReads' - { - if size := len(e.StorageReads); size > 300000 { - err = ssz.ErrListTooBigFn("encodingAccountAccess.StorageReads", size, 300000) - return - } - subIndx := hh.Index() - for _, i := range e.StorageReads { - hh.Append(i[:]) - } - numItems := uint64(len(e.StorageReads)) - hh.MerkleizeWithMixin(subIndx, numItems, 300000) - } - - // Field (3) 'BalanceChanges' - { - subIndx := hh.Index() - num := uint64(len(e.BalanceChanges)) - if num > 300000 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.BalanceChanges { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 300000) - } - - // Field (4) 'NonceChanges' - { - subIndx := hh.Index() - num := uint64(len(e.NonceChanges)) - if num > 300000 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.NonceChanges { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 300000) - } - - // Field (5) 'Code' - { - subIndx := hh.Index() - num := uint64(len(e.Code)) - if num > 1 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.Code { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 1) - } - - hh.Merkleize(indx) - return -} - -// GetTree ssz hashes the encodingAccountAccess object -func (e *encodingAccountAccess) GetTree() (*ssz.Node, error) { - return ssz.ProofTree(e) -} - // MarshalSSZ ssz marshals the encodingBalanceChange object func (e *encodingBalanceChange) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(e) @@ -801,16 +443,208 @@ func (e *encodingSlotWrites) MarshalSSZTo(buf []byte) (dst []byte, err error) { // Field (0) 'Slot' dst = append(dst, e.Slot[:]...) - // Offset (1) 'Accesses' - dst = ssz.WriteOffset(dst, offset) + // Offset (1) 'Accesses' + dst = ssz.WriteOffset(dst, offset) + + // Field (1) 'Accesses' + if size := len(e.Accesses); size > 300000 { + err = ssz.ErrListTooBigFn("encodingSlotWrites.Accesses", size, 300000) + return + } + for ii := 0; ii < len(e.Accesses); ii++ { + if dst, err = e.Accesses[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + return +} + +// UnmarshalSSZ ssz unmarshals the encodingSlotWrites object +func (e *encodingSlotWrites) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 36 { + return ssz.ErrSize + } + + tail := buf + var o1 uint64 + + // Field (0) 'Slot' + copy(e.Slot[:], buf[0:32]) + + // Offset (1) 'Accesses' + if o1 = ssz.ReadOffset(buf[32:36]); o1 > size { + return ssz.ErrOffset + } + + if o1 != 36 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'Accesses' + { + buf = tail[o1:] + num, err := ssz.DivideInt2(len(buf), 34, 300000) + if err != nil { + return err + } + e.Accesses = make([]encodingStorageWrite, num) + for ii := 0; ii < num; ii++ { + if err = e.Accesses[ii].UnmarshalSSZ(buf[ii*34 : (ii+1)*34]); err != nil { + return err + } + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the encodingSlotWrites object +func (e *encodingSlotWrites) SizeSSZ() (size int) { + size = 36 + + // Field (1) 'Accesses' + size += len(e.Accesses) * 34 + + return +} + +// HashTreeRoot ssz hashes the encodingSlotWrites object +func (e *encodingSlotWrites) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(e) +} + +// HashTreeRootWith ssz hashes the encodingSlotWrites object with a hasher +func (e *encodingSlotWrites) HashTreeRootWith(hh ssz.HashWalker) (err error) { + indx := hh.Index() + + // Field (0) 'Slot' + hh.PutBytes(e.Slot[:]) + + // Field (1) 'Accesses' + { + subIndx := hh.Index() + num := uint64(len(e.Accesses)) + if num > 300000 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.Accesses { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 300000) + } + + hh.Merkleize(indx) + return +} + +// GetTree ssz hashes the encodingSlotWrites object +func (e *encodingSlotWrites) GetTree() (*ssz.Node, error) { + return ssz.ProofTree(e) +} + +// MarshalSSZ ssz marshals the encodingAccountAccess object +func (e *encodingAccountAccess) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(e) +} + +// MarshalSSZTo ssz marshals the encodingAccountAccess object to a target array +func (e *encodingAccountAccess) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(40) + + // Field (0) 'Address' + dst = append(dst, e.Address[:]...) + + // Offset (1) 'StorageWrites' + dst = ssz.WriteOffset(dst, offset) + for ii := 0; ii < len(e.StorageWrites); ii++ { + offset += 4 + offset += e.StorageWrites[ii].SizeSSZ() + } + + // Offset (2) 'StorageReads' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.StorageReads) * 32 + + // Offset (3) 'BalanceChanges' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.BalanceChanges) * 18 + + // Offset (4) 'NonceChanges' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.NonceChanges) * 10 + + // Offset (5) 'Code' + dst = ssz.WriteOffset(dst, offset) + + // Field (1) 'StorageWrites' + if size := len(e.StorageWrites); size > 300000 { + err = ssz.ErrListTooBigFn("encodingAccountAccess.StorageWrites", size, 300000) + return + } + { + offset = 4 * len(e.StorageWrites) + for ii := 0; ii < len(e.StorageWrites); ii++ { + dst = ssz.WriteOffset(dst, offset) + offset += e.StorageWrites[ii].SizeSSZ() + } + } + for ii := 0; ii < len(e.StorageWrites); ii++ { + if dst, err = e.StorageWrites[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (2) 'StorageReads' + if size := len(e.StorageReads); size > 300000 { + err = ssz.ErrListTooBigFn("encodingAccountAccess.StorageReads", size, 300000) + return + } + for ii := 0; ii < len(e.StorageReads); ii++ { + dst = append(dst, e.StorageReads[ii][:]...) + } + + // Field (3) 'BalanceChanges' + if size := len(e.BalanceChanges); size > 300000 { + err = ssz.ErrListTooBigFn("encodingAccountAccess.BalanceChanges", size, 300000) + return + } + for ii := 0; ii < len(e.BalanceChanges); ii++ { + if dst, err = e.BalanceChanges[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (4) 'NonceChanges' + if size := len(e.NonceChanges); size > 300000 { + err = ssz.ErrListTooBigFn("encodingAccountAccess.NonceChanges", size, 300000) + return + } + for ii := 0; ii < len(e.NonceChanges); ii++ { + if dst, err = e.NonceChanges[ii].MarshalSSZTo(dst); err != nil { + return + } + } - // Field (1) 'Accesses' - if size := len(e.Accesses); size > 300000 { - err = ssz.ErrListTooBigFn("encodingSlotWrites.Accesses", size, 300000) + // Field (5) 'Code' + if size := len(e.Code); size > 1 { + err = ssz.ErrListTooBigFn("encodingAccountAccess.Code", size, 1) return } - for ii := 0; ii < len(e.Accesses); ii++ { - if dst, err = e.Accesses[ii].MarshalSSZTo(dst); err != nil { + { + offset = 4 * len(e.Code) + for ii := 0; ii < len(e.Code); ii++ { + dst = ssz.WriteOffset(dst, offset) + offset += e.Code[ii].SizeSSZ() + } + } + for ii := 0; ii < len(e.Code); ii++ { + if dst, err = e.Code[ii].MarshalSSZTo(dst); err != nil { return } } @@ -818,77 +652,227 @@ func (e *encodingSlotWrites) MarshalSSZTo(buf []byte) (dst []byte, err error) { return } -// UnmarshalSSZ ssz unmarshals the encodingSlotWrites object -func (e *encodingSlotWrites) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the encodingAccountAccess object +func (e *encodingAccountAccess) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 36 { + if size < 40 { return ssz.ErrSize } tail := buf - var o1 uint64 + var o1, o2, o3, o4, o5 uint64 - // Field (0) 'Slot' - copy(e.Slot[:], buf[0:32]) + // Field (0) 'Address' + copy(e.Address[:], buf[0:20]) - // Offset (1) 'Accesses' - if o1 = ssz.ReadOffset(buf[32:36]); o1 > size { + // Offset (1) 'StorageWrites' + if o1 = ssz.ReadOffset(buf[20:24]); o1 > size { return ssz.ErrOffset } - if o1 != 36 { + if o1 != 40 { return ssz.ErrInvalidVariableOffset } - // Field (1) 'Accesses' + // Offset (2) 'StorageReads' + if o2 = ssz.ReadOffset(buf[24:28]); o2 > size || o1 > o2 { + return ssz.ErrOffset + } + + // Offset (3) 'BalanceChanges' + if o3 = ssz.ReadOffset(buf[28:32]); o3 > size || o2 > o3 { + return ssz.ErrOffset + } + + // Offset (4) 'NonceChanges' + if o4 = ssz.ReadOffset(buf[32:36]); o4 > size || o3 > o4 { + return ssz.ErrOffset + } + + // Offset (5) 'Code' + if o5 = ssz.ReadOffset(buf[36:40]); o5 > size || o4 > o5 { + return ssz.ErrOffset + } + + // Field (1) 'StorageWrites' { - buf = tail[o1:] - num, err := ssz.DivideInt2(len(buf), 34, 300000) + buf = tail[o1:o2] + num, err := ssz.DecodeDynamicLength(buf, 300000) if err != nil { return err } - e.Accesses = make([]encodingStorageWrite, num) + e.StorageWrites = make([]encodingSlotWrites, num) + err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { + if err = e.StorageWrites[indx].UnmarshalSSZ(buf); err != nil { + return err + } + return nil + }) + if err != nil { + return err + } + } + + // Field (2) 'StorageReads' + { + buf = tail[o2:o3] + num, err := ssz.DivideInt2(len(buf), 32, 300000) + if err != nil { + return err + } + e.StorageReads = make([][32]byte, num) for ii := 0; ii < num; ii++ { - if err = e.Accesses[ii].UnmarshalSSZ(buf[ii*34 : (ii+1)*34]); err != nil { + copy(e.StorageReads[ii][:], buf[ii*32:(ii+1)*32]) + } + } + + // Field (3) 'BalanceChanges' + { + buf = tail[o3:o4] + num, err := ssz.DivideInt2(len(buf), 18, 300000) + if err != nil { + return err + } + e.BalanceChanges = make([]encodingBalanceChange, num) + for ii := 0; ii < num; ii++ { + if err = e.BalanceChanges[ii].UnmarshalSSZ(buf[ii*18 : (ii+1)*18]); err != nil { + return err + } + } + } + + // Field (4) 'NonceChanges' + { + buf = tail[o4:o5] + num, err := ssz.DivideInt2(len(buf), 10, 300000) + if err != nil { + return err + } + e.NonceChanges = make([]encodingAccountNonce, num) + for ii := 0; ii < num; ii++ { + if err = e.NonceChanges[ii].UnmarshalSSZ(buf[ii*10 : (ii+1)*10]); err != nil { + return err + } + } + } + + // Field (5) 'Code' + { + buf = tail[o5:] + num, err := ssz.DecodeDynamicLength(buf, 1) + if err != nil { + return err + } + e.Code = make([]encodingCodeChange, num) + err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { + if err = e.Code[indx].UnmarshalSSZ(buf); err != nil { return err } + return nil + }) + if err != nil { + return err } } return err } -// SizeSSZ returns the ssz encoded size in bytes for the encodingSlotWrites object -func (e *encodingSlotWrites) SizeSSZ() (size int) { - size = 36 +// SizeSSZ returns the ssz encoded size in bytes for the encodingAccountAccess object +func (e *encodingAccountAccess) SizeSSZ() (size int) { + size = 40 - // Field (1) 'Accesses' - size += len(e.Accesses) * 34 + // Field (1) 'StorageWrites' + for ii := 0; ii < len(e.StorageWrites); ii++ { + size += 4 + size += e.StorageWrites[ii].SizeSSZ() + } + + // Field (2) 'StorageReads' + size += len(e.StorageReads) * 32 + + // Field (3) 'BalanceChanges' + size += len(e.BalanceChanges) * 18 + + // Field (4) 'NonceChanges' + size += len(e.NonceChanges) * 10 + + // Field (5) 'Code' + for ii := 0; ii < len(e.Code); ii++ { + size += 4 + size += e.Code[ii].SizeSSZ() + } return } -// HashTreeRoot ssz hashes the encodingSlotWrites object -func (e *encodingSlotWrites) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the encodingAccountAccess object +func (e *encodingAccountAccess) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(e) } -// HashTreeRootWith ssz hashes the encodingSlotWrites object with a hasher -func (e *encodingSlotWrites) HashTreeRootWith(hh ssz.HashWalker) (err error) { +// HashTreeRootWith ssz hashes the encodingAccountAccess object with a hasher +func (e *encodingAccountAccess) HashTreeRootWith(hh ssz.HashWalker) (err error) { indx := hh.Index() - // Field (0) 'Slot' - hh.PutBytes(e.Slot[:]) + // Field (0) 'Address' + hh.PutBytes(e.Address[:]) - // Field (1) 'Accesses' + // Field (1) 'StorageWrites' { subIndx := hh.Index() - num := uint64(len(e.Accesses)) + num := uint64(len(e.StorageWrites)) if num > 300000 { err = ssz.ErrIncorrectListSize return } - for _, elem := range e.Accesses { + for _, elem := range e.StorageWrites { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 300000) + } + + // Field (2) 'StorageReads' + { + if size := len(e.StorageReads); size > 300000 { + err = ssz.ErrListTooBigFn("encodingAccountAccess.StorageReads", size, 300000) + return + } + subIndx := hh.Index() + for _, i := range e.StorageReads { + hh.Append(i[:]) + } + numItems := uint64(len(e.StorageReads)) + hh.MerkleizeWithMixin(subIndx, numItems, 300000) + } + + // Field (3) 'BalanceChanges' + { + subIndx := hh.Index() + num := uint64(len(e.BalanceChanges)) + if num > 300000 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.BalanceChanges { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 300000) + } + + // Field (4) 'NonceChanges' + { + subIndx := hh.Index() + num := uint64(len(e.NonceChanges)) + if num > 300000 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.NonceChanges { if err = elem.HashTreeRootWith(hh); err != nil { return } @@ -896,11 +880,27 @@ func (e *encodingSlotWrites) HashTreeRootWith(hh ssz.HashWalker) (err error) { hh.MerkleizeWithMixin(subIndx, num, 300000) } + // Field (5) 'Code' + { + subIndx := hh.Index() + num := uint64(len(e.Code)) + if num > 1 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.Code { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 1) + } + hh.Merkleize(indx) return } -// GetTree ssz hashes the encodingSlotWrites object -func (e *encodingSlotWrites) GetTree() (*ssz.Node, error) { +// GetTree ssz hashes the encodingAccountAccess object +func (e *encodingAccountAccess) GetTree() (*ssz.Node, error) { return ssz.ProofTree(e) } diff --git a/core/types/bal/bal_test.go b/core/types/bal/bal_test.go index dfb4fe5fdfa0..585aeb845b29 100644 --- a/core/types/bal/bal_test.go +++ b/core/types/bal/bal_test.go @@ -1,71 +1,92 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package bal import ( "bytes" + "io/fs" "os" + "path/filepath" "testing" - "github.com/holiman/uint256" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" ) -// test that a populated access list can be encoded/decoded correctly -func TestBALEncoding(t *testing.T) { - b := BlockAccessList{ - map[common.Address]*accountAccess{ +func makeTestBAL() *BlockAccessList { + return &BlockAccessList{ + map[common.Address]*AccountAccess{ common.BytesToAddress([]byte{0xff, 0xff}): { - StorageWrites: map[common.Hash]slotWrites{ - common.BytesToHash([]byte{0x01}): map[uint16]common.Hash{ + StorageWrites: map[common.Hash]map[uint16]common.Hash{ + common.BytesToHash([]byte{0x01}): { 1: common.BytesToHash([]byte{1, 2, 3, 4}), 2: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6}), }, - common.BytesToHash([]byte{0x10}): map[uint16]common.Hash{ + common.BytesToHash([]byte{0x10}): { 20: common.BytesToHash([]byte{1, 2, 3, 4}), }, }, StorageReads: map[common.Hash]struct{}{ common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7}): {}, }, - BalanceChanges: balanceDiff{ + BalanceChanges: map[uint16]*uint256.Int{ 1: uint256.NewInt(100), 2: uint256.NewInt(500), }, - NonceChanges: accountNonceDiffs{ + NonceChanges: map[uint16]uint64{ 1: 2, 2: 6, }, - CodeChange: &codeChange{ + CodeChange: &CodeChange{ TxIndex: 0, Code: common.Hex2Bytes("deadbeef"), }, }, common.BytesToAddress([]byte{0xff, 0xff, 0xff}): { - StorageWrites: map[common.Hash]slotWrites{ - common.BytesToHash([]byte{0x01}): map[uint16]common.Hash{ + StorageWrites: map[common.Hash]map[uint16]common.Hash{ + common.BytesToHash([]byte{0x01}): { 2: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6}), 3: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7, 8}), }, - common.BytesToHash([]byte{0x10}): map[uint16]common.Hash{ + common.BytesToHash([]byte{0x10}): { 21: common.BytesToHash([]byte{1, 2, 3, 4, 5}), }, }, StorageReads: map[common.Hash]struct{}{ common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7, 8}): {}, }, - BalanceChanges: balanceDiff{ + BalanceChanges: map[uint16]*uint256.Int{ 2: uint256.NewInt(100), 3: uint256.NewInt(500), }, - NonceChanges: accountNonceDiffs{ + NonceChanges: map[uint16]uint64{ 1: 2, }, }, }, } +} + +// TestBALEncoding tests that a populated access list can be encoded/decoded correctly. +func TestBALEncoding(t *testing.T) { var buf bytes.Buffer - err := b.EncodeRLP(&buf) + bal := makeTestBAL() + err := bal.EncodeRLP(&buf) if err != nil { t.Fatalf("encoding failed: %v\n", err) } @@ -73,20 +94,29 @@ func TestBALEncoding(t *testing.T) { if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 10000000)); err != nil { t.Fatalf("decoding failed: %v\n", err) } - if dec.Hash() != b.Hash() { + if dec.Hash() != bal.Hash() { t.Fatalf("encoded block hash doesn't match decoded") } } -// test that a mainnet BAL produced by https://github.com/nerolation/eth-bal-analysis +// TestBALDecoding tests that a mainnet BAL produced by https://github.com/nerolation/eth-bal-analysis // can be decoded. func TestBALDecoding(t *testing.T) { - data, err := os.ReadFile("testdata/22615532_block_access_list_with_reads_eip7928.ssz") - if err != nil { - t.Fatal(err) - } - var b BlockAccessList - if err := b.decodeSSZ(data); err != nil { - t.Fatal(err) - } + filepath.WalkDir("testdata/ssz", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + return nil + } + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + var b BlockAccessList + if err := b.decodeSSZ(data); err != nil { + t.Fatal(err) + } + return nil + }) } diff --git a/core/types/bal/testdata/ssz/22615532_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615532_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..a3f23822a81c Binary files /dev/null and b/core/types/bal/testdata/ssz/22615532_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615542_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615542_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..2504d8ce2884 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615542_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615552_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615552_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..9de4952b8788 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615552_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615562_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615562_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..c27802c5b33c Binary files /dev/null and b/core/types/bal/testdata/ssz/22615562_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615572_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615572_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..fed7949edbc4 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615572_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615582_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615582_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..a3d5bd8e36a3 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615582_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615592_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615592_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..133eab3c31cd Binary files /dev/null and b/core/types/bal/testdata/ssz/22615592_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615602_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615602_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..9e3c3d7c6d0f Binary files /dev/null and b/core/types/bal/testdata/ssz/22615602_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615612_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615612_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..a768dd1f83e2 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615612_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615622_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615622_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..48191d3449ed Binary files /dev/null and b/core/types/bal/testdata/ssz/22615622_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615632_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615632_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..271855be7682 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615632_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615642_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615642_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..c2574d7b3140 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615642_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615652_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615652_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..cb74d4d93f8f Binary files /dev/null and b/core/types/bal/testdata/ssz/22615652_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615662_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615662_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..84c60acb6a48 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615662_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615672_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615672_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..a4a0684c3ee5 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615672_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615682_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615682_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..d537bee64f2e Binary files /dev/null and b/core/types/bal/testdata/ssz/22615682_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615692_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615692_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..4ddb9783e39d Binary files /dev/null and b/core/types/bal/testdata/ssz/22615692_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615702_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615702_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..8e1ac6e68876 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615702_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615712_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615712_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..82b193779df2 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615712_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615722_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615722_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..18d32d71242c Binary files /dev/null and b/core/types/bal/testdata/ssz/22615722_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615732_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615732_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..bec34697cf1e Binary files /dev/null and b/core/types/bal/testdata/ssz/22615732_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615742_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615742_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..01dbcea44bdb Binary files /dev/null and b/core/types/bal/testdata/ssz/22615742_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615752_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615752_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..5413226a8a22 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615752_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615762_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615762_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..c2671565f0c4 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615762_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615772_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615772_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..44802a320e0a Binary files /dev/null and b/core/types/bal/testdata/ssz/22615772_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615782_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615782_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..c5ccff6ee47b Binary files /dev/null and b/core/types/bal/testdata/ssz/22615782_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615792_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615792_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..3c78efc54623 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615792_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615802_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615802_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..5c656bd0f451 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615802_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615812_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615812_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..12e71d010075 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615812_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615822_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615822_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..a5befeea8ecc Binary files /dev/null and b/core/types/bal/testdata/ssz/22615822_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615832_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615832_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..5f90c86d4acb Binary files /dev/null and b/core/types/bal/testdata/ssz/22615832_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615842_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615842_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..06cd0b543fde Binary files /dev/null and b/core/types/bal/testdata/ssz/22615842_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615852_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615852_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..5137afea4215 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615852_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615862_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615862_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..54e9153bdc44 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615862_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615872_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615872_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..f8087c33e87c Binary files /dev/null and b/core/types/bal/testdata/ssz/22615872_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615882_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615882_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..9ce522dccb65 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615882_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615892_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615892_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..fe23dae4cfc5 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615892_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615902_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615902_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..bec96c3d1add Binary files /dev/null and b/core/types/bal/testdata/ssz/22615902_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615912_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615912_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..1b919a2715cf Binary files /dev/null and b/core/types/bal/testdata/ssz/22615912_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615922_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615922_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..4f369b81f04e Binary files /dev/null and b/core/types/bal/testdata/ssz/22615922_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615932_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615932_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..5f73a9a5d16f Binary files /dev/null and b/core/types/bal/testdata/ssz/22615932_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615942_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615942_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..737740a81c69 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615942_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615952_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615952_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..59699f6bc6fe Binary files /dev/null and b/core/types/bal/testdata/ssz/22615952_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615962_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615962_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..84ae548dd5e3 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615962_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615972_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615972_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..29d50e996441 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615972_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615982_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615982_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..53691e60b8a1 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615982_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22615992_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22615992_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..13d4c35c2d83 Binary files /dev/null and b/core/types/bal/testdata/ssz/22615992_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22616002_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22616002_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..dddcfe7bce68 Binary files /dev/null and b/core/types/bal/testdata/ssz/22616002_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22616012_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22616012_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..4a63bd6be41a Binary files /dev/null and b/core/types/bal/testdata/ssz/22616012_block_access_list_with_reads_eip7928.txt differ diff --git a/core/types/bal/testdata/ssz/22616022_block_access_list_with_reads_eip7928.txt b/core/types/bal/testdata/ssz/22616022_block_access_list_with_reads_eip7928.txt new file mode 100644 index 000000000000..61fa0aaf93e3 Binary files /dev/null and b/core/types/bal/testdata/ssz/22616022_block_access_list_with_reads_eip7928.txt differ