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	"sync"
   9	"time"
  10
  11	"github.com/ethereum/go-ethereum"
  12	"github.com/hermeznetwork/hermez-node/common"
  13	"github.com/hermeznetwork/hermez-node/db/historydb"
  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/tracerr"
  18)
  19
  20var (
  21// ErrNotAbleToSync is used when there is not possible to find a valid block to sync
  22// ErrNotAbleToSync = errors.New("it has not been possible to synchronize any block")
  23)
  24
  25// // SyncronizerState describes the synchronization progress of the smart contracts
  26// type SyncronizerState struct {
  27// 	LastUpdate                time.Time // last time this information was updated
  28// 	CurrentBatchNum           BatchNum  // Last batch that was forged on the blockchain
  29// 	CurrentBlockNum           uint64    // Last block that was mined on Ethereum
  30// 	CurrentToForgeL1TxsNum    uint32
  31// 	LastSyncedBatchNum        BatchNum // last batch synchronized by the coordinator
  32// 	LastSyncedBlockNum        uint64   // last Ethereum block synchronized by the coordinator
  33// 	LastSyncedToForgeL1TxsNum uint32
  34// }
  35
  36// // SyncStatus is returned by the Status method of the Synchronizer
  37// type SyncStatus struct {
  38// 	CurrentBlock      int64
  39// 	CurrentBatch      BatchNum
  40// 	CurrentForgerAddr ethCommon.Address
  41// 	NextForgerAddr    ethCommon.Address
  42// 	Synchronized      bool
  43// }
  44
  45// Stats of the syncrhonizer
  46type Stats struct {
  47	Eth struct {
  48		RefreshPeriod time.Duration
  49		Updated       time.Time
  50		FirstBlockNum int64
  51		LastBlock     common.Block
  52		LastBatch     int64
  53	}
  54	Sync struct {
  55		Updated   time.Time
  56		LastBlock common.Block
  57		LastBatch int64
  58		// LastL1BatchBlock is the last ethereum block in which an
  59		// l1Batch was forged
  60		LastL1BatchBlock  int64
  61		LastForgeL1TxsNum int64
  62		Auction           struct {
  63			CurrentSlot common.Slot
  64		}
  65	}
  66}
  67
  68// Synced returns true if the Synchronizer is up to date with the last ethereum block
  69func (s *Stats) Synced() bool {
  70	return s.Eth.LastBlock == s.Sync.LastBlock
  71}
  72
  73// TODO(Edu): Consider removing all the mutexes from StatsHolder, make
  74// Synchronizer.Stats not thread-safe, don't pass the synchronizer to the
  75// debugAPI, and have a copy of the Stats in the DebugAPI that the node passes
  76// when the Sync updates.
  77
  78// StatsHolder stores stats and that allows reading and writing them
  79// concurrently
  80type StatsHolder struct {
  81	Stats
  82	rw sync.RWMutex
  83}
  84
  85// NewStatsHolder creates a new StatsHolder
  86func NewStatsHolder(firstBlockNum int64, refreshPeriod time.Duration) *StatsHolder {
  87	stats := Stats{}
  88	stats.Eth.RefreshPeriod = refreshPeriod
  89	stats.Eth.FirstBlockNum = firstBlockNum
  90	return &StatsHolder{Stats: stats}
  91}
  92
  93// UpdateCurrentSlot updates the auction stats
  94func (s *StatsHolder) UpdateCurrentSlot(slot common.Slot) {
  95	s.rw.Lock()
  96	s.Sync.Auction.CurrentSlot = slot
  97	s.rw.Unlock()
  98}
  99
 100// UpdateSync updates the synchronizer stats
 101func (s *StatsHolder) UpdateSync(lastBlock *common.Block, lastBatch *common.BatchNum,
 102	lastL1BatchBlock *int64, lastForgeL1TxsNum *int64) {
 103	now := time.Now()
 104	s.rw.Lock()
 105	s.Sync.LastBlock = *lastBlock
 106	if lastBatch != nil {
 107		s.Sync.LastBatch = int64(*lastBatch)
 108	}
 109	if lastL1BatchBlock != nil {
 110		s.Sync.LastL1BatchBlock = *lastL1BatchBlock
 111		s.Sync.LastForgeL1TxsNum = *lastForgeL1TxsNum
 112	}
 113	s.Sync.Updated = now
 114	s.rw.Unlock()
 115}
 116
 117// UpdateEth updates the ethereum stats, only if the previous stats expired
 118func (s *StatsHolder) UpdateEth(ethClient eth.ClientInterface) error {
 119	now := time.Now()
 120	s.rw.RLock()
 121	elapsed := now.Sub(s.Eth.Updated)
 122	s.rw.RUnlock()
 123	if elapsed < s.Eth.RefreshPeriod {
 124		return nil
 125	}
 126
 127	lastBlock, err := ethClient.EthBlockByNumber(context.TODO(), -1)
 128	if err != nil {
 129		return tracerr.Wrap(err)
 130	}
 131	lastBatch, err := ethClient.RollupLastForgedBatch()
 132	if err != nil {
 133		return tracerr.Wrap(err)
 134	}
 135	s.rw.Lock()
 136	s.Eth.Updated = now
 137	s.Eth.LastBlock = *lastBlock
 138	s.Eth.LastBatch = lastBatch
 139	s.rw.Unlock()
 140	return nil
 141}
 142
 143// CopyStats returns a copy of the inner Stats
 144func (s *StatsHolder) CopyStats() *Stats {
 145	s.rw.RLock()
 146	sCopy := s.Stats
 147	if s.Sync.Auction.CurrentSlot.BidValue != nil {
 148		sCopy.Sync.Auction.CurrentSlot.BidValue =
 149			common.CopyBigInt(s.Sync.Auction.CurrentSlot.BidValue)
 150	}
 151	if s.Sync.Auction.CurrentSlot.DefaultSlotBid != nil {
 152		sCopy.Sync.Auction.CurrentSlot.DefaultSlotBid =
 153			common.CopyBigInt(s.Sync.Auction.CurrentSlot.DefaultSlotBid)
 154	}
 155	s.rw.RUnlock()
 156	return &sCopy
 157}
 158
 159func (s *StatsHolder) blocksPerc() float64 {
 160	syncLastBlockNum := s.Sync.LastBlock.Num
 161	if s.Sync.LastBlock.Num == 0 {
 162		syncLastBlockNum = s.Eth.FirstBlockNum - 1
 163	}
 164	return float64(syncLastBlockNum-(s.Eth.FirstBlockNum-1)) * 100.0 /
 165		float64(s.Eth.LastBlock.Num-(s.Eth.FirstBlockNum-1))
 166}
 167
 168func (s *StatsHolder) batchesPerc(batchNum int64) float64 {
 169	return float64(batchNum) * 100.0 /
 170		float64(s.Eth.LastBatch)
 171}
 172
 173// ConfigStartBlockNum sets the first block used to start tracking the smart
 174// contracts
 175type ConfigStartBlockNum struct {
 176	Rollup   int64 `validate:"required"`
 177	Auction  int64 `validate:"required"`
 178	WDelayer int64 `validate:"required"`
 179}
 180
 181// SCVariables joins all the smart contract variables in a single struct
 182type SCVariables struct {
 183	Rollup   common.RollupVariables   `validate:"required"`
 184	Auction  common.AuctionVariables  `validate:"required"`
 185	WDelayer common.WDelayerVariables `validate:"required"`
 186}
 187
 188// SCConsts joins all the smart contract constants in a single struct
 189type SCConsts struct {
 190	Rollup   common.RollupConstants
 191	Auction  common.AuctionConstants
 192	WDelayer common.WDelayerConstants
 193}
 194
 195// Config is the Synchronizer configuration
 196type Config struct {
 197	StartBlockNum      ConfigStartBlockNum
 198	InitialVariables   SCVariables
 199	StatsRefreshPeriod time.Duration
 200}
 201
 202// Synchronizer implements the Synchronizer type
 203type Synchronizer struct {
 204	ethClient eth.ClientInterface
 205	// auctionConstants  common.AuctionConstants
 206	// rollupConstants   common.RollupConstants
 207	// wDelayerConstants common.WDelayerConstants
 208	consts        SCConsts
 209	historyDB     *historydb.HistoryDB
 210	stateDB       *statedb.StateDB
 211	cfg           Config
 212	startBlockNum int64
 213	vars          SCVariables
 214	stats         *StatsHolder
 215	// firstSavedBlock  *common.Block
 216	// mux sync.Mutex
 217}
 218
 219// NewSynchronizer creates a new Synchronizer
 220func NewSynchronizer(ethClient eth.ClientInterface, historyDB *historydb.HistoryDB,
 221	stateDB *statedb.StateDB, cfg Config) (*Synchronizer, error) {
 222	auctionConstants, err := ethClient.AuctionConstants()
 223	if err != nil {
 224		log.Errorw("NewSynchronizer ethClient.AuctionConstants()", "err", err)
 225		return nil, tracerr.Wrap(err)
 226	}
 227	rollupConstants, err := ethClient.RollupConstants()
 228	if err != nil {
 229		log.Errorw("NewSynchronizer ethClient.RollupConstants()", "err", err)
 230		return nil, tracerr.Wrap(err)
 231	}
 232	wDelayerConstants, err := ethClient.WDelayerConstants()
 233	if err != nil {
 234		log.Errorw("NewSynchronizer ethClient.WDelayerConstants()", "err", err)
 235		return nil, tracerr.Wrap(err)
 236	}
 237
 238	// Set startBlockNum to the minimum between Auction, Rollup and
 239	// WDelayer StartBlockNum
 240	startBlockNum := cfg.StartBlockNum.Auction
 241	if startBlockNum < cfg.StartBlockNum.Rollup {
 242		startBlockNum = cfg.StartBlockNum.Rollup
 243	}
 244	if startBlockNum < cfg.StartBlockNum.WDelayer {
 245		startBlockNum = cfg.StartBlockNum.WDelayer
 246	}
 247	stats := NewStatsHolder(startBlockNum, cfg.StatsRefreshPeriod)
 248	s := &Synchronizer{
 249		ethClient: ethClient,
 250		consts: SCConsts{
 251			Rollup:   *rollupConstants,
 252			Auction:  *auctionConstants,
 253			WDelayer: *wDelayerConstants,
 254		},
 255		historyDB:     historyDB,
 256		stateDB:       stateDB,
 257		cfg:           cfg,
 258		startBlockNum: startBlockNum,
 259		stats:         stats,
 260	}
 261	return s, s.init()
 262}
 263
 264// Stats returns a copy of the Synchronizer Stats.  It is safe to call Stats()
 265// during a Sync call
 266func (s *Synchronizer) Stats() *Stats {
 267	return s.stats.CopyStats()
 268}
 269
 270// AuctionConstants returns the AuctionConstants read from the smart contract
 271func (s *Synchronizer) AuctionConstants() *common.AuctionConstants {
 272	return &s.consts.Auction
 273}
 274
 275// RollupConstants returns the RollupConstants read from the smart contract
 276func (s *Synchronizer) RollupConstants() *common.RollupConstants {
 277	return &s.consts.Rollup
 278}
 279
 280// WDelayerConstants returns the WDelayerConstants read from the smart contract
 281func (s *Synchronizer) WDelayerConstants() *common.WDelayerConstants {
 282	return &s.consts.WDelayer
 283}
 284
 285// SCVars returns a copy of the Smart Contract Variables
 286func (s *Synchronizer) SCVars() (*common.RollupVariables, *common.AuctionVariables, *common.WDelayerVariables) {
 287	return s.vars.Rollup.Copy(), s.vars.Auction.Copy(), s.vars.WDelayer.Copy()
 288}
 289
 290func (s *Synchronizer) updateCurrentSlotIfSync(batchesLen int) error {
 291	slot := common.Slot{
 292		SlotNum:    s.stats.Sync.Auction.CurrentSlot.SlotNum,
 293		BatchesLen: int(s.stats.Sync.Auction.CurrentSlot.BatchesLen),
 294	}
 295	// We want the next block because the current one is already mined
 296	blockNum := s.stats.Sync.LastBlock.Num + 1
 297	slotNum := s.consts.Auction.SlotNum(blockNum)
 298	if batchesLen == -1 {
 299		dbBatchesLen, err := s.historyDB.GetBatchesLen(slotNum)
 300		// fmt.Printf("DBG -1 from: %v, to: %v, len: %v\n", from, to, dbBatchesLen)
 301		if err != nil {
 302			log.Errorw("historyDB.GetBatchesLen", "err", err)
 303			return tracerr.Wrap(err)
 304		}
 305		slot.BatchesLen = dbBatchesLen
 306	} else if slotNum > slot.SlotNum {
 307		// fmt.Printf("DBG batchesLen Reset len: %v (%v %v)\n", batchesLen, slotNum, slot.SlotNum)
 308		slot.BatchesLen = batchesLen
 309	} else {
 310		// fmt.Printf("DBG batchesLen add len: %v: %v\n", batchesLen, slot.BatchesLen+batchesLen)
 311		slot.BatchesLen += batchesLen
 312	}
 313	slot.SlotNum = slotNum
 314	slot.StartBlock, slot.EndBlock = s.consts.Auction.SlotBlocks(slot.SlotNum)
 315	// If Synced, update the current coordinator
 316	if s.stats.Synced() && blockNum >= s.consts.Auction.GenesisBlockNum {
 317		bidCoord, err := s.historyDB.GetBestBidCoordinator(slot.SlotNum)
 318		if err != nil && tracerr.Unwrap(err) != sql.ErrNoRows {
 319			return tracerr.Wrap(err)
 320		}
 321		if tracerr.Unwrap(err) == sql.ErrNoRows {
 322			slot.BootCoord = true
 323			slot.Forger = s.vars.Auction.BootCoordinator
 324			slot.URL = "???"
 325		} else if err == nil {
 326			slot.BidValue = bidCoord.BidValue
 327			slot.DefaultSlotBid = bidCoord.DefaultSlotSetBid[slot.SlotNum%6]
 328			// Only if the highest bid value is higher than the
 329			// default slot bid, the bidder is the winner of the
 330			// slot.  Otherwise the boot coordinator is the winner.
 331			if slot.BidValue.Cmp(slot.DefaultSlotBid) >= 0 {
 332				slot.Bidder = bidCoord.Bidder
 333				slot.Forger = bidCoord.Forger
 334				slot.URL = bidCoord.URL
 335			} else {
 336				slot.BootCoord = true
 337				slot.Forger = s.vars.Auction.BootCoordinator
 338				slot.URL = "???"
 339			}
 340		}
 341
 342		// TODO: Remove this SANITY CHECK once this code is tested enough
 343		// BEGIN SANITY CHECK
 344		canForge, err := s.ethClient.AuctionCanForge(slot.Forger, blockNum)
 345		if err != nil {
 346			return tracerr.Wrap(err)
 347		}
 348		if !canForge {
 349			return tracerr.Wrap(fmt.Errorf("Synchronized value of forger address for closed slot "+
 350				"differs from smart contract: %+v", slot))
 351		}
 352		// END SANITY CHECK
 353	}
 354	s.stats.UpdateCurrentSlot(slot)
 355	return nil
 356}
 357
 358func (s *Synchronizer) init() error {
 359	// Update stats parameters so that they have valid values before the
 360	// first Sync call
 361	if err := s.stats.UpdateEth(s.ethClient); err != nil {
 362		return tracerr.Wrap(err)
 363	}
 364	lastBlock := &common.Block{}
 365	lastSavedBlock, err := s.historyDB.GetLastBlock()
 366	if err != nil && tracerr.Unwrap(err) != sql.ErrNoRows {
 367		return tracerr.Wrap(err)
 368	}
 369	// If there's no block in the DB (or we only have the default block 0),
 370	// make sure that the stateDB is clean
 371	if tracerr.Unwrap(err) == sql.ErrNoRows || lastSavedBlock.Num == 0 {
 372		if err := s.stateDB.Reset(0); err != nil {
 373			return tracerr.Wrap(err)
 374		}
 375	} else {
 376		lastBlock = lastSavedBlock
 377	}
 378	if err := s.resetState(lastBlock); err != nil {
 379		return tracerr.Wrap(err)
 380	}
 381
 382	log.Infow("Sync init block",
 383		"syncLastBlock", s.stats.Sync.LastBlock,
 384		"syncBlocksPerc", s.stats.blocksPerc(),
 385		"ethFirstBlockNum", s.stats.Eth.FirstBlockNum,
 386		"ethLastBlock", s.stats.Eth.LastBlock,
 387	)
 388	log.Infow("Sync init batch",
 389		"syncLastBatch", s.stats.Sync.LastBatch,
 390		"syncBatchesPerc", s.stats.batchesPerc(s.stats.Sync.LastBatch),
 391		"ethLastBatch", s.stats.Eth.LastBatch,
 392	)
 393	return nil
 394}
 395
 396// Sync2 attems to synchronize an ethereum block starting from lastSavedBlock.
 397// If lastSavedBlock is nil, the lastSavedBlock value is obtained from de DB.
 398// If a block is synched, it will be returned and also stored in the DB.  If a
 399// reorg is detected, the number of discarded blocks will be returned and no
 400// synchronization will be made.
 401// TODO: Be smart about locking: only lock during the read/write operations
 402func (s *Synchronizer) Sync2(ctx context.Context, lastSavedBlock *common.Block) (*common.BlockData, *int64, error) {
 403	var nextBlockNum int64 // next block number to sync
 404	if lastSavedBlock == nil {
 405		var err error
 406		// Get lastSavedBlock from History DB
 407		lastSavedBlock, err = s.historyDB.GetLastBlock()
 408		if err != nil && tracerr.Unwrap(err) != sql.ErrNoRows {
 409			return nil, nil, tracerr.Wrap(err)
 410		}
 411		// If we don't have any stored block, we must do a full sync
 412		// starting from the startBlockNum
 413		if tracerr.Unwrap(err) == sql.ErrNoRows || lastSavedBlock.Num == 0 {
 414			nextBlockNum = s.startBlockNum
 415			lastSavedBlock = nil
 416		}
 417	}
 418	if lastSavedBlock != nil {
 419		nextBlockNum = lastSavedBlock.Num + 1
 420	}
 421
 422	ethBlock, err := s.ethClient.EthBlockByNumber(ctx, nextBlockNum)
 423	if tracerr.Unwrap(err) == ethereum.NotFound {
 424		return nil, nil, nil
 425	} else if err != nil {
 426		return nil, nil, tracerr.Wrap(err)
 427	}
 428	log.Debugf("ethBlock: num: %v, parent: %v, hash: %v",
 429		ethBlock.Num, ethBlock.ParentHash.String(), ethBlock.Hash.String())
 430
 431	if err := s.stats.UpdateEth(s.ethClient); err != nil {
 432		return nil, nil, tracerr.Wrap(err)
 433	}
 434
 435	log.Debugw("Syncing...",
 436		"block", nextBlockNum,
 437		"ethLastBlock", s.stats.Eth.LastBlock,
 438	)
 439
 440	// Check that the obtianed ethBlock.ParentHash == prevEthBlock.Hash; if not, reorg!
 441	if lastSavedBlock != nil {
 442		if lastSavedBlock.Hash != ethBlock.ParentHash {
 443			// Reorg detected
 444			log.Debugw("Reorg Detected",
 445				"blockNum", ethBlock.Num,
 446				"block.parent(got)", ethBlock.ParentHash, "parent.hash(exp)", lastSavedBlock.Hash)
 447			lastDBBlockNum, err := s.reorg(lastSavedBlock)
 448			if err != nil {
 449				return nil, nil, tracerr.Wrap(err)
 450			}
 451			discarded := lastSavedBlock.Num - lastDBBlockNum
 452			return nil, &discarded, nil
 453		}
 454	}
 455
 456	// Get data from the rollup contract
 457	rollupData, err := s.rollupSync(ethBlock)
 458	if err != nil {
 459		return nil, nil, tracerr.Wrap(err)
 460	}
 461
 462	// Get data from the auction contract
 463	auctionData, err := s.auctionSync(ethBlock)
 464	if err != nil {
 465		return nil, nil, tracerr.Wrap(err)
 466	}
 467
 468	// Get data from the WithdrawalDelayer contract
 469	wDelayerData, err := s.wdelayerSync(ethBlock)
 470	if err != nil {
 471		return nil, nil, tracerr.Wrap(err)
 472	}
 473
 474	for i := range rollupData.Withdrawals {
 475		withdrawal := &rollupData.Withdrawals[i]
 476		if !withdrawal.InstantWithdraw {
 477			wDelayerTransfers := wDelayerData.DepositsByTxHash[withdrawal.TxHash]
 478			if len(wDelayerTransfers) == 0 {
 479				return nil, nil, tracerr.Wrap(fmt.Errorf("WDelayer deposit corresponding to " +
 480					"non-instant rollup withdrawal not found"))
 481			}
 482			// Pop the first wDelayerTransfer to consume them in chronological order
 483			wDelayerTransfer := wDelayerTransfers[0]
 484			wDelayerData.DepositsByTxHash[withdrawal.TxHash] =
 485				wDelayerData.DepositsByTxHash[withdrawal.TxHash][1:]
 486
 487			withdrawal.Owner = wDelayerTransfer.Owner
 488			withdrawal.Token = wDelayerTransfer.Token
 489		}
 490	}
 491
 492	// Group all the block data into the structs to save into HistoryDB
 493	blockData := common.BlockData{
 494		Block:    *ethBlock,
 495		Rollup:   *rollupData,
 496		Auction:  *auctionData,
 497		WDelayer: *wDelayerData,
 498	}
 499
 500	// log.Debugw("Sync()", "block", blockData)
 501	// err = s.historyDB.AddBlock(blockData.Block)
 502	// if err != nil {
 503	// 	return err
 504	// }
 505	err = s.historyDB.AddBlockSCData(&blockData)
 506	if err != nil {
 507		return nil, nil, tracerr.Wrap(err)
 508	}
 509
 510	batchesLen := len(rollupData.Batches)
 511	if batchesLen == 0 {
 512		s.stats.UpdateSync(ethBlock, nil, nil, nil)
 513	} else {
 514		var lastL1BatchBlock *int64
 515		var lastForgeL1TxsNum *int64
 516		for _, batchData := range rollupData.Batches {
 517			if batchData.L1Batch {
 518				lastL1BatchBlock = &batchData.Batch.EthBlockNum
 519				lastForgeL1TxsNum = batchData.Batch.ForgeL1TxsNum
 520			}
 521		}
 522		s.stats.UpdateSync(ethBlock,
 523			&rollupData.Batches[batchesLen-1].Batch.BatchNum, lastL1BatchBlock, lastForgeL1TxsNum)
 524	}
 525	if err := s.updateCurrentSlotIfSync(len(rollupData.Batches)); err != nil {
 526		return nil, nil, tracerr.Wrap(err)
 527	}
 528
 529	log.Debugw("Synced block",
 530		"syncLastBlockNum", s.stats.Sync.LastBlock.Num,
 531		"syncBlocksPerc", s.stats.blocksPerc(),
 532		"ethLastBlockNum", s.stats.Eth.LastBlock.Num,
 533	)
 534	for _, batchData := range rollupData.Batches {
 535		log.Debugw("Synced batch",
 536			"syncLastBatch", batchData.Batch.BatchNum,
 537			"syncBatchesPerc", s.stats.batchesPerc(int64(batchData.Batch.BatchNum)),
 538			"ethLastBatch", s.stats.Eth.LastBatch,
 539		)
 540	}
 541
 542	return &blockData, nil, nil
 543}
 544
 545// reorg manages a reorg, updating History and State DB as needed.  Keeps
 546// checking previous blocks from the HistoryDB against the blockchain until a
 547// block hash match is found.  All future blocks in the HistoryDB and
 548// corresponding batches in StateBD are discarded.  Returns the last valid
 549// blockNum from the HistoryDB.
 550func (s *Synchronizer) reorg(uncleBlock *common.Block) (int64, error) {
 551	blockNum := uncleBlock.Num
 552
 553	var block *common.Block
 554	for blockNum >= s.startBlockNum {
 555		ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), blockNum)
 556		if err != nil {
 557			log.Errorw("ethClient.EthBlockByNumber", "err", err)
 558			return 0, tracerr.Wrap(err)
 559		}
 560
 561		block, err = s.historyDB.GetBlock(blockNum)
 562		if err != nil {
 563			log.Errorw("historyDB.GetBlock", "err", err)
 564			return 0, tracerr.Wrap(err)
 565		}
 566		if block.Hash == ethBlock.Hash {
 567			log.Debugf("Found valid block: %v", blockNum)
 568			break
 569		}
 570		blockNum--
 571	}
 572	total := uncleBlock.Num - block.Num
 573	log.Debugw("Discarding blocks", "total", total, "from", uncleBlock.Num, "to", block.Num+1)
 574
 575	// Set History DB and State DB to the correct state
 576	err := s.historyDB.Reorg(block.Num)
 577	if err != nil {
 578		return 0, tracerr.Wrap(err)
 579	}
 580
 581	if err := s.resetState(block); err != nil {
 582		return 0, tracerr.Wrap(err)
 583	}
 584
 585	return block.Num, nil
 586}
 587
 588func (s *Synchronizer) resetState(block *common.Block) error {
 589	rollup, auction, wDelayer, err := s.historyDB.GetSCVars()
 590	// If SCVars are not in the HistoryDB, this is probably the first run
 591	// of the Synchronizer: store the initial vars taken from config
 592	if tracerr.Unwrap(err) == sql.ErrNoRows {
 593		rollup = &s.cfg.InitialVariables.Rollup
 594		auction = &s.cfg.InitialVariables.Auction
 595		wDelayer = &s.cfg.InitialVariables.WDelayer
 596		log.Info("Setting initial SCVars in HistoryDB")
 597		if err = s.historyDB.SetInitialSCVars(rollup, auction, wDelayer); err != nil {
 598			log.Errorw("historyDB.SetInitialSCVars", "err", err)
 599			return tracerr.Wrap(err)
 600		}
 601	}
 602	s.vars.Rollup = *rollup
 603	s.vars.Auction = *auction
 604	s.vars.WDelayer = *wDelayer
 605
 606	batchNum, err := s.historyDB.GetLastBatchNum()
 607	if err != nil && tracerr.Unwrap(err) != sql.ErrNoRows {
 608		log.Errorw("historyDB.GetLastBatchNum", "err", err)
 609		return tracerr.Wrap(err)
 610	}
 611	if tracerr.Unwrap(err) == sql.ErrNoRows {
 612		batchNum = 0
 613	}
 614
 615	lastL1BatchBlockNum, err := s.historyDB.GetLastL1BatchBlockNum()
 616	if err != nil && tracerr.Unwrap(err) != sql.ErrNoRows {
 617		log.Errorw("historyDB.GetLastL1BatchBlockNum", "err", err)
 618		return tracerr.Wrap(err)
 619	}
 620	if tracerr.Unwrap(err) == sql.ErrNoRows {
 621		lastL1BatchBlockNum = 0
 622	}
 623
 624	lastForgeL1TxsNum, err := s.historyDB.GetLastL1TxsNum()
 625	if err != nil && tracerr.Unwrap(err) != sql.ErrNoRows {
 626		log.Errorw("historyDB.GetLastL1BatchBlockNum", "err", err)
 627		return tracerr.Wrap(err)
 628	}
 629	if tracerr.Unwrap(err) == sql.ErrNoRows || lastForgeL1TxsNum == nil {
 630		n := int64(-1)
 631		lastForgeL1TxsNum = &n
 632	}
 633
 634	err = s.stateDB.Reset(batchNum)
 635	if err != nil {
 636		log.Errorw("stateDB.Reset", "err", err)
 637		return tracerr.Wrap(err)
 638	}
 639
 640	s.stats.UpdateSync(block, &batchNum, &lastL1BatchBlockNum, lastForgeL1TxsNum)
 641
 642	if err := s.updateCurrentSlotIfSync(-1); err != nil {
 643		return tracerr.Wrap(err)
 644	}
 645	return nil
 646}
 647
 648// TODO: Figure out who will use the Status output, and only return what's strictly need
 649/*
 650// Status returns current status values from the Synchronizer
 651func (s *Synchronizer) Status() (*common.SyncStatus, error) {
 652	// Avoid possible inconsistencies
 653	s.mux.Lock()
 654	defer s.mux.Unlock()
 655
 656	var status *common.SyncStatus
 657
 658	// TODO: Join all queries to the DB into a single transaction so that
 659	// we can remove the mutex locking here:
 660	// - HistoryDB.GetLastBlock
 661	// - HistoryDB.GetLastBatchNum
 662	// - HistoryDB.GetCurrentForgerAddr
 663	// - HistoryDB.GetNextForgerAddr
 664
 665	// Get latest block in History DB
 666	lastSavedBlock, err := s.historyDB.GetLastBlock()
 667	if err != nil {
 668		return nil, err
 669	}
 670	status.CurrentBlock = lastSavedBlock.EthBlockNum
 671
 672	// Get latest batch in History DB
 673	lastSavedBatch, err := s.historyDB.GetLastBatchNum()
 674	if err != nil && err != sql.ErrNoRows {
 675		return nil, err
 676	}
 677	status.CurrentBatch = lastSavedBatch
 678
 679	// Get latest blockNum in blockchain
 680	latestBlockNum, err := s.ethClient.EthLastBlock()
 681	if err != nil {
 682		return nil, err
 683	}
 684
 685	// TODO: Get CurrentForgerAddr & NextForgerAddr from the Auction SC / Or from the HistoryDB
 686
 687	// Check if Synchronizer is synchronized
 688	status.Synchronized = status.CurrentBlock == latestBlockNum
 689	return status, nil
 690}
 691*/
 692
 693// rollupSync retreives all the Rollup Smart Contract Data that happened at
 694// ethBlock.blockNum with ethBlock.Hash.
 695func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, error) {
 696	blockNum := ethBlock.Num
 697	var rollupData = common.NewRollupData()
 698	// var forgeL1TxsNum int64
 699
 700	// Get rollup events in the block, and make sure the block hash matches
 701	// the expected one.
 702	rollupEvents, blockHash, err := s.ethClient.RollupEventsByBlock(blockNum)
 703	if err != nil {
 704		return nil, tracerr.Wrap(err)
 705	}
 706	// No events in this block
 707	if blockHash == nil {
 708		return &rollupData, nil
 709	}
 710	if *blockHash != ethBlock.Hash {
 711		log.Errorw("Block hash mismatch in Rollup events", "expected", ethBlock.Hash.String(),
 712			"got", blockHash.String())
 713		return nil, tracerr.Wrap(eth.ErrBlockHashMismatchEvent)
 714	}
 715
 716	var nextForgeL1TxsNum int64 // forgeL1TxsNum for the next L1Batch
 717	nextForgeL1TxsNumPtr, err := s.historyDB.GetLastL1TxsNum()
 718	if err != nil {
 719		return nil, tracerr.Wrap(err)
 720	}
 721	if nextForgeL1TxsNumPtr != nil {
 722		nextForgeL1TxsNum = *nextForgeL1TxsNumPtr + 1
 723	} else {
 724		nextForgeL1TxsNum = 0
 725	}
 726
 727	// Get L1UserTX
 728	rollupData.L1UserTxs, err = getL1UserTx(rollupEvents.L1UserTx, blockNum)
 729	if err != nil {
 730		return nil, tracerr.Wrap(err)
 731	}
 732
 733	// Get ForgeBatch events to get the L1CoordinatorTxs
 734	for _, evtForgeBatch := range rollupEvents.ForgeBatch {
 735		batchData := common.NewBatchData()
 736		position := 0
 737
 738		// Get the input for each Tx
 739		forgeBatchArgs, sender, err := s.ethClient.RollupForgeBatchArgs(evtForgeBatch.EthTxHash,
 740			evtForgeBatch.L1UserTxsLen)
 741		if err != nil {
 742			return nil, tracerr.Wrap(err)
 743		}
 744
 745		batchNum := common.BatchNum(evtForgeBatch.BatchNum)
 746		var l1UserTxs []common.L1Tx
 747		// Check if this is a L1Batch to get L1 Tx from it
 748		if forgeBatchArgs.L1Batch {
 749			// Get L1UserTxs with toForgeL1TxsNum, which correspond
 750			// to the L1UserTxs that are forged in this batch, so
 751			// that stateDB can process them.
 752
 753			// First try to find them in HistoryDB.
 754			l1UserTxs, err = s.historyDB.GetUnforgedL1UserTxs(nextForgeL1TxsNum)
 755			if err != nil {
 756				return nil, tracerr.Wrap(err)
 757			}
 758			// Apart from the DB, try to find them in this block.
 759			// This could happen because in a block there could be
 760			// multiple batches with L1Batch = true (although it's
 761			// a very rare case).  If not found in the DB and the
 762			// block doesn't contain the l1UserTxs, it means that
 763			// the L1UserTxs queue with toForgeL1TxsNum was closed
 764			// empty, so we leave `l1UserTxs` as an empty slice.
 765			for _, l1UserTx := range rollupData.L1UserTxs {
 766				if *l1UserTx.ToForgeL1TxsNum == nextForgeL1TxsNum {
 767					l1UserTxs = append(l1UserTxs, l1UserTx)
 768				}
 769			}
 770
 771			position = len(l1UserTxs)
 772		}
 773		// Get L1 Coordinator Txs
 774		for i := range forgeBatchArgs.L1CoordinatorTxs {
 775			l1CoordinatorTx := forgeBatchArgs.L1CoordinatorTxs[i]
 776			l1CoordinatorTx.Position = position
 777			// l1CoordinatorTx.ToForgeL1TxsNum = &forgeL1TxsNum
 778			l1CoordinatorTx.UserOrigin = false
 779			l1CoordinatorTx.EthBlockNum = blockNum
 780			l1CoordinatorTx.BatchNum = &batchNum
 781			l1Tx, err := common.NewL1Tx(&l1CoordinatorTx)
 782			if err != nil {
 783				return nil, tracerr.Wrap(err)
 784			}
 785
 786			batchData.L1CoordinatorTxs = append(batchData.L1CoordinatorTxs, *l1Tx)
 787			position++
 788			// fmt.Println("DGB l1coordtx")
 789		}
 790
 791		// Insert all the txs forged in this batch (l1UserTxs,
 792		// L1CoordinatorTxs, PoolL2Txs) into stateDB so that they are
 793		// processed.
 794		poolL2Txs := common.L2TxsToPoolL2Txs(forgeBatchArgs.L2TxsData) // NOTE: This is a big ugly, find a better way
 795
 796		// ProcessTxs updates poolL2Txs adding: Nonce (and also TokenID, but we don't use it).
 797		//nolint:gomnd
 798		ptc := statedb.ProcessTxsConfig{ // TODO TMP
 799			NLevels:  32,
 800			MaxFeeTx: 64,
 801			MaxTx:    512,
 802			MaxL1Tx:  64,
 803		}
 804		processTxsOut, err := s.stateDB.ProcessTxs(ptc, forgeBatchArgs.FeeIdxCoordinator,
 805			l1UserTxs, batchData.L1CoordinatorTxs, poolL2Txs)
 806		if err != nil {
 807			return nil, tracerr.Wrap(err)
 808		}
 809		// Set the BatchNum in the forged L1UserTxs
 810		for i := range l1UserTxs {
 811			l1UserTxs[i].BatchNum = &batchNum
 812		}
 813		batchData.L1UserTxs = l1UserTxs
 814
 815		// Set batchNum in exits
 816		for i := range processTxsOut.ExitInfos {
 817			exit := &processTxsOut.ExitInfos[i]
 818			exit.BatchNum = batchNum
 819		}
 820		batchData.ExitTree = processTxsOut.ExitInfos
 821
 822		l2Txs, err := common.PoolL2TxsToL2Txs(poolL2Txs) // NOTE: This is a big uggly, find a better way
 823		if err != nil {
 824			return nil, tracerr.Wrap(err)
 825		}
 826
 827		for i := range l2Txs {
 828			tx := &l2Txs[i]
 829			tx.Position = position
 830			tx.EthBlockNum = blockNum
 831			tx.BatchNum = batchNum
 832			nTx, err := common.NewL2Tx(tx)
 833			if err != nil {
 834				return nil, tracerr.Wrap(err)
 835			}
 836
 837			batchData.L2Txs = append(batchData.L2Txs, *nTx)
 838			position++
 839		}
 840
 841		for i := range processTxsOut.CreatedAccounts {
 842			createdAccount := &processTxsOut.CreatedAccounts[i]
 843			createdAccount.Nonce = 0
 844			createdAccount.Balance = big.NewInt(0)
 845			createdAccount.BatchNum = batchNum
 846		}
 847		batchData.CreatedAccounts = processTxsOut.CreatedAccounts
 848
 849		slotNum := int64(0)
 850		if ethBlock.Num >= s.consts.Auction.GenesisBlockNum {
 851			slotNum = (ethBlock.Num - s.consts.Auction.GenesisBlockNum) /
 852				int64(s.consts.Auction.BlocksPerSlot)
 853		}
 854
 855		// Get Batch information
 856		batch := common.Batch{
 857			BatchNum:           batchNum,
 858			EthBlockNum:        blockNum,
 859			ForgerAddr:         *sender,
 860			CollectedFees:      processTxsOut.CollectedFees,
 861			FeeIdxsCoordinator: forgeBatchArgs.FeeIdxCoordinator,
 862			StateRoot:          forgeBatchArgs.NewStRoot,
 863			NumAccounts:        len(batchData.CreatedAccounts),
 864			LastIdx:            forgeBatchArgs.NewLastIdx,
 865			ExitRoot:           forgeBatchArgs.NewExitRoot,
 866			SlotNum:            slotNum,
 867		}
 868		nextForgeL1TxsNumCpy := nextForgeL1TxsNum
 869		if forgeBatchArgs.L1Batch {
 870			batch.ForgeL1TxsNum = &nextForgeL1TxsNumCpy
 871			batchData.L1Batch = true
 872			nextForgeL1TxsNum++
 873		}
 874		batchData.Batch = batch
 875		rollupData.Batches = append(rollupData.Batches, *batchData)
 876	}
 877
 878	// Get Registered Tokens
 879	for _, evtAddToken := range rollupEvents.AddToken {
 880		var token common.Token
 881
 882		token.TokenID = common.TokenID(evtAddToken.TokenID)
 883		token.EthAddr = evtAddToken.TokenAddress
 884		token.EthBlockNum = blockNum
 885
 886		if consts, err := s.ethClient.EthERC20Consts(evtAddToken.TokenAddress); err != nil {
 887			log.Warnw("Error retreiving ERC20 token constants", "addr", evtAddToken.TokenAddress)
 888			token.Name = "ERC20_ETH_ERROR"
 889			token.Symbol = "ERROR"
 890			token.Decimals = 1
 891		} else {
 892			token.Name = cutStringMax(consts.Name, 20)
 893			token.Symbol = cutStringMax(consts.Symbol, 10)
 894			token.Decimals = consts.Decimals
 895		}
 896
 897		rollupData.AddedTokens = append(rollupData.AddedTokens, token)
 898	}
 899
 900	for _, evt := range rollupEvents.UpdateBucketWithdraw {
 901		rollupData.UpdateBucketWithdraw = append(rollupData.UpdateBucketWithdraw,
 902			common.BucketUpdate{
 903				EthBlockNum: blockNum,
 904				NumBucket:   evt.NumBucket,
 905				BlockStamp:  evt.BlockStamp,
 906				Withdrawals: evt.Withdrawals,
 907			})
 908	}
 909
 910	for _, evt := range rollupEvents.Withdraw {
 911		rollupData.Withdrawals = append(rollupData.Withdrawals, common.WithdrawInfo{
 912			Idx:             common.Idx(evt.Idx),
 913			NumExitRoot:     common.BatchNum(evt.NumExitRoot),
 914			InstantWithdraw: evt.InstantWithdraw,
 915			TxHash:          evt.TxHash,
 916		})
 917	}
 918
 919	for _, evt := range rollupEvents.UpdateTokenExchange {
 920		if len(evt.AddressArray) != len(evt.ValueArray) {
 921			return nil, tracerr.Wrap(fmt.Errorf("in RollupEventUpdateTokenExchange "+
 922				"len(AddressArray) != len(ValueArray) (%v != %v)",
 923				len(evt.AddressArray), len(evt.ValueArray)))
 924		}
 925		for i := range evt.AddressArray {
 926			rollupData.TokenExchanges = append(rollupData.TokenExchanges,
 927				common.TokenExchange{
 928					EthBlockNum: blockNum,
 929					Address:     evt.AddressArray[i],
 930					ValueUSD:    int64(evt.ValueArray[i]),
 931				})
 932		}
 933	}
 934
 935	varsUpdate := false
 936
 937	for _, evt := range rollupEvents.UpdateForgeL1L2BatchTimeout {
 938		s.vars.Rollup.ForgeL1L2BatchTimeout = evt.NewForgeL1L2BatchTimeout
 939		varsUpdate = true
 940	}
 941
 942	for _, evt := range rollupEvents.UpdateFeeAddToken {
 943		s.vars.Rollup.FeeAddToken = evt.NewFeeAddToken
 944		varsUpdate = true
 945	}
 946
 947	for _, evt := range rollupEvents.UpdateWithdrawalDelay {
 948		s.vars.Rollup.WithdrawalDelay = evt.NewWithdrawalDelay
 949		varsUpdate = true
 950	}
 951
 952	// NOTE: We skip the event rollupEvents.SafeMode because the
 953	// implementation RollupEventsByBlock already inserts a non-existing
 954	// RollupEventUpdateBucketsParameters into UpdateBucketsParameters with
 955	// all the bucket values at 0 and SafeMode = true
 956
 957	for _, evt := range rollupEvents.UpdateBucketsParameters {
 958		for i, bucket := range evt.ArrayBuckets {
 959			s.vars.Rollup.Buckets[i] = common.BucketParams{
 960				CeilUSD:             bucket.CeilUSD,
 961				Withdrawals:         bucket.Withdrawals,
 962				BlockWithdrawalRate: bucket.BlockWithdrawalRate,
 963				MaxWithdrawals:      bucket.MaxWithdrawals,
 964			}
 965		}
 966		s.vars.Rollup.SafeMode = evt.SafeMode
 967		varsUpdate = true
 968	}
 969
 970	if varsUpdate {
 971		s.vars.Rollup.EthBlockNum = blockNum
 972		rollupData.Vars = s.vars.Rollup.Copy()
 973	}
 974
 975	return &rollupData, nil
 976}
 977
 978func cutStringMax(s string, max int) string {
 979	if len(s) > max {
 980		return s[:max]
 981	}
 982	return s
 983}
 984
 985// auctionSync gets information from the Auction Contract
 986func (s *Synchronizer) auctionSync(ethBlock *common.Block) (*common.AuctionData, error) {
 987	blockNum := ethBlock.Num
 988	var auctionData = common.NewAuctionData()
 989
 990	// Get auction events in the block
 991	auctionEvents, blockHash, err := s.ethClient.AuctionEventsByBlock(blockNum)
 992	if err != nil {
 993		return nil, tracerr.Wrap(err)
 994	}
 995	// No events in this block
 996	if blockHash == nil {
 997		return &auctionData, nil
 998	}
 999	if *blockHash != ethBlock.Hash {
1000		log.Errorw("Block hash mismatch in Auction events", "expected", ethBlock.Hash.String(),
1001			"got", blockHash.String())
1002		return nil, tracerr.Wrap(eth.ErrBlockHashMismatchEvent)
1003	}
1004
1005	// Get bids
1006	for _, evt := range auctionEvents.NewBid {
1007		bid := common.Bid{
1008			SlotNum:     evt.Slot,
1009			BidValue:    evt.BidAmount,
1010			Bidder:      evt.Bidder,
1011			EthBlockNum: blockNum,
1012		}
1013		auctionData.Bids = append(auctionData.Bids, bid)
1014	}
1015
1016	// Get Coordinators
1017	for _, evt := range auctionEvents.SetCoordinator {
1018		coordinator := common.Coordinator{
1019			Bidder:      evt.BidderAddress,
1020			Forger:      evt.ForgerAddress,
1021			URL:         evt.CoordinatorURL,
1022			EthBlockNum: blockNum,
1023		}
1024		auctionData.Coordinators = append(auctionData.Coordinators, coordinator)
1025	}
1026
1027	varsUpdate := false
1028
1029	for _, evt := range auctionEvents.NewSlotDeadline {
1030		s.vars.Auction.SlotDeadline = evt.NewSlotDeadline
1031		varsUpdate = true
1032	}
1033	for _, evt := range auctionEvents.NewClosedAuctionSlots {
1034		s.vars.Auction.ClosedAuctionSlots = evt.NewClosedAuctionSlots
1035		varsUpdate = true
1036	}
1037	for _, evt := range auctionEvents.NewOutbidding {
1038		s.vars.Auction.Outbidding = evt.NewOutbidding
1039		varsUpdate = true
1040	}
1041	for _, evt := range auctionEvents.NewDonationAddress {
1042		s.vars.Auction.DonationAddress = evt.NewDonationAddress
1043		varsUpdate = true
1044	}
1045	for _, evt := range auctionEvents.NewBootCoordinator {
1046		s.vars.Auction.BootCoordinator = evt.NewBootCoordinator
1047		s.vars.Auction.BootCoordinatorURL = evt.NewBootCoordinatorURL
1048		varsUpdate = true
1049	}
1050	for _, evt := range auctionEvents.NewOpenAuctionSlots {
1051		s.vars.Auction.OpenAuctionSlots = evt.NewOpenAuctionSlots
1052		varsUpdate = true
1053	}
1054	for _, evt := range auctionEvents.NewAllocationRatio {
1055		s.vars.Auction.AllocationRatio = evt.NewAllocationRatio
1056		varsUpdate = true
1057	}
1058	for _, evt := range auctionEvents.NewDefaultSlotSetBid {
1059		if evt.SlotSet > 6 { //nolint:gomnd
1060			return nil, tracerr.Wrap(fmt.Errorf("unexpected SlotSet in "+
1061				"auctionEvents.NewDefaultSlotSetBid: %v", evt.SlotSet))
1062		}
1063		s.vars.Auction.DefaultSlotSetBid[evt.SlotSet] = evt.NewInitialMinBid
1064		s.vars.Auction.DefaultSlotSetBidSlotNum = s.consts.Auction.SlotNum(blockNum) +
1065			int64(s.vars.Auction.ClosedAuctionSlots) + 1
1066		varsUpdate = true
1067	}
1068
1069	// NOTE: We ignore NewForgeAllocated
1070	// NOTE: We ignore NewForge because we're already tracking ForgeBatch event from Rollup
1071	// NOTE: We ignore HEZClaimed
1072
1073	if varsUpdate {
1074		s.vars.Auction.EthBlockNum = blockNum
1075		auctionData.Vars = s.vars.Auction.Copy()
1076	}
1077
1078	return &auctionData, nil
1079}
1080
1081// wdelayerSync gets information from the Withdrawal Delayer Contract
1082func (s *Synchronizer) wdelayerSync(ethBlock *common.Block) (*common.WDelayerData, error) {
1083	blockNum := ethBlock.Num
1084	wDelayerData := common.NewWDelayerData()
1085
1086	// Get wDelayer events in the block
1087	wDelayerEvents, blockHash, err := s.ethClient.WDelayerEventsByBlock(blockNum)
1088	if err != nil {
1089		return nil, tracerr.Wrap(err)
1090	}
1091	// No events in this block
1092	if blockHash == nil {
1093		return &wDelayerData, nil
1094	}
1095	if *blockHash != ethBlock.Hash {
1096		log.Errorw("Block hash mismatch in WDelayer events", "expected", ethBlock.Hash.String(),
1097			"got", blockHash.String())
1098		return nil, tracerr.Wrap(eth.ErrBlockHashMismatchEvent)
1099	}
1100
1101	for _, evt := range wDelayerEvents.Deposit {
1102		wDelayerData.Deposits = append(wDelayerData.Deposits, common.WDelayerTransfer{
1103			Owner:  evt.Owner,
1104			Token:  evt.Token,
1105			Amount: evt.Amount,
1106		})
1107		wDelayerData.DepositsByTxHash[evt.TxHash] =
1108			append(wDelayerData.DepositsByTxHash[evt.TxHash],
1109				&wDelayerData.Deposits[len(wDelayerData.Deposits)-1])
1110	}
1111	for _, evt := range wDelayerEvents.Withdraw {
1112		wDelayerData.Withdrawals = append(wDelayerData.Withdrawals, common.WDelayerTransfer{
1113			Owner:  evt.Owner,
1114			Token:  evt.Token,
1115			Amount: evt.Amount,
1116		})
1117	}
1118	for _, evt := range wDelayerEvents.EscapeHatchWithdrawal {
1119		wDelayerData.EscapeHatchWithdrawals = append(wDelayerData.EscapeHatchWithdrawals,
1120			common.WDelayerEscapeHatchWithdrawal{
1121				EthBlockNum: blockNum,
1122				Who:         evt.Who,
1123				To:          evt.To,
1124				TokenAddr:   evt.Token,
1125				Amount:      evt.Amount,
1126			})
1127	}
1128
1129	varsUpdate := false
1130
1131	for range wDelayerEvents.EmergencyModeEnabled {
1132		s.vars.WDelayer.EmergencyMode = true
1133		varsUpdate = true
1134	}
1135	for _, evt := range wDelayerEvents.NewWithdrawalDelay {
1136		s.vars.WDelayer.WithdrawalDelay = evt.WithdrawalDelay
1137		varsUpdate = true
1138	}
1139	for _, evt := range wDelayerEvents.NewEmergencyCouncil {
1140		s.vars.WDelayer.EmergencyCouncilAddress = evt.NewEmergencyCouncil
1141		varsUpdate = true
1142	}
1143	for _, evt := range wDelayerEvents.NewHermezGovernanceAddress {
1144		s.vars.WDelayer.HermezGovernanceAddress = evt.NewHermezGovernanceAddress
1145		varsUpdate = true
1146	}
1147
1148	if varsUpdate {
1149		s.vars.WDelayer.EthBlockNum = blockNum
1150		wDelayerData.Vars = s.vars.WDelayer.Copy()
1151	}
1152
1153	return &wDelayerData, nil
1154}
1155
1156func getL1UserTx(eventsL1UserTx []eth.RollupEventL1UserTx, blockNum int64) ([]common.L1Tx, error) {
1157	l1Txs := make([]common.L1Tx, len(eventsL1UserTx))
1158	for i := range eventsL1UserTx {
1159		eventsL1UserTx[i].L1UserTx.EthBlockNum = blockNum
1160		// Check validity of L1UserTx
1161		l1Tx, err := common.NewL1Tx(&eventsL1UserTx[i].L1UserTx)
1162		if err != nil {
1163			return nil, tracerr.Wrap(err)
1164		}
1165		l1Txs[i] = *l1Tx
1166	}
1167	return l1Txs, nil
1168}