remove snapshot usage and unused internal methods; note this is different than the journaling used to simulate state transitions

This commit is contained in:
i-norden 2023-02-27 15:51:04 -06:00
parent b7b1896699
commit ae70c88e19
5 changed files with 23 additions and 151 deletions

View File

@ -37,7 +37,6 @@ func makePGXConfig(config Config) (*pgxpool.Config, error) {
return nil, err return nil, err
} }
//conf.ConnConfig.BuildStatementCache = nil
conf.ConnConfig.Config.Host = config.Hostname conf.ConnConfig.Config.Host = config.Hostname
conf.ConnConfig.Config.Port = uint16(config.Port) conf.ConnConfig.Config.Port = uint16(config.Port)
conf.ConnConfig.Config.Database = config.DatabaseName conf.ConnConfig.Config.Database = config.DatabaseName

View File

@ -3,6 +3,8 @@ package ipld_eth_statedb
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie"
"github.com/jackc/pgx/pgxpool" "github.com/jackc/pgx/pgxpool"
) )
@ -15,10 +17,13 @@ type Database interface {
} }
type StateDatabase struct { type StateDatabase struct {
pgxpool.Pool db pgxpool.Pool
trieDB *trie.Database
ethDB ethdb.Database
} }
func (sd *StateDatabase) ContractCode(addrHash common.Hash, codeHash common.Hash) ([]byte, error) { func (sd *StateDatabase) ContractCode(addrHash common.Hash, codeHash common.Hash) ([]byte, error) {
panic("implement me") panic("implement me")
} }
@ -27,7 +32,7 @@ func (sd *StateDatabase) ContractCodeSize(addrHash common.Hash, codeHash common.
} }
func (sd *StateDatabase) OpenTrie(root common.Hash) (state.Trie, error) { func (sd *StateDatabase) OpenTrie(root common.Hash) (state.Trie, error) {
panic("replace my usage") return trie.NewStateTrie(common.Hash{}, root, sd.trieDB), nil
} }
func (sd *StateDatabase) OpenStorageTrie(addrHash common.Hash, root common.Hash) (state.Trie, error) { func (sd *StateDatabase) OpenStorageTrie(addrHash common.Hash, root common.Hash) (state.Trie, error) {

View File

@ -135,9 +135,6 @@ func (ch createObjectChange) dirtied() *common.Address {
func (ch resetObjectChange) revert(s *StateDB) { func (ch resetObjectChange) revert(s *StateDB) {
s.setStateObject(ch.prev) s.setStateObject(ch.prev)
if !ch.prevdestruct && s.snap != nil {
delete(s.snapDestructs, ch.prev.addrHash)
}
} }
func (ch resetObjectChange) dirtied() *common.Address { func (ch resetObjectChange) dirtied() *common.Address {

View File

@ -186,36 +186,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
// If no live objects are available, attempt to use snapshots // If no live objects are available, attempt to use snapshots
var ( var (
enc []byte enc []byte
err error
) )
if s.db.snap != nil {
// If the object was destructed in *this* block (and potentially resurrected),
// the storage has been cleared out, and we should *not* consult the previous
// snapshot about any storage values. The only possible alternatives are:
// 1) resurrect happened, and new slot values were set -- those should
// have been handles via pendingStorage above.
// 2) we don't have new values, and can deliver empty response back
if _, destructed := s.db.snapDestructs[s.addrHash]; destructed {
return common.Hash{}
}
start := time.Now()
enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key.Bytes()))
if metrics.EnabledExpensive {
s.db.SnapshotStorageReads += time.Since(start)
}
}
// If the snapshot is unavailable or reading from it fails, load from the database.
if s.db.snap == nil || err != nil {
start := time.Now()
enc, err = s.getTrie(db).TryGet(key.Bytes())
if metrics.EnabledExpensive {
s.db.StorageReads += time.Since(start)
}
if err != nil {
s.setError(err)
return common.Hash{}
}
}
var value common.Hash var value common.Hash
if len(enc) > 0 { if len(enc) > 0 {
_, content, _, err := rlp.Split(enc) _, content, _, err := rlp.Split(enc)
@ -301,11 +272,8 @@ func (s *stateObject) updateTrie(db Database) state.Trie {
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now()) defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now())
} }
// The snapshot storage map for the object
var storage map[common.Hash][]byte
// Insert all the pending updates into the trie // Insert all the pending updates into the trie
tr := s.getTrie(db) tr := s.getTrie(db)
hasher := s.db.hasher
usedStorage := make([][]byte, 0, len(s.pendingStorage)) usedStorage := make([][]byte, 0, len(s.pendingStorage))
for key, value := range s.pendingStorage { for key, value := range s.pendingStorage {
@ -325,17 +293,6 @@ func (s *stateObject) updateTrie(db Database) state.Trie {
s.setError(tr.TryUpdate(key[:], v)) s.setError(tr.TryUpdate(key[:], v))
s.db.StorageUpdated += 1 s.db.StorageUpdated += 1
} }
// If state snapshotting is active, cache the data til commit
if s.db.snap != nil {
if storage == nil {
// Retrieve the old storage map, if available, create a new one otherwise
if storage = s.db.snapStorage[s.addrHash]; storage == nil {
storage = make(map[common.Hash][]byte)
s.db.snapStorage[s.addrHash] = storage
}
}
storage[crypto.HashData(hasher, key[:])] = v // v will be nil if it's deleted
}
usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure
} }
if s.db.prefetcher != nil { if s.db.prefetcher != nil {

View File

@ -65,7 +65,6 @@ type StateDB struct {
originalRoot common.Hash originalRoot common.Hash
snaps *snapshot.Tree snaps *snapshot.Tree
snap snapshot.Snapshot
snapDestructs map[common.Hash]struct{} snapDestructs map[common.Hash]struct{}
snapAccounts map[common.Hash][]byte snapAccounts map[common.Hash][]byte
snapStorage map[common.Hash]map[common.Hash][]byte snapStorage map[common.Hash]map[common.Hash][]byte
@ -140,13 +139,6 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
accessList: newAccessList(), accessList: newAccessList(),
hasher: crypto.NewKeccakState(), hasher: crypto.NewKeccakState(),
} }
if sdb.snaps != nil {
if sdb.snap = sdb.snaps.Snapshot(root); sdb.snap != nil {
sdb.snapDestructs = make(map[common.Hash]struct{})
sdb.snapAccounts = make(map[common.Hash][]byte)
sdb.snapStorage = make(map[common.Hash]map[common.Hash][]byte)
}
}
return sdb, nil return sdb, nil
} }
@ -347,42 +339,6 @@ func (s *StateDB) Suicide(addr common.Address) bool {
// Setting, updating & deleting state object methods. // Setting, updating & deleting state object methods.
// //
// updateStateObject writes the given object to the trie.
// TODO:
func (s *StateDB) updateStateObject(obj *stateObject) {
// Track the amount of time wasted on updating the account from the trie
if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())
}
// Encode the account and update the account trie
addr := obj.Address()
if err := s.trie.TryUpdateAccount(addr[:], &obj.data); err != nil {
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))
}
// If state snapshotting is active, cache the data til commit. Note, this
// update mechanism is not symmetric to the deletion, because whereas it is
// enough to track account updates at commit time, deletions need tracking
// at transaction boundary level to ensure we capture state clearing.
if s.snap != nil {
s.snapAccounts[obj.addrHash] = snapshot.SlimAccountRLP(obj.data.Nonce, obj.data.Balance, obj.data.Root, obj.data.CodeHash)
}
}
// deleteStateObject removes the given object from the state trie.
// TODO:
func (s *StateDB) deleteStateObject(obj *stateObject) {
// Track the amount of time wasted on deleting the account from the trie
if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())
}
// Delete the account from the trie
addr := obj.Address()
if err := s.trie.TryDeleteAccount(addr[:]); err != nil {
s.setError(fmt.Errorf("deleteStateObject (%x) error: %v", addr[:], err))
}
}
// getStateObject retrieves a state object given by the address, returning nil if // getStateObject retrieves a state object given by the address, returning nil if
// the object is not found or was deleted in this execution context. If you need // the object is not found or was deleted in this execution context. If you need
// to differentiate between non-existent/just-deleted, use getDeletedStateObject. // to differentiate between non-existent/just-deleted, use getDeletedStateObject.
@ -403,37 +359,11 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
if obj := s.stateObjects[addr]; obj != nil { if obj := s.stateObjects[addr]; obj != nil {
return obj return obj
} }
// If no live objects are available, attempt to use snapshots // If no live objects are available, load from the database
var data *types.StateAccount // TODO: REPLACE TRIE ACCESS HERE
if s.snap != nil { // can add a fallback option to use ipfsethdb to do the trie access if direct access fails
start := time.Now() start := time.Now()
acc, err := s.snap.Account(crypto.HashData(s.hasher, addr.Bytes())) data, err := s.trie.TryGetAccount(addr.Bytes())
if metrics.EnabledExpensive {
s.SnapshotAccountReads += time.Since(start)
}
if err == nil {
if acc == nil {
return nil
}
data = &types.StateAccount{
Nonce: acc.Nonce,
Balance: acc.Balance,
CodeHash: acc.CodeHash,
Root: common.BytesToHash(acc.Root),
}
if len(data.CodeHash) == 0 {
data.CodeHash = emptyCodeHash
}
if data.Root == (common.Hash{}) {
data.Root = emptyRoot
}
}
}
// If snapshot unavailable or reading from it failed, load from the database
if data == nil {
start := time.Now()
var err error
data, err = s.trie.TryGetAccount(addr.Bytes())
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
s.AccountReads += time.Since(start) s.AccountReads += time.Since(start)
} }
@ -444,7 +374,6 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
if data == nil { if data == nil {
return nil return nil
} }
}
// Insert into the live set // Insert into the live set
obj := newObject(s, addr, *data) obj := newObject(s, addr, *data)
s.setStateObject(obj) s.setStateObject(obj)
@ -468,19 +397,11 @@ func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject {
// the given address, it is overwritten and returned as the second return value. // the given address, it is overwritten and returned as the second return value.
func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that!
var prevdestruct bool
if s.snap != nil && prev != nil {
_, prevdestruct = s.snapDestructs[prev.addrHash]
if !prevdestruct {
s.snapDestructs[prev.addrHash] = struct{}{}
}
}
newobj = newObject(s, addr, types.StateAccount{}) newobj = newObject(s, addr, types.StateAccount{})
if prev == nil { if prev == nil {
s.journal.append(createObjectChange{account: &addr}) s.journal.append(createObjectChange{account: &addr})
} else { } else {
s.journal.append(resetObjectChange{prev: prev, prevdestruct: prevdestruct}) s.journal.append(resetObjectChange{prev: prev}) // NOTE: prevdestruct used to be set here from snapshot
} }
s.setStateObject(newobj) s.setStateObject(newobj)
if prev != nil && !prev.deleted { if prev != nil && !prev.deleted {
@ -506,6 +427,7 @@ func (s *StateDB) CreateAccount(addr common.Address) {
} }
} }
// TODO: not sure trie access can be replaced for this method, might need to use ipfs-ethdb
func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error { func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error {
so := db.getStateObject(addr) so := db.getStateObject(addr)
if so == nil { if so == nil {
@ -552,10 +474,10 @@ func (s *StateDB) RevertToSnapshot(revid int) {
if idx == len(s.validRevisions) || s.validRevisions[idx].id != revid { if idx == len(s.validRevisions) || s.validRevisions[idx].id != revid {
panic(fmt.Errorf("revision id %v cannot be reverted", revid)) panic(fmt.Errorf("revision id %v cannot be reverted", revid))
} }
snapshot := s.validRevisions[idx].journalIndex snp := s.validRevisions[idx].journalIndex
// Replay the journal to undo changes and remove invalidated snapshots // Replay the journal to undo changes and remove invalidated snapshots
s.journal.revert(s, snapshot) s.journal.revert(s, snp)
s.validRevisions = s.validRevisions[:idx] s.validRevisions = s.validRevisions[:idx]
} }
@ -564,14 +486,6 @@ func (s *StateDB) GetRefund() uint64 {
return s.refund return s.refund
} }
func (s *StateDB) clearJournalAndRefund() {
if len(s.journal.entries) > 0 {
s.journal = newJournal()
s.refund = 0
}
s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entries
}
// PrepareAccessList handles the preparatory steps for executing a state transition with // PrepareAccessList handles the preparatory steps for executing a state transition with
// regards to both EIP-2929 and EIP-2930: // regards to both EIP-2929 and EIP-2930:
// //