| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- package main
- import (
- "encoding/hex"
- "errors"
- "fmt"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/console/prompt"
- tronaddr "github.com/fbsobreira/gotron-sdk/pkg/address"
- logging "github.com/ipfs/go-log/v2"
- "github.com/urfave/cli/v2"
- "google.golang.org/grpc"
- "gorm.io/gorm"
- "io/ioutil"
- "key-manager/conf"
- "key-manager/crypto"
- "key-manager/dao"
- "key-manager/service"
- "net"
- "os"
- "strings"
- )
- var log = logging.Logger("main")
- func main() {
- _ = logging.SetLogLevel("*", "INFO")
- app := cli.App{
- Name: "key-manager",
- Usage: "eth and tron key manager service",
- Commands: []*cli.Command{
- initCmd,
- runCmd,
- whitelistCmd,
- },
- EnableBashCompletion: true,
- }
- if err := app.Run(os.Args); err != nil {
- fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
- os.Exit(1)
- }
- }
- var initCmd = &cli.Command{
- Name: "init",
- Usage: "init key-manager service",
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "config",
- Usage: "config file path",
- },
- },
- Action: func(cctx *cli.Context) error {
- err := conf.InitConfig(cctx.String("config"))
- if err != nil {
- return err
- }
- db, err := dao.InitMysqlDB()
- if err != nil {
- return err
- }
- _, err = db.GetPassword()
- if err == nil {
- return errors.New("password already set")
- }
- if !errors.Is(err, gorm.ErrRecordNotFound) {
- return err
- }
- log.Info("Please set a password for the encrypted mnemonic")
- password, err := stdinPassword(true)
- if err != nil {
- return err
- }
- scrypt := crypto.Scrypt(password)
- scryptKey := hex.EncodeToString(scrypt)
- err = db.CreatePassword(&dao.Password{
- Password: scryptKey,
- })
- if err != nil {
- return err
- }
- return nil
- },
- }
- var runCmd = &cli.Command{
- Name: "run",
- Usage: "run key-manager process",
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "listen",
- Usage: "The host address and port on which the key manager will listen",
- Value: "127.0.0.1:5556",
- },
- &cli.StringFlag{
- Name: "config",
- Usage: "config file path",
- },
- &cli.StringFlag{
- Name: "password",
- Usage: "password file path",
- },
- },
- Action: func(cctx *cli.Context) error {
- err := conf.InitConfig(cctx.String("config"))
- if err != nil {
- return err
- }
- db, err := dao.InitMysqlDB()
- if err != nil {
- return err
- }
- scrypt, err := db.GetPassword()
- if errors.Is(err, gorm.ErrRecordNotFound) {
- return errors.New("please set a password first. run: key-manager init")
- } else if err != nil {
- return err
- }
- scryptKey, err := hex.DecodeString(scrypt)
- if err != nil {
- return err
- }
- var password string
- if cctx.IsSet("password") {
- p := cctx.String("password")
- data, err := ioutil.ReadFile(p)
- if err != nil {
- return err
- }
- password = strings.TrimSpace(string(data))
- } else {
- var err error
- password, err = stdinPassword(false)
- if err != nil {
- return err
- }
- }
- ok, err := crypto.VerifyScrypt(password, scryptKey)
- if err != nil {
- return err
- }
- if !ok {
- return errors.New("password verification failed")
- }
- listen := cctx.String("listen")
- listener, err := net.Listen("tcp", listen)
- if err != nil {
- return err
- }
- log.Infof("grpc server Listing on: %s", listen)
- grpcServer := grpc.NewServer()
- server, err := service.NewKeyManager(db, password)
- if err != nil {
- return err
- }
- service.RegisterKeyManagerServer(grpcServer, server)
- if err = grpcServer.Serve(listener); err != nil {
- log.Error(err)
- return err
- }
- return nil
- },
- }
- var whitelistCmd = &cli.Command{
- Name: "whitelist",
- Usage: "whitelist tools",
- Subcommands: []*cli.Command{
- listCmd,
- addCmd,
- deleteCmd,
- },
- }
- var addCmd = &cli.Command{
- Name: "add",
- Usage: "add whitelist address",
- ArgsUsage: "[name] [address]",
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "config",
- Usage: "config file path",
- },
- },
- Action: func(cctx *cli.Context) error {
- err := conf.InitConfig(cctx.String("config"))
- if err != nil {
- return err
- }
- db, err := dao.InitMysqlDB()
- if err != nil {
- return err
- }
- if cctx.NArg() != 2 {
- return errors.New("params need [name] [address]")
- }
- name := cctx.Args().Get(0)
- address := cctx.Args().Get(1)
- if address[:2] == "0x" {
- address = common.HexToAddress(address).String()
- } else {
- addr, err := tronaddr.Base58ToAddress(address)
- if err != nil {
- return err
- }
- address = addr.String()
- }
- err = db.CreateWhitelist(&dao.Whitelist{
- Name: name,
- WhiteAddress: address,
- })
- if err != nil {
- return err
- }
- fmt.Printf("add whitelist address success, name: %s, addr: %s \n", name, address)
- return nil
- },
- }
- var deleteCmd = &cli.Command{
- Name: "delete",
- Usage: "delete whitelist address",
- ArgsUsage: "[name]",
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "config",
- Usage: "config file path",
- },
- },
- Action: func(cctx *cli.Context) error {
- err := conf.InitConfig(cctx.String("config"))
- if err != nil {
- return err
- }
- db, err := dao.InitMysqlDB()
- if err != nil {
- return err
- }
- if cctx.NArg() != 1 {
- return errors.New("params need [name]")
- }
- name := cctx.Args().Get(0)
- err = db.DeleteWhitelist(name)
- if err != nil {
- return err
- }
- fmt.Printf("delete whitelist address success, name: %s \n", name)
- return nil
- },
- }
- var listCmd = &cli.Command{
- Name: "list",
- Usage: "list whitelist address",
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "config",
- Usage: "config file path",
- },
- },
- Action: func(cctx *cli.Context) error {
- err := conf.InitConfig(cctx.String("config"))
- if err != nil {
- return err
- }
- db, err := dao.InitMysqlDB()
- if err != nil {
- return err
- }
- list, err := db.GetAllWhitelists()
- if err != nil {
- return err
- }
- for _, l := range list {
- fmt.Printf("whitelist address, name: %s, addr: %s \n", l.Name, l.WhiteAddress)
- }
- return nil
- },
- }
- func stdinPassword(isConfirm bool) (string, error) {
- password, err := prompt.Stdin.PromptPassword("Password: ")
- if err != nil {
- return "", err
- }
- if isConfirm {
- confirm, err := prompt.Stdin.PromptPassword("Confirm Password: ")
- if err != nil {
- return "", fmt.Errorf("failed to read password confirmation: %v", err)
- }
- if password != confirm {
- return "", errors.New("passwords do not match")
- }
- }
- return password, nil
- }
|