update fork

This commit is contained in:
0xmuralik
2022-10-10 16:08:33 +05:30
parent 632d53e34a
commit 56d59feaa0
383 changed files with 36784 additions and 21462 deletions
+45 -28
View File
@@ -28,7 +28,7 @@ const (
// DefaultEVMTracer is the default vm.Tracer type
DefaultEVMTracer = ""
DefaultMaxTxGasWanted = 500000
DefaultMaxTxGasWanted = 0
DefaultGasCap uint64 = 25000000
@@ -47,6 +47,10 @@ const (
DefaultHTTPTimeout = 30 * time.Second
DefaultHTTPIdleTimeout = 120 * time.Second
// DefaultAllowUnprotectedTxs value is false
DefaultAllowUnprotectedTxs = false
// DefaultMaxOpenConnections represents the amount of open connections (unlimited = 0)
DefaultMaxOpenConnections = 0
)
var evmTracers = []string{"json", "markdown", "struct", "access_list"}
@@ -98,6 +102,14 @@ type JSONRPCConfig struct {
HTTPTimeout time.Duration `mapstructure:"http-timeout"`
// HTTPIdleTimeout is the idle timeout of http json-rpc server.
HTTPIdleTimeout time.Duration `mapstructure:"http-idle-timeout"`
// AllowUnprotectedTxs restricts unprotected (non EIP155 signed) transactions to be submitted via
// the node's RPC when global parameter is disabled.
AllowUnprotectedTxs bool `mapstructure:"allow-unprotected-txs"`
// MaxOpenConnections sets the maximum number of simultaneous connections
// for the server listener.
MaxOpenConnections int `mapstructure:"max-open-connections"`
// EnableIndexer defines if enable the custom indexer service.
EnableIndexer bool `mapstructure:"enable-indexer"`
}
// TLSConfig defines the certificate and matching private key for the server.
@@ -183,19 +195,22 @@ func GetAPINamespaces() []string {
// DefaultJSONRPCConfig returns an EVM config with the JSON-RPC API enabled by default
func DefaultJSONRPCConfig() *JSONRPCConfig {
return &JSONRPCConfig{
Enable: true,
API: GetDefaultAPINamespaces(),
Address: DefaultJSONRPCAddress,
WsAddress: DefaultJSONRPCWsAddress,
GasCap: DefaultGasCap,
EVMTimeout: DefaultEVMTimeout,
TxFeeCap: DefaultTxFeeCap,
FilterCap: DefaultFilterCap,
FeeHistoryCap: DefaultFeeHistoryCap,
BlockRangeCap: DefaultBlockRangeCap,
LogsCap: DefaultLogsCap,
HTTPTimeout: DefaultHTTPTimeout,
HTTPIdleTimeout: DefaultHTTPIdleTimeout,
Enable: true,
API: GetDefaultAPINamespaces(),
Address: DefaultJSONRPCAddress,
WsAddress: DefaultJSONRPCWsAddress,
GasCap: DefaultGasCap,
EVMTimeout: DefaultEVMTimeout,
TxFeeCap: DefaultTxFeeCap,
FilterCap: DefaultFilterCap,
FeeHistoryCap: DefaultFeeHistoryCap,
BlockRangeCap: DefaultBlockRangeCap,
LogsCap: DefaultLogsCap,
HTTPTimeout: DefaultHTTPTimeout,
HTTPIdleTimeout: DefaultHTTPIdleTimeout,
AllowUnprotectedTxs: DefaultAllowUnprotectedTxs,
MaxOpenConnections: DefaultMaxOpenConnections,
EnableIndexer: false,
}
}
@@ -237,7 +252,7 @@ func (c JSONRPCConfig) Validate() error {
return errors.New("JSON-RPC HTTP idle timeout duration cannot be negative")
}
// TODO: validate APIs
// check for duplicates
seenAPIs := make(map[string]bool)
for _, api := range c.API {
if seenAPIs[api] {
@@ -289,19 +304,21 @@ func GetConfig(v *viper.Viper) (Config, error) {
MaxTxGasWanted: v.GetUint64("evm.max-tx-gas-wanted"),
},
JSONRPC: JSONRPCConfig{
Enable: v.GetBool("json-rpc.enable"),
API: v.GetStringSlice("json-rpc.api"),
Address: v.GetString("json-rpc.address"),
WsAddress: v.GetString("json-rpc.ws-address"),
GasCap: v.GetUint64("json-rpc.gas-cap"),
FilterCap: v.GetInt32("json-rpc.filter-cap"),
FeeHistoryCap: v.GetInt32("json-rpc.feehistory-cap"),
TxFeeCap: v.GetFloat64("json-rpc.txfee-cap"),
EVMTimeout: v.GetDuration("json-rpc.evm-timeout"),
LogsCap: v.GetInt32("json-rpc.logs-cap"),
BlockRangeCap: v.GetInt32("json-rpc.block-range-cap"),
HTTPTimeout: v.GetDuration("json-rpc.http-timeout"),
HTTPIdleTimeout: v.GetDuration("json-rpc.http-idle-timeout"),
Enable: v.GetBool("json-rpc.enable"),
API: v.GetStringSlice("json-rpc.api"),
Address: v.GetString("json-rpc.address"),
WsAddress: v.GetString("json-rpc.ws-address"),
GasCap: v.GetUint64("json-rpc.gas-cap"),
FilterCap: v.GetInt32("json-rpc.filter-cap"),
FeeHistoryCap: v.GetInt32("json-rpc.feehistory-cap"),
TxFeeCap: v.GetFloat64("json-rpc.txfee-cap"),
EVMTimeout: v.GetDuration("json-rpc.evm-timeout"),
LogsCap: v.GetInt32("json-rpc.logs-cap"),
BlockRangeCap: v.GetInt32("json-rpc.block-range-cap"),
HTTPTimeout: v.GetDuration("json-rpc.http-timeout"),
HTTPIdleTimeout: v.GetDuration("json-rpc.http-idle-timeout"),
MaxOpenConnections: v.GetInt("json-rpc.max-open-connections"),
EnableIndexer: v.GetBool("json-rpc.enable-indexer"),
},
TLS: TLSConfig{
CertificatePath: v.GetString("tls.certificate-path"),
+11
View File
@@ -62,6 +62,17 @@ http-timeout = "{{ .JSONRPC.HTTPTimeout }}"
# HTTPIdleTimeout is the idle timeout of http json-rpc server.
http-idle-timeout = "{{ .JSONRPC.HTTPIdleTimeout }}"
# AllowUnprotectedTxs restricts unprotected (non EIP155 signed) transactions to be submitted via
# the node's RPC when the global parameter is disabled.
allow-unprotected-txs = {{ .JSONRPC.AllowUnprotectedTxs }}
# MaxOpenConnections sets the maximum number of simultaneous connections
# for the server listener.
max-open-connections = {{ .JSONRPC.MaxOpenConnections }}
# EnableIndexer enables the custom transaction indexer for the EVM (ethereum transactions).
enable-indexer = {{ .JSONRPC.EnableIndexer }}
###############################################################################
### TLS Configuration ###
###############################################################################
+20 -30
View File
@@ -5,16 +5,17 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/spf13/cobra"
"github.com/spf13/viper"
tmcli "github.com/tendermint/tendermint/libs/cli"
)
// Tendermint full-node start flags
// Tendermint/cosmos-sdk full-node start flags
const (
WithTendermint = "with-tendermint"
Address = "address"
Transport = "transport"
TraceStore = "trace-store"
CPUProfile = "cpu-profile"
// The type of database for application and snapshots databases
AppDBBackend = "app-db-backend"
)
// GRPC-related flags.
@@ -33,18 +34,21 @@ const (
// JSON-RPC flags
const (
JSONRPCEnable = "json-rpc.enable"
JSONRPCAPI = "json-rpc.api"
JSONRPCAddress = "json-rpc.address"
JSONWsAddress = "json-rpc.ws-address"
JSONRPCGasCap = "json-rpc.gas-cap"
JSONRPCEVMTimeout = "json-rpc.evm-timeout"
JSONRPCTxFeeCap = "json-rpc.txfee-cap"
JSONRPCFilterCap = "json-rpc.filter-cap"
JSONRPCLogsCap = "json-rpc.logs-cap"
JSONRPCBlockRangeCap = "json-rpc.block-range-cap"
JSONRPCHTTPTimeout = "json-rpc.http-timeout"
JSONRPCHTTPIdleTimeout = "json-rpc.http-idle-timeout"
JSONRPCEnable = "json-rpc.enable"
JSONRPCAPI = "json-rpc.api"
JSONRPCAddress = "json-rpc.address"
JSONWsAddress = "json-rpc.ws-address"
JSONRPCGasCap = "json-rpc.gas-cap"
JSONRPCEVMTimeout = "json-rpc.evm-timeout"
JSONRPCTxFeeCap = "json-rpc.txfee-cap"
JSONRPCFilterCap = "json-rpc.filter-cap"
JSONRPCLogsCap = "json-rpc.logs-cap"
JSONRPCBlockRangeCap = "json-rpc.block-range-cap"
JSONRPCHTTPTimeout = "json-rpc.http-timeout"
JSONRPCHTTPIdleTimeout = "json-rpc.http-idle-timeout"
JSONRPCAllowUnprotectedTxs = "json-rpc.allow-unprotected-txs"
JSONRPCMaxOpenConnections = "json-rpc.max-open-connections"
JSONRPCEnableIndexer = "json-rpc.enable-indexer"
)
// EVM flags
@@ -65,12 +69,10 @@ func AddTxFlags(cmd *cobra.Command) (*cobra.Command, error) {
cmd.PersistentFlags().String(flags.FlagFrom, "", "Name or address of private key with which to sign")
cmd.PersistentFlags().String(flags.FlagFees, "", "Fees to pay along with transaction; eg: 10aphoton")
cmd.PersistentFlags().String(flags.FlagGasPrices, "", "Gas prices to determine the transaction fee (e.g. 10aphoton)")
cmd.PersistentFlags().String(flags.FlagNode, "tcp://localhost:26657", "<host>:<port> to tendermint rpc interface for this chain")
cmd.PersistentFlags().Float64(flags.FlagGasAdjustment, flags.DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ")
cmd.PersistentFlags().String(flags.FlagNode, "tcp://localhost:26657", "<host>:<port> to tendermint rpc interface for this chain") //nolint:lll
cmd.PersistentFlags().Float64(flags.FlagGasAdjustment, flags.DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ") //nolint:lll
cmd.PersistentFlags().StringP(flags.FlagBroadcastMode, "b", flags.BroadcastSync, "Transaction broadcasting mode (sync|async|block)")
cmd.PersistentFlags().String(flags.FlagKeyringBackend, keyring.BackendOS, "Select keyring's backend")
cmd.PersistentFlags().BoolP(flags.FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation")
cmd.Flags().StringP(tmcli.OutputFlag, "o", "text", "Output format (text|json)")
// --gas can accept integers and "simulate"
// cmd.PersistentFlags().Var(&flags.GasFlagVar, "gas", fmt.Sprintf(
@@ -87,15 +89,3 @@ func AddTxFlags(cmd *cobra.Command) (*cobra.Command, error) {
}
return cmd, nil
}
// AddGQLFlags adds gql flags for
func AddGQLFlags(cmd *cobra.Command) *cobra.Command {
// Add flags for GQL server.
cmd.PersistentFlags().Bool("gql-server", false, "Start GQL server.")
cmd.PersistentFlags().Bool("gql-playground", false, "Enable GQL playground.")
cmd.PersistentFlags().String("gql-playground-api-base", "", "GQL API base path to use in GQL playground.")
cmd.PersistentFlags().String("gql-port", "9473", "Port to use for the GQL server.")
cmd.PersistentFlags().String("log-file", "", "File to tail for GQL 'getLogs' API.")
return cmd
}
+118
View File
@@ -0,0 +1,118 @@
package server
import (
"fmt"
"github.com/spf13/cobra"
"github.com/cerc-io/laconicd/indexer"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server"
tmnode "github.com/tendermint/tendermint/node"
sm "github.com/tendermint/tendermint/state"
tmstore "github.com/tendermint/tendermint/store"
)
func NewIndexTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "index-eth-tx [backward|forward]",
Short: "Index historical eth txs",
Long: `Index historical eth txs, it only support two traverse direction to avoid creating gaps in the indexer db if using arbitrary block ranges:
- backward: index the blocks from the first indexed block to the earliest block in the chain, if indexer db is empty, start from the latest block.
- forward: index the blocks from the latest indexed block to latest block in the chain.
When start the node, the indexer start from the latest indexed block to avoid creating gap.
Backward mode should be used most of the time, so the latest indexed block is always up-to-date.
`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
serverCtx := server.GetServerContextFromCmd(cmd)
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
direction := args[0]
if direction != "backward" && direction != "forward" {
return fmt.Errorf("unknown index direction, expect: backward|forward, got: %s", direction)
}
cfg := serverCtx.Config
home := cfg.RootDir
logger := serverCtx.Logger
idxDB, err := OpenIndexerDB(home, server.GetAppDBBackend(serverCtx.Viper))
if err != nil {
logger.Error("failed to open evm indexer DB", "error", err.Error())
return err
}
idxer := indexer.NewKVIndexer(idxDB, logger.With("module", "evmindex"), clientCtx)
// open local tendermint db, because the local rpc won't be available.
tmdb, err := tmnode.DefaultDBProvider(&tmnode.DBContext{ID: "blockstore", Config: cfg})
if err != nil {
return err
}
blockStore := tmstore.NewBlockStore(tmdb)
stateDB, err := tmnode.DefaultDBProvider(&tmnode.DBContext{ID: "state", Config: cfg})
if err != nil {
return err
}
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: cfg.Storage.DiscardABCIResponses,
})
indexBlock := func(height int64) error {
blk := blockStore.LoadBlock(height)
if blk == nil {
return fmt.Errorf("block not found %d", height)
}
resBlk, err := stateStore.LoadABCIResponses(height)
if err != nil {
return err
}
if err := idxer.IndexBlock(blk, resBlk.DeliverTxs); err != nil {
return err
}
fmt.Println(height)
return nil
}
switch args[0] {
case "backward":
first, err := idxer.FirstIndexedBlock()
if err != nil {
return err
}
if first == -1 {
// start from the latest block if indexer db is empty
first = blockStore.Height()
}
for i := first - 1; i > 0; i-- {
if err := indexBlock(i); err != nil {
return err
}
}
case "forward":
latest, err := idxer.LastIndexedBlock()
if err != nil {
return err
}
if latest == -1 {
// start from genesis if empty
latest = 0
}
for i := latest + 1; i <= blockStore.Height(); i++ {
if err := indexBlock(i); err != nil {
return err
}
}
default:
return fmt.Errorf("unknown direction %s", args[0])
}
return nil
},
}
return cmd
}
+109
View File
@@ -0,0 +1,109 @@
package server
import (
"context"
"time"
"github.com/tendermint/tendermint/libs/service"
rpcclient "github.com/tendermint/tendermint/rpc/client"
"github.com/tendermint/tendermint/types"
ethermint "github.com/cerc-io/laconicd/types"
)
const (
ServiceName = "EVMIndexerService"
NewBlockWaitTimeout = 60 * time.Second
)
// EVMIndexerService indexes transactions for json-rpc service.
type EVMIndexerService struct {
service.BaseService
txIdxr ethermint.EVMTxIndexer
client rpcclient.Client
}
// NewEVMIndexerService returns a new service instance.
func NewEVMIndexerService(
txIdxr ethermint.EVMTxIndexer,
client rpcclient.Client,
) *EVMIndexerService {
is := &EVMIndexerService{txIdxr: txIdxr, client: client}
is.BaseService = *service.NewBaseService(nil, ServiceName, is)
return is
}
// OnStart implements service.Service by subscribing for new blocks
// and indexing them by events.
func (eis *EVMIndexerService) OnStart() error {
ctx := context.Background()
status, err := eis.client.Status(ctx)
if err != nil {
return err
}
latestBlock := status.SyncInfo.LatestBlockHeight
newBlockSignal := make(chan struct{}, 1)
// Use SubscribeUnbuffered here to ensure both subscriptions does not get
// canceled due to not pulling messages fast enough. Cause this might
// sometimes happen when there are no other subscribers.
blockHeadersChan, err := eis.client.Subscribe(
ctx,
ServiceName,
types.QueryForEvent(types.EventNewBlockHeader).String(),
0)
if err != nil {
return err
}
go func() {
for {
msg := <-blockHeadersChan
eventDataHeader := msg.Data.(types.EventDataNewBlockHeader)
if eventDataHeader.Header.Height > latestBlock {
latestBlock = eventDataHeader.Header.Height
// notify
select {
case newBlockSignal <- struct{}{}:
default:
}
}
}
}()
lastBlock, err := eis.txIdxr.LastIndexedBlock()
if err != nil {
return err
}
if lastBlock == -1 {
lastBlock = latestBlock
}
for {
if latestBlock <= lastBlock {
// nothing to index. wait for signal of new block
select {
case <-newBlockSignal:
case <-time.After(NewBlockWaitTimeout):
}
continue
}
for i := lastBlock + 1; i <= latestBlock; i++ {
block, err := eis.client.Block(ctx, &i)
if err != nil {
eis.Logger.Error("failed to fetch block", "height", i, "err", err)
break
}
blockResult, err := eis.client.BlockResults(ctx, &i)
if err != nil {
eis.Logger.Error("failed to fetch block result", "height", i, "err", err)
break
}
if err := eis.txIdxr.IndexBlock(block.Block, blockResult.TxsResults); err != nil {
eis.Logger.Error("failed to index block", "height", i, "err", err)
}
lastBlock = blockResult.Height
}
}
}
+23 -8
View File
@@ -15,10 +15,17 @@ import (
ethrpc "github.com/ethereum/go-ethereum/rpc"
"github.com/cerc-io/laconicd/server/config"
ethermint "github.com/cerc-io/laconicd/types"
)
// StartJSONRPC starts the JSON-RPC server
func StartJSONRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr, tmEndpoint string, config config.Config) (*http.Server, chan struct{}, error) {
func StartJSONRPC(ctx *server.Context,
clientCtx client.Context,
tmRPCAddr,
tmEndpoint string,
config *config.Config,
indexer ethermint.EVMTxIndexer,
) (*http.Server, chan struct{}, error) {
tmWsClient := ConnectTmWS(tmRPCAddr, tmEndpoint, ctx.Logger)
logger := ctx.Logger.With("module", "geth")
@@ -36,8 +43,10 @@ func StartJSONRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr, tmEn
rpcServer := ethrpc.NewServer()
allowUnprotectedTxs := config.JSONRPC.AllowUnprotectedTxs
rpcAPIArr := config.JSONRPC.API
apis := rpc.GetRPCAPIs(ctx, clientCtx, tmWsClient, rpcAPIArr)
apis := rpc.GetRPCAPIs(ctx, clientCtx, tmWsClient, allowUnprotectedTxs, indexer, rpcAPIArr)
for _, api := range apis {
if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil {
@@ -59,18 +68,24 @@ func StartJSONRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr, tmEn
}
httpSrv := &http.Server{
Addr: config.JSONRPC.Address,
Handler: handlerWithCors.Handler(r),
ReadTimeout: config.JSONRPC.HTTPTimeout,
WriteTimeout: config.JSONRPC.HTTPTimeout,
IdleTimeout: config.JSONRPC.HTTPIdleTimeout,
Addr: config.JSONRPC.Address,
Handler: handlerWithCors.Handler(r),
ReadHeaderTimeout: config.JSONRPC.HTTPTimeout,
ReadTimeout: config.JSONRPC.HTTPTimeout,
WriteTimeout: config.JSONRPC.HTTPTimeout,
IdleTimeout: config.JSONRPC.HTTPIdleTimeout,
}
httpSrvDone := make(chan struct{}, 1)
ln, err := Listen(httpSrv.Addr, config)
if err != nil {
return nil, nil, err
}
errCh := make(chan error)
go func() {
ctx.Logger.Info("Starting JSON-RPC server", "address", config.JSONRPC.Address)
if err := httpSrv.ListenAndServe(); err != nil {
if err := httpSrv.Serve(ln); err != nil {
if err == http.ErrServerClosed {
close(httpSrvDone)
return
+113 -50
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"net"
"net/http"
"os"
"path/filepath"
@@ -17,43 +18,36 @@ import (
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/tendermint/tendermint/p2p"
pvm "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/api"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
"github.com/cosmos/cosmos-sdk/server/rosetta"
crgserver "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server"
"github.com/cosmos/cosmos-sdk/server/types"
abciserver "github.com/tendermint/tendermint/abci/server"
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
tmos "github.com/tendermint/tendermint/libs/os"
"github.com/tendermint/tendermint/node"
"github.com/tendermint/tendermint/p2p"
pvm "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
"github.com/tendermint/tendermint/rpc/client/local"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cerc-io/laconicd/gql"
ethdebug "github.com/cerc-io/laconicd/rpc/ethereum/namespaces/debug"
"github.com/cosmos/cosmos-sdk/server/rosetta"
crgserver "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/api"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
"github.com/cosmos/cosmos-sdk/server/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cerc-io/laconicd/indexer"
ethdebug "github.com/cerc-io/laconicd/rpc/namespaces/ethereum/debug"
"github.com/cerc-io/laconicd/server/config"
srvflags "github.com/cerc-io/laconicd/server/flags"
pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types"
)
const (
// gRPC-related flags
flagGRPCOnly = "grpc-only"
flagGRPCEnable = "grpc.enable"
flagGRPCAddress = "grpc.address"
flagGRPCWebEnable = "grpc-web.enable"
flagGRPCWebAddress = "grpc-web.address"
ethermint "github.com/cerc-io/laconicd/types"
)
// StartCmd runs the service passed in, either stand-alone or in-process with
@@ -140,7 +134,7 @@ which accepts a path for the resulting pprof file.
cmd.Flags().String(srvflags.Address, "tcp://0.0.0.0:26658", "Listen address")
cmd.Flags().String(srvflags.Transport, "socket", "Transport protocol: socket, grpc")
cmd.Flags().String(srvflags.TraceStore, "", "Enable KVStore tracing to an output file")
cmd.Flags().String(server.FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photon;0.0001stake)")
cmd.Flags().String(server.FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photon;0.0001stake)") //nolint:lll
cmd.Flags().IntSlice(server.FlagUnsafeSkipUpgrades, []int{}, "Skip a set of upgrade heights to continue the old binary")
cmd.Flags().Uint64(server.FlagHaltHeight, 0, "Block height at which to gracefully halt the chain and shutdown the node")
cmd.Flags().Uint64(server.FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node")
@@ -149,9 +143,10 @@ which accepts a path for the resulting pprof file.
cmd.Flags().Bool(server.FlagTrace, false, "Provide full stack traces for errors in ABCI Log")
cmd.Flags().String(server.FlagPruning, pruningtypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
cmd.Flags().Uint64(server.FlagPruningKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')")
cmd.Flags().Uint64(server.FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')")
cmd.Flags().Uint64(server.FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')") //nolint:lll
cmd.Flags().Uint(server.FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks")
cmd.Flags().Uint64(server.FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks")
cmd.Flags().String(srvflags.AppDBBackend, "", "The type of database for application and snapshots databases")
cmd.Flags().Bool(srvflags.GRPCEnable, true, "Define if the gRPC server should be enabled")
cmd.Flags().String(srvflags.GRPCAddress, serverconfig.DefaultGRPCAddress, "the gRPC server address to listen on")
@@ -165,17 +160,20 @@ which accepts a path for the resulting pprof file.
cmd.Flags().StringSlice(srvflags.JSONRPCAPI, config.GetDefaultAPINamespaces(), "Defines a list of JSON-RPC namespaces that should be enabled")
cmd.Flags().String(srvflags.JSONRPCAddress, config.DefaultJSONRPCAddress, "the JSON-RPC server address to listen on")
cmd.Flags().String(srvflags.JSONWsAddress, config.DefaultJSONRPCWsAddress, "the JSON-RPC WS server address to listen on")
cmd.Flags().Uint64(srvflags.JSONRPCGasCap, config.DefaultGasCap, "Sets a cap on gas that can be used in eth_call/estimateGas unit is aphoton (0=infinite)")
cmd.Flags().Float64(srvflags.JSONRPCTxFeeCap, config.DefaultTxFeeCap, "Sets a cap on transaction fee that can be sent via the RPC APIs (1 = default 1 photon)")
cmd.Flags().Uint64(srvflags.JSONRPCGasCap, config.DefaultGasCap, "Sets a cap on gas that can be used in eth_call/estimateGas unit is aphoton (0=infinite)") //nolint:lll
cmd.Flags().Float64(srvflags.JSONRPCTxFeeCap, config.DefaultTxFeeCap, "Sets a cap on transaction fee that can be sent via the RPC APIs (1 = default 1 photon)") //nolint:lll
cmd.Flags().Int32(srvflags.JSONRPCFilterCap, config.DefaultFilterCap, "Sets the global cap for total number of filters that can be created")
cmd.Flags().Duration(srvflags.JSONRPCEVMTimeout, config.DefaultEVMTimeout, "Sets a timeout used for eth_call (0=infinite)")
cmd.Flags().Duration(srvflags.JSONRPCHTTPTimeout, config.DefaultHTTPTimeout, "Sets a read/write timeout for json-rpc http server (0=infinite)")
cmd.Flags().Duration(srvflags.JSONRPCHTTPIdleTimeout, config.DefaultHTTPIdleTimeout, "Sets a idle timeout for json-rpc http server (0=infinite)")
cmd.Flags().Bool(srvflags.JSONRPCAllowUnprotectedTxs, config.DefaultAllowUnprotectedTxs, "Allow for unprotected (non EIP155 signed) transactions to be submitted via the node's RPC when the global parameter is disabled") //nolint:lll
cmd.Flags().Int32(srvflags.JSONRPCLogsCap, config.DefaultLogsCap, "Sets the max number of results can be returned from single `eth_getLogs` query")
cmd.Flags().Int32(srvflags.JSONRPCBlockRangeCap, config.DefaultBlockRangeCap, "Sets the max block range allowed for `eth_getLogs` query")
cmd.Flags().Int(srvflags.JSONRPCMaxOpenConnections, config.DefaultMaxOpenConnections, "Sets the maximum number of simultaneous connections for the server listener") //nolint:lll
cmd.Flags().Bool(srvflags.JSONRPCEnableIndexer, false, "Enable the custom tx indexer for json-rpc")
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)")
cmd.Flags().Uint64(srvflags.EVMMaxTxGasWanted, config.DefaultMaxTxGasWanted, "the gas wanted for each eth tx returned in ante handler in check tx mode")
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
cmd.Flags().String(srvflags.TLSCertPath, "", "the cert.pem file path for the server TLS configuration")
cmd.Flags().String(srvflags.TLSKeyPath, "", "the key.pem file path for the server TLS configuration")
@@ -193,11 +191,10 @@ func startStandAlone(ctx *server.Context, appCreator types.AppCreator) error {
transport := ctx.Viper.GetString(srvflags.Transport)
home := ctx.Viper.GetString(flags.FlagHome)
db, err := openDB(home, server.GetAppDBBackend((ctx.Viper)))
db, err := openDB(home, server.GetAppDBBackend(ctx.Viper))
if err != nil {
return err
}
defer func() {
if err := db.Close(); err != nil {
ctx.Logger.With("error", err).Error("error closing db")
@@ -271,6 +268,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
traceWriterFile := ctx.Viper.GetString(srvflags.TraceStore)
db, err := openDB(home, server.GetAppDBBackend(ctx.Viper))
if err != nil {
logger.Error("failed to open DB", "error", err.Error())
return err
}
defer func() {
@@ -311,8 +309,6 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
return err
}
ctx.Logger.Info("starting node with ABCI Tendermint in-process")
genDocProvider := node.DefaultGenesisDocProviderFunc(cfg)
tmNode, err := node.NewNode(
cfg,
@@ -324,7 +320,6 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
node.DefaultMetricsProvider(cfg.Instrumentation),
ctx.Logger.With("server", "node"),
)
if err != nil {
logger.Error("failed init node", "error", err.Error())
return err
@@ -338,25 +333,90 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
// Add the tx service to the gRPC router. We only need to register this
// service if API or gRPC or JSONRPC 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 {
if config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable || config.JSONRPC.EnableIndexer {
clientCtx = clientCtx.WithClient(local.New(tmNode))
app.RegisterTxService(clientCtx)
app.RegisterTendermintService(clientCtx)
}
var apiSrv *api.Server
if config.API.Enable {
genDoc, err := tmtypes.GenesisDocFromFile(cfg.GenesisFile())
var idxer ethermint.EVMTxIndexer
if config.JSONRPC.EnableIndexer {
idxDB, err := OpenIndexerDB(home, server.GetAppDBBackend(ctx.Viper))
if err != nil {
logger.Error("failed to open evm indexer DB", "error", err.Error())
return err
}
idxLogger := ctx.Logger.With("module", "evmindex")
idxer = indexer.NewKVIndexer(idxDB, idxLogger, clientCtx)
indexerService := NewEVMIndexerService(idxer, clientCtx.Client)
indexerService.SetLogger(idxLogger)
errCh := make(chan error)
go func() {
if err := indexerService.Start(); err != nil {
errCh <- err
}
}()
select {
case err := <-errCh:
return err
case <-time.After(types.ServerStartTime): // assume server started successfully
}
}
if config.API.Enable || config.JSONRPC.Enable {
genDoc, err := genDocProvider()
if err != nil {
return err
}
clientCtx := clientCtx.
clientCtx = clientCtx.
WithHomeDir(home).
WithChainID(genDoc.ChainID)
// Set `GRPCClient` to `clientCtx` to enjoy concurrent grpc query.
// only use it if gRPC server is enabled.
if config.GRPC.Enable {
_, port, err := net.SplitHostPort(config.GRPC.Address)
if err != nil {
return sdkerrors.Wrapf(err, "invalid grpc address %s", config.GRPC.Address)
}
maxSendMsgSize := config.GRPC.MaxSendMsgSize
if maxSendMsgSize == 0 {
maxSendMsgSize = serverconfig.DefaultGRPCMaxSendMsgSize
}
maxRecvMsgSize := config.GRPC.MaxRecvMsgSize
if maxRecvMsgSize == 0 {
maxRecvMsgSize = serverconfig.DefaultGRPCMaxRecvMsgSize
}
grpcAddress := fmt.Sprintf("127.0.0.1:%s", port)
// If grpc is enabled, configure grpc client for grpc gateway and json-rpc.
grpcClient, err := grpc.Dial(
grpcAddress,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultCallOptions(
grpc.ForceCodec(codec.NewProtoCodec(clientCtx.InterfaceRegistry).GRPCCodec()),
grpc.MaxCallRecvMsgSize(maxRecvMsgSize),
grpc.MaxCallSendMsgSize(maxSendMsgSize),
),
)
if err != nil {
return err
}
clientCtx = clientCtx.WithGRPCClient(grpcClient)
ctx.Logger.Debug("gRPC client assigned to client context", "address", grpcAddress)
}
}
var apiSrv *api.Server
if config.API.Enable {
apiSrv = api.New(clientCtx, ctx.Logger.With("server", "api"))
app.RegisterAPIRoutes(apiSrv, config.API)
errCh := make(chan error)
@@ -434,7 +494,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
)
if config.JSONRPC.Enable {
genDoc, err := tmtypes.GenesisDocFromFile(cfg.GenesisFile())
genDoc, err := genDocProvider()
if err != nil {
return err
}
@@ -443,15 +503,12 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
tmEndpoint := "/websocket"
tmRPCAddr := cfg.RPC.ListenAddress
httpSrv, httpSrvDone, err = StartJSONRPC(ctx, clientCtx, tmRPCAddr, tmEndpoint, config)
httpSrv, httpSrvDone, err = StartJSONRPC(ctx, clientCtx, tmRPCAddr, tmEndpoint, &config, idxer)
if err != nil {
return err
}
}
// Start the GQL Server
go gql.Server(clientCtx)
defer func() {
if tmNode.IsRunning() {
_ = tmNode.Stop()
@@ -501,6 +558,12 @@ func openDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) {
return dbm.NewDB("application", backendType, dataDir)
}
// OpenIndexerDB opens the custom eth indexer db, using the same db backend as the main app
func OpenIndexerDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) {
dataDir := filepath.Join(rootDir, "data")
return dbm.NewDB("evmindexer", backendType, dataDir)
}
func openTraceWriter(traceWriterFile string) (w io.Writer, err error) {
if traceWriterFile == "" {
return
+32 -4
View File
@@ -1,24 +1,33 @@
package server
import (
"net"
"net/http"
"time"
"github.com/cerc-io/laconicd/server/config"
"github.com/gorilla/mux"
"github.com/improbable-eng/grpc-web/go/grpcweb"
"github.com/spf13/cobra"
"golang.org/x/net/netutil"
sdkserver "github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/version"
tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
tmlog "github.com/tendermint/tendermint/libs/log"
rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client"
)
// add server commands
func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator types.AppCreator, appExport types.AppExporter, addStartFlags types.ModuleInitFlags) {
// AddCommands adds server commands
func AddCommands(
rootCmd *cobra.Command,
defaultNodeHome string,
appCreator types.AppCreator,
appExport types.AppExporter,
addStartFlags types.ModuleInitFlags,
) {
tendermintCmd := &cobra.Command{
Use: "tendermint",
Short: "Tendermint subcommands",
@@ -41,6 +50,10 @@ func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator type
tendermintCmd,
sdkserver.ExportCmd(appExport, defaultNodeHome),
version.NewVersionCommand(),
sdkserver.NewRollbackCmd(appCreator, defaultNodeHome),
// custom tx indexer command
NewIndexTxCmd(),
)
}
@@ -79,7 +92,6 @@ func MountGRPCWebServices(
logger tmlog.Logger,
) {
for _, res := range grpcResources {
logger.Info("[GRPC Web] HTTP POST mounted", "resource", res)
s := router.Methods("POST").Subrouter()
@@ -96,3 +108,19 @@ func MountGRPCWebServices(
})
}
}
// Listen starts a net.Listener on the tcp network on the given address.
// If there is a specified MaxOpenConnections in the config, it will also set the limitListener.
func Listen(addr string, config *config.Config) (net.Listener, error) {
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
if config.JSONRPC.MaxOpenConnections > 0 {
ln = netutil.LimitListener(ln, config.JSONRPC.MaxOpenConnections)
}
return ln, err
}