github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/cmd/gvnt/main.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // gvnt is the official command-line client for VNT.
    18  package main
    19  
    20  import (
    21  	"fmt"
    22  	"math"
    23  	"os"
    24  	"runtime"
    25  	godebug "runtime/debug"
    26  	"sort"
    27  	"strconv"
    28  	"strings"
    29  	"time"
    30  
    31  	"github.com/elastic/gosigar"
    32  	"github.com/vntchain/go-vnt/accounts"
    33  	"github.com/vntchain/go-vnt/accounts/keystore"
    34  	"github.com/vntchain/go-vnt/cmd/utils"
    35  	"github.com/vntchain/go-vnt/console"
    36  	"github.com/vntchain/go-vnt/internal/debug"
    37  	"github.com/vntchain/go-vnt/log"
    38  	"github.com/vntchain/go-vnt/metrics"
    39  	"github.com/vntchain/go-vnt/node"
    40  	"github.com/vntchain/go-vnt/vnt"
    41  	"github.com/vntchain/go-vnt/vntclient"
    42  	cli "gopkg.in/urfave/cli.v1"
    43  )
    44  
    45  const (
    46  	clientIdentifier = "gvnt" // Client identifier to advertise over the network
    47  )
    48  
    49  var (
    50  	// Git SHA1 commit hash of the release (set via linker flags)
    51  	gitCommit = ""
    52  	// The app that holds all commands and flags.
    53  	app = utils.NewApp(gitCommit, "the go-vnt command line interface")
    54  	// flags that configure the node
    55  	nodeFlags = []cli.Flag{
    56  		utils.IdentityFlag,
    57  		utils.UnlockedAccountFlag,
    58  		utils.PasswordFileFlag,
    59  		utils.FindNodeFlag,
    60  		utils.VNTBootnodeFlag,
    61  		utils.BootnodesFlag,
    62  		utils.BootnodesV4Flag,
    63  		utils.BootnodesV5Flag,
    64  		utils.DataDirFlag,
    65  		utils.KeyStoreDirFlag,
    66  		utils.TxPoolNoLocalsFlag,
    67  		utils.TxPoolJournalFlag,
    68  		utils.TxPoolRejournalFlag,
    69  		utils.TxPoolPriceLimitFlag,
    70  		utils.TxPoolPriceBumpFlag,
    71  		utils.TxPoolAccountSlotsFlag,
    72  		utils.TxPoolGlobalSlotsFlag,
    73  		utils.TxPoolAccountQueueFlag,
    74  		utils.TxPoolGlobalQueueFlag,
    75  		utils.TxPoolLifetimeFlag,
    76  		utils.SyncModeFlag,
    77  		utils.GCModeFlag,
    78  		utils.LightServFlag,
    79  		utils.LightPeersFlag,
    80  		utils.LightKDFFlag,
    81  		utils.CacheFlag,
    82  		utils.CacheDatabaseFlag,
    83  		utils.CacheGCFlag,
    84  		utils.TrieCacheGenFlag,
    85  		utils.ListenPortFlag,
    86  		utils.MaxPeersFlag,
    87  		utils.MaxPendingPeersFlag,
    88  		utils.CoinbaseFlag,
    89  		utils.GasPriceFlag,
    90  		utils.ProducingEnabledFlag,
    91  		utils.TargetGasLimitFlag,
    92  		utils.NATFlag,
    93  		utils.NoDiscoverFlag,
    94  		utils.DiscoveryV5Flag,
    95  		utils.NetrestrictFlag,
    96  		utils.NodeKeyFileFlag,
    97  		utils.NodeKeyHexFlag,
    98  		utils.VMEnableDebugFlag,
    99  		utils.NetworkIdFlag,
   100  		utils.RPCCORSDomainFlag,
   101  		utils.RPCVirtualHostsFlag,
   102  		utils.VntStatsURLFlag,
   103  		utils.MetricsEnabledFlag,
   104  		utils.NoCompactionFlag,
   105  		utils.GpoBlocksFlag,
   106  		utils.GpoPercentileFlag,
   107  		utils.ExtraDataFlag,
   108  		configFileFlag,
   109  	}
   110  
   111  	rpcFlags = []cli.Flag{
   112  		utils.RPCEnabledFlag,
   113  		utils.RPCListenAddrFlag,
   114  		utils.RPCPortFlag,
   115  		utils.RPCApiFlag,
   116  		utils.WSEnabledFlag,
   117  		utils.WSListenAddrFlag,
   118  		utils.WSPortFlag,
   119  		utils.WSApiFlag,
   120  		utils.WSAllowedOriginsFlag,
   121  		utils.IPCDisabledFlag,
   122  		utils.IPCPathFlag,
   123  	}
   124  
   125  	whisperFlags = []cli.Flag{
   126  		utils.WhisperEnabledFlag,
   127  		utils.WhisperMaxMessageSizeFlag,
   128  		utils.WhisperMinPOWFlag,
   129  	}
   130  )
   131  
   132  func init() {
   133  	// Initialize the CLI app and start Gvnt
   134  	app.Action = gvnt
   135  	app.HideVersion = true // we have a command to print the version
   136  	app.Copyright = "Copyright 2018-2019 The go-vnt Authors"
   137  	app.Commands = []cli.Command{
   138  		// See chaincmd.go:
   139  		initCommand,
   140  		importCommand,
   141  		exportCommand,
   142  		importPreimagesCommand,
   143  		exportPreimagesCommand,
   144  		copydbCommand,
   145  		removedbCommand,
   146  		dumpCommand,
   147  		// See monitorcmd.go:
   148  		monitorCommand,
   149  		// See accountcmd.go:
   150  		accountCommand,
   151  		// See consolecmd.go:
   152  		consoleCommand,
   153  		attachCommand,
   154  		javascriptCommand,
   155  		// See misccmd.go:
   156  		versionCommand,
   157  		bugCommand,
   158  		licenseCommand,
   159  		// See config.go
   160  		dumpConfigCommand,
   161  	}
   162  	sort.Sort(cli.CommandsByName(app.Commands))
   163  
   164  	app.Flags = append(app.Flags, nodeFlags...)
   165  	app.Flags = append(app.Flags, rpcFlags...)
   166  	app.Flags = append(app.Flags, consoleFlags...)
   167  	app.Flags = append(app.Flags, debug.Flags...)
   168  	app.Flags = append(app.Flags, whisperFlags...)
   169  
   170  	app.Before = func(ctx *cli.Context) error {
   171  		runtime.GOMAXPROCS(runtime.NumCPU())
   172  		if err := debug.Setup(ctx); err != nil {
   173  			return err
   174  		}
   175  		// Cap the cache allowance and tune the garbage colelctor
   176  		var mem gosigar.Mem
   177  		if err := mem.Get(); err == nil {
   178  			allowance := int(mem.Total / 1024 / 1024 / 3)
   179  			if cache := ctx.GlobalInt(utils.CacheFlag.Name); cache > allowance {
   180  				log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
   181  				ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(allowance))
   182  			}
   183  		}
   184  		// Ensure Go's GC ignores the database cache for trigger percentage
   185  		cache := ctx.GlobalInt(utils.CacheFlag.Name)
   186  		gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))
   187  
   188  		log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
   189  		godebug.SetGCPercent(int(gogc))
   190  
   191  		// Start system runtime metrics collection
   192  		go metrics.CollectProcessMetrics(3 * time.Second)
   193  
   194  		utils.SetupNetwork(ctx)
   195  		return nil
   196  	}
   197  
   198  	app.After = func(ctx *cli.Context) error {
   199  		debug.Exit()
   200  		console.Stdin.Close() // Resets terminal mode.
   201  		return nil
   202  	}
   203  }
   204  
   205  func main() {
   206  	if err := app.Run(os.Args); err != nil {
   207  		fmt.Fprintln(os.Stderr, err)
   208  		os.Exit(1)
   209  	}
   210  }
   211  
   212  // gvnt is the main entry point into the system if no special subcommand is ran.
   213  // It creates a default node based on the command line arguments and runs it in
   214  // blocking mode, waiting for it to be shut down.
   215  func gvnt(ctx *cli.Context) error {
   216  	node := makeFullNode(ctx)
   217  	// go startVNTNode(node)
   218  	startNode(ctx, node)
   219  	node.Wait()
   220  	return nil
   221  }
   222  
   223  /* func startVNTNode(stack *node.Node) {
   224  	findnode := stack.Config().P2P.FindNode
   225  	bootnode := stack.Config().P2P.VNTBootnode
   226  	listenPort := stack.Config().P2P.ListenAddr[1:]
   227  	log.Info("startVNTNode()", "listenPort", listenPort)
   228  	ctx, cancel := context.WithCancel(context.Background())
   229  	defer cancel()
   230  
   231  	vdht, host, err := vntp2p.ConstructDHT(ctx, vntp2p.MakePort(listenPort), nil)
   232  	if err != nil {
   233  		log.Error("startVNTNode()", "constructDHT error", err)
   234  		return
   235  	}
   236  	log.Info("startVNTNode()", "own nodeID", host.ID())
   237  
   238  	h := &vntprotocol.HostWrapper{
   239  		Host: host,
   240  	}
   241  
   242  	host.SetStreamHandler(vntp2p.PID, h.HandleStream)
   243  	bootnodeAddr, bootnodeID, err := vntp2p.GetAddr(bootnode)
   244  	if err != nil {
   245  		log.Error("startVNTNode()", "getAddr error", err)
   246  		return
   247  	}
   248  	host.Peerstore().AddAddrs(bootnodeID, []ma.Multiaddr{bootnodeAddr}, peerstore.PermanentAddrTTL)
   249  	vdht.Update(ctx, bootnodeID)
   250  
   251  	// test vntdb
   252  	//err = vdht.PutValue(ctx, "/v/hello2", []byte("helloworld2"))
   253  	//if err != nil {
   254  	//	log.Error("startVNTNode()", "putValue error", err)
   255  	//}
   256  
   257  	contentKey := "/v/hello2"
   258  	log.Info("begin getValue now!")
   259  	best, err := vdht.GetValue(ctx, contentKey)
   260  	if err != nil {
   261  		log.Error("startVNTNode()", "getValue error", err)
   262  	} else {
   263  		log.Info("startVNTNode(), value gotten", "key", contentKey, "value", string(best))
   264  	}
   265  
   266  	content := host.Peerstore().Peers()
   267  	for i := range content {
   268  		log.Info("startVNTNode()", "---> index", i, "PeerInfo", host.Peerstore().PeerInfo(content[i]))
   269  	}
   270  
   271  	//sayHelloToBootnode(ctx, host, bootnodeID)
   272  
   273  	if findnode != "" {
   274  		findNode(ctx, findnode, vdht)
   275  	}
   276  
   277  	select {}
   278  } */
   279  
   280  /* func findNode(ctx context.Context, findnode string, vdht *dht.IpfsDHT) {
   281  	_, findnodeID, err := vntp2p.GetAddr(findnode)
   282  	if err != nil {
   283  		log.Error("findNode()", "getAddr error", err)
   284  		return
   285  	}
   286  	log.Info("findNode()", "findnodeID", findnodeID)
   287  	targetPeerInfo, err := vdht.FindPeer(ctx, findnodeID)
   288  	if err != nil {
   289  		log.Error("findNode()", "findPeer error", err)
   290  		return
   291  	}
   292  	log.Info("findNode()", "find peerid SUCCESS with info", targetPeerInfo)
   293  } */
   294  
   295  /* func sayHelloToBootnode(ctx context.Context, host p2phost.Host, nodeID peer.ID) {
   296  	s, err := host.NewStream(ctx, nodeID, vntp2p.PID)
   297  	if err != nil {
   298  		log.Error("sayHelloToBootnode()", "NewStream Error", err)
   299  		return
   300  	}
   301  
   302  	rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s))
   303  
   304  	// 封包,并且发送
   305  	msg, err := vntp2p.WritePackage(rw, 1, []byte("yoyoyo\n"))
   306  	if err != nil {
   307  		log.Error("sayHelloToBootnode()", "WritePackage Error", err)
   308  		return
   309  	}
   310  
   311  	log.Info("sayHelloToBootnode()", "msg", string(msg))
   312  	_, err = rw.Write(msg)
   313  	if err != nil {
   314  		log.Error("sayHelloToBootnode()", "Write Error", err)
   315  		return
   316  	}
   317  	rw.WriteByte('\n')
   318  	rw.Flush()
   319  } */
   320  
   321  // startNode boots up the system node and all registered protocols, after which
   322  // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
   323  // producer.
   324  func startNode(ctx *cli.Context, stack *node.Node) {
   325  	debug.Memsize.Add("node", stack)
   326  
   327  	// Start up the node itself
   328  	utils.StartNode(stack)
   329  
   330  	// Unlock any account specifically requested
   331  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   332  	passwords := utils.MakePasswordList(ctx)
   333  	unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
   334  	for i, account := range unlocks {
   335  		if trimmed := strings.TrimSpace(account); trimmed != "" {
   336  			unlockAccount(ctx, ks, trimmed, i, passwords)
   337  		}
   338  	}
   339  	// Register wallet event handlers to open and auto-derive wallets
   340  	events := make(chan accounts.WalletEvent, 16)
   341  	stack.AccountManager().Subscribe(events)
   342  
   343  	go func() {
   344  		// Create a chain state reader for self-derivation
   345  		rpcClient, err := stack.Attach()
   346  		if err != nil {
   347  			utils.Fatalf("Failed to attach to self: %v", err)
   348  		}
   349  		stateReader := vntclient.NewClient(rpcClient)
   350  
   351  		// Open any wallets already attached
   352  		for _, wallet := range stack.AccountManager().Wallets() {
   353  			if err := wallet.Open(""); err != nil {
   354  				log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
   355  			}
   356  		}
   357  		// Listen for wallet event till termination
   358  		for event := range events {
   359  			switch event.Kind {
   360  			case accounts.WalletArrived:
   361  				if err := event.Wallet.Open(""); err != nil {
   362  					log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
   363  				}
   364  			case accounts.WalletOpened:
   365  				status, _ := event.Wallet.Status()
   366  				log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status)
   367  
   368  				if event.Wallet.URL().Scheme == "ledger" {
   369  					event.Wallet.SelfDerive(accounts.DefaultLedgerBaseDerivationPath, stateReader)
   370  				} else {
   371  					event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
   372  				}
   373  
   374  			case accounts.WalletDropped:
   375  				log.Info("Old wallet dropped", "url", event.Wallet.URL())
   376  				event.Wallet.Close()
   377  			}
   378  		}
   379  	}()
   380  	// Start auxiliary services if enabled
   381  	if ctx.GlobalBool(utils.ProducingEnabledFlag.Name) {
   382  		// Producing only makes sense if a full VNT node is running
   383  		if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
   384  			utils.Fatalf("Light clients do not support block producing")
   385  		}
   386  		var vnt *vnt.VNT
   387  		if err := stack.Service(&vnt); err != nil {
   388  			utils.Fatalf("VNT service not running: %v", err)
   389  		}
   390  
   391  		// Set the gas price to the limits from the CLI and start producing
   392  		vnt.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name))
   393  		if err := vnt.StartProducing(true); err != nil {
   394  			utils.Fatalf("Failed to start block producing: %v", err)
   395  		}
   396  	}
   397  }