Skip to content

Commit

Permalink
Geth 1.13 (Deneb/Cancun) update (#5)
Browse files Browse the repository at this point in the history
The Geth `core/state` and `trie` packages underwent a big refactor between `v1.11.6` and `1.13.14`.
This code, which was adapted from those, needed corresponding updates. To do this I applied the diff patches from Geth directly where possible and in some places had to clone new parts of the Geth code and adapt them.

In order to make this process as straightforward as possible in the future, I've attempted to minimize the number of changes vs. Geth and added some documentation in the `trie_by_cid` package.

Reviewed-on: https://git.vdb.to/cerc-io/ipld-eth-statedb/pulls/5
  • Loading branch information
roysc committed May 29, 2024
1 parent 6f79445 commit 761d60a
Show file tree
Hide file tree
Showing 78 changed files with 12,392 additions and 3,022 deletions.
30 changes: 16 additions & 14 deletions direct_by_leaf/state_database.go → direct_by_leaf/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"context"
"errors"
"fmt"
"math/big"

"github.com/VictoriaMetrics/fastcache"
lru "github.com/hashicorp/golang-lru"
"github.com/holiman/uint256"

"github.com/cerc-io/plugeth-statediff/indexer/ipld"
"github.com/ethereum/go-ethereum/common"
Expand All @@ -30,35 +30,35 @@ var (
errNotFound = errors.New("not found")
)

// StateDatabase interface is a union of the subset of the geth state.Database interface required
// Database interface is a union of the subset of the geth state.Database interface required
// to support the vm.StateDB implementation as well as methods specific to this Postgres based implementation
type StateDatabase interface {
type Database interface {
ContractCode(codeHash common.Hash) ([]byte, error)
ContractCodeSize(codeHash common.Hash) (int, error)
StateAccount(addressHash, blockHash common.Hash) (*types.StateAccount, error)
StorageValue(addressHash, slotHash, blockHash common.Hash) ([]byte, error)
}

var _ StateDatabase = &stateDatabase{}
var _ Database = &cachingDB{}

type stateDatabase struct {
type cachingDB struct {
db sql.Database
codeSizeCache *lru.Cache
codeCache *fastcache.Cache
}

// NewStateDatabase returns a new Database implementation using the passed parameters
func NewStateDatabase(db sql.Database) *stateDatabase {
// NewDatabase returns a new Database implementation using the passed parameters
func NewDatabase(db sql.Database) *cachingDB {
csc, _ := lru.New(codeSizeCacheSize)
return &stateDatabase{
return &cachingDB{
db: db,
codeSizeCache: csc,
codeCache: fastcache.New(codeCacheSize),
}
}

// ContractCode satisfies Database, it returns the contract code for a given codehash
func (sd *stateDatabase) ContractCode(codeHash common.Hash) ([]byte, error) {
func (sd *cachingDB) ContractCode(codeHash common.Hash) ([]byte, error) {
if code := sd.codeCache.Get(nil, codeHash.Bytes()); len(code) > 0 {
return code, nil
}
Expand All @@ -79,7 +79,7 @@ func (sd *stateDatabase) ContractCode(codeHash common.Hash) ([]byte, error) {
}

// ContractCodeSize satisfies Database, it returns the length of the code for a provided codehash
func (sd *stateDatabase) ContractCodeSize(codeHash common.Hash) (int, error) {
func (sd *cachingDB) ContractCodeSize(codeHash common.Hash) (int, error) {
if cached, ok := sd.codeSizeCache.Get(codeHash); ok {
return cached.(int), nil
}
Expand All @@ -88,7 +88,7 @@ func (sd *stateDatabase) ContractCodeSize(codeHash common.Hash) (int, error) {
}

// StateAccount satisfies Database, it returns the types.StateAccount for a provided address and block hash
func (sd *stateDatabase) StateAccount(addressHash, blockHash common.Hash) (*types.StateAccount, error) {
func (sd *cachingDB) StateAccount(addressHash, blockHash common.Hash) (*types.StateAccount, error) {
res := StateAccountResult{}
err := sd.db.QueryRow(context.Background(), GetStateAccount, addressHash.Hex(), blockHash.Hex()).
Scan(&res.Balance, &res.Nonce, &res.CodeHash, &res.StorageRoot, &res.Removed)
Expand All @@ -99,8 +99,10 @@ func (sd *stateDatabase) StateAccount(addressHash, blockHash common.Hash) (*type
// TODO: check expected behavior for deleted/non existing accounts
return nil, nil
}
bal := new(big.Int)
bal.SetString(res.Balance, 10)
bal, err := uint256.FromDecimal(res.Balance)
if err != nil {
return nil, err
}
return &types.StateAccount{
Nonce: res.Nonce,
Balance: bal,
Expand All @@ -111,7 +113,7 @@ func (sd *stateDatabase) StateAccount(addressHash, blockHash common.Hash) (*type

// StorageValue satisfies Database, it returns the RLP-encoded storage value for the provided address, slot,
// and block hash
func (sd *stateDatabase) StorageValue(addressHash, slotHash, blockHash common.Hash) ([]byte, error) {
func (sd *cachingDB) StorageValue(addressHash, slotHash, blockHash common.Hash) ([]byte, error) {
res := StorageSlotResult{}
err := sd.db.QueryRow(context.Background(), GetStorageSlot,
addressHash.Hex(), slotHash.Hex(), blockHash.Hex()).
Expand Down
41 changes: 31 additions & 10 deletions direct_by_leaf/journal.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package state

import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
)

// journalEntry is a modification entry in the state change journal that can be
Expand Down Expand Up @@ -74,19 +73,26 @@ type (
account *common.Address
}
resetObjectChange struct {
account *common.Address
prev *stateObject
prevdestruct bool
prevAccount []byte
prevStorage map[common.Hash][]byte

prevAccountOriginExist bool
prevAccountOrigin []byte
prevStorageOrigin map[common.Hash][]byte
}
suicideChange struct {
selfDestructChange struct {
account *common.Address
prev bool // whether account had already suicided
prevbalance *big.Int
prev bool // whether account had already self-destructed
prevbalance *uint256.Int
}

// Changes to individual accounts.
balanceChange struct {
account *common.Address
prev *big.Int
prev *uint256.Int
}
nonceChange struct {
account *common.Address
Expand Down Expand Up @@ -141,21 +147,36 @@ func (ch createObjectChange) dirtied() *common.Address {

func (ch resetObjectChange) revert(s *StateDB) {
s.setStateObject(ch.prev)
if !ch.prevdestruct {
delete(s.stateObjectsDestruct, ch.prev.address)
}
if ch.prevAccount != nil {
s.accounts[ch.prev.addrHash] = ch.prevAccount
}
if ch.prevStorage != nil {
s.storages[ch.prev.addrHash] = ch.prevStorage
}
if ch.prevAccountOriginExist {
s.accountsOrigin[ch.prev.address] = ch.prevAccountOrigin
}
if ch.prevStorageOrigin != nil {
s.storagesOrigin[ch.prev.address] = ch.prevStorageOrigin
}
}

func (ch resetObjectChange) dirtied() *common.Address {
return nil
return ch.account
}

func (ch suicideChange) revert(s *StateDB) {
func (ch selfDestructChange) revert(s *StateDB) {
obj := s.getStateObject(*ch.account)
if obj != nil {
obj.suicided = ch.prev
obj.selfDestructed = ch.prev
obj.setBalance(ch.prevbalance)
}
}

func (ch suicideChange) dirtied() *common.Address {
func (ch selfDestructChange) dirtied() *common.Address {
return ch.account
}

Expand Down
Loading

0 comments on commit 761d60a

Please sign in to comment.