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	"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			coordCfg.L2DB.Name,
 90			coordCfg.L2DB.SafetyPeriod,
 91			coordCfg.L2DB.MaxTxs,
 92			coordCfg.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(coordCfg.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(coordCfg.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		serverProofs := make([]coordinator.ServerProofInterface, len(coordCfg.ServerProofs))
112		for i, serverProofCfg := range coordCfg.ServerProofs {
113			serverProofs[i] = coordinator.NewServerProof(serverProofCfg.URL)
114		}
115		coord = coordinator.NewCoordinator(
116			coordinator.Config{
117				ForgerAddress: coordCfg.ForgerAddress,
118			},
119			historyDB,
120			txSelector,
121			batchBuilder,
122			serverProofs,
123			client,
124		)
125	}
126	return &Node{
127		coord:    coord,
128		coordCfg: coordCfg,
129		sync:     sync,
130		cfg:      cfg,
131		mode:     mode,
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}