arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
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, true, 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}