You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.8 KiB

Allow serving API only via new cli command - Add new command to the cli/node: `serveapi` that alows serving the API just by connecting to the PostgreSQL database. The mode flag should me passed in order to select whether we are connecting to a synchronizer database or a coordinator database. If `coord` is chosen as mode, the coordinator endpoints can be activated in order to allow inserting l2txs and authorizations into the L2DB. Summary of the implementation details - New SQL table with 3 columns (plus `item_id` pk). The table only contains a single row with `item_id` = 1. Columns: - state: historydb.StateAPI in JSON. This is the struct that is served via the `/state` API endpoint. The node will periodically update this struct and store it int he DB. The api server will query it from the DB to serve it. - config: historydb.NodeConfig in JSON. This struct contains node configuration parameters that the API needs to be aware of. It's updated once every time the node starts. - constants: historydb.Constants in JSON. This struct contains all the hermez network constants gathered via the ethereum client by the node. It's written once every time the node starts. - The HistoryDB contains methods to get and update each one of these columns individually. - The HistoryDB contains all methods that query the DB and prepare objects that will appear in the StateAPI endpoint. - The configuration used in for the `serveapi` cli/node command is defined in `config.APIServer`, and is a subset of `node.Config` in order to allow reusing the same configuration file of the node if desired. - A new object is introduced in the api: `StateAPIUpdater`, which contains all the necessary information to update the StateAPI in the DB periodically by the node. - Moved the types `SCConsts`, `SCVariables` and `SCVariablesPtr` from `syncrhonizer` to `common` for convenience.
3 years ago
  1. package historydb
  2. import (
  3. "time"
  4. ethCommon "github.com/ethereum/go-ethereum/common"
  5. "github.com/hermeznetwork/hermez-node/common"
  6. "github.com/hermeznetwork/tracerr"
  7. "github.com/russross/meddler"
  8. )
  9. // Period represents a time period in ethereum
  10. type Period struct {
  11. SlotNum int64 `json:"slotNum"`
  12. FromBlock int64 `json:"fromBlock"`
  13. ToBlock int64 `json:"toBlock"`
  14. FromTimestamp time.Time `json:"fromTimestamp"`
  15. ToTimestamp time.Time `json:"toTimestamp"`
  16. }
  17. // NextForgerAPI represents the next forger exposed via the API
  18. type NextForgerAPI struct {
  19. Coordinator CoordinatorAPI `json:"coordinator"`
  20. Period Period `json:"period"`
  21. }
  22. // NetworkAPI is the network state exposed via the API
  23. type NetworkAPI struct {
  24. LastEthBlock int64 `json:"lastEthereumBlock"`
  25. LastSyncBlock int64 `json:"lastSynchedBlock"`
  26. LastBatch *BatchAPI `json:"lastBatch"`
  27. CurrentSlot int64 `json:"currentSlot"`
  28. NextForgers []NextForgerAPI `json:"nextForgers"`
  29. }
  30. // NodePublicConfig is the configuration of the node that is exposed via API
  31. type NodePublicConfig struct {
  32. // ForgeDelay in seconds
  33. ForgeDelay float64 `json:"forgeDelay"`
  34. }
  35. // StateAPI is an object representing the node and network state exposed via the API
  36. type StateAPI struct {
  37. // NodePublicConfig is the configuration of the node that is exposed via API
  38. NodePublicConfig NodePublicConfig `json:"nodeConfig"`
  39. Network NetworkAPI `json:"network"`
  40. Metrics MetricsAPI `json:"metrics"`
  41. Rollup RollupVariablesAPI `json:"rollup"`
  42. Auction AuctionVariablesAPI `json:"auction"`
  43. WithdrawalDelayer common.WDelayerVariables `json:"withdrawalDelayer"`
  44. RecommendedFee common.RecommendedFee `json:"recommendedFee"`
  45. }
  46. // Constants contains network constants
  47. type Constants struct {
  48. common.SCConsts
  49. ChainID uint16
  50. HermezAddress ethCommon.Address
  51. }
  52. // NodeConfig contains the node config exposed in the API
  53. type NodeConfig struct {
  54. MaxPoolTxs uint32
  55. MinFeeUSD float64
  56. ForgeDelay float64
  57. }
  58. // NodeInfo contains information about he node used when serving the API
  59. type NodeInfo struct {
  60. ItemID int `meddler:"item_id,pk"`
  61. StateAPI *StateAPI `meddler:"state,json"`
  62. NodeConfig *NodeConfig `meddler:"config,json"`
  63. Constants *Constants `meddler:"constants,json"`
  64. }
  65. // GetNodeInfo returns the NodeInfo
  66. func (hdb *HistoryDB) GetNodeInfo() (*NodeInfo, error) {
  67. ni := &NodeInfo{}
  68. err := meddler.QueryRow(
  69. hdb.dbRead, ni, `SELECT * FROM node_info WHERE item_id = 1;`,
  70. )
  71. return ni, tracerr.Wrap(err)
  72. }
  73. // GetConstants returns the Constats
  74. func (hdb *HistoryDB) GetConstants() (*Constants, error) {
  75. var nodeInfo NodeInfo
  76. err := meddler.QueryRow(
  77. hdb.dbRead, &nodeInfo,
  78. "SELECT constants FROM node_info WHERE item_id = 1;",
  79. )
  80. return nodeInfo.Constants, tracerr.Wrap(err)
  81. }
  82. // SetConstants sets the Constants
  83. func (hdb *HistoryDB) SetConstants(constants *Constants) error {
  84. _constants := struct {
  85. Constants *Constants `meddler:"constants,json"`
  86. }{constants}
  87. values, err := meddler.Default.Values(&_constants, false)
  88. if err != nil {
  89. return tracerr.Wrap(err)
  90. }
  91. _, err = hdb.dbWrite.Exec(
  92. "UPDATE node_info SET constants = $1 WHERE item_id = 1;",
  93. values[0],
  94. )
  95. return tracerr.Wrap(err)
  96. }
  97. // GetStateInternalAPI returns the StateAPI
  98. func (hdb *HistoryDB) GetStateInternalAPI() (*StateAPI, error) {
  99. return hdb.getStateAPI(hdb.dbRead)
  100. }
  101. func (hdb *HistoryDB) getStateAPI(d meddler.DB) (*StateAPI, error) {
  102. var nodeInfo NodeInfo
  103. err := meddler.QueryRow(
  104. d, &nodeInfo,
  105. "SELECT state FROM node_info WHERE item_id = 1;",
  106. )
  107. return nodeInfo.StateAPI, tracerr.Wrap(err)
  108. }
  109. // SetStateInternalAPI sets the StateAPI
  110. func (hdb *HistoryDB) SetStateInternalAPI(stateAPI *StateAPI) error {
  111. _stateAPI := struct {
  112. StateAPI *StateAPI `meddler:"state,json"`
  113. }{stateAPI}
  114. values, err := meddler.Default.Values(&_stateAPI, false)
  115. if err != nil {
  116. return tracerr.Wrap(err)
  117. }
  118. _, err = hdb.dbWrite.Exec(
  119. "UPDATE node_info SET state = $1 WHERE item_id = 1;",
  120. values[0],
  121. )
  122. return tracerr.Wrap(err)
  123. }
  124. // GetNodeConfig returns the NodeConfig
  125. func (hdb *HistoryDB) GetNodeConfig() (*NodeConfig, error) {
  126. var nodeInfo NodeInfo
  127. err := meddler.QueryRow(
  128. hdb.dbRead, &nodeInfo,
  129. "SELECT config FROM node_info WHERE item_id = 1;",
  130. )
  131. return nodeInfo.NodeConfig, tracerr.Wrap(err)
  132. }
  133. // SetNodeConfig sets the NodeConfig
  134. func (hdb *HistoryDB) SetNodeConfig(nodeConfig *NodeConfig) error {
  135. _nodeConfig := struct {
  136. NodeConfig *NodeConfig `meddler:"config,json"`
  137. }{nodeConfig}
  138. values, err := meddler.Default.Values(&_nodeConfig, false)
  139. if err != nil {
  140. return tracerr.Wrap(err)
  141. }
  142. _, err = hdb.dbWrite.Exec(
  143. "UPDATE node_info SET config = $1 WHERE item_id = 1;",
  144. values[0],
  145. )
  146. return tracerr.Wrap(err)
  147. }