From 5501f300625fecd83864db4a9cd9899a667ffa13 Mon Sep 17 00:00:00 2001 From: Eduard S Date: Thu, 4 Mar 2021 14:05:35 +0100 Subject: [PATCH] WIP2 --- api/slots_test.go | 4 +- api/state.go | 2 +- api/state_test.go | 32 ++-- db/historydb/historydb.go | 25 +++ db/historydb/historydb_test.go | 44 +++++- db/historydb/nodeinfo.go | 280 ++++++++++++++++++++++++--------- db/migrations/0001.sql | 5 +- 7 files changed, 296 insertions(+), 96 deletions(-) diff --git a/api/slots_test.go b/api/slots_test.go index a001a22..11ac0d3 100644 --- a/api/slots_test.go +++ b/api/slots_test.go @@ -101,7 +101,7 @@ func TestGetSlot(t *testing.T) { ) ni, err := api.h.GetNodeInfoAPI() assert.NoError(t, err) - emptySlot := api.getEmptyTestSlot(slotNum, ni.StateAPI.Network.LastSyncBlock, tc.auctionVars) + emptySlot := api.getEmptyTestSlot(slotNum, ni.APIState.Network.LastSyncBlock, tc.auctionVars) assertSlot(t, emptySlot, fetchedSlot) // Invalid slotNum @@ -132,7 +132,7 @@ func TestGetSlots(t *testing.T) { ni, err := api.h.GetNodeInfoAPI() assert.NoError(t, err) for i := tc.slots[len(tc.slots)-1].SlotNum; i < maxSlotNum; i++ { - emptySlot := api.getEmptyTestSlot(i+1, ni.StateAPI.Network.LastSyncBlock, tc.auctionVars) + emptySlot := api.getEmptyTestSlot(i+1, ni.APIState.Network.LastSyncBlock, tc.auctionVars) allSlots = append(allSlots, emptySlot) } assertSlots(t, allSlots, fetchedSlots) diff --git a/api/state.go b/api/state.go index 52ff8f0..c03374b 100644 --- a/api/state.go +++ b/api/state.go @@ -12,5 +12,5 @@ func (a *API) getState(c *gin.Context) { retBadReq(err, c) return } - c.JSON(http.StatusOK, ni.StateAPI) + c.JSON(http.StatusOK, ni.APIState) } diff --git a/api/state_test.go b/api/state_test.go index 812e29f..6f3fb12 100644 --- a/api/state_test.go +++ b/api/state_test.go @@ -32,7 +32,7 @@ func TestSetRollupVariables(t *testing.T) { api.h.SetRollupVariables(&tc.rollupVars) ni, err := api.h.GetNodeInfoAPI() assert.NoError(t, err) - assertEqualRollupVariables(t, tc.rollupVars, ni.StateAPI.Rollup, true) + assertEqualRollupVariables(t, tc.rollupVars, ni.APIState.Rollup, true) } func assertEqualRollupVariables(t *testing.T, rollupVariables common.RollupVariables, apiVariables historydb.RollupVariablesAPI, checkBuckets bool) { @@ -54,14 +54,14 @@ func TestSetWDelayerVariables(t *testing.T) { api.h.SetWDelayerVariables(&tc.wdelayerVars) ni, err := api.h.GetNodeInfoAPI() assert.NoError(t, err) - assert.Equal(t, tc.wdelayerVars, ni.StateAPI.WithdrawalDelayer) + assert.Equal(t, tc.wdelayerVars, ni.APIState.WithdrawalDelayer) } func TestSetAuctionVariables(t *testing.T) { api.h.SetAuctionVariables(&tc.auctionVars) ni, err := api.h.GetNodeInfoAPI() assert.NoError(t, err) - assertEqualAuctionVariables(t, tc.auctionVars, ni.StateAPI.Auction) + assertEqualAuctionVariables(t, tc.auctionVars, ni.APIState.Auction) } func assertEqualAuctionVariables(t *testing.T, auctionVariables common.AuctionVariables, apiVariables historydb.AuctionVariablesAPI) { @@ -117,12 +117,12 @@ func TestUpdateNetworkInfo(t *testing.T) { assert.NoError(t, err) ni, err := api.h.GetNodeInfoAPI() assert.NoError(t, err) - assert.Equal(t, lastBlock.Num, ni.StateAPI.Network.LastSyncBlock) - assert.Equal(t, lastBatchNum, ni.StateAPI.Network.LastBatch.BatchNum) - assert.Equal(t, currentSlotNum, ni.StateAPI.Network.CurrentSlot) - assert.Equal(t, int(ni.StateAPI.Auction.ClosedAuctionSlots)+1, len(ni.StateAPI.Network.NextForgers)) - assert.Equal(t, ni.StateAPI.Rollup.Buckets[0].Withdrawals, apitypes.NewBigIntStr(big.NewInt(123))) - assert.Equal(t, ni.StateAPI.Rollup.Buckets[2].Withdrawals, apitypes.NewBigIntStr(big.NewInt(43))) + assert.Equal(t, lastBlock.Num, ni.APIState.Network.LastSyncBlock) + assert.Equal(t, lastBatchNum, ni.APIState.Network.LastBatch.BatchNum) + assert.Equal(t, currentSlotNum, ni.APIState.Network.CurrentSlot) + assert.Equal(t, int(ni.APIState.Auction.ClosedAuctionSlots)+1, len(ni.APIState.Network.NextForgers)) + assert.Equal(t, ni.APIState.Rollup.Buckets[0].Withdrawals, apitypes.NewBigIntStr(big.NewInt(123))) + assert.Equal(t, ni.APIState.Rollup.Buckets[2].Withdrawals, apitypes.NewBigIntStr(big.NewInt(43))) } func TestUpdateMetrics(t *testing.T) { @@ -137,12 +137,12 @@ func TestUpdateMetrics(t *testing.T) { assert.NoError(t, err) ni, err := api.h.GetNodeInfoAPI() assert.NoError(t, err) - assert.Greater(t, ni.StateAPI.Metrics.TransactionsPerBatch, float64(0)) - assert.Greater(t, ni.StateAPI.Metrics.BatchFrequency, float64(0)) - assert.Greater(t, ni.StateAPI.Metrics.TransactionsPerSecond, float64(0)) - assert.Greater(t, ni.StateAPI.Metrics.TotalAccounts, int64(0)) - assert.Greater(t, ni.StateAPI.Metrics.TotalBJJs, int64(0)) - assert.Greater(t, ni.StateAPI.Metrics.AvgTransactionFee, float64(0)) + assert.Greater(t, ni.APIState.Metrics.TransactionsPerBatch, float64(0)) + assert.Greater(t, ni.APIState.Metrics.BatchFrequency, float64(0)) + assert.Greater(t, ni.APIState.Metrics.TransactionsPerSecond, float64(0)) + assert.Greater(t, ni.APIState.Metrics.TotalAccounts, int64(0)) + assert.Greater(t, ni.APIState.Metrics.TotalBJJs, int64(0)) + assert.Greater(t, ni.APIState.Metrics.AvgTransactionFee, float64(0)) } func TestUpdateRecommendedFee(t *testing.T) { @@ -154,7 +154,7 @@ func TestUpdateRecommendedFee(t *testing.T) { } ni, err := api.h.GetNodeInfoAPI() assert.NoError(t, err) - assert.Greater(t, ni.StateAPI.RecommendedFee.ExistingAccount, minFeeUSD) + assert.Greater(t, ni.APIState.RecommendedFee.ExistingAccount, minFeeUSD) // assert.Equal(t, ni.StateAPI.RecommendedFee.CreatesAccount, // ni.StateAPI.RecommendedFee.ExistingAccount*createAccountExtraFeePercentage) // assert.Equal(t, ni.StateAPI.RecommendedFee.CreatesAccountAndRegister, diff --git a/db/historydb/historydb.go b/db/historydb/historydb.go index 3997f57..eadf576 100644 --- a/db/historydb/historydb.go +++ b/db/historydb/historydb.go @@ -841,6 +841,31 @@ func (hdb *HistoryDB) GetAllBucketUpdates() ([]common.BucketUpdate, error) { return db.SlicePtrsToSlice(bucketUpdates).([]common.BucketUpdate), tracerr.Wrap(err) } +func (hdb *HistoryDB) getBucketUpdatesAPI(txn *sqlx.Tx) ([]BucketUpdateAPI, error) { + var bucketUpdates []*BucketUpdateAPI + // var bucketUpdates []*common.BucketUpdate + err := meddler.QueryAll( + txn, &bucketUpdates, + `SELECT num_bucket, withdrawals FROM bucket_update + WHERE item_id in(SELECT max(item_id) FROM bucket_update + group by num_bucket) + ORDER BY num_bucket ASC;`, + ) + return db.SlicePtrsToSlice(bucketUpdates).([]BucketUpdateAPI), tracerr.Wrap(err) +} + +func (hdb *HistoryDB) getMinBidInfo(txn *sqlx.Tx, + currentSlot, lastClosedSlot int64) ([]MinBidInfo, error) { + minBidInfo := []*MinBidInfo{} + query := ` + SELECT DISTINCT default_slot_set_bid, default_slot_set_bid_slot_num FROM auction_vars + WHERE default_slot_set_bid_slot_num < $1 + ORDER BY default_slot_set_bid_slot_num DESC + LIMIT $2;` + err := meddler.QueryAll(txn, &minBidInfo, query, lastClosedSlot, int(lastClosedSlot-currentSlot)+1) + return db.SlicePtrsToSlice(minBidInfo).([]MinBidInfo), tracerr.Wrap(err) +} + func (hdb *HistoryDB) addTokenExchanges(d meddler.DB, tokenExchanges []common.TokenExchange) error { if len(tokenExchanges) == 0 { return nil diff --git a/db/historydb/historydb_test.go b/db/historydb/historydb_test.go index b9627e7..85207a0 100644 --- a/db/historydb/historydb_test.go +++ b/db/historydb/historydb_test.go @@ -1464,6 +1464,9 @@ func setTestBlocks(from, to int64) []common.Block { func TestNodeInfo(t *testing.T) { test.WipeDB(historyDB.DB()) + err := historyDB.SetAPIState(&APIState{}) + require.NoError(t, err) + clientSetup := test.NewClientSetupExample() constants := &Constants{ RollupConstants: *clientSetup.RollupConstants, @@ -1472,9 +1475,48 @@ func TestNodeInfo(t *testing.T) { ChainID: 42, HermezAddress: clientSetup.AuctionConstants.HermezRollup, } - err := historyDB.SetConstants(constants) + err = historyDB.SetConstants(constants) + require.NoError(t, err) + + // Test parameters + apiState := &APIState{ + NodePublicConfig: NodePublicConfig{ + ForgeDelay: 3.1, + }, + Network: Network{ + LastEthBlock: 12, + LastSyncBlock: 34, + }, + Metrics: Metrics{ + TransactionsPerBatch: 1.1, + TotalAccounts: 42, + }, + Rollup: *NewRollupVariablesAPI(clientSetup.RollupVariables), + Auction: *NewAuctionVariablesAPI(clientSetup.AuctionVariables), + WithdrawalDelayer: *clientSetup.WDelayerVariables, + RecommendedFee: common.RecommendedFee{ + ExistingAccount: 0.15, + }, + } + err = historyDB.SetAPIState(apiState) require.NoError(t, err) + + nodeConfig := &NodeConfig{ + MaxPoolTxs: 123, + MinFeeUSD: 0.5, + } + err = historyDB.SetNodeConfig(nodeConfig) + require.NoError(t, err) + dbConstants, err := historyDB.GetConstants() require.NoError(t, err) assert.Equal(t, constants, dbConstants) + + dbNodeConfig, err := historyDB.GetNodeConfig() + require.NoError(t, err) + assert.Equal(t, nodeConfig, dbNodeConfig) + + dbAPIState, err := historyDB.GetAPIState() + require.NoError(t, err) + assert.Equal(t, apiState, dbAPIState) } diff --git a/db/historydb/nodeinfo.go b/db/historydb/nodeinfo.go index 5d3b461..6d4234c 100644 --- a/db/historydb/nodeinfo.go +++ b/db/historydb/nodeinfo.go @@ -21,11 +21,6 @@ const ( createAccountInternalExtraFeePercentage float64 = 2.5 ) -// NodePublicConfig is the configuration of the node that is exposed via API -type NodePublicConfig struct { - // ForgeDelay in seconds - ForgeDelay float64 `json:"forgeDelay"` -} type Period struct { SlotNum int64 `json:"slotNum"` FromBlock int64 `json:"fromBlock"` @@ -33,10 +28,12 @@ type Period struct { FromTimestamp time.Time `json:"fromTimestamp"` ToTimestamp time.Time `json:"toTimestamp"` } + type NextForger struct { Coordinator CoordinatorAPI `json:"coordinator"` Period Period `json:"period"` } + type Network struct { LastEthBlock int64 `json:"lastEthereumBlock"` LastSyncBlock int64 `json:"lastSynchedBlock"` @@ -44,7 +41,15 @@ type Network struct { CurrentSlot int64 `json:"currentSlot"` NextForgers []NextForger `json:"nextForgers"` } -type StateAPI struct { + +// NodePublicConfig is the configuration of the node that is exposed via API +type NodePublicConfig struct { + // ForgeDelay in seconds + ForgeDelay float64 `json:"forgeDelay"` +} + +type APIState struct { + // NodePublicConfig is the configuration of the node that is exposed via API NodePublicConfig NodePublicConfig `json:"nodeConfig"` Network Network `json:"network"` Metrics Metrics `json:"metrics"` @@ -62,22 +67,35 @@ type Constants struct { HermezAddress ethCommon.Address } +type NodeConfig struct { + MaxPoolTxs uint32 `meddler:"max_pool_txs"` + MinFeeUSD float64 `meddler:"min_fee"` +} + type NodeInfo struct { - ItemID int `meddler:"item_id"` - MaxPoolTxs *uint32 `meddler:"max_pool_txs"` - MinFeeUSD *float64 `meddler:"min_fee"` - StateAPI *StateAPI `meddler:"state,json"` - Constants *Constants `meddler:"constants,json"` + ItemID int `meddler:"item_id,pk"` + APIState *APIState `meddler:"state,json"` + NodeConfig *NodeConfig `meddler:"config,json"` + Constants *Constants `meddler:"constants,json"` } func (hdb *HistoryDB) GetNodeInfo() (*NodeInfo, error) { ni := &NodeInfo{} err := meddler.QueryRow( - hdb.dbRead, ni, `SELECT * FROM node_info ORDER BY item_id DESC LIMIT 1;`, + hdb.dbRead, ni, `SELECT * FROM node_info WHERE item_id = 1;`, ) return ni, tracerr.Wrap(err) } +func (hdb *HistoryDB) GetConstants() (*Constants, error) { + var nodeInfo NodeInfo + err := meddler.QueryRow( + hdb.dbRead, &nodeInfo, + "SELECT constants FROM node_info WHERE item_id = 1;", + ) + return nodeInfo.Constants, tracerr.Wrap(err) +} + func (hdb *HistoryDB) SetConstants(constants *Constants) error { _constants := struct { Constants *Constants `meddler:"constants,json"` @@ -93,60 +111,176 @@ func (hdb *HistoryDB) SetConstants(constants *Constants) error { return tracerr.Wrap(err) } -func (hdb *HistoryDB) GetConstants() (*Constants, error) { +func (hdb *HistoryDB) GetAPIState() (*APIState, error) { var nodeInfo NodeInfo err := meddler.QueryRow( hdb.dbRead, &nodeInfo, - "SELECT constants FROM node_info WHERE item_id = 1;", + "SELECT state FROM node_info WHERE item_id = 1;", ) - return nodeInfo.Constants, tracerr.Wrap(err) + return nodeInfo.APIState, tracerr.Wrap(err) +} + +func (hdb *HistoryDB) SetAPIState(apiState *APIState) error { + _apiState := struct { + APIState *APIState `meddler:"state,json"` + }{apiState} + values, err := meddler.Default.Values(&_apiState, false) + if err != nil { + return tracerr.Wrap(err) + } + _, err = hdb.dbWrite.Exec( + "UPDATE node_info SET state = $1 WHERE item_id = 1;", + values[0], + ) + return tracerr.Wrap(err) +} + +func (hdb *HistoryDB) GetNodeConfig() (*NodeConfig, error) { + var nodeInfo NodeInfo + err := meddler.QueryRow( + hdb.dbRead, &nodeInfo, + "SELECT config FROM node_info WHERE item_id = 1;", + ) + return nodeInfo.NodeConfig, tracerr.Wrap(err) +} + +func (hdb *HistoryDB) SetNodeConfig(nodeConfig *NodeConfig) error { + _nodeConfig := struct { + NodeConfig *NodeConfig `meddler:"config,json"` + }{nodeConfig} + values, err := meddler.Default.Values(&_nodeConfig, false) + if err != nil { + return tracerr.Wrap(err) + } + _, err = hdb.dbWrite.Exec( + "UPDATE config SET state = $1 WHERE item_id = 1;", + values[0], + ) + return tracerr.Wrap(err) +} + +// func (hdb *HistoryDB) SetInitialNodeInfo(maxPoolTxs uint32, minFeeUSD float64, constants *Constants) error { +// ni := &NodeInfo{ +// MaxPoolTxs: &maxPoolTxs, +// MinFeeUSD: &minFeeUSD, +// Constants: constants, +// } +// return tracerr.Wrap(meddler.Insert(hdb.dbWrite, "node_info", ni)) +// } + +type APIStateUpdater struct { + hdb *HistoryDB + state APIState + config NodeConfig + constants Constants +} + +func (u *APIStateUpdater) SetSCVars(rollupVariables *common.RollupVariables, + auctionVariables *common.AuctionVariables, + wDelayerVariables *common.WDelayerVariables) { + if rollupVariables != nil { + rollupVars := NewRollupVariablesAPI(rollupVariables) + u.state.Rollup = *rollupVars + } + if auctionVariables != nil { + auctionVars := NewAuctionVariablesAPI(auctionVariables) + u.state.Auction = *auctionVars + } + if wDelayerVariables != nil { + u.state.WithdrawalDelayer = *wDelayerVariables + } } -func (hdb *HistoryDB) SetInitialNodeInfo(maxPoolTxs uint32, minFeeUSD float64, constants *Constants) error { - ni := &NodeInfo{ - MaxPoolTxs: &maxPoolTxs, - MinFeeUSD: &minFeeUSD, - Constants: constants, +func (u *APIStateUpdater) UpdateNetworkInfoBlock(lastEthBlock, lastSyncBlock common.Block) { + u.state.Network.LastSyncBlock = lastSyncBlock.Num + u.state.Network.LastEthBlock = lastEthBlock.Num +} + +func (u *APIStateUpdater) UpdateNetworkInfo( + txn *sqlx.Tx, + lastEthBlock, lastSyncBlock common.Block, + lastBatchNum common.BatchNum, currentSlot int64, +) error { + // Get last batch in API format + lastBatch, err := u.hdb.getBatchAPI(txn, lastBatchNum) + if tracerr.Unwrap(err) == sql.ErrNoRows { + lastBatch = nil + } else if err != nil { + return tracerr.Wrap(err) + } + // Get next forrgers + lastClosedSlot := currentSlot + int64(u.state.Auction.ClosedAuctionSlots) + nextForgers, err := u.getNextForgers(txn, lastSyncBlock, currentSlot, lastClosedSlot) + if tracerr.Unwrap(err) == sql.ErrNoRows { + nextForgers = nil + } else if err != nil { + return tracerr.Wrap(err) + } + + bucketUpdates, err := u.hdb.getBucketUpdatesAPI(txn) + if err == sql.ErrNoRows { + bucketUpdates = nil + } else if err != nil { + return tracerr.Wrap(err) + } + // Update NodeInfo struct + for i, bucketParams := range u.state.Rollup.Buckets { + for _, bucketUpdate := range bucketUpdates { + if bucketUpdate.NumBucket == i { + bucketParams.Withdrawals = bucketUpdate.Withdrawals + u.state.Rollup.Buckets[i] = bucketParams + break + } + } } - return tracerr.Wrap(meddler.Insert(hdb.dbWrite, "node_info", ni)) + u.state.Network.LastSyncBlock = lastSyncBlock.Num + u.state.Network.LastEthBlock = lastEthBlock.Num + u.state.Network.LastBatch = lastBatch + u.state.Network.CurrentSlot = currentSlot + u.state.Network.NextForgers = nextForgers + return nil } +// TODO: Remove // SetRollupVariables set Status.Rollup variables func (hdb *HistoryDB) SetRollupVariables(rollupVariables *common.RollupVariables) error { setUpdatedNodeInfo := func(txn *sqlx.Tx, ni *NodeInfo) error { rollupVars := NewRollupVariablesAPI(rollupVariables) - ni.StateAPI.Rollup = *rollupVars + ni.APIState.Rollup = *rollupVars return nil } return hdb.updateNodeInfo(setUpdatedNodeInfo) } +// TODO: Remove // SetWDelayerVariables set Status.WithdrawalDelayer variables func (hdb *HistoryDB) SetWDelayerVariables(wDelayerVariables *common.WDelayerVariables) error { setUpdatedNodeInfo := func(txn *sqlx.Tx, ni *NodeInfo) error { - ni.StateAPI.WithdrawalDelayer = *wDelayerVariables + ni.APIState.WithdrawalDelayer = *wDelayerVariables return nil } return hdb.updateNodeInfo(setUpdatedNodeInfo) } +// TODO: Remove // SetAuctionVariables set Status.Auction variables func (hdb *HistoryDB) SetAuctionVariables(auctionVariables *common.AuctionVariables) error { setUpdatedNodeInfo := func(txn *sqlx.Tx, ni *NodeInfo) error { auctionVars := NewAuctionVariablesAPI(auctionVariables) - ni.StateAPI.Auction = *auctionVars + ni.APIState.Auction = *auctionVars return nil } return hdb.updateNodeInfo(setUpdatedNodeInfo) } +// TODO: Remove // UpdateNetworkInfoBlock update Status.Network block related information func (hdb *HistoryDB) UpdateNetworkInfoBlock( lastEthBlock, lastSyncBlock common.Block, ) error { setUpdatedNodeInfo := func(txn *sqlx.Tx, ni *NodeInfo) error { - ni.StateAPI.Network.LastSyncBlock = lastSyncBlock.Num - ni.StateAPI.Network.LastEthBlock = lastEthBlock.Num + ni.APIState.Network.LastSyncBlock = lastSyncBlock.Num + ni.APIState.Network.LastEthBlock = lastEthBlock.Num return nil } return hdb.updateNodeInfo(setUpdatedNodeInfo) @@ -166,7 +300,7 @@ func (hdb *HistoryDB) UpdateNetworkInfo( return tracerr.Wrap(err) } // Get next forrgers - lastClosedSlot := currentSlot + int64(ni.StateAPI.Auction.ClosedAuctionSlots) + lastClosedSlot := currentSlot + int64(ni.APIState.Auction.ClosedAuctionSlots) nextForgers, err := hdb.getNextForgers(txn, ni, lastSyncBlock, currentSlot, lastClosedSlot) if tracerr.Unwrap(err) == sql.ErrNoRows { nextForgers = nil @@ -192,20 +326,20 @@ func (hdb *HistoryDB) UpdateNetworkInfo( bucketUpdates = db.SlicePtrsToSlice(bucketUpdatesPtrs).([]BucketUpdateAPI) } // Update NodeInfo struct - for i, bucketParams := range ni.StateAPI.Rollup.Buckets { + for i, bucketParams := range ni.APIState.Rollup.Buckets { for _, bucketUpdate := range bucketUpdates { if bucketUpdate.NumBucket == i { bucketParams.Withdrawals = bucketUpdate.Withdrawals - ni.StateAPI.Rollup.Buckets[i] = bucketParams + ni.APIState.Rollup.Buckets[i] = bucketParams break } } } - ni.StateAPI.Network.LastSyncBlock = lastSyncBlock.Num - ni.StateAPI.Network.LastEthBlock = lastEthBlock.Num - ni.StateAPI.Network.LastBatch = lastBatch - ni.StateAPI.Network.CurrentSlot = currentSlot - ni.StateAPI.Network.NextForgers = nextForgers + ni.APIState.Network.LastSyncBlock = lastSyncBlock.Num + ni.APIState.Network.LastEthBlock = lastEthBlock.Num + ni.APIState.Network.LastBatch = lastBatch + ni.APIState.Network.CurrentSlot = currentSlot + ni.APIState.Network.NextForgers = nextForgers return nil } return hdb.updateNodeInfo(setUpdatedNodeInfo) @@ -227,54 +361,51 @@ func apiSlotToBigInts(defaultSlotSetBid [6]*apitypes.BigIntStr) ([6]*big.Int, er } // getNextForgers returns next forgers -func (hdb *HistoryDB) getNextForgers(txn *sqlx.Tx, ni *NodeInfo, lastBlock common.Block, currentSlot, lastClosedSlot int64) ([]NextForger, error) { +func (u *APIStateUpdater) getNextForgers(txn *sqlx.Tx, + lastBlock common.Block, currentSlot, lastClosedSlot int64) ([]NextForger, error) { secondsPerBlock := int64(15) //nolint:gomnd // currentSlot and lastClosedSlot included limit := uint(lastClosedSlot - currentSlot + 1) - bids, _, err := hdb.getBestBidsAPI(txn, ¤tSlot, &lastClosedSlot, nil, &limit, "ASC") + bids, _, err := u.hdb.getBestBidsAPI(txn, ¤tSlot, &lastClosedSlot, nil, &limit, "ASC") if err != nil && tracerr.Unwrap(err) != sql.ErrNoRows { return nil, tracerr.Wrap(err) } nextForgers := []NextForger{} // Get min bid info var minBidInfo []MinBidInfo - if currentSlot >= ni.StateAPI.Auction.DefaultSlotSetBidSlotNum { + if currentSlot >= u.state.Auction.DefaultSlotSetBidSlotNum { // All min bids can be calculated with the last update of AuctionVariables - bigIntSlots, err := apiSlotToBigInts(ni.StateAPI.Auction.DefaultSlotSetBid) + bigIntSlots, err := apiSlotToBigInts(u.state.Auction.DefaultSlotSetBid) if err != nil { return nil, tracerr.Wrap(err) } minBidInfo = []MinBidInfo{{ DefaultSlotSetBid: bigIntSlots, - DefaultSlotSetBidSlotNum: ni.StateAPI.Auction.DefaultSlotSetBidSlotNum, + DefaultSlotSetBidSlotNum: u.state.Auction.DefaultSlotSetBidSlotNum, }} } else { // Get all the relevant updates from the DB - minBidInfoPtrs := []*MinBidInfo{} - query := ` - SELECT DISTINCT default_slot_set_bid, default_slot_set_bid_slot_num FROM auction_vars - WHERE default_slot_set_bid_slot_num < $1 - ORDER BY default_slot_set_bid_slot_num DESC - LIMIT $2;` - if err := meddler.QueryAll( - txn, &minBidInfoPtrs, query, lastClosedSlot, int(lastClosedSlot-currentSlot)+1, - ); err != nil { + minBidInfo, err = u.hdb.getMinBidInfo(txn, currentSlot, lastClosedSlot) + if err != nil { return nil, tracerr.Wrap(err) } - minBidInfo = db.SlicePtrsToSlice(minBidInfoPtrs).([]MinBidInfo) } // Create nextForger for each slot for i := currentSlot; i <= lastClosedSlot; i++ { - fromBlock := i*int64(ni.Constants.AuctionConstants.BlocksPerSlot) + ni.Constants.AuctionConstants.GenesisBlockNum - toBlock := (i+1)*int64(ni.Constants.AuctionConstants.BlocksPerSlot) + ni.Constants.AuctionConstants.GenesisBlockNum - 1 + fromBlock := i*int64(u.constants.AuctionConstants.BlocksPerSlot) + + u.constants.AuctionConstants.GenesisBlockNum + toBlock := (i+1)*int64(u.constants.AuctionConstants.BlocksPerSlot) + + u.constants.AuctionConstants.GenesisBlockNum - 1 nextForger := NextForger{ Period: Period{ - SlotNum: i, - FromBlock: fromBlock, - ToBlock: toBlock, - FromTimestamp: lastBlock.Timestamp.Add(time.Second * time.Duration(secondsPerBlock*(fromBlock-lastBlock.Num))), - ToTimestamp: lastBlock.Timestamp.Add(time.Second * time.Duration(secondsPerBlock*(toBlock-lastBlock.Num))), + SlotNum: i, + FromBlock: fromBlock, + ToBlock: toBlock, + FromTimestamp: lastBlock.Timestamp.Add(time.Second * + time.Duration(secondsPerBlock*(fromBlock-lastBlock.Num))), + ToTimestamp: lastBlock.Timestamp.Add(time.Second * + time.Duration(secondsPerBlock*(toBlock-lastBlock.Num))), }, } foundForger := false @@ -288,7 +419,7 @@ func (hdb *HistoryDB) getNextForgers(txn *sqlx.Tx, ni *NodeInfo, lastBlock commo // Find the most recent update if slotNum >= minBidInfo[i].DefaultSlotSetBidSlotNum { // Get min bid - minBidSelector := slotNum % int64(len(ni.StateAPI.Auction.DefaultSlotSetBid)) + minBidSelector := slotNum % int64(len(u.state.Auction.DefaultSlotSetBid)) minBid := minBidInfo[i].DefaultSlotSetBid[minBidSelector] // Check if the bid has beaten the minimum bid, ok := new(big.Int).SetString(string(bids[j].BidValue), 10) @@ -306,7 +437,7 @@ func (hdb *HistoryDB) getNextForgers(txn *sqlx.Tx, ni *NodeInfo, lastBlock commo if !foundForger { // There is no bid or it's smaller than the minimum break } - coordinator, err := hdb.GetCoordinatorAPI(bids[j].Bidder) + coordinator, err := u.hdb.GetCoordinatorAPI(bids[j].Bidder) if err != nil { return nil, tracerr.Wrap(err) } @@ -317,8 +448,8 @@ func (hdb *HistoryDB) getNextForgers(txn *sqlx.Tx, ni *NodeInfo, lastBlock commo // If there is no bid, the coordinator that will forge is boot coordinator if !foundForger { nextForger.Coordinator = CoordinatorAPI{ - Forger: ni.StateAPI.Auction.BootCoordinator, - URL: ni.StateAPI.Auction.BootCoordinatorURL, + Forger: u.state.Auction.BootCoordinator, + URL: u.state.Auction.BootCoordinatorURL, } } nextForgers = append(nextForgers, nextForger) @@ -326,11 +457,12 @@ func (hdb *HistoryDB) getNextForgers(txn *sqlx.Tx, ni *NodeInfo, lastBlock commo return nextForgers, nil } +// TODO: Rename to getMetrics and don't write anything // UpdateMetrics update Status.Metrics information func (hdb *HistoryDB) UpdateMetrics() error { setUpdatedNodeInfo := func(txn *sqlx.Tx, ni *NodeInfo) error { // Get the first and last batch of the last 24h and their timestamps - if ni.StateAPI.Network.LastBatch == nil { + if ni.APIState.Network.LastBatch == nil { return nil } type period struct { @@ -340,7 +472,7 @@ func (hdb *HistoryDB) UpdateMetrics() error { ToTimestamp time.Time `meddler:"to_timestamp"` } p := &period{ - ToBatchNum: ni.StateAPI.Network.LastBatch.BatchNum, + ToBatchNum: ni.APIState.Network.LastBatch.BatchNum, } if err := meddler.QueryRow( txn, p, `SELECT @@ -366,17 +498,17 @@ func (hdb *HistoryDB) UpdateMetrics() error { if seconds == 0 { // Avoid dividing by 0 seconds++ } - ni.StateAPI.Metrics.TransactionsPerSecond = float64(nTxs) / seconds + ni.APIState.Metrics.TransactionsPerSecond = float64(nTxs) / seconds // Set txs/batch nBatches := p.ToBatchNum - p.FromBatchNum if nBatches == 0 { // Avoid dividing by 0 nBatches++ } if (p.ToBatchNum - p.FromBatchNum) > 0 { - ni.StateAPI.Metrics.TransactionsPerBatch = float64(nTxs) / + ni.APIState.Metrics.TransactionsPerBatch = float64(nTxs) / float64(nBatches) } else { - ni.StateAPI.Metrics.TransactionsPerBatch = 0 + ni.APIState.Metrics.TransactionsPerBatch = 0 } // Get total fee of that period row = txn.QueryRow( @@ -388,11 +520,11 @@ func (hdb *HistoryDB) UpdateMetrics() error { return tracerr.Wrap(err) } // Set batch frequency - ni.StateAPI.Metrics.BatchFrequency = seconds / float64(nBatches) + ni.APIState.Metrics.BatchFrequency = seconds / float64(nBatches) if nTxs > 0 { - ni.StateAPI.Metrics.AvgTransactionFee = totalFee / float64(nTxs) + ni.APIState.Metrics.AvgTransactionFee = totalFee / float64(nTxs) } else { - ni.StateAPI.Metrics.AvgTransactionFee = 0 + ni.APIState.Metrics.AvgTransactionFee = 0 } // Get and set amount of registered accounts type registeredAccounts struct { @@ -406,8 +538,8 @@ func (hdb *HistoryDB) UpdateMetrics() error { ); err != nil { return tracerr.Wrap(err) } - ni.StateAPI.Metrics.TotalAccounts = ra.TotalIdx - ni.StateAPI.Metrics.TotalBJJs = ra.TotalBJJ + ni.APIState.Metrics.TotalAccounts = ra.TotalIdx + ni.APIState.Metrics.TotalBJJs = ra.TotalBJJ // Get and set estimated time to forge L1 tx row = txn.QueryRow( `SELECT COALESCE (AVG(EXTRACT(EPOCH FROM (forged.timestamp - added.timestamp))), 0) FROM tx @@ -421,7 +553,7 @@ func (hdb *HistoryDB) UpdateMetrics() error { if err := row.Scan(&timeToForgeL1); err != nil { return tracerr.Wrap(err) } - ni.StateAPI.Metrics.EstimatedTimeToForgeL1 = timeToForgeL1 + ni.APIState.Metrics.EstimatedTimeToForgeL1 = timeToForgeL1 return nil } return hdb.updateNodeInfo(setUpdatedNodeInfo) @@ -464,11 +596,11 @@ func (hdb *HistoryDB) UpdateRecommendedFee() error { } else { avgTransactionFee = 0 } - ni.StateAPI.RecommendedFee.ExistingAccount = + ni.APIState.RecommendedFee.ExistingAccount = math.Max(avgTransactionFee, *ni.MinFeeUSD) - ni.StateAPI.RecommendedFee.CreatesAccount = + ni.APIState.RecommendedFee.CreatesAccount = math.Max(createAccountExtraFeePercentage*avgTransactionFee, *ni.MinFeeUSD) - ni.StateAPI.RecommendedFee.CreatesAccountAndRegister = + ni.APIState.RecommendedFee.CreatesAccountAndRegister = math.Max(createAccountInternalExtraFeePercentage*avgTransactionFee, *ni.MinFeeUSD) return nil } diff --git a/db/migrations/0001.sql b/db/migrations/0001.sql index 0024ed7..268c0e6 100644 --- a/db/migrations/0001.sql +++ b/db/migrations/0001.sql @@ -664,8 +664,9 @@ CREATE TABLE account_creation_auth ( CREATE TABLE node_info ( item_id SERIAL PRIMARY KEY, state BYTEA, -- object returned by GET /state - max_pool_txs BIGINT, -- L2DB config - min_fee NUMERIC, -- L2DB config + config BYTEA, -- Node config + -- max_pool_txs BIGINT, -- L2DB config + -- min_fee NUMERIC, -- L2DB config constants BYTEA -- info of the network that is constant ); INSERT INTO node_info(item_id) VALUES (1); -- Always have a single row that we will update