mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
core/state: better randomized testing (postcheck) on journalling
This commit is contained in:
parent
4f4f9d88d3
commit
903bf512a9
3 changed files with 93 additions and 4 deletions
|
|
@ -17,7 +17,10 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
@ -130,3 +133,34 @@ func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) {
|
||||||
func (al *accessList) DeleteAddress(address common.Address) {
|
func (al *accessList) DeleteAddress(address common.Address) {
|
||||||
delete(al.addresses, address)
|
delete(al.addresses, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equal returns true if the two access lists are identical
|
||||||
|
func (al *accessList) Equal(other *accessList) bool {
|
||||||
|
if !maps.Equal(al.addresses, other.addresses) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return slices.EqualFunc(al.slots, other.slots,
|
||||||
|
func(m map[common.Hash]struct{}, m2 map[common.Hash]struct{}) bool {
|
||||||
|
return maps.Equal(m, m2)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al *accessList) PrettyPrint() string {
|
||||||
|
out := new(strings.Builder)
|
||||||
|
var sortedAddrs []common.Address
|
||||||
|
for addr, _ := range al.addresses {
|
||||||
|
sortedAddrs = append(sortedAddrs, addr)
|
||||||
|
}
|
||||||
|
slices.SortFunc(sortedAddrs, common.Address.Cmp)
|
||||||
|
for _, addr := range sortedAddrs {
|
||||||
|
idx := al.addresses[addr]
|
||||||
|
fmt.Fprintf(out, "%#x : (idx %d)\n", addr, idx)
|
||||||
|
if idx >= 0 {
|
||||||
|
slotmap := al.slots[idx]
|
||||||
|
for h, _ := range slotmap {
|
||||||
|
fmt.Fprintf(out, " %#x\n", h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"maps"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
@ -609,11 +610,29 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
|
||||||
return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
|
return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// Check transient storage.
|
||||||
|
{
|
||||||
|
have := state.transientStorage
|
||||||
|
want := checkstate.transientStorage
|
||||||
|
eq := maps.EqualFunc(have, want,
|
||||||
|
func(a Storage, b Storage) bool {
|
||||||
|
return maps.Equal(a, b)
|
||||||
|
})
|
||||||
|
if !eq {
|
||||||
|
return fmt.Errorf("transient storage differs ,have\n%v\nwant\n%v",
|
||||||
|
have.PrettyPrint(),
|
||||||
|
want.PrettyPrint())
|
||||||
|
}
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !checkstate.accessList.Equal(state.accessList) { // Check access lists
|
||||||
|
return fmt.Errorf("AccessLists are wrong, have \n%v\nwant\n%v",
|
||||||
|
checkstate.accessList.PrettyPrint(),
|
||||||
|
state.accessList.PrettyPrint())
|
||||||
|
}
|
||||||
if state.GetRefund() != checkstate.GetRefund() {
|
if state.GetRefund() != checkstate.GetRefund() {
|
||||||
return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
|
return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
|
||||||
state.GetRefund(), checkstate.GetRefund())
|
state.GetRefund(), checkstate.GetRefund())
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -30,10 +34,19 @@ func newTransientStorage() transientStorage {
|
||||||
|
|
||||||
// Set sets the transient-storage `value` for `key` at the given `addr`.
|
// Set sets the transient-storage `value` for `key` at the given `addr`.
|
||||||
func (t transientStorage) Set(addr common.Address, key, value common.Hash) {
|
func (t transientStorage) Set(addr common.Address, key, value common.Hash) {
|
||||||
|
if value == (common.Hash{}) { // this is a 'delete'
|
||||||
|
if _, ok := t[addr]; ok {
|
||||||
|
delete(t[addr], key)
|
||||||
|
if len(t[addr]) == 0 {
|
||||||
|
delete(t, addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if _, ok := t[addr]; !ok {
|
if _, ok := t[addr]; !ok {
|
||||||
t[addr] = make(Storage)
|
t[addr] = make(Storage)
|
||||||
}
|
}
|
||||||
t[addr][key] = value
|
t[addr][key] = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gets the transient storage for `key` at the given `addr`.
|
// Get gets the transient storage for `key` at the given `addr`.
|
||||||
|
|
@ -53,3 +66,26 @@ func (t transientStorage) Copy() transientStorage {
|
||||||
}
|
}
|
||||||
return storage
|
return storage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t transientStorage) PrettyPrint() string {
|
||||||
|
out := new(strings.Builder)
|
||||||
|
var sortedAddrs []common.Address
|
||||||
|
for addr := range t {
|
||||||
|
sortedAddrs = append(sortedAddrs, addr)
|
||||||
|
slices.SortFunc(sortedAddrs, common.Address.Cmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range sortedAddrs {
|
||||||
|
fmt.Fprintf(out, "%#x:", addr)
|
||||||
|
var sortedKeys []common.Hash
|
||||||
|
storage := t[addr]
|
||||||
|
for key := range storage {
|
||||||
|
sortedKeys = append(sortedKeys, key)
|
||||||
|
}
|
||||||
|
slices.SortFunc(sortedKeys, common.Hash.Cmp)
|
||||||
|
for _, key := range sortedKeys {
|
||||||
|
fmt.Fprintf(out, " %X : %X\n", key, storage[key])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue