mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 19:00:46 +00:00
core/types/bal, eth/protocols/snap: convert the storage key and value
This commit is contained in:
parent
5a54af9fc9
commit
9b8e379b5e
4 changed files with 80 additions and 42 deletions
|
|
@ -88,12 +88,12 @@ type encodingAccountNonce struct {
|
||||||
// encodingStorageWrite is the encoding format of StorageWrites.
|
// encodingStorageWrite is the encoding format of StorageWrites.
|
||||||
type encodingStorageWrite struct {
|
type encodingStorageWrite struct {
|
||||||
TxIdx uint32
|
TxIdx uint32
|
||||||
ValueAfter [32]byte
|
ValueAfter *uint256.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodingStorageWrite is the encoding format of SlotWrites.
|
// encodingStorageWrite is the encoding format of SlotWrites.
|
||||||
type encodingSlotWrites struct {
|
type encodingSlotWrites struct {
|
||||||
Slot [32]byte
|
Slot *uint256.Int
|
||||||
Accesses []encodingStorageWrite
|
Accesses []encodingStorageWrite
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ type encodingCodeChange struct {
|
||||||
type AccountAccess struct {
|
type AccountAccess struct {
|
||||||
Address [20]byte // 20-byte Ethereum address
|
Address [20]byte // 20-byte Ethereum address
|
||||||
StorageWrites []encodingSlotWrites // Storage changes (slot -> [tx_index -> new_value])
|
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])
|
BalanceChanges []encodingBalanceChange // Balance changes ([tx_index -> post_balance])
|
||||||
NonceChanges []encodingAccountNonce // Nonce changes ([tx_index -> new_nonce])
|
NonceChanges []encodingAccountNonce // Nonce changes ([tx_index -> new_nonce])
|
||||||
CodeChanges []encodingCodeChange // Code changes ([tx_index -> new_code])
|
CodeChanges []encodingCodeChange // Code changes ([tx_index -> new_code])
|
||||||
|
|
@ -131,7 +131,7 @@ type AccountAccess struct {
|
||||||
func (e *AccountAccess) validate() error {
|
func (e *AccountAccess) validate() error {
|
||||||
// Check the storage write slots are sorted in order
|
// Check the storage write slots are sorted in order
|
||||||
if !slices.IsSortedFunc(e.StorageWrites, func(a, b encodingSlotWrites) int {
|
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")
|
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
|
// Check the storage read slots are sorted in order
|
||||||
if !slices.IsSortedFunc(e.StorageReads, func(a, b [32]byte) int {
|
if !slices.IsSortedFunc(e.StorageReads, func(a, b *uint256.Int) int {
|
||||||
return bytes.Compare(a[:], b[:])
|
return a.Cmp(b)
|
||||||
}) {
|
}) {
|
||||||
return errors.New("storage read slots not in lexicographic order")
|
return errors.New("storage read slots not in lexicographic order")
|
||||||
}
|
}
|
||||||
|
|
@ -182,16 +182,32 @@ func (e *AccountAccess) validate() error {
|
||||||
func (e *AccountAccess) Copy() AccountAccess {
|
func (e *AccountAccess) Copy() AccountAccess {
|
||||||
res := AccountAccess{
|
res := AccountAccess{
|
||||||
Address: e.Address,
|
Address: e.Address,
|
||||||
StorageReads: slices.Clone(e.StorageReads),
|
StorageReads: make([]*uint256.Int, 0, len(e.StorageReads)),
|
||||||
BalanceChanges: slices.Clone(e.BalanceChanges),
|
BalanceChanges: make([]encodingBalanceChange, 0, len(e.BalanceChanges)),
|
||||||
NonceChanges: slices.Clone(e.NonceChanges),
|
NonceChanges: slices.Clone(e.NonceChanges),
|
||||||
StorageWrites: make([]encodingSlotWrites, 0, len(e.StorageWrites)),
|
StorageWrites: make([]encodingSlotWrites, 0, len(e.StorageWrites)),
|
||||||
CodeChanges: make([]encodingCodeChange, 0, len(e.CodeChanges)),
|
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 {
|
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{
|
res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{
|
||||||
Slot: storageWrite.Slot,
|
Slot: storageWrite.Slot.Clone(),
|
||||||
Accesses: slices.Clone(storageWrite.Accesses),
|
Accesses: accesses,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, codeChange := range e.CodeChanges {
|
for _, codeChange := range e.CodeChanges {
|
||||||
|
|
@ -216,7 +232,7 @@ func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAc
|
||||||
res := AccountAccess{
|
res := AccountAccess{
|
||||||
Address: addr,
|
Address: addr,
|
||||||
StorageWrites: make([]encodingSlotWrites, 0, len(a.StorageWrites)),
|
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)),
|
BalanceChanges: make([]encodingBalanceChange, 0, len(a.BalanceChanges)),
|
||||||
NonceChanges: make([]encodingAccountNonce, 0, len(a.NonceChanges)),
|
NonceChanges: make([]encodingAccountNonce, 0, len(a.NonceChanges)),
|
||||||
CodeChanges: make([]encodingCodeChange, 0, len(a.CodeChange)),
|
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))
|
writeSlots := slices.Collect(maps.Keys(a.StorageWrites))
|
||||||
slices.SortFunc(writeSlots, common.Hash.Cmp)
|
slices.SortFunc(writeSlots, common.Hash.Cmp)
|
||||||
for _, slot := range writeSlots {
|
for _, slot := range writeSlots {
|
||||||
var obj encodingSlotWrites
|
obj := encodingSlotWrites{
|
||||||
obj.Slot = slot
|
Slot: new(uint256.Int).SetBytes(slot[:]),
|
||||||
|
}
|
||||||
slotWrites := a.StorageWrites[slot]
|
slotWrites := a.StorageWrites[slot]
|
||||||
obj.Accesses = make([]encodingStorageWrite, 0, len(slotWrites))
|
obj.Accesses = make([]encodingStorageWrite, 0, len(slotWrites))
|
||||||
|
|
||||||
indices := slices.Collect(maps.Keys(slotWrites))
|
indices := slices.Collect(maps.Keys(slotWrites))
|
||||||
slices.SortFunc(indices, cmp.Compare[uint32])
|
slices.SortFunc(indices, cmp.Compare[uint32])
|
||||||
for _, index := range indices {
|
for _, index := range indices {
|
||||||
|
val := slotWrites[index]
|
||||||
obj.Accesses = append(obj.Accesses, encodingStorageWrite{
|
obj.Accesses = append(obj.Accesses, encodingStorageWrite{
|
||||||
TxIdx: index,
|
TxIdx: index,
|
||||||
ValueAfter: slotWrites[index],
|
ValueAfter: new(uint256.Int).SetBytes(val[:]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
res.StorageWrites = append(res.StorageWrites, obj)
|
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))
|
readSlots := slices.Collect(maps.Keys(a.StorageReads))
|
||||||
slices.SortFunc(readSlots, common.Hash.Cmp)
|
slices.SortFunc(readSlots, common.Hash.Cmp)
|
||||||
for _, slot := range readSlots {
|
for _, slot := range readSlots {
|
||||||
res.StorageReads = append(res.StorageReads, slot)
|
res.StorageReads = append(res.StorageReads, new(uint256.Int).SetBytes(slot[:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert balance changes
|
// Convert balance changes
|
||||||
|
|
@ -308,15 +325,15 @@ func (e *BlockAccessList) PrettyPrint() string {
|
||||||
|
|
||||||
printWithIndent(1, "storage writes:")
|
printWithIndent(1, "storage writes:")
|
||||||
for _, sWrite := range accountDiff.StorageWrites {
|
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 {
|
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:")
|
printWithIndent(1, "storage reads:")
|
||||||
for _, slot := range accountDiff.StorageReads {
|
for _, slot := range accountDiff.StorageReads {
|
||||||
printWithIndent(2, fmt.Sprintf("%x", slot))
|
printWithIndent(2, slot.Hex())
|
||||||
}
|
}
|
||||||
|
|
||||||
printWithIndent(1, "balance changes:")
|
printWithIndent(1, "balance changes:")
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,20 @@ func (obj *BlockAccessList) EncodeRLP(_w io.Writer) error {
|
||||||
_tmp4 := w.List()
|
_tmp4 := w.List()
|
||||||
for _, _tmp5 := range _tmp2.StorageWrites {
|
for _, _tmp5 := range _tmp2.StorageWrites {
|
||||||
_tmp6 := w.List()
|
_tmp6 := w.List()
|
||||||
w.WriteBytes(_tmp5.Slot[:])
|
if _tmp5.Slot == nil {
|
||||||
|
w.Write(rlp.EmptyString)
|
||||||
|
} else {
|
||||||
|
w.WriteUint256(_tmp5.Slot)
|
||||||
|
}
|
||||||
_tmp7 := w.List()
|
_tmp7 := w.List()
|
||||||
for _, _tmp8 := range _tmp5.Accesses {
|
for _, _tmp8 := range _tmp5.Accesses {
|
||||||
_tmp9 := w.List()
|
_tmp9 := w.List()
|
||||||
w.WriteUint64(uint64(_tmp8.TxIdx))
|
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(_tmp9)
|
||||||
}
|
}
|
||||||
w.ListEnd(_tmp7)
|
w.ListEnd(_tmp7)
|
||||||
|
|
@ -30,7 +38,11 @@ func (obj *BlockAccessList) EncodeRLP(_w io.Writer) error {
|
||||||
w.ListEnd(_tmp4)
|
w.ListEnd(_tmp4)
|
||||||
_tmp10 := w.List()
|
_tmp10 := w.List()
|
||||||
for _, _tmp11 := range _tmp2.StorageReads {
|
for _, _tmp11 := range _tmp2.StorageReads {
|
||||||
w.WriteBytes(_tmp11[:])
|
if _tmp11 == nil {
|
||||||
|
w.Write(rlp.EmptyString)
|
||||||
|
} else {
|
||||||
|
w.WriteUint256(_tmp11)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
w.ListEnd(_tmp10)
|
w.ListEnd(_tmp10)
|
||||||
_tmp12 := w.List()
|
_tmp12 := w.List()
|
||||||
|
|
@ -103,11 +115,11 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Slot:
|
// Slot:
|
||||||
var _tmp6 [32]byte
|
var _tmp6 uint256.Int
|
||||||
if err := dec.ReadBytes(_tmp6[:]); err != nil {
|
if err := dec.ReadUint256(&_tmp6); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_tmp5.Slot = _tmp6
|
_tmp5.Slot = &_tmp6
|
||||||
// Accesses:
|
// Accesses:
|
||||||
var _tmp7 []encodingStorageWrite
|
var _tmp7 []encodingStorageWrite
|
||||||
if _, err := dec.List(); err != nil {
|
if _, err := dec.List(); err != nil {
|
||||||
|
|
@ -126,11 +138,11 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error {
|
||||||
}
|
}
|
||||||
_tmp8.TxIdx = _tmp9
|
_tmp8.TxIdx = _tmp9
|
||||||
// ValueAfter:
|
// ValueAfter:
|
||||||
var _tmp10 [32]byte
|
var _tmp10 uint256.Int
|
||||||
if err := dec.ReadBytes(_tmp10[:]); err != nil {
|
if err := dec.ReadUint256(&_tmp10); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_tmp8.ValueAfter = _tmp10
|
_tmp8.ValueAfter = &_tmp10
|
||||||
if err := dec.ListEnd(); err != nil {
|
if err := dec.ListEnd(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -152,16 +164,16 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error {
|
||||||
}
|
}
|
||||||
_tmp2.StorageWrites = _tmp4
|
_tmp2.StorageWrites = _tmp4
|
||||||
// StorageReads:
|
// StorageReads:
|
||||||
var _tmp11 [][32]byte
|
var _tmp11 []*uint256.Int
|
||||||
if _, err := dec.List(); err != nil {
|
if _, err := dec.List(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for dec.MoreDataInList() {
|
for dec.MoreDataInList() {
|
||||||
var _tmp12 [32]byte
|
var _tmp12 uint256.Int
|
||||||
if err := dec.ReadBytes(_tmp12[:]); err != nil {
|
if err := dec.ReadUint256(&_tmp12); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_tmp11 = append(_tmp11, _tmp12)
|
_tmp11 = append(_tmp11, &_tmp12)
|
||||||
}
|
}
|
||||||
if err := dec.ListEnd(); err != nil {
|
if err := dec.ListEnd(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -115,18 +115,21 @@ func TestBALEncoding(t *testing.T) {
|
||||||
func makeTestAccountAccess(sort bool) AccountAccess {
|
func makeTestAccountAccess(sort bool) AccountAccess {
|
||||||
var (
|
var (
|
||||||
storageWrites []encodingSlotWrites
|
storageWrites []encodingSlotWrites
|
||||||
storageReads [][32]byte
|
storageReads []*uint256.Int
|
||||||
balances []encodingBalanceChange
|
balances []encodingBalanceChange
|
||||||
nonces []encodingAccountNonce
|
nonces []encodingAccountNonce
|
||||||
)
|
)
|
||||||
|
randSlot := func() *uint256.Int {
|
||||||
|
return new(uint256.Int).SetBytes(testrand.Bytes(32))
|
||||||
|
}
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
slot := encodingSlotWrites{
|
slot := encodingSlotWrites{
|
||||||
Slot: testrand.Hash(),
|
Slot: randSlot(),
|
||||||
}
|
}
|
||||||
for j := 0; j < 3; j++ {
|
for j := 0; j < 3; j++ {
|
||||||
slot.Accesses = append(slot.Accesses, encodingStorageWrite{
|
slot.Accesses = append(slot.Accesses, encodingStorageWrite{
|
||||||
TxIdx: uint32(2 * j),
|
TxIdx: uint32(2 * j),
|
||||||
ValueAfter: testrand.Hash(),
|
ValueAfter: randSlot(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if sort {
|
if sort {
|
||||||
|
|
@ -138,16 +141,16 @@ func makeTestAccountAccess(sort bool) AccountAccess {
|
||||||
}
|
}
|
||||||
if sort {
|
if sort {
|
||||||
slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int {
|
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++ {
|
for i := 0; i < 5; i++ {
|
||||||
storageReads = append(storageReads, testrand.Hash())
|
storageReads = append(storageReads, randSlot())
|
||||||
}
|
}
|
||||||
if sort {
|
if sort {
|
||||||
slices.SortFunc(storageReads, func(a, b [32]byte) int {
|
slices.SortFunc(storageReads, func(a, b *uint256.Int) int {
|
||||||
return bytes.Compare(a[:], b[:])
|
return a.Cmp(b)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,7 +221,7 @@ func TestBlockAccessListCopy(t *testing.T) {
|
||||||
// Make sure the mutations on copy won't affect the origin
|
// Make sure the mutations on copy won't affect the origin
|
||||||
for _, aa := range cpyCpy.Accesses {
|
for _, aa := range cpyCpy.Accesses {
|
||||||
for i := 0; i < len(aa.StorageReads); i++ {
|
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) {
|
if !reflect.DeepEqual(list, cpy) {
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,22 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeTestBAL(minSize int) *bal.BlockAccessList {
|
func makeTestBAL(minSize int) *bal.BlockAccessList {
|
||||||
n := minSize/33 + 1 // 33 bytes per storage read slot in RLP
|
n := minSize/33 + 1 // 33 bytes per storage read slot in RLP
|
||||||
access := bal.AccountAccess{
|
access := bal.AccountAccess{
|
||||||
Address: common.HexToAddress("0x01"),
|
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 {
|
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}}
|
return &bal.BlockAccessList{Accesses: []bal.AccountAccess{access}}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue