arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/api/stateapiupdater/stateapiupdater.go
api/stateapiupdater/stateapiupdater.goRaw
  1package stateapiupdater
  2
  3import (
  4	"database/sql"
  5	"sync"
  6
  7	"github.com/hermeznetwork/hermez-node/common"
  8	"github.com/hermeznetwork/hermez-node/db/historydb"
  9	"github.com/hermeznetwork/hermez-node/log"
 10	"github.com/hermeznetwork/tracerr"
 11)
 12
 13// Updater is an utility object to facilitate updating the StateAPI
 14type Updater struct {
 15	hdb    *historydb.HistoryDB
 16	state  historydb.StateAPI
 17	config historydb.NodeConfig
 18	vars   common.SCVariablesPtr
 19	consts historydb.Constants
 20	rw     sync.RWMutex
 21	rfp    *RecommendedFeePolicy
 22}
 23
 24// RecommendedFeePolicy describes how the recommended fee is calculated
 25type RecommendedFeePolicy struct {
 26	PolicyType  RecommendedFeePolicyType
 27	StaticValue float64
 28}
 29
 30// RecommendedFeePolicyType describes the different available recommended fee strategies
 31type RecommendedFeePolicyType string
 32
 33const (
 34	// Always give the same StaticValue as recommended fee
 35	RecommendedFeePolicyTypeStatic RecommendedFeePolicyType = "Static"
 36	// Set the recommended fee using the average fee of the last hour
 37	RecommendedFeePolicyTypeAvgLastHour RecommendedFeePolicyType = "AvgLastHour"
 38)
 39
 40func (rfp *RecommendedFeePolicy) valid() bool {
 41	switch rfp.PolicyType {
 42	case RecommendedFeePolicyTypeStatic:
 43		if rfp.StaticValue == 0 {
 44			log.Warn("RcommendedFee is set to 0 USD, and the policy is static")
 45		}
 46		return true
 47	case RecommendedFeePolicyTypeAvgLastHour:
 48		return true
 49	default:
 50		return false
 51	}
 52}
 53
 54// NewUpdater creates a new Updater
 55func NewUpdater(hdb *historydb.HistoryDB, config *historydb.NodeConfig, vars *common.SCVariables,
 56	consts *historydb.Constants, rfp *RecommendedFeePolicy) (*Updater, error) {
 57	if ok := rfp.valid(); !ok {
 58		return nil, tracerr.New("Invalid recommende fee policy")
 59	}
 60	u := Updater{
 61		hdb:    hdb,
 62		config: *config,
 63		consts: *consts,
 64		state: historydb.StateAPI{
 65			NodePublicInfo: historydb.NodePublicInfo{
 66				ForgeDelay: config.ForgeDelay,
 67			},
 68		},
 69		rfp: rfp,
 70	}
 71	u.SetSCVars(vars.AsPtr())
 72	return &u, nil
 73}
 74
 75// Store the State in the HistoryDB
 76func (u *Updater) Store() error {
 77	u.rw.RLock()
 78	defer u.rw.RUnlock()
 79	return tracerr.Wrap(u.hdb.SetStateInternalAPI(&u.state))
 80}
 81
 82// SetSCVars sets the smart contract vars (ony updates those that are not nil)
 83func (u *Updater) SetSCVars(vars *common.SCVariablesPtr) {
 84	u.rw.Lock()
 85	defer u.rw.Unlock()
 86	if vars.Rollup != nil {
 87		u.vars.Rollup = vars.Rollup
 88		rollupVars := historydb.NewRollupVariablesAPI(u.vars.Rollup)
 89		u.state.Rollup = *rollupVars
 90	}
 91	if vars.Auction != nil {
 92		u.vars.Auction = vars.Auction
 93		auctionVars := historydb.NewAuctionVariablesAPI(u.vars.Auction)
 94		u.state.Auction = *auctionVars
 95	}
 96	if vars.WDelayer != nil {
 97		u.vars.WDelayer = vars.WDelayer
 98		u.state.WithdrawalDelayer = *u.vars.WDelayer
 99	}
100}
101
102// UpdateRecommendedFee update Status.RecommendedFee information
103func (u *Updater) UpdateRecommendedFee() error {
104	switch u.rfp.PolicyType {
105	case RecommendedFeePolicyTypeStatic:
106		u.rw.Lock()
107		u.state.RecommendedFee = common.RecommendedFee{
108			ExistingAccount:        u.rfp.StaticValue,
109			CreatesAccount:         u.rfp.StaticValue,
110			CreatesAccountInternal: u.rfp.StaticValue,
111		}
112		u.rw.Unlock()
113	case RecommendedFeePolicyTypeAvgLastHour:
114		recommendedFee, err := u.hdb.GetRecommendedFee(u.config.MinFeeUSD, u.config.MaxFeeUSD)
115		if err != nil {
116			return tracerr.Wrap(err)
117		}
118		u.rw.Lock()
119		u.state.RecommendedFee = *recommendedFee
120		u.rw.Unlock()
121	default:
122		return tracerr.New("Invalid recommende fee policy")
123	}
124
125	return nil
126}
127
128// UpdateMetrics update Status.Metrics information
129func (u *Updater) UpdateMetrics() error {
130	u.rw.RLock()
131	lastBatch := u.state.Network.LastBatch
132	u.rw.RUnlock()
133	if lastBatch == nil {
134		return nil
135	}
136	lastBatchNum := lastBatch.BatchNum
137	metrics, poolLoad, err := u.hdb.GetMetricsInternalAPI(lastBatchNum)
138	if err != nil {
139		return tracerr.Wrap(err)
140	}
141	u.rw.Lock()
142	u.state.Metrics = *metrics
143	u.state.NodePublicInfo.PoolLoad = poolLoad
144	u.rw.Unlock()
145	return nil
146}
147
148// UpdateNetworkInfoBlock update Status.Network block related information
149func (u *Updater) UpdateNetworkInfoBlock(lastEthBlock, lastSyncBlock common.Block) {
150	u.rw.Lock()
151	u.state.Network.LastSyncBlock = lastSyncBlock.Num
152	u.state.Network.LastEthBlock = lastEthBlock.Num
153	u.rw.Unlock()
154}
155
156// UpdateNetworkInfo update Status.Network information
157func (u *Updater) UpdateNetworkInfo(
158	lastEthBlock, lastSyncBlock common.Block,
159	lastBatchNum common.BatchNum, currentSlot int64,
160) error {
161	// Get last batch in API format
162	lastBatch, err := u.hdb.GetBatchInternalAPI(lastBatchNum)
163	if tracerr.Unwrap(err) == sql.ErrNoRows {
164		lastBatch = nil
165	} else if err != nil {
166		return tracerr.Wrap(err)
167	}
168	u.rw.RLock()
169	auctionVars := u.vars.Auction
170	u.rw.RUnlock()
171	// Get next forgers
172	lastClosedSlot := currentSlot + int64(auctionVars.ClosedAuctionSlots)
173	nextForgers, err := u.hdb.GetNextForgersInternalAPI(auctionVars, &u.consts.Auction,
174		lastSyncBlock, currentSlot, lastClosedSlot)
175	if tracerr.Unwrap(err) == sql.ErrNoRows {
176		nextForgers = nil
177	} else if err != nil {
178		return tracerr.Wrap(err)
179	}
180
181	bucketUpdates, err := u.hdb.GetBucketUpdatesInternalAPI()
182	if err == sql.ErrNoRows {
183		bucketUpdates = nil
184	} else if err != nil {
185		return tracerr.Wrap(err)
186	}
187
188	u.rw.Lock()
189	// Update NodeInfo struct
190	for i, bucketParams := range u.state.Rollup.Buckets {
191		for _, bucketUpdate := range bucketUpdates {
192			if bucketUpdate.NumBucket == i {
193				bucketParams.Withdrawals = bucketUpdate.Withdrawals
194				u.state.Rollup.Buckets[i] = bucketParams
195				break
196			}
197		}
198	}
199	// Update pending L1s
200	pendingL1s, err := u.hdb.GetUnforgedL1UserTxsCount()
201	if err != nil {
202		return tracerr.Wrap(err)
203	}
204	u.state.Network.LastSyncBlock = lastSyncBlock.Num
205	u.state.Network.LastEthBlock = lastEthBlock.Num
206	u.state.Network.LastBatch = lastBatch
207	u.state.Network.CurrentSlot = currentSlot
208	u.state.Network.NextForgers = nextForgers
209	u.state.Network.PendingL1Txs = pendingL1s
210	u.rw.Unlock()
211	return nil
212}