2018-02-14 11:04:34 -08:00
package server
2019-08-30 08:46:48 -07:00
// DONTCOVER
2018-02-14 11:04:34 -08:00
import (
2019-02-08 11:37:46 -08:00
"fmt"
2021-01-18 10:25:22 -08:00
"net/http"
2019-08-30 08:46:48 -07:00
"os"
"runtime/pprof"
2020-06-26 09:30:49 -07:00
"time"
2019-02-08 11:37:46 -08:00
2018-02-14 11:04:34 -08:00
"github.com/spf13/cobra"
2021-11-16 11:24:38 -08:00
abciclient "github.com/tendermint/tendermint/abci/client"
2018-06-28 17:54:47 -07:00
"github.com/tendermint/tendermint/abci/server"
2018-02-14 11:04:34 -08:00
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
2020-01-16 13:46:51 -08:00
tmos "github.com/tendermint/tendermint/libs/os"
2018-02-14 11:04:34 -08:00
"github.com/tendermint/tendermint/node"
2020-06-15 10:39:09 -07:00
"github.com/tendermint/tendermint/rpc/client/local"
2021-11-16 11:24:38 -08:00
tmtypes "github.com/tendermint/tendermint/types"
"google.golang.org/grpc"
2021-05-14 15:18:59 -07:00
2020-06-15 10:39:09 -07:00
"github.com/cosmos/cosmos-sdk/client"
2020-07-05 09:56:17 -07:00
"github.com/cosmos/cosmos-sdk/client/flags"
2021-11-16 11:24:38 -08:00
"github.com/cosmos/cosmos-sdk/codec"
2020-06-15 10:39:09 -07:00
"github.com/cosmos/cosmos-sdk/server/api"
"github.com/cosmos/cosmos-sdk/server/config"
2020-07-27 10:57:15 -07:00
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
2021-11-16 11:24:38 -08:00
"github.com/cosmos/cosmos-sdk/server/rosetta"
crgserver "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server"
2020-07-27 10:57:15 -07:00
"github.com/cosmos/cosmos-sdk/server/types"
2020-06-22 13:31:33 -07:00
storetypes "github.com/cosmos/cosmos-sdk/store/types"
2018-02-14 11:04:34 -08:00
)
2019-01-18 08:45:20 -08:00
// Tendermint full-node start flags
2018-02-14 11:04:34 -08:00
const (
2020-06-22 13:31:33 -07:00
flagWithTendermint = "with-tendermint"
flagAddress = "address"
2020-07-21 12:01:30 -07:00
flagTransport = "transport"
2020-06-22 13:31:33 -07:00
flagTraceStore = "trace-store"
flagCPUProfile = "cpu-profile"
FlagMinGasPrices = "minimum-gas-prices"
FlagHaltHeight = "halt-height"
FlagHaltTime = "halt-time"
FlagInterBlockCache = "inter-block-cache"
FlagUnsafeSkipUpgrades = "unsafe-skip-upgrades"
2020-07-05 09:56:17 -07:00
FlagTrace = "trace"
FlagInvCheckPeriod = "inv-check-period"
2020-06-22 13:31:33 -07:00
FlagPruning = "pruning"
FlagPruningKeepRecent = "pruning-keep-recent"
FlagPruningKeepEvery = "pruning-keep-every"
FlagPruningInterval = "pruning-interval"
2020-08-20 09:19:16 -07:00
FlagIndexEvents = "index-events"
2020-09-14 07:12:49 -07:00
FlagMinRetainBlocks = "min-retain-blocks"
2018-02-14 11:04:34 -08:00
)
2020-08-05 08:45:22 -07:00
// GRPC-related flags.
const (
2021-01-18 10:25:22 -08:00
flagGRPCEnable = "grpc.enable"
flagGRPCAddress = "grpc.address"
flagGRPCWebEnable = "grpc-web.enable"
flagGRPCWebAddress = "grpc-web.address"
2020-08-05 08:45:22 -07:00
)
2020-09-08 02:05:44 -07:00
// State sync-related flags.
const (
FlagStateSyncSnapshotInterval = "state-sync.snapshot-interval"
FlagStateSyncSnapshotKeepRecent = "state-sync.snapshot-keep-recent"
)
2018-07-12 16:58:51 -07:00
// StartCmd runs the service passed in, either stand-alone or in-process with
// Tendermint.
2020-07-27 10:57:15 -07:00
func StartCmd ( appCreator types . AppCreator , defaultNodeHome string ) * cobra . Command {
2018-02-14 11:04:34 -08:00
cmd := & cobra . Command {
Use : "start" ,
Short : "Run the full node" ,
2019-09-09 07:08:10 -07:00
Long : ` Run the full node application with Tendermint in or out of process . By
default , the application will run with Tendermint in process .
2020-06-22 13:31:33 -07:00
Pruning options can be provided via the ' -- pruning ' flag or alternatively with ' -- pruning - keep - recent ' ,
' pruning - keep - every ' , and ' pruning - interval ' together .
2020-02-27 07:05:10 -08:00
For ' -- pruning ' the options are as follows :
2019-09-09 07:08:10 -07:00
2020-06-22 13:31:33 -07:00
default : the last 100 states are kept in addition to every 500 th state ; pruning at 10 block intervals
2019-09-09 07:08:10 -07:00
nothing : all historic states will be saved , nothing will be deleted ( i . e . archiving node )
2020-06-22 13:31:33 -07:00
everything : all saved states will be deleted , storing only the current state ; pruning at 10 block intervals
custom : allow pruning options to be manually specified through ' pruning - keep - recent ' , ' pruning - keep - every ' , and ' pruning - interval '
2019-09-09 07:08:10 -07:00
Node halting configurations exist in the form of two flags : ' -- halt - height ' and ' -- halt - time ' . During
the ABCI Commit phase , the node will check if the current block height is greater than or equal to
the halt - height or if the current block time is greater than or equal to the halt - time . If so , the
node will attempt to gracefully shutdown and the block will not be committed . In addition , the node
will not be able to commit subsequent blocks .
For profiling and benchmarking purposes , CPU profiling can be enabled via the ' -- cpu - profile ' flag
which accepts a path for the resulting pprof file .
` ,
2020-07-07 08:40:46 -07:00
PreRunE : func ( cmd * cobra . Command , _ [ ] string ) error {
serverCtx := GetServerContextFromCmd ( cmd )
// Bind flags to the Context's Viper so the app construction can set
// options accordingly.
serverCtx . Viper . BindPFlags ( cmd . Flags ( ) )
_ , err := GetPruningOptionsFromFlags ( serverCtx . Viper )
2020-04-14 08:24:27 -07:00
return err
2020-02-27 03:01:27 -08:00
} ,
2020-07-07 08:40:46 -07:00
RunE : func ( cmd * cobra . Command , _ [ ] string ) error {
serverCtx := GetServerContextFromCmd ( cmd )
2020-12-14 14:09:51 -08:00
clientCtx , err := client . GetClientQueryContext ( cmd )
if err != nil {
return err
}
2020-07-07 08:40:46 -07:00
2020-07-05 09:56:17 -07:00
withTM , _ := cmd . Flags ( ) . GetBool ( flagWithTendermint )
if ! withTM {
2020-07-07 08:40:46 -07:00
serverCtx . Logger . Info ( "starting ABCI without Tendermint" )
return startStandAlone ( serverCtx , appCreator )
2018-04-21 19:26:46 -07:00
}
2018-07-12 16:58:51 -07:00
2020-07-07 08:40:46 -07:00
serverCtx . Logger . Info ( "starting ABCI with Tendermint" )
2018-07-12 16:58:51 -07:00
2020-08-13 06:20:02 -07:00
// amino is needed here for backwards compatibility of REST routes
2020-12-14 14:09:51 -08:00
err = startInProcess ( serverCtx , clientCtx , appCreator )
2020-12-10 03:37:57 -08:00
errCode , ok := err . ( ErrorCode )
if ! ok {
return err
}
serverCtx . Logger . Debug ( fmt . Sprintf ( "received quit signal: %d" , errCode . Code ) )
return nil
2018-04-21 19:26:46 -07:00
} ,
2018-02-14 11:04:34 -08:00
}
2018-04-21 19:26:46 -07:00
2020-07-20 08:12:33 -07:00
cmd . Flags ( ) . String ( flags . FlagHome , defaultNodeHome , "The application home directory" )
2018-07-12 16:58:51 -07:00
cmd . Flags ( ) . Bool ( flagWithTendermint , true , "Run abci app embedded in-process with tendermint" )
2018-06-13 15:13:51 -07:00
cmd . Flags ( ) . String ( flagAddress , "tcp://0.0.0.0:26658" , "Listen address" )
2020-07-21 12:01:30 -07:00
cmd . Flags ( ) . String ( flagTransport , "socket" , "Transport protocol: socket, grpc" )
2018-07-12 16:58:51 -07:00
cmd . Flags ( ) . String ( flagTraceStore , "" , "Enable KVStore tracing to an output file" )
2020-07-05 09:56:17 -07:00
cmd . Flags ( ) . String ( FlagMinGasPrices , "" , "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)" )
2020-01-03 06:37:29 -08:00
cmd . Flags ( ) . IntSlice ( FlagUnsafeSkipUpgrades , [ ] int { } , "Skip a set of upgrade heights to continue the old binary" )
2019-09-09 07:08:10 -07:00
cmd . Flags ( ) . Uint64 ( FlagHaltHeight , 0 , "Block height at which to gracefully halt the chain and shutdown the node" )
cmd . Flags ( ) . Uint64 ( FlagHaltTime , 0 , "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node" )
2019-09-04 10:33:32 -07:00
cmd . Flags ( ) . Bool ( FlagInterBlockCache , true , "Enable inter-block caching" )
2019-08-30 08:46:48 -07:00
cmd . Flags ( ) . String ( flagCPUProfile , "" , "Enable CPU profiling and write to the provided file" )
2020-07-05 09:56:17 -07:00
cmd . Flags ( ) . Bool ( FlagTrace , false , "Provide full stack traces for errors in ABCI Log" )
2020-06-22 13:31:33 -07:00
cmd . Flags ( ) . String ( FlagPruning , storetypes . PruningOptionDefault , "Pruning strategy (default|nothing|everything|custom)" )
cmd . Flags ( ) . Uint64 ( FlagPruningKeepRecent , 0 , "Number of recent heights to keep on disk (ignored if pruning is not 'custom')" )
cmd . Flags ( ) . Uint64 ( FlagPruningKeepEvery , 0 , "Offset heights to keep on disk after 'keep-every' (ignored if pruning is not 'custom')" )
cmd . Flags ( ) . Uint64 ( FlagPruningInterval , 0 , "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')" )
2020-07-05 09:56:17 -07:00
cmd . Flags ( ) . Uint ( FlagInvCheckPeriod , 0 , "Assert registered invariants every N blocks" )
2020-09-14 07:12:49 -07:00
cmd . Flags ( ) . Uint64 ( FlagMinRetainBlocks , 0 , "Minimum block height offset during ABCI commit to prune Tendermint blocks" )
2020-07-05 09:56:17 -07:00
2020-08-05 08:45:22 -07:00
cmd . Flags ( ) . Bool ( flagGRPCEnable , true , "Define if the gRPC server should be enabled" )
cmd . Flags ( ) . String ( flagGRPCAddress , config . DefaultGRPCAddress , "the gRPC server address to listen on" )
2021-01-18 10:25:22 -08:00
cmd . Flags ( ) . Bool ( flagGRPCWebEnable , true , "Define if the gRPC-Web server should be enabled. (Note: gRPC must also be enabled.)" )
2021-01-21 20:12:22 -08:00
cmd . Flags ( ) . String ( flagGRPCWebAddress , config . DefaultGRPCWebAddress , "The gRPC-Web server address to listen on" )
2021-01-18 10:25:22 -08:00
2020-09-08 02:05:44 -07:00
cmd . Flags ( ) . Uint64 ( FlagStateSyncSnapshotInterval , 0 , "State sync snapshot interval" )
cmd . Flags ( ) . Uint32 ( FlagStateSyncSnapshotKeepRecent , 2 , "State sync snapshot to keep" )
2018-07-12 16:58:51 -07:00
// add support for all Tendermint-specific command line options
2018-02-14 11:04:34 -08:00
tcmd . AddNodeFlags ( cmd )
return cmd
}
2020-07-27 10:57:15 -07:00
func startStandAlone ( ctx * Context , appCreator types . AppCreator ) error {
2020-07-05 09:56:17 -07:00
addr := ctx . Viper . GetString ( flagAddress )
2020-07-21 12:01:30 -07:00
transport := ctx . Viper . GetString ( flagTransport )
2020-07-05 09:56:17 -07:00
home := ctx . Viper . GetString ( flags . FlagHome )
2018-07-12 16:58:51 -07:00
2018-10-10 15:45:41 -07:00
db , err := openDB ( home )
2018-02-21 09:56:04 -08:00
if err != nil {
return err
}
2020-07-05 09:56:17 -07:00
traceWriterFile := ctx . Viper . GetString ( flagTraceStore )
2018-10-10 15:45:41 -07:00
traceWriter , err := openTraceWriter ( traceWriterFile )
if err != nil {
return err
}
2020-07-05 09:56:17 -07:00
app := appCreator ( ctx . Logger , db , traceWriter , ctx . Viper )
2018-02-21 09:56:04 -08:00
2020-07-21 12:01:30 -07:00
svr , err := server . NewServer ( addr , transport , app )
2018-02-14 11:04:34 -08:00
if err != nil {
2019-02-08 11:37:46 -08:00
return fmt . Errorf ( "error creating listener: %v" , err )
2018-02-14 11:04:34 -08:00
}
2018-07-12 16:58:51 -07:00
2018-04-21 19:26:46 -07:00
svr . SetLogger ( ctx . Logger . With ( "module" , "abci-server" ) )
2018-07-12 16:58:51 -07:00
2018-06-28 15:52:10 -07:00
err = svr . Start ( )
if err != nil {
2020-01-16 13:46:51 -08:00
tmos . Exit ( err . Error ( ) )
2018-06-28 15:52:10 -07:00
}
2018-02-14 11:04:34 -08:00
2020-10-14 08:13:48 -07:00
defer func ( ) {
2020-07-07 08:40:46 -07:00
if err = svr . Stop ( ) ; err != nil {
2020-01-16 13:46:51 -08:00
tmos . Exit ( err . Error ( ) )
2018-06-28 15:52:10 -07:00
}
2020-10-14 08:13:48 -07:00
} ( )
2019-08-11 15:42:10 -07:00
2020-10-14 08:13:48 -07:00
// Wait for SIGINT or SIGTERM signal
return WaitForQuitSignals ( )
2018-02-14 11:04:34 -08:00
}
2020-08-13 06:20:02 -07:00
// legacyAminoCdc is used for the legacy REST API
2020-08-28 10:25:10 -07:00
func startInProcess ( ctx * Context , clientCtx client . Context , appCreator types . AppCreator ) error {
2018-04-21 19:26:46 -07:00
cfg := ctx . Config
2018-02-21 09:56:04 -08:00
home := cfg . RootDir
2020-11-02 11:10:14 -08:00
var cpuProfileCleanup func ( )
if cpuProfile := ctx . Viper . GetString ( flagCPUProfile ) ; cpuProfile != "" {
f , err := os . Create ( cpuProfile )
if err != nil {
return err
}
ctx . Logger . Info ( "starting CPU profiler" , "profile" , cpuProfile )
if err := pprof . StartCPUProfile ( f ) ; err != nil {
return err
}
cpuProfileCleanup = func ( ) {
ctx . Logger . Info ( "stopping CPU profiler" , "profile" , cpuProfile )
pprof . StopCPUProfile ( )
f . Close ( )
}
}
2018-07-12 16:58:51 -07:00
2020-07-05 09:56:17 -07:00
traceWriterFile := ctx . Viper . GetString ( flagTraceStore )
2018-10-10 15:45:41 -07:00
db , err := openDB ( home )
2018-02-21 09:56:04 -08:00
if err != nil {
2020-05-02 12:26:59 -07:00
return err
2018-02-21 09:56:04 -08:00
}
2020-01-03 06:37:29 -08:00
2018-10-10 15:45:41 -07:00
traceWriter , err := openTraceWriter ( traceWriterFile )
if err != nil {
2020-05-02 12:26:59 -07:00
return err
2018-10-10 15:45:41 -07:00
}
2021-06-25 03:41:32 -07:00
config := config . GetConfig ( ctx . Viper )
if err := config . ValidateBasic ( ) ; err != nil {
return err
}
2020-07-05 09:56:17 -07:00
app := appCreator ( ctx . Logger , db , traceWriter , ctx . Viper )
2018-02-21 09:56:04 -08:00
2021-11-16 11:24:38 -08:00
genDoc , err := tmtypes . GenesisDocFromFile ( cfg . GenesisFile ( ) )
2018-10-03 08:48:23 -07:00
if err != nil {
2020-05-02 12:26:59 -07:00
return err
2018-10-03 08:48:23 -07:00
}
2021-11-16 11:24:38 -08:00
tmNode , err := node . New (
2018-07-12 16:58:51 -07:00
cfg ,
2020-12-03 15:17:21 -08:00
ctx . Logger ,
2021-11-16 11:24:38 -08:00
abciclient . NewLocalCreator ( app ) ,
genDoc ,
2018-07-12 16:58:51 -07:00
)
2018-02-14 11:04:34 -08:00
if err != nil {
2020-05-02 12:26:59 -07:00
return err
2018-02-14 11:04:34 -08:00
}
2020-12-03 15:17:21 -08:00
ctx . Logger . Debug ( "initialization: tmNode created" )
2019-08-30 08:46:48 -07:00
if err := tmNode . Start ( ) ; err != nil {
2020-05-02 12:26:59 -07:00
return err
2018-02-14 11:04:34 -08:00
}
2020-12-03 15:17:21 -08:00
ctx . Logger . Debug ( "initialization: tmNode started" )
2018-02-14 11:04:34 -08:00
2020-11-10 05:01:55 -08:00
// 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 {
2021-11-16 11:24:38 -08:00
node , ok := tmNode . ( local . NodeService )
if ! ok {
panic ( "unable to set node type. Please try reinstalling the binary." )
}
localNode , err := local . New ( node )
if err != nil {
panic ( err )
}
clientCtx = clientCtx . WithClient ( localNode )
2020-11-10 05:01:55 -08:00
app . RegisterTxService ( clientCtx )
2020-11-25 07:58:11 -08:00
app . RegisterTendermintService ( clientCtx )
2020-11-10 05:01:55 -08:00
}
2020-10-30 05:32:02 -07:00
2020-06-16 10:31:35 -07:00
var apiSrv * api . Server
if config . API . Enable {
2021-11-16 11:24:38 -08:00
genDoc , err := tmtypes . GenesisDocFromFile ( cfg . GenesisFile ( ) )
2020-06-15 10:39:09 -07:00
if err != nil {
return err
}
2020-08-28 10:25:10 -07:00
clientCtx := clientCtx .
2020-06-15 10:39:09 -07:00
WithHomeDir ( home ) .
2020-11-10 05:01:55 -08:00
WithChainID ( genDoc . ChainID )
2020-06-15 10:39:09 -07:00
2020-06-26 09:30:49 -07:00
apiSrv = api . New ( clientCtx , ctx . Logger . With ( "module" , "api-server" ) )
2020-09-18 17:34:56 -07:00
app . RegisterAPIRoutes ( apiSrv , config . API )
2020-06-26 09:30:49 -07:00
errCh := make ( chan error )
go func ( ) {
if err := apiSrv . Start ( config ) ; err != nil {
errCh <- err
}
} ( )
select {
case err := <- errCh :
2020-06-15 10:39:09 -07:00
return err
2021-07-18 18:20:55 -07:00
case <- time . After ( types . ServerStartTime ) : // assume server started successfully
2020-06-15 10:39:09 -07:00
}
}
2021-01-18 10:25:22 -08:00
var (
grpcSrv * grpc . Server
grpcWebSrv * http . Server
)
2020-07-27 10:57:15 -07:00
if config . GRPC . Enable {
2021-02-15 02:01:44 -08:00
grpcSrv , err = servergrpc . StartGRPCServer ( clientCtx , app , config . GRPC . Address )
2020-07-27 10:57:15 -07:00
if err != nil {
return err
}
2021-01-18 10:25:22 -08:00
if config . GRPCWeb . Enable {
grpcWebSrv , err = servergrpc . StartGRPCWeb ( grpcSrv , config )
if err != nil {
ctx . Logger . Error ( "failed to start grpc-web http server: " , err )
return err
}
}
2020-07-27 10:57:15 -07:00
}
2021-01-21 01:33:02 -08:00
var rosettaSrv crgserver . Server
if config . Rosetta . Enable {
offlineMode := config . Rosetta . Offline
if ! config . GRPC . Enable { // If GRPC is not enabled rosetta cannot work in online mode, so it works in offline mode.
offlineMode = true
}
conf := & rosetta . Config {
Blockchain : config . Rosetta . Blockchain ,
Network : config . Rosetta . Network ,
TendermintRPC : ctx . Config . RPC . ListenAddress ,
GRPCEndpoint : config . GRPC . Address ,
Addr : config . Rosetta . Address ,
Retries : config . Rosetta . Retries ,
Offline : offlineMode ,
}
2021-06-11 04:49:39 -07:00
conf . WithCodec ( clientCtx . InterfaceRegistry , clientCtx . Codec . ( * codec . ProtoCodec ) )
2021-01-21 01:33:02 -08:00
rosettaSrv , err = rosetta . ServerFromConfig ( conf )
if err != nil {
return err
}
errCh := make ( chan error )
go func ( ) {
if err := rosettaSrv . Start ( ) ; err != nil {
errCh <- err
}
} ( )
select {
case err := <- errCh :
return err
2021-07-18 18:20:55 -07:00
case <- time . After ( types . ServerStartTime ) : // assume server started successfully
2021-01-21 01:33:02 -08:00
}
}
2020-10-14 08:13:48 -07:00
defer func ( ) {
2018-11-04 18:28:38 -08:00
if tmNode . IsRunning ( ) {
_ = tmNode . Stop ( )
}
2019-08-30 08:46:48 -07:00
if cpuProfileCleanup != nil {
cpuProfileCleanup ( )
}
2020-06-16 10:31:35 -07:00
if apiSrv != nil {
_ = apiSrv . Close ( )
}
2020-07-27 10:57:15 -07:00
if grpcSrv != nil {
grpcSrv . Stop ( )
2021-01-18 10:25:22 -08:00
if grpcWebSrv != nil {
grpcWebSrv . Close ( )
}
2020-07-27 10:57:15 -07:00
}
2019-08-30 08:46:48 -07:00
ctx . Logger . Info ( "exiting..." )
2020-10-14 08:13:48 -07:00
} ( )
2018-11-04 18:28:38 -08:00
2020-10-14 08:13:48 -07:00
// Wait for SIGINT or SIGTERM signal
return WaitForQuitSignals ( )
2018-02-14 11:04:34 -08:00
}