mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-09 13:33:50 +00:00
Merge branch 'ethereum:master' into gethintegration
This commit is contained in:
commit
bb2eb441f6
5 changed files with 65 additions and 47 deletions
2
go.mod
2
go.mod
|
|
@ -25,7 +25,7 @@ require (
|
||||||
github.com/ethereum/go-verkle v0.2.2
|
github.com/ethereum/go-verkle v0.2.2
|
||||||
github.com/fatih/color v1.16.0
|
github.com/fatih/color v1.16.0
|
||||||
github.com/ferranbt/fastssz v0.1.2
|
github.com/ferranbt/fastssz v0.1.2
|
||||||
github.com/fjl/gencodec v0.0.0-20250117152317-bc3e1c7619d4
|
github.com/fjl/gencodec v0.1.0
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
|
||||||
github.com/gofrs/flock v0.8.1
|
github.com/gofrs/flock v0.8.1
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -172,8 +172,8 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||||
github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk=
|
github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk=
|
||||||
github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs=
|
github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs=
|
||||||
github.com/fjl/gencodec v0.0.0-20250117152317-bc3e1c7619d4 h1:HhaRPDFEB1BrvBF+UCUnhyY9y5dtuBxy0myn+7sFjAw=
|
github.com/fjl/gencodec v0.1.0 h1:B3K0xPfc52cw52BBgUbSPxYo+HlLfAgWMVKRWXUXBcs=
|
||||||
github.com/fjl/gencodec v0.0.0-20250117152317-bc3e1c7619d4/go.mod h1:Um1dFHPONZGTHog1qD1NaWjXJW/SPB38wPv0O8uZ2fI=
|
github.com/fjl/gencodec v0.1.0/go.mod h1:Um1dFHPONZGTHog1qD1NaWjXJW/SPB38wPv0O8uZ2fI=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
|
|
|
||||||
|
|
@ -73,10 +73,10 @@ const (
|
||||||
|
|
||||||
type genctx struct {
|
type genctx struct {
|
||||||
stateRoot common.Hash
|
stateRoot common.Hash
|
||||||
accounts map[common.Hash][]byte
|
accounts map[common.Hash][]byte // Keyed by the hash of account address
|
||||||
storages map[common.Hash]map[common.Hash][]byte
|
storages map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address and the hash of storage key
|
||||||
accountOrigin map[common.Address][]byte
|
accountOrigin map[common.Address][]byte // Keyed by the account address
|
||||||
storageOrigin map[common.Address]map[common.Hash][]byte
|
storageOrigin map[common.Address]map[common.Hash][]byte // Keyed by the account address and the hash of storage key
|
||||||
nodes *trienode.MergedNodeSet
|
nodes *trienode.MergedNodeSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,22 +113,23 @@ type tester struct {
|
||||||
preimages map[common.Hash][]byte
|
preimages map[common.Hash][]byte
|
||||||
|
|
||||||
// current state set
|
// current state set
|
||||||
accounts map[common.Hash][]byte
|
accounts map[common.Hash][]byte // Keyed by the hash of account address
|
||||||
storages map[common.Hash]map[common.Hash][]byte
|
storages map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address and the hash of storage key
|
||||||
|
|
||||||
// state snapshots
|
// state snapshots
|
||||||
snapAccounts map[common.Hash]map[common.Hash][]byte
|
snapAccounts map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address
|
||||||
snapStorages map[common.Hash]map[common.Hash]map[common.Hash][]byte
|
snapStorages map[common.Hash]map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address and the hash of storage key
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTester(t *testing.T, historyLimit uint64, isVerkle bool) *tester {
|
func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int) *tester {
|
||||||
var (
|
var (
|
||||||
disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false)
|
disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false)
|
||||||
db = New(disk, &Config{
|
db = New(disk, &Config{
|
||||||
StateHistory: historyLimit,
|
StateHistory: historyLimit,
|
||||||
CleanCacheSize: 16 * 1024,
|
CleanCacheSize: 256 * 1024,
|
||||||
WriteBufferSize: 16 * 1024,
|
WriteBufferSize: 256 * 1024,
|
||||||
}, isVerkle)
|
}, isVerkle)
|
||||||
|
|
||||||
obj = &tester{
|
obj = &tester{
|
||||||
db: db,
|
db: db,
|
||||||
preimages: make(map[common.Hash][]byte),
|
preimages: make(map[common.Hash][]byte),
|
||||||
|
|
@ -138,7 +139,7 @@ func newTester(t *testing.T, historyLimit uint64, isVerkle bool) *tester {
|
||||||
snapStorages: make(map[common.Hash]map[common.Hash]map[common.Hash][]byte),
|
snapStorages: make(map[common.Hash]map[common.Hash]map[common.Hash][]byte),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < layers; i++ {
|
||||||
var parent = types.EmptyRootHash
|
var parent = types.EmptyRootHash
|
||||||
if len(obj.roots) != 0 {
|
if len(obj.roots) != 0 {
|
||||||
parent = obj.roots[len(obj.roots)-1]
|
parent = obj.roots[len(obj.roots)-1]
|
||||||
|
|
@ -264,11 +265,11 @@ func (t *tester) generate(parent common.Hash, rawStorageKey bool) (common.Hash,
|
||||||
addr := testrand.Address()
|
addr := testrand.Address()
|
||||||
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||||
|
|
||||||
// short circuit if the account was already existent
|
// Short circuit if the account was already existent
|
||||||
if _, ok := t.accounts[addrHash]; ok {
|
if _, ok := t.accounts[addrHash]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// short circuit if the account has been modified within the same transition
|
// Short circuit if the account has been modified within the same transition
|
||||||
if _, ok := dirties[addrHash]; ok {
|
if _, ok := dirties[addrHash]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -448,7 +449,7 @@ func TestDatabaseRollback(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Verify state histories
|
// Verify state histories
|
||||||
tester := newTester(t, 0, false)
|
tester := newTester(t, 0, false, 32)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
||||||
if err := tester.verifyHistory(); err != nil {
|
if err := tester.verifyHistory(); err != nil {
|
||||||
|
|
@ -482,7 +483,7 @@ func TestDatabaseRecoverable(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tester = newTester(t, 0, false)
|
tester = newTester(t, 0, false, 12)
|
||||||
index = tester.bottomIndex()
|
index = tester.bottomIndex()
|
||||||
)
|
)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
@ -526,7 +527,7 @@ func TestDisable(t *testing.T) {
|
||||||
maxDiffLayers = 128
|
maxDiffLayers = 128
|
||||||
}()
|
}()
|
||||||
|
|
||||||
tester := newTester(t, 0, false)
|
tester := newTester(t, 0, false, 32)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
||||||
stored := crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(tester.db.diskdb, nil))
|
stored := crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(tester.db.diskdb, nil))
|
||||||
|
|
@ -568,7 +569,7 @@ func TestCommit(t *testing.T) {
|
||||||
maxDiffLayers = 128
|
maxDiffLayers = 128
|
||||||
}()
|
}()
|
||||||
|
|
||||||
tester := newTester(t, 0, false)
|
tester := newTester(t, 0, false, 12)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
||||||
if err := tester.db.Commit(tester.lastHash(), false); err != nil {
|
if err := tester.db.Commit(tester.lastHash(), false); err != nil {
|
||||||
|
|
@ -598,7 +599,7 @@ func TestJournal(t *testing.T) {
|
||||||
maxDiffLayers = 128
|
maxDiffLayers = 128
|
||||||
}()
|
}()
|
||||||
|
|
||||||
tester := newTester(t, 0, false)
|
tester := newTester(t, 0, false, 12)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
||||||
if err := tester.db.Journal(tester.lastHash()); err != nil {
|
if err := tester.db.Journal(tester.lastHash()); err != nil {
|
||||||
|
|
@ -628,7 +629,7 @@ func TestCorruptedJournal(t *testing.T) {
|
||||||
maxDiffLayers = 128
|
maxDiffLayers = 128
|
||||||
}()
|
}()
|
||||||
|
|
||||||
tester := newTester(t, 0, false)
|
tester := newTester(t, 0, false, 12)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
||||||
if err := tester.db.Journal(tester.lastHash()); err != nil {
|
if err := tester.db.Journal(tester.lastHash()); err != nil {
|
||||||
|
|
@ -676,7 +677,7 @@ func TestTailTruncateHistory(t *testing.T) {
|
||||||
maxDiffLayers = 128
|
maxDiffLayers = 128
|
||||||
}()
|
}()
|
||||||
|
|
||||||
tester := newTester(t, 10, false)
|
tester := newTester(t, 10, false, 12)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
||||||
tester.db.Close()
|
tester.db.Close()
|
||||||
|
|
|
||||||
|
|
@ -295,24 +295,6 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) {
|
||||||
if dl.id == 0 {
|
if dl.id == 0 {
|
||||||
return nil, fmt.Errorf("%w: zero state id", errStateUnrecoverable)
|
return nil, fmt.Errorf("%w: zero state id", errStateUnrecoverable)
|
||||||
}
|
}
|
||||||
var (
|
|
||||||
buff = crypto.NewKeccakState()
|
|
||||||
hashes = make(map[common.Address]common.Hash)
|
|
||||||
accounts = make(map[common.Hash][]byte)
|
|
||||||
storages = make(map[common.Hash]map[common.Hash][]byte)
|
|
||||||
)
|
|
||||||
for addr, blob := range h.accounts {
|
|
||||||
hash := crypto.HashData(buff, addr.Bytes())
|
|
||||||
hashes[addr] = hash
|
|
||||||
accounts[hash] = blob
|
|
||||||
}
|
|
||||||
for addr, storage := range h.storages {
|
|
||||||
hash, ok := hashes[addr]
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Errorf("storage history with no account %x", addr))
|
|
||||||
}
|
|
||||||
storages[hash] = storage
|
|
||||||
}
|
|
||||||
// Apply the reverse state changes upon the current state. This must
|
// Apply the reverse state changes upon the current state. This must
|
||||||
// be done before holding the lock in order to access state in "this"
|
// be done before holding the lock in order to access state in "this"
|
||||||
// layer.
|
// layer.
|
||||||
|
|
@ -320,6 +302,10 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Derive the state modification set from the history, keyed by the hash
|
||||||
|
// of the account address and the storage key.
|
||||||
|
accounts, storages := h.stateSet()
|
||||||
|
|
||||||
// Mark the diskLayer as stale before applying any mutations on top.
|
// Mark the diskLayer as stale before applying any mutations on top.
|
||||||
dl.lock.Lock()
|
dl.lock.Lock()
|
||||||
defer dl.lock.Unlock()
|
defer dl.lock.Unlock()
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
|
|
@ -68,8 +69,9 @@ const (
|
||||||
slotIndexSize = common.HashLength + 5 // The length of encoded slot index
|
slotIndexSize = common.HashLength + 5 // The length of encoded slot index
|
||||||
historyMetaSize = 9 + 2*common.HashLength // The length of encoded history meta
|
historyMetaSize = 9 + 2*common.HashLength // The length of encoded history meta
|
||||||
|
|
||||||
stateHistoryV0 = uint8(0) // initial version of state history structure
|
stateHistoryV0 = uint8(0) // initial version of state history structure
|
||||||
stateHistoryV1 = uint8(1) // use the storage slot raw key as the identifier instead of the key hash
|
stateHistoryV1 = uint8(1) // use the storage slot raw key as the identifier instead of the key hash
|
||||||
|
historyVersion = stateHistoryV1 // the default state history version
|
||||||
)
|
)
|
||||||
|
|
||||||
// Each state history entry is consisted of five elements:
|
// Each state history entry is consisted of five elements:
|
||||||
|
|
@ -258,9 +260,9 @@ func newHistory(root common.Hash, parent common.Hash, block uint64, accounts map
|
||||||
slices.SortFunc(slist, common.Hash.Cmp)
|
slices.SortFunc(slist, common.Hash.Cmp)
|
||||||
storageList[addr] = slist
|
storageList[addr] = slist
|
||||||
}
|
}
|
||||||
version := stateHistoryV0
|
version := historyVersion
|
||||||
if rawStorageKey {
|
if !rawStorageKey {
|
||||||
version = stateHistoryV1
|
version = stateHistoryV0
|
||||||
}
|
}
|
||||||
return &history{
|
return &history{
|
||||||
meta: &meta{
|
meta: &meta{
|
||||||
|
|
@ -276,6 +278,35 @@ func newHistory(root common.Hash, parent common.Hash, block uint64, accounts map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stateSet returns the state set, keyed by the hash of the account address
|
||||||
|
// and the hash of the storage slot key.
|
||||||
|
func (h *history) stateSet() (map[common.Hash][]byte, map[common.Hash]map[common.Hash][]byte) {
|
||||||
|
var (
|
||||||
|
buff = crypto.NewKeccakState()
|
||||||
|
accounts = make(map[common.Hash][]byte)
|
||||||
|
storages = make(map[common.Hash]map[common.Hash][]byte)
|
||||||
|
)
|
||||||
|
for addr, blob := range h.accounts {
|
||||||
|
addrHash := crypto.HashData(buff, addr.Bytes())
|
||||||
|
accounts[addrHash] = blob
|
||||||
|
|
||||||
|
storage, exist := h.storages[addr]
|
||||||
|
if !exist {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if h.meta.version == stateHistoryV0 {
|
||||||
|
storages[addrHash] = storage
|
||||||
|
} else {
|
||||||
|
subset := make(map[common.Hash][]byte)
|
||||||
|
for key, slot := range storage {
|
||||||
|
subset[crypto.HashData(buff, key.Bytes())] = slot
|
||||||
|
}
|
||||||
|
storages[addrHash] = subset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return accounts, storages
|
||||||
|
}
|
||||||
|
|
||||||
// encode serializes the state history and returns four byte streams represent
|
// encode serializes the state history and returns four byte streams represent
|
||||||
// concatenated account/storage data, account/storage indexes respectively.
|
// concatenated account/storage data, account/storage indexes respectively.
|
||||||
func (h *history) encode() ([]byte, []byte, []byte, []byte) {
|
func (h *history) encode() ([]byte, []byte, []byte, []byte) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue