arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/synchronizer/synchronizer.go
synchronizer/synchronizer.goRaw
  1package synchronizer
  2
  3import (
  4	"context"
  5	"database/sql"
  6	"fmt"
  7	"math/big"
  8
  9	"github.com/ethereum/go-ethereum"
 10	"github.com/hermeznetwork/hermez-node/common"
 11	"github.com/hermeznetwork/hermez-node/db/historydb"
 12	"github.com/hermeznetwork/hermez-node/db/statedb"
 13	"github.com/hermeznetwork/hermez-node/eth"
 14	"github.com/hermeznetwork/hermez-node/log"
 15)
 16
 17var (
 18// ErrNotAbleToSync is used when there is not possible to find a valid block to sync
 19// ErrNotAbleToSync = errors.New("it has not been possible to synchronize any block")
 20)
 21
 22// // SyncronizerState describes the synchronization progress of the smart contracts
 23// type SyncronizerState struct {
 24// 	LastUpdate                time.Time // last time this information was updated
 25// 	CurrentBatchNum           BatchNum  // Last batch that was forged on the blockchain
 26// 	CurrentBlockNum           uint64    // Last block that was mined on Ethereum
 27// 	CurrentToForgeL1TxsNum    uint32
 28// 	LastSyncedBatchNum        BatchNum // last batch synchronized by the coordinator
 29// 	LastSyncedBlockNum        uint64   // last Ethereum block synchronized by the coordinator
 30// 	LastSyncedToForgeL1TxsNum uint32
 31// }
 32
 33// // SyncStatus is returned by the Status method of the Synchronizer
 34// type SyncStatus struct {
 35// 	CurrentBlock      int64
 36// 	CurrentBatch      BatchNum
 37// 	CurrentForgerAddr ethCommon.Address
 38// 	NextForgerAddr    ethCommon.Address
 39// 	Synchronized      bool
 40// }
 41
 42// ConfigStartBlockNum sets the first block used to start tracking the smart
 43// contracts
 44type ConfigStartBlockNum struct {
 45	Rollup   int64 `validate:"required"`
 46	Auction  int64 `validate:"required"`
 47	WDelayer int64 `validate:"required"`
 48}
 49
 50// SCVariables joins all the smart contract variables in a single struct
 51type SCVariables struct {
 52	Rollup   common.RollupVariables   `validate:"required"`
 53	Auction  common.AuctionVariables  `validate:"required"`
 54	WDelayer common.WDelayerVariables `validate:"required"`
 55}
 56
 57// Config is the Synchronizer configuration
 58type Config struct {
 59	StartBlockNum    ConfigStartBlockNum
 60	InitialVariables SCVariables
 61}
 62
 63// Synchronizer implements the Synchronizer type
 64type Synchronizer struct {
 65	ethClient         eth.ClientInterface
 66	auctionConstants  common.AuctionConstants
 67	rollupConstants   common.RollupConstants
 68	wDelayerConstants common.WDelayerConstants
 69	historyDB         *historydb.HistoryDB
 70	stateDB           *statedb.StateDB
 71	cfg               Config
 72	startBlockNum     int64
 73	vars              SCVariables
 74	// firstSavedBlock  *common.Block
 75	// mux sync.Mutex
 76}
 77
 78// NewSynchronizer creates a new Synchronizer
 79func NewSynchronizer(ethClient eth.ClientInterface, historyDB *historydb.HistoryDB,
 80	stateDB *statedb.StateDB, cfg Config) (*Synchronizer, error) {
 81	auctionConstants, err := ethClient.AuctionConstants()
 82	if err != nil {
 83		log.Errorw("NewSynchronizer ethClient.AuctionConstants()", "err", err)
 84		return nil, err
 85	}
 86	rollupConstants, err := ethClient.RollupConstants()
 87	if err != nil {
 88		log.Errorw("NewSynchronizer ethClient.RollupConstants()", "err", err)
 89		return nil, err
 90	}
 91	wDelayerConstants, err := ethClient.WDelayerConstants()
 92	if err != nil {
 93		log.Errorw("NewSynchronizer ethClient.WDelayerConstants()", "err", err)
 94		return nil, err
 95	}
 96
 97	// Set startBlockNum to the minimum between Auction, Rollup and
 98	// WDelayer StartBlockNum
 99	startBlockNum := cfg.StartBlockNum.Auction
100	if startBlockNum < cfg.StartBlockNum.Rollup {
101		startBlockNum = cfg.StartBlockNum.Rollup
102	}
103	if startBlockNum < cfg.StartBlockNum.WDelayer {
104		startBlockNum = cfg.StartBlockNum.WDelayer
105	}
106	s := &Synchronizer{
107		ethClient:         ethClient,
108		auctionConstants:  *auctionConstants,
109		rollupConstants:   *rollupConstants,
110		wDelayerConstants: *wDelayerConstants,
111		historyDB:         historyDB,
112		stateDB:           stateDB,
113		cfg:               cfg,
114		startBlockNum:     startBlockNum,
115	}
116	return s, s.init()
117}
118
119// AuctionConstants returns the AuctionConstants read from the smart contract
120func (s *Synchronizer) AuctionConstants() *common.AuctionConstants {
121	return &s.auctionConstants
122}
123
124// RollupConstants returns the RollupConstants read from the smart contract
125func (s *Synchronizer) RollupConstants() *common.RollupConstants {
126	return &s.rollupConstants
127}
128
129// WDelayerConstants returns the WDelayerConstants read from the smart contract
130func (s *Synchronizer) WDelayerConstants() *common.WDelayerConstants {
131	return &s.wDelayerConstants
132}
133
134func (s *Synchronizer) init() error {
135	rollup, auction, wDelayer, err := s.historyDB.GetSCVars()
136	if err == sql.ErrNoRows {
137		rollup = &s.cfg.InitialVariables.Rollup
138		auction = &s.cfg.InitialVariables.Auction
139		wDelayer = &s.cfg.InitialVariables.WDelayer
140		log.Debug("Setting initial SCVars in HistoryDB")
141		if err = s.historyDB.SetInitialSCVars(rollup, auction, wDelayer); err != nil {
142			return err
143		}
144	}
145	s.vars.Rollup = *rollup
146	s.vars.Auction = *auction
147	s.vars.WDelayer = *wDelayer
148	return nil
149}
150
151// Sync2 attems to synchronize an ethereum block starting from lastSavedBlock.
152// If lastSavedBlock is nil, the lastSavedBlock value is obtained from de DB.
153// If a block is synched, it will be returned and also stored in the DB.  If a
154// reorg is detected, the number of discarded blocks will be returned and no
155// synchronization will be made.
156// TODO: Be smart about locking: only lock during the read/write operations
157func (s *Synchronizer) Sync2(ctx context.Context, lastSavedBlock *common.Block) (*common.BlockData, *int64, error) {
158	var nextBlockNum int64 // next block number to sync
159	if lastSavedBlock == nil {
160		var err error
161		// Get lastSavedBlock from History DB
162		lastSavedBlock, err = s.historyDB.GetLastBlock()
163		if err != nil && err != sql.ErrNoRows {
164			return nil, nil, err
165		}
166		// If we don't have any stored block, we must do a full sync
167		// starting from the startBlockNum
168		if err == sql.ErrNoRows || lastSavedBlock.EthBlockNum == 0 {
169			nextBlockNum = s.startBlockNum
170			lastSavedBlock = nil
171		}
172	}
173	if lastSavedBlock != nil {
174		nextBlockNum = lastSavedBlock.EthBlockNum + 1
175	}
176
177	ethBlock, err := s.ethClient.EthBlockByNumber(ctx, nextBlockNum)
178	if err == ethereum.NotFound {
179		return nil, nil, nil
180	} else if err != nil {
181		return nil, nil, err
182	}
183	log.Debugf("ethBlock: num: %v, parent: %v, hash: %v", ethBlock.EthBlockNum, ethBlock.ParentHash.String(), ethBlock.Hash.String())
184
185	log.Debugw("Syncing...", "block", nextBlockNum)
186
187	// Check that the obtianed ethBlock.ParentHash == prevEthBlock.Hash; if not, reorg!
188	if lastSavedBlock != nil {
189		if lastSavedBlock.Hash != ethBlock.ParentHash {
190			// Reorg detected
191			log.Debugw("Reorg Detected",
192				"blockNum", ethBlock.EthBlockNum,
193				"block.parent(got)", ethBlock.ParentHash, "parent.hash(exp)", lastSavedBlock.Hash)
194			lastDBBlockNum, err := s.reorg(lastSavedBlock)
195			if err != nil {
196				return nil, nil, err
197			}
198			discarded := lastSavedBlock.EthBlockNum - lastDBBlockNum
199			return nil, &discarded, nil
200		}
201	}
202
203	// Get data from the rollup contract
204	rollupData, err := s.rollupSync(ethBlock)
205	if err != nil {
206		return nil, nil, err
207	}
208
209	// Get data from the auction contract
210	auctionData, err := s.auctionSync(ethBlock)
211	if err != nil {
212		return nil, nil, err
213	}
214
215	// Get data from the WithdrawalDelayer contract
216	wDelayerData, err := s.wdelayerSync(ethBlock)
217	if err != nil {
218		return nil, nil, err
219	}
220
221	for i := range rollupData.Withdrawals {
222		withdrawal := &rollupData.Withdrawals[i]
223		if !withdrawal.InstantWithdraw {
224			wDelayerTransfer, ok := wDelayerData.DepositsByTxHash[withdrawal.TxHash]
225			if !ok {
226				return nil, nil, fmt.Errorf("WDelayer deposit corresponding to " +
227					"non-instant rollup withdrawal not found")
228			}
229			withdrawal.Owner = wDelayerTransfer.Owner
230			withdrawal.Token = wDelayerTransfer.Token
231		}
232	}
233
234	// Group all the block data into the structs to save into HistoryDB
235	blockData := common.BlockData{
236		Block:    *ethBlock,
237		Rollup:   *rollupData,
238		Auction:  *auctionData,
239		WDelayer: *wDelayerData,
240	}
241
242	// log.Debugw("Sync()", "block", blockData)
243	// err = s.historyDB.AddBlock(blockData.Block)
244	// if err != nil {
245	// 	return err
246	// }
247	err = s.historyDB.AddBlockSCData(&blockData)
248	if err != nil {
249		return nil, nil, err
250	}
251
252	return &blockData, nil, nil
253}
254
255// reorg manages a reorg, updating History and State DB as needed.  Keeps
256// checking previous blocks from the HistoryDB against the blockchain until a
257// block hash match is found.  All future blocks in the HistoryDB and
258// corresponding batches in StateBD are discarded.  Returns the last valid
259// blockNum from the HistoryDB.
260func (s *Synchronizer) reorg(uncleBlock *common.Block) (int64, error) {
261	blockNum := uncleBlock.EthBlockNum
262
263	for blockNum >= s.startBlockNum {
264		ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), blockNum)
265		if err != nil {
266			return 0, err
267		}
268
269		block, err := s.historyDB.GetBlock(blockNum)
270		if err != nil {
271			return 0, err
272		}
273		if block.Hash == ethBlock.Hash {
274			log.Debugf("Found valid block: %v", blockNum)
275			break
276		}
277		blockNum--
278	}
279	total := uncleBlock.EthBlockNum - blockNum
280	log.Debugw("Discarding blocks", "total", total, "from", uncleBlock.EthBlockNum, "to", blockNum+1)
281
282	// Set History DB and State DB to the correct state
283	err := s.historyDB.Reorg(blockNum)
284	if err != nil {
285		return 0, err
286	}
287
288	batchNum, err := s.historyDB.GetLastBatchNum()
289	if err != nil && err != sql.ErrNoRows {
290		return 0, err
291	}
292	if batchNum != 0 {
293		err = s.stateDB.Reset(batchNum)
294		if err != nil {
295			return 0, err
296		}
297	}
298
299	return blockNum, nil
300}
301
302// TODO: Figure out who will use the Status output, and only return what's strictly need
303/*
304// Status returns current status values from the Synchronizer
305func (s *Synchronizer) Status() (*common.SyncStatus, error) {
306	// Avoid possible inconsistencies
307	s.mux.Lock()
308	defer s.mux.Unlock()
309
310	var status *common.SyncStatus
311
312	// TODO: Join all queries to the DB into a single transaction so that
313	// we can remove the mutex locking here:
314	// - HistoryDB.GetLastBlock
315	// - HistoryDB.GetLastBatchNum
316	// - HistoryDB.GetCurrentForgerAddr
317	// - HistoryDB.GetNextForgerAddr
318
319	// Get latest block in History DB
320	lastSavedBlock, err := s.historyDB.GetLastBlock()
321	if err != nil {
322		return nil, err
323	}
324	status.CurrentBlock = lastSavedBlock.EthBlockNum
325
326	// Get latest batch in History DB
327	lastSavedBatch, err := s.historyDB.GetLastBatchNum()
328	if err != nil && err != sql.ErrNoRows {
329		return nil, err
330	}
331	status.CurrentBatch = lastSavedBatch
332
333	// Get latest blockNum in blockchain
334	latestBlockNum, err := s.ethClient.EthCurrentBlock()
335	if err != nil {
336		return nil, err
337	}
338
339	// TODO: Get CurrentForgerAddr & NextForgerAddr from the Auction SC / Or from the HistoryDB
340
341	// Check if Synchronizer is synchronized
342	status.Synchronized = status.CurrentBlock == latestBlockNum
343	return status, nil
344}
345*/
346
347// rollupSync retreives all the Rollup Smart Contract Data that happened at
348// ethBlock.blockNum with ethBlock.Hash.
349func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, error) {
350	blockNum := ethBlock.EthBlockNum
351	var rollupData = common.NewRollupData()
352	// var forgeL1TxsNum int64
353
354	// Get rollup events in the block, and make sure the block hash matches
355	// the expected one.
356	rollupEvents, blockHash, err := s.ethClient.RollupEventsByBlock(blockNum)
357	if err != nil {
358		return nil, err
359	}
360	// No events in this block
361	if blockHash == nil {
362		return &rollupData, nil
363	}
364	if *blockHash != ethBlock.Hash {
365		log.Errorw("Block hash mismatch in Rollup events", "expected", ethBlock.Hash.String(),
366			"got", blockHash.String())
367		return nil, eth.ErrBlockHashMismatchEvent
368	}
369
370	var nextForgeL1TxsNum int64 // forgeL1TxsNum for the next L1Batch
371	nextForgeL1TxsNumPtr, err := s.historyDB.GetLastL1TxsNum()
372	if err != nil {
373		return nil, err
374	}
375	if nextForgeL1TxsNumPtr != nil {
376		nextForgeL1TxsNum = *nextForgeL1TxsNumPtr + 1
377	} else {
378		nextForgeL1TxsNum = 0
379	}
380
381	// Get L1UserTX
382	rollupData.L1UserTxs, err = getL1UserTx(rollupEvents.L1UserTx, blockNum)
383	if err != nil {
384		return nil, err
385	}
386
387	// Get ForgeBatch events to get the L1CoordinatorTxs
388	for _, evtForgeBatch := range rollupEvents.ForgeBatch {
389		batchData := common.NewBatchData()
390		position := 0
391
392		// Get the input for each Tx
393		forgeBatchArgs, sender, err := s.ethClient.RollupForgeBatchArgs(evtForgeBatch.EthTxHash)
394		if err != nil {
395			return nil, err
396		}
397
398		batchNum := common.BatchNum(evtForgeBatch.BatchNum)
399		var l1UserTxs []common.L1Tx
400		// Check if this is a L1Batch to get L1 Tx from it
401		if forgeBatchArgs.L1Batch {
402			// Get L1UserTxs with toForgeL1TxsNum, which correspond
403			// to the L1UserTxs that are forged in this batch, so
404			// that stateDB can process them.
405
406			// First try to find them in HistoryDB.
407			l1UserTxs, err = s.historyDB.GetL1UserTxs(nextForgeL1TxsNum)
408			if err != nil {
409				return nil, err
410			}
411			// Apart from the DB, try to find them in this block.
412			// This could happen because in a block there could be
413			// multiple batches with L1Batch = true (although it's
414			// a very rare case).  If not found in the DB and the
415			// block doesn't contain the l1UserTxs, it means that
416			// the L1UserTxs queue with toForgeL1TxsNum was closed
417			// empty, so we leave `l1UserTxs` as an empty slice.
418			for _, l1UserTx := range rollupData.L1UserTxs {
419				if *l1UserTx.ToForgeL1TxsNum == nextForgeL1TxsNum {
420					l1UserTxs = append(l1UserTxs, l1UserTx)
421				}
422			}
423
424			position = len(l1UserTxs)
425		}
426		// Get L1 Coordinator Txs
427		for i := range forgeBatchArgs.L1CoordinatorTxs {
428			l1CoordinatorTx := forgeBatchArgs.L1CoordinatorTxs[i]
429			l1CoordinatorTx.Position = position
430			// l1CoordinatorTx.ToForgeL1TxsNum = &forgeL1TxsNum
431			l1CoordinatorTx.UserOrigin = false
432			l1CoordinatorTx.EthBlockNum = blockNum
433			l1CoordinatorTx.BatchNum = &batchNum
434			l1Tx, err := common.NewL1Tx(&l1CoordinatorTx)
435			if err != nil {
436				return nil, err
437			}
438
439			batchData.L1CoordinatorTxs = append(batchData.L1CoordinatorTxs, *l1Tx)
440			position++
441			// fmt.Println("DGB l1coordtx")
442		}
443
444		// Insert all the txs forged in this batch (l1UserTxs,
445		// L1CoordinatorTxs, PoolL2Txs) into stateDB so that they are
446		// processed.
447		poolL2Txs := common.L2TxsToPoolL2Txs(forgeBatchArgs.L2TxsData) // NOTE: This is a big ugly, find a better way
448
449		// ProcessTxs updates poolL2Txs adding: Nonce (and also TokenID, but we don't use it).
450		processTxsOut, err := s.stateDB.ProcessTxs(forgeBatchArgs.FeeIdxCoordinator, l1UserTxs,
451			batchData.L1CoordinatorTxs, poolL2Txs)
452		if err != nil {
453			return nil, err
454		}
455
456		// Set batchNum in exits
457		for i := range processTxsOut.ExitInfos {
458			exit := &processTxsOut.ExitInfos[i]
459			exit.BatchNum = batchNum
460		}
461		batchData.ExitTree = processTxsOut.ExitInfos
462
463		l2Txs, err := common.PoolL2TxsToL2Txs(poolL2Txs) // NOTE: This is a big uggly, find a better way
464		if err != nil {
465			return nil, err
466		}
467
468		for i := range l2Txs {
469			tx := &l2Txs[i]
470			tx.Position = position
471			tx.EthBlockNum = blockNum
472			tx.BatchNum = batchNum
473			nTx, err := common.NewL2Tx(tx)
474			if err != nil {
475				return nil, err
476			}
477
478			batchData.L2Txs = append(batchData.L2Txs, *nTx)
479			position++
480		}
481
482		for i := range processTxsOut.CreatedAccounts {
483			createdAccount := &processTxsOut.CreatedAccounts[i]
484			createdAccount.Nonce = 0
485			createdAccount.Balance = big.NewInt(0)
486			createdAccount.BatchNum = batchNum
487		}
488		batchData.CreatedAccounts = processTxsOut.CreatedAccounts
489
490		slotNum := int64(0)
491		if ethBlock.EthBlockNum >= s.auctionConstants.GenesisBlockNum {
492			slotNum = (ethBlock.EthBlockNum - s.auctionConstants.GenesisBlockNum) /
493				int64(s.auctionConstants.BlocksPerSlot)
494		}
495
496		// Get Batch information
497		batch := common.Batch{
498			BatchNum:           batchNum,
499			EthBlockNum:        blockNum,
500			ForgerAddr:         *sender,
501			CollectedFees:      processTxsOut.CollectedFees,
502			FeeIdxsCoordinator: forgeBatchArgs.FeeIdxCoordinator,
503			StateRoot:          forgeBatchArgs.NewStRoot,
504			NumAccounts:        len(batchData.CreatedAccounts),
505			LastIdx:            forgeBatchArgs.NewLastIdx,
506			ExitRoot:           forgeBatchArgs.NewExitRoot,
507			SlotNum:            slotNum,
508		}
509		nextForgeL1TxsNumCpy := nextForgeL1TxsNum
510		if forgeBatchArgs.L1Batch {
511			batch.ForgeL1TxsNum = &nextForgeL1TxsNumCpy
512			batchData.L1Batch = true
513			nextForgeL1TxsNum++
514		}
515		batchData.Batch = batch
516		rollupData.Batches = append(rollupData.Batches, *batchData)
517	}
518
519	// Get Registered Tokens
520	for _, evtAddToken := range rollupEvents.AddToken {
521		var token common.Token
522
523		token.TokenID = common.TokenID(evtAddToken.TokenID)
524		token.EthAddr = evtAddToken.TokenAddress
525		token.EthBlockNum = blockNum
526
527		if consts, err := s.ethClient.EthERC20Consts(evtAddToken.TokenAddress); err != nil {
528			log.Warnw("Error retreiving ERC20 token constants", "addr", evtAddToken.TokenAddress)
529			token.Name = "ERC20_ETH_ERROR"
530			token.Symbol = "ERROR"
531			token.Decimals = 1
532		} else {
533			token.Name = cutStringMax(consts.Name, 20)
534			token.Symbol = cutStringMax(consts.Symbol, 10)
535			token.Decimals = consts.Decimals
536		}
537
538		rollupData.AddedTokens = append(rollupData.AddedTokens, token)
539	}
540
541	varsUpdate := false
542
543	for _, evtUpdateForgeL1L2BatchTimeout := range rollupEvents.UpdateForgeL1L2BatchTimeout {
544		s.vars.Rollup.ForgeL1L2BatchTimeout = evtUpdateForgeL1L2BatchTimeout.NewForgeL1L2BatchTimeout
545		varsUpdate = true
546	}
547
548	for _, evtUpdateFeeAddToken := range rollupEvents.UpdateFeeAddToken {
549		s.vars.Rollup.FeeAddToken = evtUpdateFeeAddToken.NewFeeAddToken
550		varsUpdate = true
551	}
552
553	// NOTE: WithdrawDelay update doesn't have event, so we can't track changes
554
555	// NOTE: Buckets update dones't have event, so we can't track changes
556
557	for _, evtWithdraw := range rollupEvents.Withdraw {
558		rollupData.Withdrawals = append(rollupData.Withdrawals, common.WithdrawInfo{
559			Idx:             common.Idx(evtWithdraw.Idx),
560			NumExitRoot:     common.BatchNum(evtWithdraw.NumExitRoot),
561			InstantWithdraw: evtWithdraw.InstantWithdraw,
562			TxHash:          evtWithdraw.TxHash,
563		})
564	}
565
566	if varsUpdate {
567		s.vars.Rollup.EthBlockNum = blockNum
568		rollupData.Vars = &s.vars.Rollup
569	}
570
571	return &rollupData, nil
572}
573
574func cutStringMax(s string, max int) string {
575	if len(s) > max {
576		return s[:max]
577	}
578	return s
579}
580
581// auctionSync gets information from the Auction Contract
582func (s *Synchronizer) auctionSync(ethBlock *common.Block) (*common.AuctionData, error) {
583	blockNum := ethBlock.EthBlockNum
584	var auctionData = common.NewAuctionData()
585
586	// Get auction events in the block
587	auctionEvents, blockHash, err := s.ethClient.AuctionEventsByBlock(blockNum)
588	if err != nil {
589		return nil, err
590	}
591	// No events in this block
592	if blockHash == nil {
593		return &auctionData, nil
594	}
595	if *blockHash != ethBlock.Hash {
596		log.Errorw("Block hash mismatch in Auction events", "expected", ethBlock.Hash.String(),
597			"got", blockHash.String())
598		return nil, eth.ErrBlockHashMismatchEvent
599	}
600
601	// Get bids
602	for _, evtNewBid := range auctionEvents.NewBid {
603		bid := common.Bid{
604			SlotNum:     evtNewBid.Slot,
605			BidValue:    evtNewBid.BidAmount,
606			Bidder:      evtNewBid.Bidder,
607			EthBlockNum: blockNum,
608		}
609		auctionData.Bids = append(auctionData.Bids, bid)
610	}
611
612	// Get Coordinators
613	for _, evtSetCoordinator := range auctionEvents.SetCoordinator {
614		coordinator := common.Coordinator{
615			Bidder: evtSetCoordinator.BidderAddress,
616			Forger: evtSetCoordinator.ForgerAddress,
617			URL:    evtSetCoordinator.CoordinatorURL,
618		}
619		auctionData.Coordinators = append(auctionData.Coordinators, coordinator)
620	}
621
622	varsUpdate := false
623
624	for _, evt := range auctionEvents.NewSlotDeadline {
625		s.vars.Auction.SlotDeadline = evt.NewSlotDeadline
626		varsUpdate = true
627	}
628	for _, evt := range auctionEvents.NewClosedAuctionSlots {
629		s.vars.Auction.ClosedAuctionSlots = evt.NewClosedAuctionSlots
630		varsUpdate = true
631	}
632	for _, evt := range auctionEvents.NewOutbidding {
633		s.vars.Auction.Outbidding = evt.NewOutbidding
634		varsUpdate = true
635	}
636	for _, evt := range auctionEvents.NewDonationAddress {
637		s.vars.Auction.DonationAddress = evt.NewDonationAddress
638		varsUpdate = true
639	}
640	for _, evt := range auctionEvents.NewBootCoordinator {
641		s.vars.Auction.BootCoordinator = evt.NewBootCoordinator
642		varsUpdate = true
643	}
644	for _, evt := range auctionEvents.NewOpenAuctionSlots {
645		s.vars.Auction.OpenAuctionSlots = evt.NewOpenAuctionSlots
646		varsUpdate = true
647	}
648	for _, evt := range auctionEvents.NewAllocationRatio {
649		s.vars.Auction.AllocationRatio = evt.NewAllocationRatio
650		varsUpdate = true
651	}
652	for _, evt := range auctionEvents.NewDefaultSlotSetBid {
653		if evt.SlotSet > 6 { //nolint:gomnd
654			return nil, fmt.Errorf("unexpected SlotSet in "+
655				"auctionEvents.NewDefaultSlotSetBid: %v", evt.SlotSet)
656		}
657		s.vars.Auction.DefaultSlotSetBid[evt.SlotSet] = evt.NewInitialMinBid
658		varsUpdate = true
659	}
660
661	// NOTE: We ignore NewForgeAllocated
662	// NOTE: We ignore NewForge because we're already tracking ForgeBatch event from Rollup
663	// NOTE: We ignore HEZClaimed
664
665	if varsUpdate {
666		s.vars.Auction.EthBlockNum = blockNum
667		auctionData.Vars = &s.vars.Auction
668	}
669
670	return &auctionData, nil
671}
672
673// wdelayerSync gets information from the Withdrawal Delayer Contract
674func (s *Synchronizer) wdelayerSync(ethBlock *common.Block) (*common.WDelayerData, error) {
675	blockNum := ethBlock.EthBlockNum
676	wDelayerData := common.NewWDelayerData()
677
678	// Get wDelayer events in the block
679	wDelayerEvents, blockHash, err := s.ethClient.WDelayerEventsByBlock(blockNum)
680	if err != nil {
681		return nil, err
682	}
683	// No events in this block
684	if blockHash == nil {
685		return &wDelayerData, nil
686	}
687	if *blockHash != ethBlock.Hash {
688		log.Errorw("Block hash mismatch in WDelayer events", "expected", ethBlock.Hash.String(),
689			"got", blockHash.String())
690		return nil, eth.ErrBlockHashMismatchEvent
691	}
692
693	for _, evt := range wDelayerEvents.Deposit {
694		wDelayerData.Deposits = append(wDelayerData.Deposits, common.WDelayerTransfer{
695			Owner:  evt.Owner,
696			Token:  evt.Token,
697			Amount: evt.Amount,
698		})
699		wDelayerData.DepositsByTxHash[evt.TxHash] =
700			&wDelayerData.Deposits[len(wDelayerData.Deposits)-1]
701	}
702	for _, evt := range wDelayerEvents.Withdraw {
703		wDelayerData.Withdrawals = append(wDelayerData.Withdrawals, common.WDelayerTransfer{
704			Owner:  evt.Owner,
705			Token:  evt.Token,
706			Amount: evt.Amount,
707		})
708	}
709
710	varsUpdate := false
711
712	// TODO EscapeHatchWithdrawal
713	for range wDelayerEvents.EmergencyModeEnabled {
714		s.vars.WDelayer.EmergencyMode = true
715		varsUpdate = true
716	}
717	for _, evt := range wDelayerEvents.NewWithdrawalDelay {
718		s.vars.WDelayer.WithdrawalDelay = evt.WithdrawalDelay
719		varsUpdate = true
720	}
721	for _, evt := range wDelayerEvents.NewHermezKeeperAddress {
722		s.vars.WDelayer.HermezKeeperAddress = evt.NewHermezKeeperAddress
723		varsUpdate = true
724	}
725	for _, evt := range wDelayerEvents.NewWhiteHackGroupAddress {
726		s.vars.WDelayer.WhiteHackGroupAddress = evt.NewWhiteHackGroupAddress
727		varsUpdate = true
728	}
729	for _, evt := range wDelayerEvents.NewHermezGovernanceDAOAddress {
730		s.vars.WDelayer.HermezGovernanceDAOAddress = evt.NewHermezGovernanceDAOAddress
731		varsUpdate = true
732	}
733
734	if varsUpdate {
735		s.vars.WDelayer.EthBlockNum = blockNum
736		wDelayerData.Vars = &s.vars.WDelayer
737	}
738
739	return &wDelayerData, nil
740}
741
742func getL1UserTx(eventsL1UserTx []eth.RollupEventL1UserTx, blockNum int64) ([]common.L1Tx, error) {
743	l1Txs := make([]common.L1Tx, len(eventsL1UserTx))
744	for i := range eventsL1UserTx {
745		eventsL1UserTx[i].L1UserTx.EthBlockNum = blockNum
746		// Check validity of L1UserTx
747		l1Tx, err := common.NewL1Tx(&eventsL1UserTx[i].L1UserTx)
748		if err != nil {
749			return nil, err
750		}
751		l1Txs[i] = *l1Tx
752	}
753	return l1Txs, nil
754}