mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
core/types/bal: remove ssz testdata and add tests
This commit is contained in:
parent
0b3283a030
commit
1dc017c289
53 changed files with 179 additions and 99 deletions
|
|
@ -76,7 +76,7 @@ type ConstructionBlockAccessList struct {
|
|||
Accounts map[common.Address]*ConstructionAccountAccess
|
||||
}
|
||||
|
||||
// NewBlockAccessList instantiates an empty access list.
|
||||
// NewConstructionBlockAccessList instantiates an empty access list.
|
||||
func NewConstructionBlockAccessList() ConstructionBlockAccessList {
|
||||
return ConstructionBlockAccessList{
|
||||
Accounts: make(map[common.Address]*ConstructionAccountAccess),
|
||||
|
|
|
|||
|
|
@ -19,16 +19,16 @@ package bal
|
|||
import (
|
||||
"bytes"
|
||||
"cmp"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
|
@ -47,19 +47,15 @@ type BlockAccessList struct {
|
|||
// according to the spec or any code changes are contained which exceed protocol
|
||||
// max code size.
|
||||
func (e *BlockAccessList) Validate() error {
|
||||
var (
|
||||
prev *[20]byte
|
||||
)
|
||||
if !slices.IsSortedFunc(e.Accesses, func(a, b AccountAccess) int {
|
||||
return bytes.Compare(a.Address[:], b.Address[:])
|
||||
}) {
|
||||
return errors.New("block access list accounts not in lexicographic order")
|
||||
}
|
||||
for _, entry := range e.Accesses {
|
||||
if prev != nil {
|
||||
if bytes.Compare(entry.Address[:], (*prev)[:]) <= 0 {
|
||||
return fmt.Errorf("block access list accounts not in lexicographic order")
|
||||
}
|
||||
}
|
||||
if err := entry.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
prev = &entry.Address
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -115,16 +111,12 @@ type encodingSlotWrites struct {
|
|||
// validate returns an instance of the encoding-representation slot writes in
|
||||
// working representation.
|
||||
func (e *encodingSlotWrites) validate() error {
|
||||
var prev *uint16
|
||||
for _, write := range e.Accesses {
|
||||
if prev != nil {
|
||||
if *prev >= write.TxIdx {
|
||||
return fmt.Errorf("storage write tx indices not in order")
|
||||
}
|
||||
}
|
||||
prev = &write.TxIdx
|
||||
if slices.IsSortedFunc(e.Accesses, func(a, b encodingStorageWrite) int {
|
||||
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||
}) {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
return errors.New("storage write tx indices not in order")
|
||||
}
|
||||
|
||||
// AccountAccess is the encoding format of ConstructionAccountAccess.
|
||||
|
|
@ -141,52 +133,37 @@ type AccountAccess struct {
|
|||
// If any of the keys in the encoding object are not ordered according to the
|
||||
// spec, an error is returned.
|
||||
func (e *AccountAccess) validate() error {
|
||||
// Convert slot writes
|
||||
var prevSlotWrite *[32]byte
|
||||
// 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 errors.New("storage writes slots not in lexicographic order")
|
||||
}
|
||||
for _, write := range e.StorageWrites {
|
||||
if prevSlotWrite != nil {
|
||||
if bytes.Compare((*prevSlotWrite)[:], write.Slot[:]) >= 0 {
|
||||
return fmt.Errorf("storage writes slots not in lexicographic order")
|
||||
}
|
||||
}
|
||||
prevSlotWrite = &write.Slot
|
||||
|
||||
if err := write.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Convert slot reads
|
||||
var prevSlotRead *[32]byte
|
||||
for _, read := range e.StorageReads {
|
||||
if prevSlotRead != nil {
|
||||
if bytes.Compare((*prevSlotRead)[:], read[:]) >= 0 {
|
||||
return fmt.Errorf("storage read slots not in lexicographic order")
|
||||
}
|
||||
}
|
||||
prevSlotRead = &read
|
||||
// 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[:])
|
||||
}) {
|
||||
return errors.New("storage read slots not in lexicographic order")
|
||||
}
|
||||
|
||||
// Convert balance changes
|
||||
var prevBalanceIndex *uint16
|
||||
for _, balanceChange := range e.BalanceChanges {
|
||||
if prevBalanceIndex != nil {
|
||||
if *prevBalanceIndex >= balanceChange.TxIdx {
|
||||
return fmt.Errorf("balance changes not in ascending order by tx index")
|
||||
}
|
||||
}
|
||||
prevBalanceIndex = &balanceChange.TxIdx
|
||||
// Check the balance changes are sorted in order
|
||||
if !slices.IsSortedFunc(e.BalanceChanges, func(a, b encodingBalanceChange) int {
|
||||
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||
}) {
|
||||
return errors.New("balance changes 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 fmt.Errorf("nonce diffs not in ascending order by tx index")
|
||||
}
|
||||
}
|
||||
prevNonceIndex = &nonceChange.TxIdx
|
||||
// Check the nonce changes are sorted in order
|
||||
if !slices.IsSortedFunc(e.NonceChanges, func(a, b encodingAccountNonce) int {
|
||||
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||
}) {
|
||||
return errors.New("nonce changes not in ascending order by tx index")
|
||||
}
|
||||
|
||||
// Convert code change
|
||||
|
|
@ -201,36 +178,15 @@ func (e *AccountAccess) validate() error {
|
|||
// Copy returns a deep copy of the account access
|
||||
func (e *AccountAccess) Copy() AccountAccess {
|
||||
res := AccountAccess{
|
||||
Address: e.Address,
|
||||
Address: e.Address,
|
||||
StorageReads: slices.Clone(e.StorageReads),
|
||||
BalanceChanges: slices.Clone(e.BalanceChanges),
|
||||
NonceChanges: slices.Clone(e.NonceChanges),
|
||||
}
|
||||
|
||||
for _, storageWrite := range e.StorageWrites {
|
||||
cpy := encodingSlotWrites{
|
||||
res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{
|
||||
Slot: storageWrite.Slot,
|
||||
Accesses: slices.Clone(storageWrite.Accesses),
|
||||
}
|
||||
for _, slotWrite := range storageWrite.Accesses {
|
||||
cpy.Accesses = append(cpy.Accesses, encodingStorageWrite{
|
||||
TxIdx: slotWrite.TxIdx,
|
||||
ValueAfter: slotWrite.ValueAfter,
|
||||
})
|
||||
}
|
||||
res.StorageWrites = append(res.StorageWrites, cpy)
|
||||
}
|
||||
|
||||
res.StorageReads = slices.Clone(e.StorageReads)
|
||||
|
||||
for _, balanceChange := range e.BalanceChanges {
|
||||
res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{
|
||||
TxIdx: balanceChange.TxIdx,
|
||||
Balance: balanceChange.Balance,
|
||||
})
|
||||
}
|
||||
|
||||
for _, nonceChange := range e.NonceChanges {
|
||||
res.NonceChanges = append(res.NonceChanges, encodingAccountNonce{
|
||||
TxIdx: nonceChange.TxIdx,
|
||||
Nonce: nonceChange.Nonce,
|
||||
})
|
||||
}
|
||||
if len(e.Code) == 1 {
|
||||
|
|
|
|||
|
|
@ -18,10 +18,13 @@ package bal
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"cmp"
|
||||
"reflect"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/internal/testrand"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
|
@ -33,7 +36,7 @@ func equalBALs(a *BlockAccessList, b *BlockAccessList) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func makeTestBAL() *ConstructionBlockAccessList {
|
||||
func makeTestConstructionBAL() *ConstructionBlockAccessList {
|
||||
return &ConstructionBlockAccessList{
|
||||
map[common.Address]*ConstructionAccountAccess{
|
||||
common.BytesToAddress([]byte{0xff, 0xff}): {
|
||||
|
|
@ -90,7 +93,7 @@ func makeTestBAL() *ConstructionBlockAccessList {
|
|||
// TestBALEncoding tests that a populated access list can be encoded/decoded correctly.
|
||||
func TestBALEncoding(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
bal := makeTestBAL()
|
||||
bal := makeTestConstructionBAL()
|
||||
err := bal.EncodeRLP(&buf)
|
||||
if err != nil {
|
||||
t.Fatalf("encoding failed: %v\n", err)
|
||||
|
|
@ -107,22 +110,143 @@ func TestBALEncoding(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestBALEncoding tests that a populated access list can be encoded/decoded correctly.
|
||||
func TestBALFullRLPEncoding(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
bal := makeTestBAL()
|
||||
err := bal.EncodeRLP(&buf)
|
||||
if err != nil {
|
||||
t.Fatalf("encoding failed: %v\n", err)
|
||||
func makeTestAccountAccess(sort bool) AccountAccess {
|
||||
var (
|
||||
storageWrites []encodingSlotWrites
|
||||
storageReads [][32]byte
|
||||
balances []encodingBalanceChange
|
||||
nonces []encodingAccountNonce
|
||||
)
|
||||
for i := 0; i < 5; i++ {
|
||||
slot := encodingSlotWrites{
|
||||
Slot: testrand.Hash(),
|
||||
}
|
||||
for j := 0; j < 3; j++ {
|
||||
slot.Accesses = append(slot.Accesses, encodingStorageWrite{
|
||||
TxIdx: uint16(2 * j),
|
||||
ValueAfter: testrand.Hash(),
|
||||
})
|
||||
}
|
||||
if sort {
|
||||
slices.SortFunc(slot.Accesses, func(a, b encodingStorageWrite) int {
|
||||
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||
})
|
||||
}
|
||||
storageWrites = append(storageWrites, slot)
|
||||
}
|
||||
var dec BlockAccessList
|
||||
if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 10000000)); err != nil {
|
||||
t.Fatalf("decoding failed: %v\n", err)
|
||||
if sort {
|
||||
slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int {
|
||||
return bytes.Compare(a.Slot[:], b.Slot[:])
|
||||
})
|
||||
}
|
||||
if dec.Hash() != bal.toEncodingObj().Hash() {
|
||||
t.Fatalf("encoded block hash doesn't match decoded")
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
storageReads = append(storageReads, testrand.Hash())
|
||||
}
|
||||
if !equalBALs(bal.toEncodingObj(), &dec) {
|
||||
t.Fatal("decoded BAL doesn't match")
|
||||
if sort {
|
||||
slices.SortFunc(storageReads, func(a, b [32]byte) int {
|
||||
return bytes.Compare(a[:], b[:])
|
||||
})
|
||||
}
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
balances = append(balances, encodingBalanceChange{
|
||||
TxIdx: uint16(2 * i),
|
||||
Balance: [16]byte(testrand.Bytes(16)),
|
||||
})
|
||||
}
|
||||
if sort {
|
||||
slices.SortFunc(balances, func(a, b encodingBalanceChange) int {
|
||||
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||
})
|
||||
}
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
nonces = append(nonces, encodingAccountNonce{
|
||||
TxIdx: uint16(2 * i),
|
||||
Nonce: uint64(i + 100),
|
||||
})
|
||||
}
|
||||
if sort {
|
||||
slices.SortFunc(nonces, func(a, b encodingAccountNonce) int {
|
||||
return cmp.Compare[uint16](a.TxIdx, b.TxIdx)
|
||||
})
|
||||
}
|
||||
|
||||
return AccountAccess{
|
||||
Address: [20]byte(testrand.Bytes(20)),
|
||||
StorageWrites: storageWrites,
|
||||
StorageReads: storageReads,
|
||||
BalanceChanges: balances,
|
||||
NonceChanges: nonces,
|
||||
Code: []CodeChange{
|
||||
{
|
||||
TxIndex: 100,
|
||||
Code: testrand.Bytes(256),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeTestBAL(sort bool) BlockAccessList {
|
||||
list := BlockAccessList{}
|
||||
for i := 0; i < 5; i++ {
|
||||
list.Accesses = append(list.Accesses, makeTestAccountAccess(sort))
|
||||
}
|
||||
if sort {
|
||||
slices.SortFunc(list.Accesses, func(a, b AccountAccess) int {
|
||||
return bytes.Compare(a.Address[:], b.Address[:])
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func TestBlockAccessListCopy(t *testing.T) {
|
||||
list := makeTestBAL(true)
|
||||
cpy := list.Copy()
|
||||
cpyCpy := cpy.Copy()
|
||||
|
||||
if !reflect.DeepEqual(list, cpy) {
|
||||
t.Fatal("block access mismatch")
|
||||
}
|
||||
if !reflect.DeepEqual(cpy, cpyCpy) {
|
||||
t.Fatal("block access mismatch")
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
}
|
||||
if !reflect.DeepEqual(list, cpy) {
|
||||
t.Fatal("block access mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockAccessListValidation(t *testing.T) {
|
||||
// Validate the block access list after RLP decoding
|
||||
enc := makeTestBAL(true)
|
||||
if err := enc.Validate(); err != nil {
|
||||
t.Fatalf("Unexpected validation error: %v", err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := enc.EncodeRLP(&buf); err != nil {
|
||||
t.Fatalf("Unexpected encoding error: %v", err)
|
||||
}
|
||||
|
||||
var dec BlockAccessList
|
||||
if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 0)); err != nil {
|
||||
t.Fatalf("Unexpected RLP-decode error: %v", err)
|
||||
}
|
||||
if err := dec.Validate(); err != nil {
|
||||
t.Fatalf("Unexpected validation error: %v", err)
|
||||
}
|
||||
|
||||
// Validate the derived block access list
|
||||
cBAL := makeTestConstructionBAL()
|
||||
listB := cBAL.toEncodingObj()
|
||||
if err := listB.Validate(); err != nil {
|
||||
t.Fatalf("Unexpected validation error: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue