You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
5.1 KiB

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/signal"
  6. "strings"
  7. ethKeystore "github.com/ethereum/go-ethereum/accounts/keystore"
  8. "github.com/ethereum/go-ethereum/crypto"
  9. "github.com/hermeznetwork/hermez-node/config"
  10. dbUtils "github.com/hermeznetwork/hermez-node/db"
  11. "github.com/hermeznetwork/hermez-node/log"
  12. "github.com/hermeznetwork/hermez-node/node"
  13. "github.com/hermeznetwork/tracerr"
  14. "github.com/urfave/cli/v2"
  15. )
  16. const (
  17. flagCfg = "cfg"
  18. flagMode = "mode"
  19. flagSK = "privatekey"
  20. flagYes = "yes"
  21. modeSync = "sync"
  22. modeCoord = "coord"
  23. )
  24. func cmdImportKey(c *cli.Context) error {
  25. _cfg, err := parseCli(c)
  26. if err != nil {
  27. return tracerr.Wrap(fmt.Errorf("error parsing flags and config: %w", err))
  28. }
  29. if _cfg.mode != node.ModeCoordinator {
  30. return tracerr.Wrap(fmt.Errorf("importkey must use mode coordinator"))
  31. }
  32. cfg := _cfg.node
  33. scryptN := ethKeystore.StandardScryptN
  34. scryptP := ethKeystore.StandardScryptP
  35. if cfg.Coordinator.Debug.LightScrypt {
  36. scryptN = ethKeystore.LightScryptN
  37. scryptP = ethKeystore.LightScryptP
  38. }
  39. keyStore := ethKeystore.NewKeyStore(cfg.Coordinator.EthClient.Keystore.Path,
  40. scryptN, scryptP)
  41. hexKey := c.String(flagSK)
  42. hexKey = strings.TrimPrefix(hexKey, "0x")
  43. sk, err := crypto.HexToECDSA(hexKey)
  44. if err != nil {
  45. return tracerr.Wrap(err)
  46. }
  47. acc, err := keyStore.ImportECDSA(sk, cfg.Coordinator.EthClient.Keystore.Password)
  48. if err != nil {
  49. return tracerr.Wrap(err)
  50. }
  51. log.Infow("Imported private key", "addr", acc.Address.Hex())
  52. return nil
  53. }
  54. func cmdWipeSQL(c *cli.Context) error {
  55. _cfg, err := parseCli(c)
  56. if err != nil {
  57. return tracerr.Wrap(fmt.Errorf("error parsing flags and config: %w", err))
  58. }
  59. cfg := _cfg.node
  60. yes := c.Bool(flagYes)
  61. if !yes {
  62. fmt.Print("*WARNING* Are you sure you want to delete the SQL DB? [y/N]: ")
  63. var input string
  64. if _, err := fmt.Scanln(&input); err != nil {
  65. return tracerr.Wrap(err)
  66. }
  67. input = strings.ToLower(input)
  68. if !(input == "y" || input == "yes") {
  69. return nil
  70. }
  71. }
  72. db, err := dbUtils.ConnectSQLDB(
  73. cfg.PostgreSQL.Port,
  74. cfg.PostgreSQL.Host,
  75. cfg.PostgreSQL.User,
  76. cfg.PostgreSQL.Password,
  77. cfg.PostgreSQL.Name,
  78. )
  79. if err != nil {
  80. return tracerr.Wrap(err)
  81. }
  82. log.Info("Wiping SQL DB...")
  83. if err := dbUtils.MigrationsDown(db.DB); err != nil {
  84. return tracerr.Wrap(err)
  85. }
  86. return nil
  87. }
  88. func cmdRun(c *cli.Context) error {
  89. cfg, err := parseCli(c)
  90. if err != nil {
  91. return tracerr.Wrap(fmt.Errorf("error parsing flags and config: %w", err))
  92. }
  93. node, err := node.NewNode(cfg.mode, cfg.node)
  94. if err != nil {
  95. return tracerr.Wrap(fmt.Errorf("error starting node: %w", err))
  96. }
  97. node.Start()
  98. stopCh := make(chan interface{})
  99. // catch ^C to send the stop signal
  100. ossig := make(chan os.Signal, 1)
  101. signal.Notify(ossig, os.Interrupt)
  102. go func() {
  103. for sig := range ossig {
  104. if sig == os.Interrupt {
  105. stopCh <- nil
  106. }
  107. }
  108. }()
  109. <-stopCh
  110. node.Stop()
  111. return nil
  112. }
  113. // Config is the configuration of the hermez node execution
  114. type Config struct {
  115. mode node.Mode
  116. node *config.Node
  117. }
  118. func parseCli(c *cli.Context) (*Config, error) {
  119. cfg, err := getConfig(c)
  120. if err != nil {
  121. if err := cli.ShowAppHelp(c); err != nil {
  122. panic(err)
  123. }
  124. return nil, tracerr.Wrap(err)
  125. }
  126. return cfg, nil
  127. }
  128. func getConfig(c *cli.Context) (*Config, error) {
  129. var cfg Config
  130. mode := c.String(flagMode)
  131. nodeCfgPath := c.String(flagCfg)
  132. if nodeCfgPath == "" {
  133. return nil, tracerr.Wrap(fmt.Errorf("required flag \"%v\" not set", flagCfg))
  134. }
  135. var err error
  136. switch mode {
  137. case modeSync:
  138. cfg.mode = node.ModeSynchronizer
  139. cfg.node, err = config.LoadNode(nodeCfgPath)
  140. if err != nil {
  141. return nil, tracerr.Wrap(err)
  142. }
  143. case modeCoord:
  144. cfg.mode = node.ModeCoordinator
  145. cfg.node, err = config.LoadCoordinator(nodeCfgPath)
  146. if err != nil {
  147. return nil, tracerr.Wrap(err)
  148. }
  149. default:
  150. return nil, tracerr.Wrap(fmt.Errorf("invalid mode \"%v\"", mode))
  151. }
  152. return &cfg, nil
  153. }
  154. func main() {
  155. app := cli.NewApp()
  156. app.Name = "hermez-node"
  157. app.Version = "0.1.0-alpha"
  158. app.Flags = []cli.Flag{
  159. &cli.StringFlag{
  160. Name: flagMode,
  161. Usage: fmt.Sprintf("Set node `MODE` (can be \"%v\" or \"%v\")", modeSync, modeCoord),
  162. Required: true,
  163. },
  164. &cli.StringFlag{
  165. Name: flagCfg,
  166. Usage: "Node configuration `FILE`",
  167. Required: true,
  168. },
  169. }
  170. app.Commands = []*cli.Command{
  171. {
  172. Name: "importkey",
  173. Aliases: []string{},
  174. Usage: "Import ethereum private key",
  175. Action: cmdImportKey,
  176. Flags: []cli.Flag{
  177. &cli.StringFlag{
  178. Name: flagSK,
  179. Usage: "ethereum `PRIVATE_KEY` in hex",
  180. Required: true,
  181. }},
  182. },
  183. {
  184. Name: "wipesql",
  185. Aliases: []string{},
  186. Usage: "Wipe the SQL DB (HistoryDB and L2DB), " +
  187. "leaving the DB in a clean state",
  188. Action: cmdWipeSQL,
  189. Flags: []cli.Flag{
  190. &cli.BoolFlag{
  191. Name: flagYes,
  192. Usage: "automatic yes to the prompt",
  193. Required: false,
  194. }},
  195. },
  196. {
  197. Name: "run",
  198. Aliases: []string{},
  199. Usage: "Run the hermez-node in the indicated mode",
  200. Action: cmdRun,
  201. },
  202. }
  203. err := app.Run(os.Args)
  204. if err != nil {
  205. fmt.Printf("\nError: %v\n", tracerr.Sprint(err))
  206. os.Exit(1)
  207. }
  208. }