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