hermez-node/api/state.go
api/state.goRaw
1package api
2
3import (
4 "database/sql"
5 "net/http"
6 "time"
7
8 ethCommon "github.com/ethereum/go-ethereum/common"
9 "github.com/gin-gonic/gin"
10 "github.com/hermeznetwork/hermez-node/common"
11 "github.com/hermeznetwork/hermez-node/db/historydb"
12 "github.com/hermeznetwork/tracerr"
13)
14
15// Network define status of the network
16type Network struct {
17 LastEthBlock int64 `json:"lastEthereumBlock"`
18 LastSyncBlock int64 `json:"lastSynchedBlock"`
19 LastBatch *historydb.BatchAPI `json:"lastBatch"`
20 CurrentSlot int64 `json:"currentSlot"`
21 NextForgers []NextForger `json:"nextForgers"`
22}
23
24// NextForger is a representation of the information of a coordinator and the period will forge
25type NextForger struct {
26 Coordinator historydb.CoordinatorAPI `json:"coordinator"`
27 Period Period `json:"period"`
28}
29
30// Period is a representation of a period
31type Period struct {
32 SlotNum int64 `json:"slotNum"`
33 FromBlock int64 `json:"fromBlock"`
34 ToBlock int64 `json:"toBlock"`
35 FromTimestamp time.Time `json:"fromTimestamp"`
36 ToTimestamp time.Time `json:"toTimestamp"`
37}
38
39var bootCoordinator historydb.CoordinatorAPI = historydb.CoordinatorAPI{
40 ItemID: 0,
41 Bidder: ethCommon.HexToAddress("0x111111111111111111111111111111111111111"),
42 Forger: ethCommon.HexToAddress("0x111111111111111111111111111111111111111"),
43 URL: "https://bootCoordinator",
44}
45
46func (a *API) getState(c *gin.Context) {
47 // TODO: There are no events for the buckets information, so now this information will be 0
48 a.status.RLock()
49 status := a.status //nolint
50 a.status.RUnlock()
51 c.JSON(http.StatusOK, status) //nolint
52}
53
54// SC Vars
55
56// SetRollupVariables set Status.Rollup variables
57func (a *API) SetRollupVariables(rollupVariables common.RollupVariables) {
58 a.status.Lock()
59 a.status.Rollup = rollupVariables
60 a.status.Unlock()
61}
62
63// SetWDelayerVariables set Status.WithdrawalDelayer variables
64func (a *API) SetWDelayerVariables(wDelayerVariables common.WDelayerVariables) {
65 a.status.Lock()
66 a.status.WithdrawalDelayer = wDelayerVariables
67 a.status.Unlock()
68}
69
70// SetAuctionVariables set Status.Auction variables
71func (a *API) SetAuctionVariables(auctionVariables common.AuctionVariables) {
72 a.status.Lock()
73 a.status.Auction = auctionVariables
74 a.status.Unlock()
75}
76
77// Network
78
79// UpdateNetworkInfoBlock update Status.Network block related information
80func (a *API) UpdateNetworkInfoBlock(
81 lastEthBlock, lastSyncBlock common.Block,
82) {
83 a.status.Network.LastSyncBlock = lastSyncBlock.Num
84 a.status.Network.LastEthBlock = lastEthBlock.Num
85}
86
87// UpdateNetworkInfo update Status.Network information
88func (a *API) UpdateNetworkInfo(
89 lastEthBlock, lastSyncBlock common.Block,
90 lastBatchNum common.BatchNum, currentSlot int64,
91) error {
92 lastBatch, err := a.h.GetBatchAPI(lastBatchNum)
93 if tracerr.Unwrap(err) == sql.ErrNoRows {
94 lastBatch = nil
95 } else if err != nil {
96 return tracerr.Wrap(err)
97 }
98 lastClosedSlot := currentSlot + int64(a.status.Auction.ClosedAuctionSlots)
99 nextForgers, err := a.getNextForgers(lastSyncBlock, currentSlot, lastClosedSlot)
100 if tracerr.Unwrap(err) == sql.ErrNoRows {
101 nextForgers = nil
102 } else if err != nil {
103 return tracerr.Wrap(err)
104 }
105 a.status.Lock()
106 a.status.Network.LastSyncBlock = lastSyncBlock.Num
107 a.status.Network.LastEthBlock = lastEthBlock.Num
108 a.status.Network.LastBatch = lastBatch
109 a.status.Network.CurrentSlot = currentSlot
110 a.status.Network.NextForgers = nextForgers
111 a.status.Unlock()
112 return nil
113}
114
115// getNextForgers returns next forgers
116func (a *API) getNextForgers(lastBlock common.Block, currentSlot, lastClosedSlot int64) ([]NextForger, error) {
117 secondsPerBlock := int64(15) //nolint:gomnd
118 // currentSlot and lastClosedSlot included
119 limit := uint(lastClosedSlot - currentSlot + 1)
120 bids, _, err := a.h.GetBestBidsAPI(¤tSlot, &lastClosedSlot, nil, &limit, "ASC")
121 if err != nil {
122 return nil, tracerr.Wrap(err)
123 }
124 nextForgers := []NextForger{}
125 // Create nextForger for each slot
126 for i := currentSlot; i <= lastClosedSlot; i++ {
127 fromBlock := i*int64(a.cg.AuctionConstants.BlocksPerSlot) + a.cg.AuctionConstants.GenesisBlockNum
128 toBlock := (i+1)*int64(a.cg.AuctionConstants.BlocksPerSlot) + a.cg.AuctionConstants.GenesisBlockNum - 1
129 nextForger := NextForger{
130 Period: Period{
131 SlotNum: i,
132 FromBlock: fromBlock,
133 ToBlock: toBlock,
134 FromTimestamp: lastBlock.Timestamp.Add(time.Second * time.Duration(secondsPerBlock*(fromBlock-lastBlock.Num))),
135 ToTimestamp: lastBlock.Timestamp.Add(time.Second * time.Duration(secondsPerBlock*(toBlock-lastBlock.Num))),
136 },
137 }
138 foundBid := false
139 // If there is a bid for a slot, get forger (coordinator)
140 for j := range bids {
141 if bids[j].SlotNum == i {
142 foundBid = true
143 coordinator, err := a.h.GetCoordinatorAPI(bids[j].Bidder)
144 if err != nil {
145 return nil, tracerr.Wrap(err)
146 }
147 nextForger.Coordinator = *coordinator
148 break
149 }
150 }
151 // If there is no bid, the coordinator that will forge is boot coordinator
152 if !foundBid {
153 nextForger.Coordinator = bootCoordinator
154 }
155 nextForgers = append(nextForgers, nextForger)
156 }
157 return nextForgers, nil
158}
159
160// Metrics
161
162// UpdateMetrics update Status.Metrics information
163func (a *API) UpdateMetrics() error {
164 a.status.RLock()
165 if a.status.Network.LastBatch == nil {
166 a.status.RUnlock()
167 return nil
168 }
169 batchNum := a.status.Network.LastBatch.BatchNum
170 a.status.RUnlock()
171 metrics, err := a.h.GetMetrics(batchNum)
172 if err != nil {
173 return tracerr.Wrap(err)
174 }
175 a.status.Lock()
176 a.status.Metrics = *metrics
177 a.status.Unlock()
178 return nil
179}
180
181// Recommended fee
182
183// UpdateRecommendedFee update Status.RecommendedFee information
184func (a *API) UpdateRecommendedFee() error {
185 feeExistingAccount, err := a.h.GetAvgTxFee()
186 if err != nil {
187 return tracerr.Wrap(err)
188 }
189 a.status.Lock()
190 a.status.RecommendedFee.ExistingAccount = feeExistingAccount
191 a.status.RecommendedFee.CreatesAccount = createAccountExtraFeePercentage * feeExistingAccount
192 a.status.RecommendedFee.CreatesAccountAndRegister = createAccountInternalExtraFeePercentage * feeExistingAccount
193 a.status.Unlock()
194 return nil
195}