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			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}