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