Skip to content

Commit

Permalink
feat(be): integrate block explorer Json-RPC server (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xbcdev authored Apr 2, 2024
1 parent d76ee49 commit d73b1c4
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 5 deletions.
4 changes: 4 additions & 0 deletions cmd/rollappd/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/evmos/evmos/v12/crypto/hd"

berpcconfig "github.com/bcdevtools/block-explorer-rpc-cosmos/be_rpc/config"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
Expand Down Expand Up @@ -105,6 +106,9 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
chainID := client.GetClientContextFromCmd(cmd).ChainID
dymintconf.EnsureRoot(home, dymintconf.DefaultConfig(home, chainID))

//create Block Explorer Json-RPC toml config file
berpcconfig.EnsureRoot(home, berpcconfig.DefaultBeJsonRpcConfig())

return nil
},
}
Expand Down
81 changes: 77 additions & 4 deletions cmd/rollappd/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ package cmd
import (
"context"
"fmt"
berpc "github.com/bcdevtools/block-explorer-rpc-cosmos/be_rpc"
berpcbackend "github.com/bcdevtools/block-explorer-rpc-cosmos/be_rpc/backend"
berpccfg "github.com/bcdevtools/block-explorer-rpc-cosmos/be_rpc/config"
berpctypes "github.com/bcdevtools/block-explorer-rpc-cosmos/be_rpc/types"
"github.com/bcdevtools/evm-block-explorer-rpc-cosmos/integrate_be_rpc"
evmberpcbackend "github.com/bcdevtools/evm-block-explorer-rpc-cosmos/integrate_be_rpc/backend/evm"
raeberpcbackend "github.com/dymensionxyz/rollapp-evm/ra_evm_be_rpc/backend"
raebeapi "github.com/dymensionxyz/rollapp-evm/ra_evm_be_rpc/namespaces/rae"
"github.com/ethereum/go-ethereum/rpc"
rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client"
"net"
"net/http"
"os"
Expand Down Expand Up @@ -154,9 +164,15 @@ which accepts a path for the resulting pprof file.
return err
}

beJsonRpcConfig := berpccfg.DefaultBeJsonRpcConfig()
err = beJsonRpcConfig.GetViperConfig(cmd, serverCtx.Viper.GetString(flags.FlagHome))
if err != nil {
return err
}

// amino is needed here for backwards compatibility of REST routes
err = wrapCPUProfile(serverCtx, func() error {
return startInProcess(serverCtx, clientCtx, dymconfig, appCreator)
return startInProcess(serverCtx, clientCtx, dymconfig, beJsonRpcConfig, appCreator)
})
errCode, ok := err.(server.ErrorCode)
if !ok {
Expand Down Expand Up @@ -225,12 +241,14 @@ which accepts a path for the resulting pprof file.
cmd.Flags().String(srvflags.EVMTracer, config.DefaultEVMTracer, "the EVM tracer type to collect execution traces from the EVM transaction execution (json|struct|access_list|markdown)") //nolint:lll
cmd.Flags().Uint64(srvflags.EVMMaxTxGasWanted, config.DefaultMaxTxGasWanted, "the gas wanted for each eth tx returned in ante handler in check tx mode") //nolint:lll

berpccfg.AddBeJsonRpcFlags(cmd)

dymintconf.AddNodeFlags(cmd)
rdklogger.AddLogFlags(cmd)
return cmd
}

func startInProcess(ctx *server.Context, clientCtx client.Context, nodeConfig *dymintconf.NodeConfig, appCreator types.AppCreator) error {
func startInProcess(ctx *server.Context, clientCtx client.Context, nodeConfig *dymintconf.NodeConfig, beRpcCfg *berpccfg.BeJsonRpcConfig, appCreator types.AppCreator) error {
cfg := ctx.Config
home := cfg.RootDir

Expand All @@ -255,6 +273,10 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, nodeConfig *d
return err
}

if err := beRpcCfg.Validate(); err != nil {
return err
}

app := appCreator(ctx.Logger, db, traceWriter, ctx.Viper)

nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile())
Expand Down Expand Up @@ -316,7 +338,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, nodeConfig *d
// Add the tx service to the gRPC router. We only need to register this
// service if API or gRPC is enabled, and avoid doing so in the general
// case, because it spawns a new local tendermint RPC client.
if (config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable) && tmNode != nil {
if (config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable || beRpcCfg.Enable) && tmNode != nil {
clientCtx = clientCtx.WithClient(dymserver.Client())

app.RegisterTxService(clientCtx)
Expand Down Expand Up @@ -358,7 +380,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, nodeConfig *d
}
}

if config.API.Enable || config.JSONRPC.Enable {
if config.API.Enable || config.JSONRPC.Enable || beRpcCfg.Enable {
genDoc, err := genDocProvider()
if err != nil {
return err
Expand Down Expand Up @@ -487,6 +509,57 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, nodeConfig *d
}()
}

if beRpcCfg.Enable {
genDoc, err := genDocProvider()
if err != nil {
return err
}

raeBeRpcBackend := raeberpcbackend.NewRollAppEvmBackend(ctx, ctx.Logger, clientCtx)

serverCloseDeferFunc, err := integrate_be_rpc.StartEvmBeJsonRPC(
ctx,
clientCtx,
genDoc.ChainID,
*beRpcCfg,
idxer,
nil, // external services modifier
func(evmberpcbackend.EvmBackendI) {
berpc.RegisterAPINamespace(raebeapi.DymRollAppEvmBlockExplorerNamespace, func(ctx *server.Context,
_ client.Context,
_ *rpcclient.WSClient,
_ map[string]berpctypes.MessageParser,
_ map[string]berpctypes.MessageInvolversExtractor,
_ func(berpcbackend.BackendI) berpcbackend.RequestInterceptor,
_ berpctypes.ExternalServices,
) []rpc.API {
return []rpc.API{
{
Namespace: raebeapi.DymRollAppEvmBlockExplorerNamespace,
Version: raebeapi.ApiVersion,
Service: raebeapi.NewRollAppEvmApi(ctx, raeBeRpcBackend),
Public: true,
},
}
}, false)
},
func(backend berpcbackend.BackendI, evmBeRpcBackend evmberpcbackend.EvmBackendI) berpcbackend.RequestInterceptor {
return raeberpcbackend.NewRollAppEvmRequestInterceptor(
backend,
raeBeRpcBackend,
evmberpcbackend.NewDefaultRequestInterceptor(backend, evmBeRpcBackend),
)
},
cfg.RPC.ListenAddress,
"/websocket",
)
if err != nil {
return err
}

defer serverCloseDeferFunc()
}

var rosettaSrv crgserver.Server
if config.Rosetta.Enable {
offlineMode := config.Rosetta.Offline
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ go 1.22.1

require (
cosmossdk.io/errors v1.0.1
github.com/bcdevtools/block-explorer-rpc-cosmos v1.0.1
github.com/bcdevtools/evm-block-explorer-rpc-cosmos v1.0.1
github.com/cosmos/cosmos-sdk v0.46.15
github.com/cosmos/ibc-go/v6 v6.2.1
github.com/dymensionxyz/dymension-rdk v1.2.0-beta
github.com/dymensionxyz/dymint v1.0.1-alpha
github.com/ethereum/go-ethereum v1.12.0
github.com/evmos/evmos/v12 v12.1.6
github.com/gorilla/mux v1.8.1
github.com/pkg/errors v0.9.1
github.com/rakyll/statik v0.1.7
github.com/spf13/cast v1.5.1
github.com/spf13/cobra v1.8.0
Expand Down Expand Up @@ -228,7 +231,6 @@ require (
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
github.com/pierrec/xxHash v0.1.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_golang v1.18.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0=
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM=
github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
github.com/bcdevtools/block-explorer-rpc-cosmos v1.0.1 h1:/mkYfjhJSQr71mJUFbOoyRvykSUj6TgwB9m9sKtqtOI=
github.com/bcdevtools/block-explorer-rpc-cosmos v1.0.1/go.mod h1:AWXHI5ICXK4wB+A59dNddzq5Xdc1wtQDRiIXfMw8cwc=
github.com/bcdevtools/evm-block-explorer-rpc-cosmos v1.0.1 h1:O0sWD/Hky5wUWsWMhmkifDUj2Qhjyu3pZH1/C7n0Kqg=
github.com/bcdevtools/evm-block-explorer-rpc-cosmos v1.0.1/go.mod h1:IN6s8jCudUJh8E8Mm3iNqITL05Wcj4+PJvfRUUQnipI=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
Expand Down
50 changes: 50 additions & 0 deletions ra_evm_be_rpc/backend/backend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package backend

import (
"context"
"github.com/bcdevtools/block-explorer-rpc-cosmos/be_rpc/config"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server"
hubgentypes "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types"
sequencerstypes "github.com/dymensionxyz/dymension-rdk/x/sequencers/types"
raeberpctypes "github.com/dymensionxyz/rollapp-evm/ra_evm_be_rpc/types"
"github.com/tendermint/tendermint/libs/log"
)

type RollAppEvmBackendI interface {
// Misc

GetSequencersModuleParams() (*sequencerstypes.Params, error)
GetHubGenesisModuleParams() (*hubgentypes.Params, error)
}

var _ RollAppEvmBackendI = (*RollAppEvmBackend)(nil)

// RollAppEvmBackend implements the RollAppEvmBackendI interface
type RollAppEvmBackend struct {
ctx context.Context
clientCtx client.Context
queryClient *raeberpctypes.QueryClient // gRPC query client
logger log.Logger
cfg config.BeJsonRpcConfig
}

// NewRollAppEvmBackend creates a new RollAppEvmBackend instance for RollApp EVM Block Explorer
func NewRollAppEvmBackend(
ctx *server.Context,
logger log.Logger,
clientCtx client.Context,
) *RollAppEvmBackend {
appConf, err := config.GetConfig(ctx.Viper)
if err != nil {
panic(err)
}

return &RollAppEvmBackend{
ctx: context.Background(),
clientCtx: clientCtx,
queryClient: raeberpctypes.NewQueryClient(clientCtx),
logger: logger.With("module", "rae_be_rpc"),
cfg: appConf,
}
}
13 changes: 13 additions & 0 deletions ra_evm_be_rpc/backend/hub_genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package backend

import (
hubgentypes "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types"
)

func (m *RollAppEvmBackend) GetHubGenesisModuleParams() (*hubgentypes.Params, error) {
res, err := m.queryClient.HubGenesisQueryClient.Params(m.ctx, &hubgentypes.QueryParamsRequest{})
if err != nil {
return nil, err
}
return &res.Params, nil
}
82 changes: 82 additions & 0 deletions ra_evm_be_rpc/backend/rollapp_evm_interceptor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package backend

import (
berpcbackend "github.com/bcdevtools/block-explorer-rpc-cosmos/be_rpc/backend"
berpctypes "github.com/bcdevtools/block-explorer-rpc-cosmos/be_rpc/types"
"github.com/pkg/errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

var _ berpcbackend.RequestInterceptor = (*RollAppEvmRequestInterceptor)(nil)

type RollAppEvmRequestInterceptor struct {
beRpcBackend berpcbackend.BackendI
backend RollAppEvmBackendI
defaultInterceptor berpcbackend.RequestInterceptor
}

func NewRollAppEvmRequestInterceptor(
beRpcBackend berpcbackend.BackendI,
backend RollAppEvmBackendI,
defaultInterceptor berpcbackend.RequestInterceptor,
) *RollAppEvmRequestInterceptor {
return &RollAppEvmRequestInterceptor{
beRpcBackend: beRpcBackend,
backend: backend,
defaultInterceptor: defaultInterceptor,
}
}

func (m *RollAppEvmRequestInterceptor) GetTransactionByHash(hashStr string) (intercepted bool, response berpctypes.GenericBackendResponse, err error) {
// handled completely by the default interceptor
return m.defaultInterceptor.GetTransactionByHash(hashStr)
}

func (m *RollAppEvmRequestInterceptor) GetDenomsInformation() (intercepted, append bool, denoms map[string]string, err error) {
// handled completely by the default interceptor
return m.defaultInterceptor.GetDenomsInformation()
}

func (m *RollAppEvmRequestInterceptor) GetModuleParams(moduleName string) (intercepted bool, res berpctypes.GenericBackendResponse, err error) {
var params any

switch moduleName {
case "sequencers":
sequencersParams, errFetch := m.backend.GetSequencersModuleParams()
if errFetch != nil {
err = errors.Wrap(errFetch, "failed to get sequencers params")
} else {
params = *sequencersParams
}
break
case "hub-genesis":
hubGenesisParams, errFetch := m.backend.GetHubGenesisModuleParams()
if errFetch != nil {
err = errors.Wrap(errFetch, "failed to get hub genesis params")
} else {
params = *hubGenesisParams
}
break
default:
return m.defaultInterceptor.GetModuleParams(moduleName)
}

if err != nil {
return
}

res, err = berpctypes.NewGenericBackendResponseFrom(params)
if err != nil {
err = status.Error(codes.Internal, errors.Wrap(err, "module params").Error())
return
}

intercepted = true
return
}

func (m *RollAppEvmRequestInterceptor) GetAccount(accountAddressStr string) (intercepted, append bool, response berpctypes.GenericBackendResponse, err error) {
// handled completely by the default interceptor
return m.defaultInterceptor.GetAccount(accountAddressStr)
}
13 changes: 13 additions & 0 deletions ra_evm_be_rpc/backend/sequencers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package backend

import (
sequencerstypes "github.com/dymensionxyz/dymension-rdk/x/sequencers/types"
)

func (m *RollAppEvmBackend) GetSequencersModuleParams() (*sequencerstypes.Params, error) {
res, err := m.queryClient.SequencersQueryClient.Params(m.ctx, &sequencerstypes.QueryParamsRequest{})
if err != nil {
return nil, err
}
return &res.Params, nil
}
40 changes: 40 additions & 0 deletions ra_evm_be_rpc/namespaces/rae/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package rae

import (
"fmt"
"github.com/cosmos/cosmos-sdk/server"
raeberpcbackend "github.com/dymensionxyz/rollapp-evm/ra_evm_be_rpc/backend"
"github.com/tendermint/tendermint/libs/log"
)

// RPC namespaces and API version
const (
DymRollAppEvmBlockExplorerNamespace = "rae"

ApiVersion = "1.0"
)

// API is the RollApp EVM Block Explorer JSON-RPC.
// Developers can create custom API for the chain.
type API struct {
ctx *server.Context
logger log.Logger
backend raeberpcbackend.RollAppEvmBackendI
}

// NewRollAppEvmApi creates an instance of the RollApp EVM Block Explorer API.
func NewRollAppEvmApi(
ctx *server.Context,
backend raeberpcbackend.RollAppEvmBackendI,
) *API {
return &API{
ctx: ctx,
logger: ctx.Logger.With("api", "rae"),
backend: backend,
}
}

func (api *API) Echo(text string) string {
api.logger.Debug("rae_echo")
return fmt.Sprintf("hello \"%s\" from RollApp EVM Block Explorer API", text)
}
Loading

0 comments on commit d73b1c4

Please sign in to comment.