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.

127 lines
4.9 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
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
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
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. /*
  2. Package api implements the public interface of the hermez-node using a HTTP REST API.
  3. There are two subsets of endpoints:
  4. - coordinatorEndpoints: used to receive L2 transactions and account creation authorizations. Targeted for wallets.
  5. - explorerEndpoints: used to provide all sorts of information about the network. Targeted for explorers and similar services.
  6. About the configuration of the API:
  7. - The API is supposed to be launched using the cli found at the package cli/node, and configured through the configuration file.
  8. - The mentioned configuration file allows exposing any combination of the endpoint subsets.
  9. - Although the API can run in a "standalone" manner using the serveapi command, it won't work properly
  10. unless another process acting as a coord or sync is filling the HistoryDB.
  11. Design principles and considerations:
  12. - In order to decouple the API process from the rest of the node, all the communication between this package and the rest of
  13. the system is done through the SQL database. As a matter of fact, the only public function of the package is the constructor NewAPI.
  14. All the information needed for the API to work should be obtained through the configuration file of the cli or the database.
  15. - The format of the requests / responses doesn't match directly with the common types, and for this reason, the package api/apitypes is used
  16. to facilitate the format conversion. Most of the time, this is done directly at the db level.
  17. - The API endpoints are fully documented using OpenAPI aka Swagger. All the endpoints are tested against the spec to ensure consistency
  18. between implementation and specification. To get a sense of which endpoints exist and how they work, it's strongly recommended to check this specification.
  19. The specification can be found at api/swagger.yml.
  20. - In general, all the API endpoints produce queries to the SQL database in order to retrieve / insert the requested information. The most notable exceptions to this are
  21. the /config endpoint, which returns a static object generated at construction time, and the /state, which also is retrieved from the database, but it's generated by API/stateapiupdater package.
  22. */
  23. package api
  24. import (
  25. "errors"
  26. ethCommon "github.com/ethereum/go-ethereum/common"
  27. "github.com/gin-gonic/gin"
  28. "github.com/hermeznetwork/hermez-node/db/historydb"
  29. "github.com/hermeznetwork/hermez-node/db/l2db"
  30. "github.com/hermeznetwork/hermez-node/metric"
  31. "github.com/hermeznetwork/tracerr"
  32. )
  33. // API serves HTTP requests to allow external interaction with the Hermez node
  34. type API struct {
  35. h *historydb.HistoryDB
  36. cg *configAPI
  37. l2 *l2db.L2DB
  38. hermezAddress ethCommon.Address
  39. }
  40. // NewAPI sets the endpoints and the appropriate handlers, but doesn't start the server
  41. func NewAPI(
  42. coordinatorEndpoints, explorerEndpoints bool,
  43. server *gin.Engine,
  44. hdb *historydb.HistoryDB,
  45. l2db *l2db.L2DB,
  46. ) (*API, error) {
  47. // Check input
  48. if coordinatorEndpoints && l2db == nil {
  49. return nil, tracerr.Wrap(errors.New("cannot serve Coordinator endpoints without L2DB"))
  50. }
  51. if explorerEndpoints && hdb == nil {
  52. return nil, tracerr.Wrap(errors.New("cannot serve Explorer endpoints without HistoryDB"))
  53. }
  54. consts, err := hdb.GetConstants()
  55. if err != nil {
  56. return nil, err
  57. }
  58. a := &API{
  59. h: hdb,
  60. cg: &configAPI{
  61. RollupConstants: *newRollupConstants(consts.Rollup),
  62. AuctionConstants: consts.Auction,
  63. WDelayerConstants: consts.WDelayer,
  64. ChainID: consts.ChainID,
  65. },
  66. l2: l2db,
  67. hermezAddress: consts.HermezAddress,
  68. }
  69. middleware, err := metric.PrometheusMiddleware()
  70. if err != nil {
  71. return nil, err
  72. }
  73. server.Use(middleware)
  74. server.NoRoute(a.noRoute)
  75. v1 := server.Group("/v1")
  76. // Add coordinator endpoints
  77. if coordinatorEndpoints {
  78. // Account creation authorization
  79. v1.POST("/account-creation-authorization", a.postAccountCreationAuth)
  80. v1.GET("/account-creation-authorization/:hezEthereumAddress", a.getAccountCreationAuth)
  81. // Transaction
  82. v1.POST("/transactions-pool", a.postPoolTx)
  83. v1.GET("/transactions-pool/:id", a.getPoolTx)
  84. }
  85. // Add explorer endpoints
  86. if explorerEndpoints {
  87. // Account
  88. v1.GET("/accounts", a.getAccounts)
  89. v1.GET("/accounts/:accountIndex", a.getAccount)
  90. v1.GET("/exits", a.getExits)
  91. v1.GET("/exits/:batchNum/:accountIndex", a.getExit)
  92. // Transaction
  93. v1.GET("/transactions-history", a.getHistoryTxs)
  94. v1.GET("/transactions-history/:id", a.getHistoryTx)
  95. // Batches
  96. v1.GET("/batches", a.getBatches)
  97. v1.GET("/batches/:batchNum", a.getBatch)
  98. v1.GET("/full-batches/:batchNum", a.getFullBatch)
  99. // Slots
  100. v1.GET("/slots", a.getSlots)
  101. v1.GET("/slots/:slotNum", a.getSlot)
  102. // Bids
  103. v1.GET("/bids", a.getBids)
  104. // State
  105. v1.GET("/state", a.getState)
  106. // Config
  107. v1.GET("/config", a.getConfig)
  108. // Tokens
  109. v1.GET("/tokens", a.getTokens)
  110. v1.GET("/tokens/:id", a.getToken)
  111. // Coordinators
  112. v1.GET("/coordinators", a.getCoordinators)
  113. }
  114. return a, nil
  115. }