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