github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/internal/cli/command.go (about)

     1  package cli
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  
     7  	"github.com/ethereum/go-ethereum/accounts/keystore"
     8  	"github.com/ethereum/go-ethereum/internal/cli/flagset"
     9  	"github.com/ethereum/go-ethereum/internal/cli/server"
    10  	"github.com/ethereum/go-ethereum/internal/cli/server/proto"
    11  	"github.com/ethereum/go-ethereum/node"
    12  
    13  	"github.com/mitchellh/cli"
    14  	"github.com/ryanuber/columnize"
    15  	"google.golang.org/grpc"
    16  )
    17  
    18  const (
    19  	emptyPlaceHolder = "<none>"
    20  )
    21  
    22  type MarkDownCommand interface {
    23  	MarkDown
    24  	cli.Command
    25  }
    26  
    27  type MarkDownCommandFactory func() (MarkDownCommand, error)
    28  
    29  func Run(args []string) int {
    30  	commands := Commands()
    31  
    32  	mappedCommands := make(map[string]cli.CommandFactory)
    33  
    34  	for k, v := range commands {
    35  		// Declare a new v to limit the scope of v to inside the block, so the anonymous function below
    36  		// can get the "current" value of v, instead of the value of last v in the loop.
    37  		// See this post: https://stackoverflow.com/questions/10116507/go-transfer-var-into-anonymous-function for more explanation
    38  		v := v
    39  		mappedCommands[k] = func() (cli.Command, error) {
    40  			cmd, err := v()
    41  			return cmd.(cli.Command), err
    42  		}
    43  	}
    44  
    45  	cli := &cli.CLI{
    46  		Name:     "bor",
    47  		Args:     args,
    48  		Commands: mappedCommands,
    49  	}
    50  
    51  	exitCode, err := cli.Run()
    52  	if err != nil {
    53  		fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err.Error())
    54  		return 1
    55  	}
    56  
    57  	return exitCode
    58  }
    59  
    60  func Commands() map[string]MarkDownCommandFactory {
    61  	ui := &cli.BasicUi{
    62  		Reader:      os.Stdin,
    63  		Writer:      os.Stdout,
    64  		ErrorWriter: os.Stderr,
    65  	}
    66  
    67  	meta2 := &Meta2{
    68  		UI: ui,
    69  	}
    70  	meta := &Meta{
    71  		UI: ui,
    72  	}
    73  
    74  	return map[string]MarkDownCommandFactory{
    75  		"server": func() (MarkDownCommand, error) {
    76  			return &server.Command{
    77  				UI: ui,
    78  			}, nil
    79  		},
    80  		"version": func() (MarkDownCommand, error) {
    81  			return &VersionCommand{
    82  				UI: ui,
    83  			}, nil
    84  		},
    85  		"dumpconfig": func() (MarkDownCommand, error) {
    86  			return &DumpconfigCommand{
    87  				Meta2: meta2,
    88  			}, nil
    89  		},
    90  		"debug": func() (MarkDownCommand, error) {
    91  			return &DebugCommand{
    92  				UI: ui,
    93  			}, nil
    94  		},
    95  		"debug pprof": func() (MarkDownCommand, error) {
    96  			return &DebugPprofCommand{
    97  				Meta2: meta2,
    98  			}, nil
    99  		},
   100  		"debug block": func() (MarkDownCommand, error) {
   101  			return &DebugBlockCommand{
   102  				Meta2: meta2,
   103  			}, nil
   104  		},
   105  		"chain": func() (MarkDownCommand, error) {
   106  			return &ChainCommand{
   107  				UI: ui,
   108  			}, nil
   109  		},
   110  		"chain watch": func() (MarkDownCommand, error) {
   111  			return &ChainWatchCommand{
   112  				Meta2: meta2,
   113  			}, nil
   114  		},
   115  		"chain sethead": func() (MarkDownCommand, error) {
   116  			return &ChainSetHeadCommand{
   117  				Meta2: meta2,
   118  			}, nil
   119  		},
   120  		"account": func() (MarkDownCommand, error) {
   121  			return &Account{
   122  				UI: ui,
   123  			}, nil
   124  		},
   125  		"account new": func() (MarkDownCommand, error) {
   126  			return &AccountNewCommand{
   127  				Meta: meta,
   128  			}, nil
   129  		},
   130  		"account import": func() (MarkDownCommand, error) {
   131  			return &AccountImportCommand{
   132  				Meta: meta,
   133  			}, nil
   134  		},
   135  		"account list": func() (MarkDownCommand, error) {
   136  			return &AccountListCommand{
   137  				Meta: meta,
   138  			}, nil
   139  		},
   140  		"peers": func() (MarkDownCommand, error) {
   141  			return &PeersCommand{
   142  				UI: ui,
   143  			}, nil
   144  		},
   145  		"peers add": func() (MarkDownCommand, error) {
   146  			return &PeersAddCommand{
   147  				Meta2: meta2,
   148  			}, nil
   149  		},
   150  		"peers remove": func() (MarkDownCommand, error) {
   151  			return &PeersRemoveCommand{
   152  				Meta2: meta2,
   153  			}, nil
   154  		},
   155  		"peers list": func() (MarkDownCommand, error) {
   156  			return &PeersListCommand{
   157  				Meta2: meta2,
   158  			}, nil
   159  		},
   160  		"peers status": func() (MarkDownCommand, error) {
   161  			return &PeersStatusCommand{
   162  				Meta2: meta2,
   163  			}, nil
   164  		},
   165  		"status": func() (MarkDownCommand, error) {
   166  			return &StatusCommand{
   167  				Meta2: meta2,
   168  			}, nil
   169  		},
   170  		"fingerprint": func() (MarkDownCommand, error) {
   171  			return &FingerprintCommand{
   172  				UI: ui,
   173  			}, nil
   174  		},
   175  		"attach": func() (MarkDownCommand, error) {
   176  			return &AttachCommand{
   177  				UI:    ui,
   178  				Meta:  meta,
   179  				Meta2: meta2,
   180  			}, nil
   181  		},
   182  		"bootnode": func() (MarkDownCommand, error) {
   183  			return &BootnodeCommand{
   184  				UI: ui,
   185  			}, nil
   186  		},
   187  		"removedb": func() (MarkDownCommand, error) {
   188  			return &RemoveDBCommand{
   189  				Meta2: meta2,
   190  			}, nil
   191  		},
   192  		"snapshot": func() (MarkDownCommand, error) {
   193  			return &SnapshotCommand{
   194  				UI: ui,
   195  			}, nil
   196  		},
   197  		"snapshot prune-state": func() (MarkDownCommand, error) {
   198  			return &PruneStateCommand{
   199  				Meta: meta,
   200  			}, nil
   201  		},
   202  	}
   203  }
   204  
   205  type Meta2 struct {
   206  	UI cli.Ui
   207  
   208  	addr string
   209  }
   210  
   211  func (m *Meta2) NewFlagSet(n string) *flagset.Flagset {
   212  	f := flagset.NewFlagSet(n)
   213  
   214  	f.StringFlag(&flagset.StringFlag{
   215  		Name:    "address",
   216  		Value:   &m.addr,
   217  		Usage:   "Address of the grpc endpoint",
   218  		Default: "127.0.0.1:3131",
   219  	})
   220  
   221  	return f
   222  }
   223  
   224  func (m *Meta2) Conn() (*grpc.ClientConn, error) {
   225  	conn, err := grpc.Dial(m.addr, grpc.WithInsecure())
   226  	if err != nil {
   227  		return nil, fmt.Errorf("failed to connect to server: %v", err)
   228  	}
   229  
   230  	return conn, nil
   231  }
   232  
   233  func (m *Meta2) BorConn() (proto.BorClient, error) {
   234  	conn, err := m.Conn()
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  
   239  	return proto.NewBorClient(conn), nil
   240  }
   241  
   242  // Meta is a helper utility for the commands
   243  type Meta struct {
   244  	UI cli.Ui
   245  
   246  	dataDir     string
   247  	keyStoreDir string
   248  }
   249  
   250  func (m *Meta) NewFlagSet(n string) *flagset.Flagset {
   251  	f := flagset.NewFlagSet(n)
   252  
   253  	f.StringFlag(&flagset.StringFlag{
   254  		Name:  "datadir",
   255  		Value: &m.dataDir,
   256  		Usage: "Path of the data directory to store information",
   257  	})
   258  	f.StringFlag(&flagset.StringFlag{
   259  		Name:  "keystore",
   260  		Value: &m.keyStoreDir,
   261  		Usage: "Path of the data directory to store keys",
   262  	})
   263  
   264  	return f
   265  }
   266  
   267  func (m *Meta) AskPassword() (string, error) {
   268  	return m.UI.AskSecret("Your new account is locked with a password. Please give a password. Do not forget this password")
   269  }
   270  
   271  func (m *Meta) GetKeystore() (*keystore.KeyStore, error) {
   272  	cfg := node.DefaultConfig
   273  	cfg.DataDir = m.dataDir
   274  	cfg.KeyStoreDir = m.keyStoreDir
   275  
   276  	stack, err := node.New(&cfg)
   277  	if err != nil {
   278  		return nil, err
   279  	}
   280  
   281  	keydir := stack.KeyStoreDir()
   282  	scryptN := keystore.StandardScryptN
   283  	scryptP := keystore.StandardScryptP
   284  
   285  	keys := keystore.NewKeyStore(keydir, scryptN, scryptP)
   286  
   287  	return keys, nil
   288  }
   289  
   290  func formatList(in []string) string {
   291  	columnConf := columnize.DefaultConfig()
   292  	columnConf.Empty = emptyPlaceHolder
   293  
   294  	return columnize.Format(in, columnConf)
   295  }
   296  
   297  func formatKV(in []string) string {
   298  	columnConf := columnize.DefaultConfig()
   299  	columnConf.Empty = emptyPlaceHolder
   300  	columnConf.Glue = " = "
   301  
   302  	return columnize.Format(in, columnConf)
   303  }