diff --git a/core/types/bal/bal_encoding.go b/core/types/bal/bal_encoding.go index 5deed8f752..faafc2e1f4 100644 --- a/core/types/bal/bal_encoding.go +++ b/core/types/bal/bal_encoding.go @@ -88,12 +88,12 @@ type encodingAccountNonce struct { // encodingStorageWrite is the encoding format of StorageWrites. type encodingStorageWrite struct { TxIdx uint32 - ValueAfter [32]byte + ValueAfter *uint256.Int } // encodingStorageWrite is the encoding format of SlotWrites. type encodingSlotWrites struct { - Slot [32]byte + Slot *uint256.Int Accesses []encodingStorageWrite } @@ -119,7 +119,7 @@ type encodingCodeChange struct { type AccountAccess struct { Address [20]byte // 20-byte Ethereum address StorageWrites []encodingSlotWrites // Storage changes (slot -> [tx_index -> new_value]) - StorageReads [][32]byte // Read-only storage keys + 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]) @@ -131,7 +131,7 @@ type AccountAccess struct { func (e *AccountAccess) validate() error { // Check the storage write slots are sorted in order if !slices.IsSortedFunc(e.StorageWrites, func(a, b encodingSlotWrites) int { - return bytes.Compare(a.Slot[:], b.Slot[:]) + return a.Slot.Cmp(b.Slot) }) { return errors.New("storage writes slots not in lexicographic order") } @@ -142,8 +142,8 @@ func (e *AccountAccess) validate() error { } // Check the storage read slots are sorted in order - if !slices.IsSortedFunc(e.StorageReads, func(a, b [32]byte) int { - return bytes.Compare(a[:], b[:]) + if !slices.IsSortedFunc(e.StorageReads, func(a, b *uint256.Int) int { + return a.Cmp(b) }) { return errors.New("storage read slots not in lexicographic order") } @@ -182,16 +182,32 @@ func (e *AccountAccess) validate() error { func (e *AccountAccess) Copy() AccountAccess { res := AccountAccess{ Address: e.Address, - StorageReads: slices.Clone(e.StorageReads), - BalanceChanges: slices.Clone(e.BalanceChanges), + 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)), CodeChanges: make([]encodingCodeChange, 0, len(e.CodeChanges)), } + for _, slot := range e.StorageReads { + res.StorageReads = append(res.StorageReads, slot.Clone()) + } + for _, change := range e.BalanceChanges { + res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{ + TxIdx: change.TxIdx, + Balance: change.Balance.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(), + }) + } res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{ - Slot: storageWrite.Slot, - Accesses: slices.Clone(storageWrite.Accesses), + Slot: storageWrite.Slot.Clone(), + Accesses: accesses, }) } for _, codeChange := range e.CodeChanges { @@ -216,7 +232,7 @@ func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAc res := AccountAccess{ Address: addr, StorageWrites: make([]encodingSlotWrites, 0, len(a.StorageWrites)), - StorageReads: make([][32]byte, 0, len(a.StorageReads)), + StorageReads: make([]*uint256.Int, 0, len(a.StorageReads)), BalanceChanges: make([]encodingBalanceChange, 0, len(a.BalanceChanges)), NonceChanges: make([]encodingAccountNonce, 0, len(a.NonceChanges)), CodeChanges: make([]encodingCodeChange, 0, len(a.CodeChange)), @@ -226,18 +242,19 @@ 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 { - var obj encodingSlotWrites - obj.Slot = slot - + obj := encodingSlotWrites{ + Slot: new(uint256.Int).SetBytes(slot[:]), + } slotWrites := a.StorageWrites[slot] obj.Accesses = make([]encodingStorageWrite, 0, len(slotWrites)) indices := slices.Collect(maps.Keys(slotWrites)) slices.SortFunc(indices, cmp.Compare[uint32]) for _, index := range indices { + val := slotWrites[index] obj.Accesses = append(obj.Accesses, encodingStorageWrite{ TxIdx: index, - ValueAfter: slotWrites[index], + ValueAfter: new(uint256.Int).SetBytes(val[:]), }) } res.StorageWrites = append(res.StorageWrites, obj) @@ -247,7 +264,7 @@ func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAc readSlots := slices.Collect(maps.Keys(a.StorageReads)) slices.SortFunc(readSlots, common.Hash.Cmp) for _, slot := range readSlots { - res.StorageReads = append(res.StorageReads, slot) + res.StorageReads = append(res.StorageReads, new(uint256.Int).SetBytes(slot[:])) } // Convert balance changes @@ -308,15 +325,15 @@ func (e *BlockAccessList) PrettyPrint() string { printWithIndent(1, "storage writes:") for _, sWrite := range accountDiff.StorageWrites { - printWithIndent(2, fmt.Sprintf("%x:", sWrite.Slot)) + printWithIndent(2, fmt.Sprintf("%s:", sWrite.Slot.Hex())) for _, access := range sWrite.Accesses { - printWithIndent(3, fmt.Sprintf("%d: %x", access.TxIdx, access.ValueAfter)) + printWithIndent(3, fmt.Sprintf("%d: %s", access.TxIdx, access.ValueAfter.Hex())) } } printWithIndent(1, "storage reads:") for _, slot := range accountDiff.StorageReads { - printWithIndent(2, fmt.Sprintf("%x", slot)) + printWithIndent(2, slot.Hex()) } printWithIndent(1, "balance changes:") diff --git a/core/types/bal/bal_encoding_rlp_generated.go b/core/types/bal/bal_encoding_rlp_generated.go index e9d47c8819..5376dba3b2 100644 --- a/core/types/bal/bal_encoding_rlp_generated.go +++ b/core/types/bal/bal_encoding_rlp_generated.go @@ -16,12 +16,20 @@ func (obj *BlockAccessList) EncodeRLP(_w io.Writer) error { _tmp4 := w.List() for _, _tmp5 := range _tmp2.StorageWrites { _tmp6 := w.List() - w.WriteBytes(_tmp5.Slot[:]) + if _tmp5.Slot == nil { + w.Write(rlp.EmptyString) + } else { + w.WriteUint256(_tmp5.Slot) + } _tmp7 := w.List() for _, _tmp8 := range _tmp5.Accesses { _tmp9 := w.List() w.WriteUint64(uint64(_tmp8.TxIdx)) - w.WriteBytes(_tmp8.ValueAfter[:]) + if _tmp8.ValueAfter == nil { + w.Write(rlp.EmptyString) + } else { + w.WriteUint256(_tmp8.ValueAfter) + } w.ListEnd(_tmp9) } w.ListEnd(_tmp7) @@ -30,7 +38,11 @@ func (obj *BlockAccessList) EncodeRLP(_w io.Writer) error { w.ListEnd(_tmp4) _tmp10 := w.List() for _, _tmp11 := range _tmp2.StorageReads { - w.WriteBytes(_tmp11[:]) + if _tmp11 == nil { + w.Write(rlp.EmptyString) + } else { + w.WriteUint256(_tmp11) + } } w.ListEnd(_tmp10) _tmp12 := w.List() @@ -103,11 +115,11 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error { return err } // Slot: - var _tmp6 [32]byte - if err := dec.ReadBytes(_tmp6[:]); err != nil { + var _tmp6 uint256.Int + if err := dec.ReadUint256(&_tmp6); err != nil { return err } - _tmp5.Slot = _tmp6 + _tmp5.Slot = &_tmp6 // Accesses: var _tmp7 []encodingStorageWrite if _, err := dec.List(); err != nil { @@ -126,11 +138,11 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error { } _tmp8.TxIdx = _tmp9 // ValueAfter: - var _tmp10 [32]byte - if err := dec.ReadBytes(_tmp10[:]); err != nil { + var _tmp10 uint256.Int + if err := dec.ReadUint256(&_tmp10); err != nil { return err } - _tmp8.ValueAfter = _tmp10 + _tmp8.ValueAfter = &_tmp10 if err := dec.ListEnd(); err != nil { return err } @@ -152,16 +164,16 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error { } _tmp2.StorageWrites = _tmp4 // StorageReads: - var _tmp11 [][32]byte + var _tmp11 []*uint256.Int if _, err := dec.List(); err != nil { return err } for dec.MoreDataInList() { - var _tmp12 [32]byte - if err := dec.ReadBytes(_tmp12[:]); err != nil { + var _tmp12 uint256.Int + if err := dec.ReadUint256(&_tmp12); err != nil { return err } - _tmp11 = append(_tmp11, _tmp12) + _tmp11 = append(_tmp11, &_tmp12) } 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 39602c0f05..e6befc3d05 100644 --- a/core/types/bal/bal_test.go +++ b/core/types/bal/bal_test.go @@ -115,18 +115,21 @@ func TestBALEncoding(t *testing.T) { func makeTestAccountAccess(sort bool) AccountAccess { var ( storageWrites []encodingSlotWrites - storageReads [][32]byte + storageReads []*uint256.Int balances []encodingBalanceChange nonces []encodingAccountNonce ) + randSlot := func() *uint256.Int { + return new(uint256.Int).SetBytes(testrand.Bytes(32)) + } for i := 0; i < 5; i++ { slot := encodingSlotWrites{ - Slot: testrand.Hash(), + Slot: randSlot(), } for j := 0; j < 3; j++ { slot.Accesses = append(slot.Accesses, encodingStorageWrite{ TxIdx: uint32(2 * j), - ValueAfter: testrand.Hash(), + ValueAfter: randSlot(), }) } if sort { @@ -138,16 +141,16 @@ func makeTestAccountAccess(sort bool) AccountAccess { } if sort { slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int { - return bytes.Compare(a.Slot[:], b.Slot[:]) + return a.Slot.Cmp(b.Slot) }) } for i := 0; i < 5; i++ { - storageReads = append(storageReads, testrand.Hash()) + storageReads = append(storageReads, randSlot()) } if sort { - slices.SortFunc(storageReads, func(a, b [32]byte) int { - return bytes.Compare(a[:], b[:]) + slices.SortFunc(storageReads, func(a, b *uint256.Int) int { + return a.Cmp(b) }) } @@ -218,7 +221,7 @@ func TestBlockAccessListCopy(t *testing.T) { // Make sure the mutations on copy won't affect the origin for _, aa := range cpyCpy.Accesses { for i := 0; i < len(aa.StorageReads); i++ { - aa.StorageReads[i] = [32]byte(testrand.Bytes(32)) + aa.StorageReads[i] = new(uint256.Int).SetBytes(testrand.Bytes(32)) } } if !reflect.DeepEqual(list, cpy) { diff --git a/eth/protocols/snap/handler_test.go b/eth/protocols/snap/handler_test.go index 3f6a43a059..e5da2e085b 100644 --- a/eth/protocols/snap/handler_test.go +++ b/eth/protocols/snap/handler_test.go @@ -31,16 +31,22 @@ import ( "github.com/ethereum/go-ethereum/core/types/bal" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" ) func makeTestBAL(minSize int) *bal.BlockAccessList { n := minSize/33 + 1 // 33 bytes per storage read slot in RLP access := bal.AccountAccess{ Address: common.HexToAddress("0x01"), - StorageReads: make([][32]byte, n), + StorageReads: make([]*uint256.Int, n), } + // Use a full-width 32-byte value (top byte 0xff) so each slot still + // encodes to 33 RLP bytes regardless of the index. for i := range access.StorageReads { - binary.BigEndian.PutUint64(access.StorageReads[i][24:], uint64(i)) + var b [32]byte + b[0] = 0xff + binary.BigEndian.PutUint64(b[24:], uint64(i)) + access.StorageReads[i] = new(uint256.Int).SetBytes(b[:]) } return &bal.BlockAccessList{Accesses: []bal.AccountAccess{access}} }