forked from cerc-io/plugeth
Merge tag 'v1.10.22' into feature/merge-v1.10.22
This commit is contained in:
+19
-9
@@ -63,7 +63,7 @@ type Trie interface {
|
||||
// GetKey returns the sha3 preimage of a hashed key that was previously used
|
||||
// to store a value.
|
||||
//
|
||||
// TODO(fjl): remove this when SecureTrie is removed
|
||||
// TODO(fjl): remove this when StateTrie is removed
|
||||
GetKey([]byte) []byte
|
||||
|
||||
// TryGet returns the value for key stored in the trie. The value bytes must
|
||||
@@ -71,8 +71,8 @@ type Trie interface {
|
||||
// trie.MissingNodeError is returned.
|
||||
TryGet(key []byte) ([]byte, error)
|
||||
|
||||
// TryUpdateAccount abstract an account write in the trie.
|
||||
TryUpdateAccount(key []byte, account *types.StateAccount) error
|
||||
// TryGetAccount abstract an account read from the trie.
|
||||
TryGetAccount(key []byte) (*types.StateAccount, error)
|
||||
|
||||
// TryUpdate associates key with value in the trie. If value has length zero, any
|
||||
// existing value is deleted from the trie. The value bytes must not be modified
|
||||
@@ -80,17 +80,27 @@ type Trie interface {
|
||||
// database, a trie.MissingNodeError is returned.
|
||||
TryUpdate(key, value []byte) error
|
||||
|
||||
// TryUpdateAccount abstract an account write to the trie.
|
||||
TryUpdateAccount(key []byte, account *types.StateAccount) error
|
||||
|
||||
// TryDelete removes any existing value for key from the trie. If a node was not
|
||||
// found in the database, a trie.MissingNodeError is returned.
|
||||
TryDelete(key []byte) error
|
||||
|
||||
// TryDeleteAccount abstracts an account deletion from the trie.
|
||||
TryDeleteAccount(key []byte) error
|
||||
|
||||
// Hash returns the root hash of the trie. It does not write to the database and
|
||||
// can be used even if the trie doesn't have one.
|
||||
Hash() common.Hash
|
||||
|
||||
// Commit writes all nodes to the trie's memory database, tracking the internal
|
||||
// and external (for account tries) references.
|
||||
Commit(onleaf trie.LeafCallback) (common.Hash, int, error)
|
||||
// Commit collects all dirty nodes in the trie and replace them with the
|
||||
// corresponding node hash. All collected nodes(including dirty leaves if
|
||||
// collectLeaf is true) will be encapsulated into a nodeset for return.
|
||||
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||
// be created with new root and updated trie database for following usage
|
||||
Commit(collectLeaf bool) (common.Hash, *trie.NodeSet, error)
|
||||
|
||||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
||||
// starts at the key after the given start key.
|
||||
@@ -133,7 +143,7 @@ type cachingDB struct {
|
||||
|
||||
// OpenTrie opens the main account trie at a specific root hash.
|
||||
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||
tr, err := trie.NewSecure(common.Hash{}, root, db.db)
|
||||
tr, err := trie.NewStateTrie(common.Hash{}, root, db.db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -142,7 +152,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||
|
||||
// OpenStorageTrie opens the storage trie of an account.
|
||||
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
|
||||
tr, err := trie.NewSecure(addrHash, root, db.db)
|
||||
tr, err := trie.NewStateTrie(addrHash, root, db.db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -152,7 +162,7 @@ func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
|
||||
// CopyTrie returns an independent copy of the given trie.
|
||||
func (db *cachingDB) CopyTrie(t Trie) Trie {
|
||||
switch t := t.(type) {
|
||||
case *trie.SecureTrie:
|
||||
case *trie.StateTrie:
|
||||
return t.Copy()
|
||||
default:
|
||||
panic(fmt.Errorf("unknown trie type %T", t))
|
||||
|
||||
@@ -19,10 +19,10 @@ package state
|
||||
import "github.com/ethereum/go-ethereum/metrics"
|
||||
|
||||
var (
|
||||
accountUpdatedMeter = metrics.NewRegisteredMeter("state/update/account", nil)
|
||||
storageUpdatedMeter = metrics.NewRegisteredMeter("state/update/storage", nil)
|
||||
accountDeletedMeter = metrics.NewRegisteredMeter("state/delete/account", nil)
|
||||
storageDeletedMeter = metrics.NewRegisteredMeter("state/delete/storage", nil)
|
||||
accountCommittedMeter = metrics.NewRegisteredMeter("state/commit/account", nil)
|
||||
storageCommittedMeter = metrics.NewRegisteredMeter("state/commit/storage", nil)
|
||||
accountUpdatedMeter = metrics.NewRegisteredMeter("state/update/account", nil)
|
||||
storageUpdatedMeter = metrics.NewRegisteredMeter("state/update/storage", nil)
|
||||
accountDeletedMeter = metrics.NewRegisteredMeter("state/delete/account", nil)
|
||||
storageDeletedMeter = metrics.NewRegisteredMeter("state/delete/storage", nil)
|
||||
accountTrieCommittedMeter = metrics.NewRegisteredMeter("state/commit/accountnodes", nil)
|
||||
storageTriesCommittedMeter = metrics.NewRegisteredMeter("state/commit/storagenodes", nil)
|
||||
)
|
||||
|
||||
@@ -410,7 +410,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
|
||||
if genesis == nil {
|
||||
return errors.New("missing genesis block")
|
||||
}
|
||||
t, err := trie.NewSecure(common.Hash{}, genesis.Root(), trie.NewDatabase(db))
|
||||
t, err := trie.NewStateTrie(common.Hash{}, genesis.Root(), trie.NewDatabase(db))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -430,7 +430,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
|
||||
return err
|
||||
}
|
||||
if acc.Root != emptyRoot {
|
||||
storageTrie, err := trie.NewSecure(common.BytesToHash(accIter.LeafKey()), acc.Root, trie.NewDatabase(db))
|
||||
storageTrie, err := trie.NewStateTrie(common.BytesToHash(accIter.LeafKey()), acc.Root, trie.NewDatabase(db))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -367,7 +367,10 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, owner common.Hash, roo
|
||||
for i, key := range result.keys {
|
||||
snapTrie.Update(key, result.vals[i])
|
||||
}
|
||||
root, _, _ := snapTrie.Commit(nil)
|
||||
root, nodes, _ := snapTrie.Commit(false)
|
||||
if nodes != nil {
|
||||
snapTrieDb.Update(trie.NewWithNodeSet(nodes))
|
||||
}
|
||||
snapTrieDb.Commit(root, false, nil)
|
||||
}
|
||||
// Construct the trie for state iteration, reuse the trie
|
||||
|
||||
@@ -142,17 +142,19 @@ func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) {
|
||||
type testHelper struct {
|
||||
diskdb ethdb.Database
|
||||
triedb *trie.Database
|
||||
accTrie *trie.SecureTrie
|
||||
accTrie *trie.StateTrie
|
||||
nodes *trie.MergedNodeSet
|
||||
}
|
||||
|
||||
func newHelper() *testHelper {
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
triedb := trie.NewDatabase(diskdb)
|
||||
accTrie, _ := trie.NewSecure(common.Hash{}, common.Hash{}, triedb)
|
||||
accTrie, _ := trie.NewStateTrie(common.Hash{}, common.Hash{}, triedb)
|
||||
return &testHelper{
|
||||
diskdb: diskdb,
|
||||
triedb: triedb,
|
||||
accTrie: accTrie,
|
||||
nodes: trie.NewMergedNodeSet(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,21 +182,26 @@ func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string)
|
||||
}
|
||||
|
||||
func (t *testHelper) makeStorageTrie(stateRoot, owner common.Hash, keys []string, vals []string, commit bool) []byte {
|
||||
stTrie, _ := trie.NewSecure(owner, common.Hash{}, t.triedb)
|
||||
stTrie, _ := trie.NewStateTrie(owner, common.Hash{}, t.triedb)
|
||||
for i, k := range keys {
|
||||
stTrie.Update([]byte(k), []byte(vals[i]))
|
||||
}
|
||||
var root common.Hash
|
||||
if !commit {
|
||||
root = stTrie.Hash()
|
||||
} else {
|
||||
root, _, _ = stTrie.Commit(nil)
|
||||
return stTrie.Hash().Bytes()
|
||||
}
|
||||
root, nodes, _ := stTrie.Commit(false)
|
||||
if nodes != nil {
|
||||
t.nodes.Merge(nodes)
|
||||
}
|
||||
return root.Bytes()
|
||||
}
|
||||
|
||||
func (t *testHelper) Commit() common.Hash {
|
||||
root, _, _ := t.accTrie.Commit(nil)
|
||||
root, nodes, _ := t.accTrie.Commit(true)
|
||||
if nodes != nil {
|
||||
t.nodes.Merge(nodes)
|
||||
}
|
||||
t.triedb.Update(t.nodes)
|
||||
t.triedb.Commit(root, false, nil)
|
||||
return root
|
||||
}
|
||||
@@ -378,7 +385,7 @@ func TestGenerateCorruptAccountTrie(t *testing.T) {
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
|
||||
|
||||
root, _, _ := helper.accTrie.Commit(nil) // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
|
||||
root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
|
||||
|
||||
// Delete an account trie leaf and ensure the generator chokes
|
||||
helper.triedb.Commit(root, false, nil)
|
||||
@@ -413,18 +420,8 @@ func TestGenerateMissingStorageTrie(t *testing.T) {
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
||||
root, _, _ := helper.accTrie.Commit(nil)
|
||||
|
||||
// We can only corrupt the disk database, so flush the tries out
|
||||
helper.triedb.Reference(
|
||||
common.BytesToHash(stRoot),
|
||||
common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"),
|
||||
)
|
||||
helper.triedb.Reference(
|
||||
common.BytesToHash(stRoot),
|
||||
common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"),
|
||||
)
|
||||
helper.triedb.Commit(root, false, nil)
|
||||
root := helper.Commit()
|
||||
|
||||
// Delete a storage trie root and ensure the generator chokes
|
||||
helper.diskdb.Delete(stRoot)
|
||||
@@ -458,18 +455,7 @@ func TestGenerateCorruptStorageTrie(t *testing.T) {
|
||||
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
||||
|
||||
root, _, _ := helper.accTrie.Commit(nil)
|
||||
|
||||
// We can only corrupt the disk database, so flush the tries out
|
||||
helper.triedb.Reference(
|
||||
common.BytesToHash(stRoot),
|
||||
common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"),
|
||||
)
|
||||
helper.triedb.Reference(
|
||||
common.BytesToHash(stRoot),
|
||||
common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"),
|
||||
)
|
||||
helper.triedb.Commit(root, false, nil)
|
||||
root := helper.Commit()
|
||||
|
||||
// Delete a storage trie leaf and ensure the generator chokes
|
||||
helper.diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes())
|
||||
@@ -825,10 +811,12 @@ func populateDangling(disk ethdb.KeyValueStore) {
|
||||
// This test will populate some dangling storages to see if they can be cleaned up.
|
||||
func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
|
||||
var helper = newHelper()
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
|
||||
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
|
||||
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
|
||||
@@ -858,10 +846,12 @@ func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
|
||||
// This test will populate some dangling storages to see if they can be cleaned up.
|
||||
func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) {
|
||||
var helper = newHelper()
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
|
||||
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
|
||||
populateDangling(helper.diskdb)
|
||||
|
||||
@@ -319,7 +319,7 @@ func (fi *fastIterator) Slot() []byte {
|
||||
}
|
||||
|
||||
// Release iterates over all the remaining live layer iterators and releases each
|
||||
// of thme individually.
|
||||
// of them individually.
|
||||
func (fi *fastIterator) Release() {
|
||||
for _, it := range fi.iterators {
|
||||
it.it.Release()
|
||||
@@ -327,7 +327,7 @@ func (fi *fastIterator) Release() {
|
||||
fi.iterators = nil
|
||||
}
|
||||
|
||||
// Debug is a convencience helper during testing
|
||||
// Debug is a convenience helper during testing
|
||||
func (fi *fastIterator) Debug() {
|
||||
for _, it := range fi.iterators {
|
||||
fmt.Printf("[p=%v v=%v] ", it.priority, it.it.Hash()[0])
|
||||
|
||||
@@ -265,7 +265,7 @@ func TestPostCapBasicDataAccess(t *testing.T) {
|
||||
snaps.Update(common.HexToHash("0xa3"), common.HexToHash("0xa2"), nil, setAccount("0xa3"), nil)
|
||||
snaps.Update(common.HexToHash("0xb3"), common.HexToHash("0xb2"), nil, setAccount("0xb3"), nil)
|
||||
|
||||
// checkExist verifies if an account exiss in a snapshot
|
||||
// checkExist verifies if an account exists in a snapshot
|
||||
checkExist := func(layer *diffLayer, key string) error {
|
||||
if data, _ := layer.Account(common.HexToHash(key)); data == nil {
|
||||
return fmt.Errorf("expected %x to exist, got nil", common.HexToHash(key))
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
var emptyCodeHash = crypto.Keccak256(nil)
|
||||
@@ -375,23 +376,23 @@ func (s *stateObject) updateRoot(db Database) {
|
||||
|
||||
// CommitTrie the storage trie of the object to db.
|
||||
// This updates the trie root.
|
||||
func (s *stateObject) CommitTrie(db Database) (int, error) {
|
||||
func (s *stateObject) CommitTrie(db Database) (*trie.NodeSet, error) {
|
||||
// If nothing changed, don't bother with hashing anything
|
||||
if s.updateTrie(db) == nil {
|
||||
return 0, nil
|
||||
return nil, nil
|
||||
}
|
||||
if s.dbErr != nil {
|
||||
return 0, s.dbErr
|
||||
return nil, s.dbErr
|
||||
}
|
||||
// Track the amount of time wasted on committing the storage trie
|
||||
if metrics.EnabledExpensive {
|
||||
defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now())
|
||||
}
|
||||
root, committed, err := s.trie.Commit(nil)
|
||||
root, nodes, err := s.trie.Commit(false)
|
||||
if err == nil {
|
||||
s.data.Root = root
|
||||
}
|
||||
return committed, err
|
||||
return nodes, err
|
||||
}
|
||||
|
||||
// AddBalance adds amount to s's balance.
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
type stateTest struct {
|
||||
@@ -40,7 +41,7 @@ func newStateTest() *stateTest {
|
||||
|
||||
func TestDump(t *testing.T) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
sdb, _ := New(common.Hash{}, NewDatabaseWithConfig(db, nil), nil)
|
||||
sdb, _ := New(common.Hash{}, NewDatabaseWithConfig(db, &trie.Config{Preimages: true}), nil)
|
||||
s := &stateTest{db: db, state: sdb}
|
||||
|
||||
// generate a few entries
|
||||
|
||||
+40
-32
@@ -493,7 +493,7 @@ func (s *StateDB) deleteStateObject(obj *stateObject) {
|
||||
}
|
||||
// Delete the account from the trie
|
||||
addr := obj.Address()
|
||||
if err := s.trie.TryDelete(addr[:]); err != nil {
|
||||
if err := s.trie.TryDeleteAccount(addr[:]); err != nil {
|
||||
s.setError(fmt.Errorf("deleteStateObject (%x) error: %v", addr[:], err))
|
||||
}
|
||||
}
|
||||
@@ -546,20 +546,16 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
|
||||
// If snapshot unavailable or reading from it failed, load from the database
|
||||
if data == nil {
|
||||
start := time.Now()
|
||||
enc, err := s.trie.TryGet(addr.Bytes())
|
||||
var err error
|
||||
data, err = s.trie.TryGetAccount(addr.Bytes())
|
||||
if metrics.EnabledExpensive {
|
||||
s.AccountReads += time.Since(start)
|
||||
}
|
||||
if err != nil {
|
||||
s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %v", addr.Bytes(), err))
|
||||
s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %w", addr.Bytes(), err))
|
||||
return nil
|
||||
}
|
||||
if len(enc) == 0 {
|
||||
return nil
|
||||
}
|
||||
data = new(types.StateAccount)
|
||||
if err := rlp.DecodeBytes(enc, data); err != nil {
|
||||
log.Error("Failed to decode state object", "addr", addr, "err", err)
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -783,7 +779,7 @@ func (s *StateDB) GetRefund() uint64 {
|
||||
return s.refund
|
||||
}
|
||||
|
||||
// Finalise finalises the state by removing the s destructed objects and clears
|
||||
// Finalise finalises the state by removing the destructed objects and clears
|
||||
// the journal as well as the refunds. Finalise, however, will not push any updates
|
||||
// into the tries just yet. Only IntermediateRoot or Commit will do that.
|
||||
func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||
@@ -805,7 +801,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||
// If state snapshotting is active, also mark the destruction there.
|
||||
// Note, we can't do this only at the end of a block because multiple
|
||||
// transactions within the same block might self destruct and then
|
||||
// ressurrect an account; but the snapshotter needs both events.
|
||||
// resurrect an account; but the snapshotter needs both events.
|
||||
if s.snap != nil {
|
||||
s.snapDestructs[obj.addrHash] = struct{}{} // We need to maintain account deletions explicitly (will remain set indefinitely)
|
||||
delete(s.snapAccounts, obj.addrHash) // Clear out any previously updated account data (may be recreated via a ressurrect)
|
||||
@@ -853,7 +849,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||
// Although naively it makes sense to retrieve the account trie and then do
|
||||
// the contract storage and account updates sequentially, that short circuits
|
||||
// the account prefetcher. Instead, let's process all the storage updates
|
||||
// first, giving the account prefeches just a few more milliseconds of time
|
||||
// first, giving the account prefetches just a few more milliseconds of time
|
||||
// to pull useful data from disk.
|
||||
for addr := range s.stateObjectsPending {
|
||||
if obj := s.stateObjects[addr]; !obj.deleted {
|
||||
@@ -897,7 +893,6 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||
func (s *StateDB) Prepare(thash common.Hash, ti int) {
|
||||
s.thash = thash
|
||||
s.txIndex = ti
|
||||
s.accessList = newAccessList()
|
||||
}
|
||||
|
||||
func (s *StateDB) clearJournalAndRefund() {
|
||||
@@ -905,7 +900,7 @@ func (s *StateDB) clearJournalAndRefund() {
|
||||
s.journal = newJournal()
|
||||
s.refund = 0
|
||||
}
|
||||
s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entires
|
||||
s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entries
|
||||
}
|
||||
|
||||
// Commit writes the state to the underlying in-memory trie database.
|
||||
@@ -917,23 +912,37 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
s.IntermediateRoot(deleteEmptyObjects)
|
||||
|
||||
// Commit objects to the trie, measuring the elapsed time
|
||||
var storageCommitted int
|
||||
var (
|
||||
accountTrieNodes int
|
||||
storageTrieNodes int
|
||||
nodes = trie.NewMergedNodeSet()
|
||||
)
|
||||
// PluGeth injection
|
||||
codeUpdates := make(map[common.Hash][]byte)
|
||||
// PluGeth injection
|
||||
codeWriter := s.db.TrieDB().DiskDB().NewBatch()
|
||||
for addr := range s.stateObjectsDirty {
|
||||
if obj := s.stateObjects[addr]; !obj.deleted {
|
||||
// Write any contract code associated with the state object
|
||||
if obj.code != nil && obj.dirtyCode {
|
||||
rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
|
||||
// PluGeth injection
|
||||
codeUpdates[common.BytesToHash(obj.CodeHash())] = obj.code
|
||||
// PluGeth injection
|
||||
obj.dirtyCode = false
|
||||
}
|
||||
// Write any storage changes in the state object to its storage trie
|
||||
committed, err := obj.CommitTrie(s.db)
|
||||
set, err := obj.CommitTrie(s.db)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
storageCommitted += committed
|
||||
// Merge the dirty nodes of storage trie into global set
|
||||
if set != nil {
|
||||
if err := nodes.Merge(set); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
storageTrieNodes += set.Len()
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(s.stateObjectsDirty) > 0 {
|
||||
@@ -944,26 +953,22 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
log.Crit("Failed to commit dirty codes", "error", err)
|
||||
}
|
||||
}
|
||||
// Write the account trie changes, measuing the amount of wasted time
|
||||
// Write the account trie changes, measuring the amount of wasted time
|
||||
var start time.Time
|
||||
if metrics.EnabledExpensive {
|
||||
start = time.Now()
|
||||
}
|
||||
// The onleaf func is called _serially_, so we can reuse the same account
|
||||
// for unmarshalling every time.
|
||||
var account types.StateAccount
|
||||
root, accountCommitted, err := s.trie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash, _ []byte) error {
|
||||
if err := rlp.DecodeBytes(leaf, &account); err != nil {
|
||||
return nil
|
||||
}
|
||||
if account.Root != emptyRoot {
|
||||
s.db.TrieDB().Reference(account.Root, parent)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
root, set, err := s.trie.Commit(true)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
// Merge the dirty nodes of account trie into global set
|
||||
if set != nil {
|
||||
if err := nodes.Merge(set); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
accountTrieNodes = set.Len()
|
||||
}
|
||||
if metrics.EnabledExpensive {
|
||||
s.AccountCommits += time.Since(start)
|
||||
|
||||
@@ -971,8 +976,8 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
storageUpdatedMeter.Mark(int64(s.StorageUpdated))
|
||||
accountDeletedMeter.Mark(int64(s.AccountDeleted))
|
||||
storageDeletedMeter.Mark(int64(s.StorageDeleted))
|
||||
accountCommittedMeter.Mark(int64(accountCommitted))
|
||||
storageCommittedMeter.Mark(int64(storageCommitted))
|
||||
accountTrieCommittedMeter.Mark(int64(accountTrieNodes))
|
||||
storageTriesCommittedMeter.Mark(int64(storageTrieNodes))
|
||||
s.AccountUpdated, s.AccountDeleted = 0, 0
|
||||
s.StorageUpdated, s.StorageDeleted = 0, 0
|
||||
}
|
||||
@@ -1001,6 +1006,9 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
}
|
||||
s.snap, s.snapDestructs, s.snapAccounts, s.snapStorage = nil, nil, nil, nil
|
||||
}
|
||||
if err := s.db.TrieDB().Update(nodes); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
s.originalRoot = root
|
||||
return root, err
|
||||
}
|
||||
|
||||
@@ -771,7 +771,7 @@ func TestStateDBAccessList(t *testing.T) {
|
||||
t.Fatalf("expected %x to be in access list", address)
|
||||
}
|
||||
}
|
||||
// Check that only the expected addresses are present in the acesslist
|
||||
// Check that only the expected addresses are present in the access list
|
||||
for address := range state.accessList.addresses {
|
||||
if _, exist := addressMap[address]; !exist {
|
||||
t.Fatalf("extra address %x in access list", address)
|
||||
|
||||
@@ -305,8 +305,8 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
}
|
||||
for len(nodeElements)+len(codeElements) > 0 {
|
||||
// Sync only half of the scheduled nodes
|
||||
var nodeProcessd int
|
||||
var codeProcessd int
|
||||
var nodeProcessed int
|
||||
var codeProcessed int
|
||||
if len(codeElements) > 0 {
|
||||
codeResults := make([]trie.CodeSyncResult, len(codeElements)/2+1)
|
||||
for i, element := range codeElements[:len(codeResults)] {
|
||||
@@ -321,7 +321,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
t.Fatalf("failed to process result %v", err)
|
||||
}
|
||||
}
|
||||
codeProcessd = len(codeResults)
|
||||
codeProcessed = len(codeResults)
|
||||
}
|
||||
if len(nodeElements) > 0 {
|
||||
nodeResults := make([]trie.NodeSyncResult, len(nodeElements)/2+1)
|
||||
@@ -337,7 +337,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
t.Fatalf("failed to process result %v", err)
|
||||
}
|
||||
}
|
||||
nodeProcessd = len(nodeResults)
|
||||
nodeProcessed = len(nodeResults)
|
||||
}
|
||||
batch := dstDb.NewBatch()
|
||||
if err := sched.Commit(batch); err != nil {
|
||||
@@ -346,7 +346,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
batch.Write()
|
||||
|
||||
paths, nodes, codes = sched.Missing(0)
|
||||
nodeElements = nodeElements[nodeProcessd:]
|
||||
nodeElements = nodeElements[nodeProcessed:]
|
||||
for i := 0; i < len(paths); i++ {
|
||||
nodeElements = append(nodeElements, stateElement{
|
||||
path: paths[i],
|
||||
@@ -354,7 +354,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
syncPath: trie.NewSyncPath([]byte(paths[i])),
|
||||
})
|
||||
}
|
||||
codeElements = codeElements[codeProcessd:]
|
||||
codeElements = codeElements[codeProcessed:]
|
||||
for i := 0; i < len(codes); i++ {
|
||||
codeElements = append(codeElements, stateElement{
|
||||
code: codes[i],
|
||||
|
||||
@@ -212,7 +212,7 @@ type subfetcher struct {
|
||||
|
||||
wake chan struct{} // Wake channel if a new task is scheduled
|
||||
stop chan struct{} // Channel to interrupt processing
|
||||
term chan struct{} // Channel to signal iterruption
|
||||
term chan struct{} // Channel to signal interruption
|
||||
copy chan chan Trie // Channel to request a copy of the current trie
|
||||
|
||||
seen map[string]struct{} // Tracks the entries already loaded
|
||||
@@ -331,7 +331,11 @@ func (sf *subfetcher) loop() {
|
||||
if _, ok := sf.seen[string(task)]; ok {
|
||||
sf.dups++
|
||||
} else {
|
||||
sf.trie.TryGet(task)
|
||||
if len(task) == len(common.Address{}) {
|
||||
sf.trie.TryGetAccount(task)
|
||||
} else {
|
||||
sf.trie.TryGet(task)
|
||||
}
|
||||
sf.seen[string(task)] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user