-
Notifications
You must be signed in to change notification settings - Fork 632
Expand file tree
/
Copy pathl1_watcher.go
More file actions
104 lines (85 loc) · 2.82 KB
/
l1_watcher.go
File metadata and controls
104 lines (85 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package watcher
import (
"context"
"errors"
"math/big"
"github.com/prometheus/client_golang/prometheus"
"github.com/scroll-tech/go-ethereum/consensus/misc"
gethTypes "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/log"
"gorm.io/gorm"
"scroll-tech/common/types"
"scroll-tech/rollup/internal/orm"
)
// L1WatcherClient will listen for smart contract events from Eth L1.
type L1WatcherClient struct {
ctx context.Context
client *ethclient.Client
l1BlockOrm *orm.L1Block
// The height of the block that the watcher has retrieved header rlp
processedBlockHeight uint64
metrics *l1WatcherMetrics
}
// NewL1WatcherClient returns a new instance of L1WatcherClient.
func NewL1WatcherClient(ctx context.Context, client *ethclient.Client, startHeight uint64, db *gorm.DB, reg prometheus.Registerer) *L1WatcherClient {
l1BlockOrm := orm.NewL1Block(db)
savedL1BlockHeight, err := l1BlockOrm.GetLatestL1BlockHeight(ctx)
if err != nil {
log.Warn("Failed to fetch latest L1 block height from db", "err", err)
savedL1BlockHeight = 0
}
if savedL1BlockHeight < startHeight {
savedL1BlockHeight = startHeight
}
return &L1WatcherClient{
ctx: ctx,
client: client,
l1BlockOrm: l1BlockOrm,
processedBlockHeight: savedL1BlockHeight,
metrics: initL1WatcherMetrics(reg),
}
}
// ProcessedBlockHeight get processedBlockHeight
// Currently only use for unit test
func (w *L1WatcherClient) ProcessedBlockHeight() uint64 {
return w.processedBlockHeight
}
// FetchBlockHeader pull latest L1 blocks and save in DB
func (w *L1WatcherClient) FetchBlockHeader(blockHeight uint64) error {
w.metrics.l1WatcherFetchBlockHeaderTotal.Inc()
var block *gethTypes.Header
block, err := w.client.HeaderByNumber(w.ctx, big.NewInt(int64(blockHeight)))
if err != nil {
log.Warn("Failed to get block", "height", blockHeight, "err", err)
return err
}
if block == nil {
log.Warn("Received nil block", "height", blockHeight)
return errors.New("received nil block")
}
var baseFee uint64
if block.BaseFee != nil {
baseFee = block.BaseFee.Uint64()
}
var blobBaseFee uint64
if excess := block.ExcessBlobGas; excess != nil {
blobBaseFee = misc.CalcBlobFee(*excess).Uint64()
}
l1Block := orm.L1Block{
Number: blockHeight,
Hash: block.Hash().String(),
BaseFee: baseFee,
BlobBaseFee: blobBaseFee,
GasOracleStatus: int16(types.GasOraclePending),
}
err = w.l1BlockOrm.InsertL1Blocks(w.ctx, []orm.L1Block{l1Block})
if err != nil {
log.Warn("Failed to insert L1 block to db", "blockHeight", blockHeight, "err", err)
return err
}
// update processed height
w.processedBlockHeight = blockHeight
w.metrics.l1WatcherFetchBlockHeaderProcessedBlockHeight.Set(float64(w.processedBlockHeight))
return nil
}