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 const forceStopCount = 3
123 go func() {
124 n := 0
125 for sig := range ossig {
126 if sig == os.Interrupt {
127 log.Info("Received Interrupt Signal")
128 stopCh <- nil
129 n++
130 if n == forceStopCount {
131 log.Fatalf("Received %v Interrupt Signals", forceStopCount)
132 }
133 }
134 }
135 }()
136 <-stopCh
137 node.Stop()
138
139 return nil
140}
141
142// Config is the configuration of the hermez node execution
143type Config struct {
144 mode node.Mode
145 node *config.Node
146}
147
148func parseCli(c *cli.Context) (*Config, error) {
149 cfg, err := getConfig(c)
150 if err != nil {
151 if err := cli.ShowAppHelp(c); err != nil {
152 panic(err)
153 }
154 return nil, tracerr.Wrap(err)
155 }
156 return cfg, nil
157}
158
159func getConfig(c *cli.Context) (*Config, error) {
160 var cfg Config
161 mode := c.String(flagMode)
162 nodeCfgPath := c.String(flagCfg)
163 if nodeCfgPath == "" {
164 return nil, tracerr.Wrap(fmt.Errorf("required flag \"%v\" not set", flagCfg))
165 }
166 var err error
167 switch mode {
168 case modeSync:
169 cfg.mode = node.ModeSynchronizer
170 cfg.node, err = config.LoadNode(nodeCfgPath)
171 if err != nil {
172 return nil, tracerr.Wrap(err)
173 }
174 case modeCoord:
175 cfg.mode = node.ModeCoordinator
176 cfg.node, err = config.LoadCoordinator(nodeCfgPath)
177 if err != nil {
178 return nil, tracerr.Wrap(err)
179 }
180 default:
181 return nil, tracerr.Wrap(fmt.Errorf("invalid mode \"%v\"", mode))
182 }
183
184 return &cfg, nil
185}
186
187func main() {
188 app := cli.NewApp()
189 app.Name = "hermez-node"
190 app.Version = "0.1.0-alpha"
191 app.Flags = []cli.Flag{
192 &cli.StringFlag{
193 Name: flagMode,
194 Usage: fmt.Sprintf("Set node `MODE` (can be \"%v\" or \"%v\")", modeSync, modeCoord),
195 Required: true,
196 },
197 &cli.StringFlag{
198 Name: flagCfg,
199 Usage: "Node configuration `FILE`",
200 Required: true,
201 },
202 }
203
204 app.Commands = []*cli.Command{
205 {
206 Name: "importkey",
207 Aliases: []string{},
208 Usage: "Import ethereum private key",
209 Action: cmdImportKey,
210 Flags: []cli.Flag{
211 &cli.StringFlag{
212 Name: flagSK,
213 Usage: "ethereum `PRIVATE_KEY` in hex",
214 Required: true,
215 }},
216 },
217 {
218 Name: "genbjj",
219 Aliases: []string{},
220 Usage: "Generate a new BabyJubJub key",
221 Action: cmdGenBJJ,
222 },
223 {
224 Name: "wipesql",
225 Aliases: []string{},
226 Usage: "Wipe the SQL DB (HistoryDB and L2DB), " +
227 "leaving the DB in a clean state",
228 Action: cmdWipeSQL,
229 Flags: []cli.Flag{
230 &cli.BoolFlag{
231 Name: flagYes,
232 Usage: "automatic yes to the prompt",
233 Required: false,
234 }},
235 },
236 {
237 Name: "run",
238 Aliases: []string{},
239 Usage: "Run the hermez-node in the indicated mode",
240 Action: cmdRun,
241 },
242 }
243
244 err := app.Run(os.Args)
245 if err != nil {
246 fmt.Printf("\nError: %v\n", tracerr.Sprint(err))
247 os.Exit(1)
248 }
249}