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