new backend methods using ipld_eth_statedb.StateDB

This commit is contained in:
i-norden
2023-03-13 07:51:03 -05:00
parent 4c29841c21
commit ba5cdecf93
4 changed files with 123 additions and 47 deletions
+63 -9
View File
@@ -25,10 +25,13 @@ import (
"math/big"
"time"
"github.com/jackc/pgx/v4/pgxpool"
validator "github.com/cerc-io/eth-ipfs-state-validator/v4/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v4/postgres"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
ipld_eth_statedb "github.com/cerc-io/ipld-eth-statedb"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
@@ -64,7 +67,7 @@ const (
FROM canonical_header_hash($1) AS block_hash
WHERE block_hash IS NOT NULL`
RetrieveCanonicalHeaderByNumber = `SELECT cid, data FROM eth.header_cids
INNER JOIN public.blocks ON (
INNER JOIN ipld.blocks ON (
header_cids.cid = blocks.key
AND header_cids.block_number = blocks.block_number
)
@@ -90,7 +93,7 @@ const (
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
ORDER BY header_cids.block_number DESC
LIMIT 1`
RetrieveCodeByMhKey = `SELECT data FROM public.blocks WHERE key = $1`
RetrieveCodeByMhKey = `SELECT data FROM ipld.blocks WHERE key = $1`
)
const (
@@ -107,6 +110,8 @@ type Backend struct {
// ethereum interfaces
EthDB ethdb.Database
StateDatabase state.Database
// We'll use this state.Database for eth_call and any place we don't need trie access
IpldStateDatabase ipld_eth_statedb.Database
Config *Config
}
@@ -119,7 +124,7 @@ type Config struct {
GroupCacheConfig *shared.GroupCacheConfig
}
func NewEthBackend(db *sqlx.DB, c *Config) (*Backend, error) {
func NewEthBackend(db *sqlx.DB, pgxdb *pgxpool.Pool, c *Config) (*Backend, error) {
gcc := c.GroupCacheConfig
groupName := gcc.StateDB.Name
@@ -135,13 +140,17 @@ func NewEthBackend(db *sqlx.DB, c *Config) (*Backend, error) {
})
logStateDBStatsOnTimer(ethDB.(*ipfsethdb.Database), gcc)
ipldStateDB, err := ipld_eth_statedb.NewStateDatabaseWithPool(pgxdb)
if err != nil {
return nil, err
}
return &Backend{
DB: db,
Retriever: r,
EthDB: ethDB,
StateDatabase: state.NewDatabase(ethDB),
Config: c,
DB: db,
Retriever: r,
EthDB: ethDB,
StateDatabase: state.NewDatabase(ethDB),
IpldStateDatabase: ipldStateDB,
Config: c,
}, nil
}
@@ -623,6 +632,7 @@ func (b *Backend) GetLogs(ctx context.Context, hash common.Hash, number uint64)
}
// StateAndHeaderByNumberOrHash returns the statedb and header for the provided block number or hash
// TODO: this needs to be updated to use the new StateDB implementation
func (b *Backend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok {
return b.StateAndHeaderByNumber(ctx, blockNr)
@@ -648,6 +658,50 @@ func (b *Backend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHas
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
}
// IPLDStateDBAndHeaderByNumberOrHash returns the statedb and header for the provided block number or hash
func (b *Backend) IPLDStateDBAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok {
return b.StateAndHeaderByNumber(ctx, blockNr)
}
if hash, ok := blockNrOrHash.Hash(); ok {
header, err := b.HeaderByHash(ctx, hash)
if err != nil {
return nil, nil, err
}
if header == nil {
return nil, nil, errors.New("header for hash not found")
}
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
if err != nil {
return nil, nil, err
}
if blockNrOrHash.RequireCanonical && canonicalHash != hash {
return nil, nil, errors.New("hash is not currently canonical")
}
stateDB, err := ipld_eth_statedb.New(header.Root, b.IpldStateDatabase)
return stateDB, header, err
}
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
}
// IPLDStateDBAndHeaderByNumber returns the statedb and header for a provided block number
func (b *Backend) IPLDStateDBAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) {
// Pending state is only known by the miner
if number == rpc.PendingBlockNumber {
return nil, nil, errPendingBlockNumber
}
// Otherwise resolve the block number and return its state
header, err := b.HeaderByNumber(ctx, number)
if err != nil {
return nil, nil, err
}
if header == nil {
return nil, nil, errors.New("header not found")
}
stateDb, err := ipld_eth_statedb.New(header.Root, b.IpldStateDatabase)
return stateDb, header, err
}
// StateAndHeaderByNumber returns the statedb and header for a provided block number
func (b *Backend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
// Pending state is only known by the miner
+3 -2
View File
@@ -93,6 +93,7 @@ const (
)
WHERE block_hash = $1
ORDER BY eth.transaction_cids.index ASC`
// TODO: join on ipld.blocks and return IPLD object in this query instead of round tripping back to ipld.blocks
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, state_cids.block_number, state_cids.removed
FROM eth.state_cids
INNER JOIN eth.header_cids ON (
@@ -130,8 +131,7 @@ const (
AND receipt_cids.block_number = transaction_cids.block_number
AND transaction_cids.header_id = header_cids.block_hash
AND transaction_cids.block_number = header_cids.block_number`
// TODO: replace me with new query now that we have the correct storage index
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT cid, block_number, removed, state_leaf_removed FROM get_storage_at_by_hash($1, $2, $3)`
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT cid, val, block_number, removed, state_leaf_removed FROM get_storage_at_by_hash($1, $2, $3)`
)
type ipldResult struct {
@@ -142,6 +142,7 @@ type ipldResult struct {
type nodeInfo struct {
CID string `db:"cid"`
Value []byte `db:"val"`
BlockNumber string `db:"block_number"`
Data []byte `db:"data"`
Removed bool `db:"removed"`