hermez-node/node/node.go
node/node.goRaw
1package node
2
3import (
4 "time"
5
6 "github.com/ethereum/go-ethereum/ethclient"
7 "github.com/hermeznetwork/hermez-node/batchbuilder"
8 "github.com/hermeznetwork/hermez-node/config"
9 "github.com/hermeznetwork/hermez-node/coordinator"
10 "github.com/hermeznetwork/hermez-node/db/historydb"
11 "github.com/hermeznetwork/hermez-node/db/l2db"
12 "github.com/hermeznetwork/hermez-node/db/statedb"
13 "github.com/hermeznetwork/hermez-node/eth"
14 "github.com/hermeznetwork/hermez-node/log"
15 "github.com/hermeznetwork/hermez-node/synchronizer"
16 "github.com/hermeznetwork/hermez-node/txselector"
17)
18
19// Mode sets the working mode of the node (synchronizer or coordinator)
20type Mode string
21
22const (
23 // ModeCoordinator defines the mode of the HermezNode as Coordinator, which
24 // means that the node is set to forge (which also will be synchronizing with
25 // the L1 blockchain state)
26 ModeCoordinator Mode = "coordinator"
27
28 // ModeSynchronizer defines the mode of the HermezNode as Synchronizer, which
29 // means that the node is set to only synchronize with the L1 blockchain state
30 // and will not forge
31 ModeSynchronizer Mode = "synchronizer"
32)
33
34// Node is the Hermez Node
35type Node struct {
36 // Coordinator
37 coord *coordinator.Coordinator
38 coordCfg *config.Coordinator
39 stopForge chan bool
40 stopGetProofCallForge chan bool
41 stopForgeCallConfirm chan bool
42 stoppedForge chan bool
43 stoppedGetProofCallForge chan bool
44 stoppedForgeCallConfirm chan bool
45
46 // Synchronizer
47 sync *synchronizer.Synchronizer
48 stopSync chan bool
49 stoppedSync chan bool
50
51 // General
52 cfg *config.Node
53 mode Mode
54}
55
56// NewNode creates a Node
57func NewNode(mode Mode, cfg *config.Node, coordCfg *config.Coordinator) (*Node, error) {
58 historyDB, err := historydb.NewHistoryDB(
59 cfg.PostgreSQL.Port,
60 cfg.PostgreSQL.Host,
61 cfg.PostgreSQL.User,
62 cfg.PostgreSQL.Password,
63 cfg.HistoryDB.Name,
64 )
65 if err != nil {
66 return nil, err
67 }
68
69 stateDB, err := statedb.NewStateDB(cfg.StateDB.Path, true, 32)
70 if err != nil {
71 return nil, err
72 }
73
74 ethClient, err := ethclient.Dial(cfg.Web3.URL)
75 if err != nil {
76 return nil, err
77 }
78 client := eth.NewClient(ethClient, nil, nil, nil)
79
80 sync := synchronizer.NewSynchronizer(client, historyDB, stateDB)
81
82 var coord *coordinator.Coordinator
83 if mode == ModeCoordinator {
84 l2DB, err := l2db.NewL2DB(
85 cfg.PostgreSQL.Port,
86 cfg.PostgreSQL.Host,
87 cfg.PostgreSQL.User,
88 cfg.PostgreSQL.Password,
89 cfg.L2DB.Name,
90 cfg.L2DB.SafetyPeriod,
91 cfg.L2DB.MaxTxs,
92 cfg.L2DB.TTL.Duration,
93 )
94 if err != nil {
95 return nil, err
96 }
97 // TODO: Get (maxL1UserTxs, maxL1OperatorTxs, maxTxs) from the smart contract
98 txSelector, err := txselector.NewTxSelector(cfg.TxSelector.Path, stateDB, l2DB, 10, 10, 10)
99 if err != nil {
100 return nil, err
101 }
102 // TODO: Get (configCircuits []ConfigCircuit, batchNum common.BatchNum, nLevels uint64) from smart contract
103 nLevels := uint64(32) //nolint:gomnd
104 batchBuilder, err := batchbuilder.NewBatchBuilder(cfg.BatchBuilder.Path, stateDB, nil, 0, nLevels)
105 if err != nil {
106 return nil, err
107 }
108 if err != nil {
109 return nil, err
110 }
111 coord = coordinator.NewCoordinator(
112 coordinator.Config{
113 ForgerAddress: coordCfg.ForgerAddress,
114 },
115 historyDB,
116 txSelector,
117 batchBuilder,
118 client,
119 )
120 }
121 return &Node{
122 coord: coord,
123 coordCfg: coordCfg,
124 sync: sync,
125 cfg: cfg,
126 mode: mode,
127 }, nil
128}
129
130// StartCoordinator starts the coordinator
131func (n *Node) StartCoordinator() {
132 log.Info("Starting Coordinator...")
133
134 n.stopForge = make(chan bool)
135 n.stopGetProofCallForge = make(chan bool)
136 n.stopForgeCallConfirm = make(chan bool)
137
138 n.stoppedForge = make(chan bool)
139 n.stoppedGetProofCallForge = make(chan bool)
140 n.stoppedForgeCallConfirm = make(chan bool)
141
142 batchCh0 := make(chan *coordinator.BatchInfo)
143 batchCh1 := make(chan *coordinator.BatchInfo)
144
145 go func() {
146 defer func() { n.stoppedForge <- true }()
147 for {
148 select {
149 case <-n.stopForge:
150 return
151 default:
152 if forge, err := n.coord.ForgeLoopFn(batchCh0, n.stopForge); err == coordinator.ErrStop {
153 return
154 } else if err != nil {
155 log.Errorw("Coordinator.ForgeLoopFn", "error", err)
156 } else if !forge {
157 time.Sleep(n.coordCfg.ForgeLoopInterval.Duration)
158 }
159 }
160 }
161 }()
162 go func() {
163 defer func() { n.stoppedGetProofCallForge <- true }()
164 for {
165 select {
166 case <-n.stopGetProofCallForge:
167 return
168 default:
169 if err := n.coord.GetProofCallForgeLoopFn(
170 batchCh0, batchCh1, n.stopGetProofCallForge); err == coordinator.ErrStop {
171 return
172 } else if err != nil {
173 log.Errorw("Coordinator.GetProofCallForgeLoopFn", "error", err)
174 }
175 }
176 }
177 }()
178 go func() {
179 defer func() { n.stoppedForgeCallConfirm <- true }()
180 for {
181 select {
182 case <-n.stopForgeCallConfirm:
183 return
184 default:
185 if err := n.coord.ForgeCallConfirmLoopFn(
186 batchCh1, n.stopForgeCallConfirm); err == coordinator.ErrStop {
187 return
188 } else if err != nil {
189 log.Errorw("Coordinator.ForgeCallConfirmLoopFn", "error", err)
190 }
191 }
192 }
193 }()
194}
195
196// StopCoordinator stops the coordinator
197func (n *Node) StopCoordinator() {
198 log.Info("Stopping Coordinator...")
199 n.stopForge <- true
200 n.stopGetProofCallForge <- true
201 n.stopForgeCallConfirm <- true
202 <-n.stoppedForge
203 <-n.stoppedGetProofCallForge
204 <-n.stoppedForgeCallConfirm
205}
206
207// StartSynchronizer starts the synchronizer
208func (n *Node) StartSynchronizer() {
209 log.Info("Starting Synchronizer...")
210 n.stopSync = make(chan bool)
211 n.stoppedSync = make(chan bool)
212 go func() {
213 defer func() { n.stoppedSync <- true }()
214 for {
215 select {
216 case <-n.stopSync:
217 log.Info("Coordinator stopped")
218 return
219 case <-time.After(n.cfg.Synchronizer.SyncLoopInterval.Duration):
220 if err := n.sync.Sync(); err != nil {
221 log.Errorw("Synchronizer.Sync", "error", err)
222 }
223 }
224 }
225 }()
226}
227
228// StopSynchronizer stops the synchronizer
229func (n *Node) StopSynchronizer() {
230 log.Info("Stopping Synchronizer...")
231 n.stopSync <- true
232 <-n.stoppedSync
233}
234
235// Start the node
236func (n *Node) Start() {
237 log.Infow("Starting node...", "mode", n.mode)
238 if n.mode == ModeCoordinator {
239 n.StartCoordinator()
240 }
241 n.StartSynchronizer()
242}
243
244// Stop the node
245func (n *Node) Stop() {
246 log.Infow("Stopping node...")
247 if n.mode == ModeCoordinator {
248 n.StopCoordinator()
249 }
250 n.StopSynchronizer()
251}