From aab5a2ef0bd475462b2ab8199892e10a0fd66ac1 Mon Sep 17 00:00:00 2001 From: i-norden Date: Mon, 13 Mar 2023 11:25:19 -0500 Subject: [PATCH] use ipld-eth-statedb for eth_call and graphql endpoints --- go.mod | 4 ++-- go.sum | 4 ++-- pkg/debug/backend.go | 1 + pkg/eth/api.go | 7 ++++--- pkg/eth/backend.go | 43 +++++++++++++++++++++--------------------- pkg/graphql/graphql.go | 5 ++--- pkg/graphql/service.go | 2 +- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index f25d5c81..f31c5dc9 100644 --- a/go.mod +++ b/go.mod @@ -6,13 +6,14 @@ require ( github.com/cerc-io/eth-ipfs-state-validator/v4 v4.0.10-alpha github.com/cerc-io/go-eth-state-node-iterator v1.1.9 github.com/cerc-io/ipfs-ethdb/v4 v4.0.10-alpha - github.com/cerc-io/ipld-eth-statedb v0.0.1-alpha + github.com/cerc-io/ipld-eth-statedb v0.0.2-alpha github.com/ethereum/go-ethereum v1.10.26 github.com/google/uuid v1.3.0 github.com/graph-gophers/graphql-go v1.3.0 github.com/ipfs/go-cid v0.2.0 github.com/ipfs/go-ipfs-blockstore v1.2.0 github.com/ipfs/go-ipfs-ds-help v1.1.0 + github.com/jackc/pgx/v4 v4.18.1 github.com/jmoiron/sqlx v1.3.5 github.com/joho/godotenv v1.4.0 github.com/lib/pq v1.10.6 @@ -145,7 +146,6 @@ require ( github.com/jackc/pgproto3/v2 v2.3.2 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgtype v1.14.0 // indirect - github.com/jackc/pgx/v4 v4.18.1 // indirect github.com/jackc/puddle v1.3.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect diff --git a/go.sum b/go.sum index 11a7b12e..4d78b373 100644 --- a/go.sum +++ b/go.sum @@ -153,8 +153,8 @@ github.com/cerc-io/go-ethereum v1.10.26-statediff-4.2.2-alpha h1:gesMZEbNU+fcAMc github.com/cerc-io/go-ethereum v1.10.26-statediff-4.2.2-alpha/go.mod h1:lKBVBWksSwBDR/5D9CAxaGQzDPIS3ueWb6idy7X1Shg= github.com/cerc-io/ipfs-ethdb/v4 v4.0.10-alpha h1:5iqNXeitkj3g7FxyKK/Pz+1HN7Ac9JZzCRj3Lv+uHiw= github.com/cerc-io/ipfs-ethdb/v4 v4.0.10-alpha/go.mod h1:dPscFRMvTWPKnoZ4U0D9v4bsrw6XdH7sOp8hUrVzOWA= -github.com/cerc-io/ipld-eth-statedb v0.0.1-alpha h1:oUSxncZCzMO4JXep/CoP+u1lgpdf97mbCUYWnjcHw6w= -github.com/cerc-io/ipld-eth-statedb v0.0.1-alpha/go.mod h1:914KQXnRylWQxRQOvlIr74NmGw7t1CyJJaEr5VSKW8E= +github.com/cerc-io/ipld-eth-statedb v0.0.2-alpha h1:Dj6XG6T14iHRBMFYHKcnMkNsdxZ7xqAaah2Z+QiOe1k= +github.com/cerc-io/ipld-eth-statedb v0.0.2-alpha/go.mod h1:914KQXnRylWQxRQOvlIr74NmGw7t1CyJJaEr5VSKW8E= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= diff --git a/pkg/debug/backend.go b/pkg/debug/backend.go index bf4a1b40..258d1708 100644 --- a/pkg/debug/backend.go +++ b/pkg/debug/backend.go @@ -42,6 +42,7 @@ type Backend struct { } // StateAtBlock retrieves the state database associated with a certain block +// We can't sub in our ipld-eth-statedb here because to match the expected interface we need to return *state.StateDB not vm.StateDB func (b *Backend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error) { rpcBlockNumber := rpc.BlockNumber(block.NumberU64()) statedb, _, err := b.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpcBlockNumber)) diff --git a/pkg/eth/api.go b/pkg/eth/api.go index 96196df9..fa932e48 100644 --- a/pkg/eth/api.go +++ b/pkg/eth/api.go @@ -28,13 +28,13 @@ import ( "time" "github.com/cerc-io/ipld-eth-server/v4/pkg/log" + ipld_eth_statedb "github.com/cerc-io/ipld-eth-statedb" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/filters" @@ -875,6 +875,7 @@ func (pea *PublicEthAPI) GetProof(ctx context.Context, address common.Address, s return nil, err } +// this continues to use ipfs-ethdb based geth StateDB as it requires trie access func (pea *PublicEthAPI) localGetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) { state, _, err := pea.B.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { @@ -977,7 +978,7 @@ type OverrideAccount struct { type StateOverride map[common.Address]OverrideAccount // Apply overrides the fields of specified accounts into the given state. -func (diff *StateOverride) Apply(state *state.StateDB) error { +func (diff *StateOverride) Apply(state *ipld_eth_statedb.StateDB) error { if diff == nil { return nil } @@ -1054,7 +1055,7 @@ func DoCall(ctx context.Context, b *Backend, args CallArgs, blockNrOrHash rpc.Bl log.Debugxf(ctx, "Executing EVM call finished %s runtime %s", time.Now().String(), time.Since(start).String()) }(time.Now()) - state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) + state, header, err := b.IPLDStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { return nil, err } diff --git a/pkg/eth/backend.go b/pkg/eth/backend.go index b868393b..2f8432e3 100644 --- a/pkg/eth/backend.go +++ b/pkg/eth/backend.go @@ -632,7 +632,6 @@ 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) @@ -659,9 +658,9 @@ func (b *Backend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHas } // 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) { +func (b *Backend) IPLDStateDBAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*ipld_eth_statedb.StateDB, *types.Header, error) { if blockNr, ok := blockNrOrHash.Number(); ok { - return b.StateAndHeaderByNumber(ctx, blockNr) + return b.IPLDStateDBAndHeaderByNumber(ctx, blockNr) } if hash, ok := blockNrOrHash.Hash(); ok { header, err := b.HeaderByHash(ctx, hash) @@ -684,24 +683,6 @@ func (b *Backend) IPLDStateDBAndHeaderByNumberOrHash(ctx context.Context, blockN 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 @@ -720,6 +701,24 @@ func (b *Backend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNu return stateDb, header, err } +// IPLDStateDBAndHeaderByNumber returns the statedb and header for a provided block number +func (b *Backend) IPLDStateDBAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*ipld_eth_statedb.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 +} + // GetCanonicalHash gets the canonical hash for the provided number, if there is one func (b *Backend) GetCanonicalHash(number uint64) (common.Hash, error) { var hashResult string @@ -741,7 +740,7 @@ func (b *Backend) GetCanonicalHeader(number uint64) (string, []byte, error) { } // GetEVM constructs and returns a vm.EVM -func (b *Backend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) { +func (b *Backend) GetEVM(ctx context.Context, msg core.Message, state vm.StateDB, header *types.Header) (*vm.EVM, func() error, error) { vmError := func() error { return nil } txContext := core.NewEVMTxContext(msg) blockContext := core.NewEVMBlockContext(header, b, nil) diff --git a/pkg/graphql/graphql.go b/pkg/graphql/graphql.go index 1f73b606..715cebb9 100644 --- a/pkg/graphql/graphql.go +++ b/pkg/graphql/graphql.go @@ -29,7 +29,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/rlp" @@ -51,8 +50,8 @@ type Account struct { } // getState fetches the StateDB object for an account. -func (a *Account) getState(ctx context.Context) (*state.StateDB, error) { - state, _, err := a.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) +func (a *Account) getState(ctx context.Context) (*ipld_eth_statedb.StateDB, error) { + state, _, err := a.backend.IPLDStateDBAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) return state, err } diff --git a/pkg/graphql/service.go b/pkg/graphql/service.go index 95211d7a..f3df0d48 100644 --- a/pkg/graphql/service.go +++ b/pkg/graphql/service.go @@ -81,7 +81,7 @@ func (s *Service) Start(server *p2p.Server) error { return nil } -// newHandler returns a new `http.Handler` that will answer GraphQL queries. +// NewHandler returns a new `http.Handler` that will answer GraphQL queries. // It additionally exports an interactive query browser on the / endpoint. func NewHandler(backend *eth.Backend) (http.Handler, error) { q := Resolver{backend}