cmd/aergosvr/aergosvr.go
/**
* @file
* @copyright defined in aergo/LICENSE.txt
*/
package main
import (
"fmt"
"os"
"github.com/aergoio/aergo-lib/log"
"github.com/aergoio/aergo/v2/account"
"github.com/aergoio/aergo/v2/chain"
polarisclient "github.com/aergoio/aergo/v2/cmd/polaris/client"
"github.com/aergoio/aergo/v2/config"
"github.com/aergoio/aergo/v2/consensus"
"github.com/aergoio/aergo/v2/consensus/impl"
"github.com/aergoio/aergo/v2/internal/common"
"github.com/aergoio/aergo/v2/mempool"
"github.com/aergoio/aergo/v2/p2p"
"github.com/aergoio/aergo/v2/p2p/p2pkey"
"github.com/aergoio/aergo/v2/pkg/component"
"github.com/aergoio/aergo/v2/rpc"
"github.com/aergoio/aergo/v2/rpc/web3"
"github.com/aergoio/aergo/v2/syncer"
"github.com/spf13/cobra"
)
var (
gitRevision, gitBranch string
)
func main() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
var (
rootCmd = &cobra.Command{
Use: "aergosvr",
Short: "Aergo Server",
Long: "Aergo Server Full-node implementation",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
if homePath != "" && configFilePath != "" && verbose {
fmt.Println("ignore home path if given config file has valid configuration")
}
},
Run: rootRun,
}
homePath string
configFilePath string
enableTestmode bool
useTestnet bool
verbose bool
svrlog *log.Logger
cfg *config.Config
)
func init() {
cobra.OnInitialize(initConfig)
localFlags := rootCmd.Flags()
localFlags.SortFlags = false
localFlags.BoolVar(&useTestnet, "testnet", false, "use Aergo TestNet; this only affects if there's no genesis block")
localFlags.BoolVar(&enableTestmode, "testmode", false, "enable unsafe test mode (skips certain validations); can NOT use with --testnet")
fs := rootCmd.PersistentFlags()
fs.StringVar(&homePath, "home", "", "path of aergo home")
fs.StringVar(&configFilePath, "config", "", "path of configuration file")
fs.BoolVarP(&verbose, "verbose", "v", false, "verbose mode")
}
func initConfig() {
serverCtx := config.NewServerContext(homePath, configFilePath)
cfg = serverCtx.GetDefaultConfig().(*config.Config)
err := serverCtx.LoadOrCreateConfig(cfg)
if err != nil {
fmt.Printf("Fail to load configuration file %v: %v", serverCtx.Vc.ConfigFileUsed(), err.Error())
os.Exit(1)
}
if enableTestmode {
cfg.EnableTestmode = true
}
if useTestnet {
cfg.UseTestnet = true
}
if cfg.EnableTestmode && cfg.UseTestnet {
fmt.Println("Turn off test mode for Aergo Public Chains")
os.Exit(1)
}
}
func rootRun(cmd *cobra.Command, args []string) {
svrlog = log.NewLogger("asvr")
svrlog.Info().Str("revision", gitRevision).Str("branch", gitBranch).Msg("AERGO SVR STARTED")
if cfg.EnableTestmode {
svrlog.Warn().Msgf("Running with unsafe test mode. Turn off test mode for production use!")
}
p2pkey.InitNodeInfo(&cfg.BaseConfig, cfg.P2P, githash, svrlog)
compMng := component.NewComponentHub()
chainSvc := chain.NewChainService(cfg)
mpoolSvc := mempool.NewMemPoolService(cfg, chainSvc)
rpcSvc := rpc.NewRPC(cfg, chainSvc, githash)
admSvc := rpc.NewAdminService(cfg.RPC, compMng)
syncSvc := syncer.NewSyncer(cfg, chainSvc, nil)
p2pSvc := p2p.NewP2P(cfg, chainSvc)
pmapSvc := polarisclient.NewPolarisConnectSvc(cfg.P2P, p2pSvc)
var accountSvc component.IComponent
if cfg.Personal {
accountSvc = account.NewAccountService(cfg, chainSvc.SDB())
}
var web3Svr component.IComponent
if cfg.Web3.Enable {
web3Svr = web3.NewWeb3(cfg, rpcSvc.GetActualServer())
}
// Register services to Hub. Don't need to do nil-check since Register
// function skips nil parameters.
var verifyOnly = cfg.Blockchain.VerifyOnly || cfg.Blockchain.VerifyBlock != 0
if !verifyOnly {
compMng.Register(chainSvc, mpoolSvc, rpcSvc, web3Svr, syncSvc, p2pSvc, accountSvc, pmapSvc)
} else {
compMng.Register(chainSvc, mpoolSvc, rpcSvc, web3Svr)
}
consensusSvc, err := impl.New(cfg, compMng, chainSvc, p2pSvc, rpcSvc)
if err != nil {
svrlog.Error().Err(err).Msg("Failed to start consensus service.")
os.Exit(1)
}
dmp := NewDumper(cfg, compMng)
// All the services objects including Consensus must be created before the
// actors are started.
compMng.Start()
if cfg.Consensus.EnableBp {
// Warning: The consensus service must start after all the other
// services.
consensus.Start(consensusSvc)
}
if cfg.EnableDump {
dmp.Start()
}
if len(cfg.RPC.NetServicePath) > 0 {
admSvc.Start()
}
var interrupt = common.HandleKillSig(func() {
consensus.Stop(consensusSvc)
compMng.Stop()
}, svrlog)
// Wait main routine to stop
<-interrupt.C
}