diff --git a/api/api.go b/api/api.go index d374aa6..b995aac 100644 --- a/api/api.go +++ b/api/api.go @@ -100,7 +100,6 @@ func NewAPI( server.GET("/tokens", a.getTokens) server.GET("/tokens/:id", a.getToken) server.GET("/coordinators", a.getCoordinators) - server.GET("/coordinators/:bidderAddr", a.getCoordinator) } return a, nil diff --git a/api/coordinator.go b/api/coordinator.go index 1471457..b1d507f 100644 --- a/api/coordinator.go +++ b/api/coordinator.go @@ -7,29 +7,17 @@ import ( "github.com/hermeznetwork/hermez-node/db/historydb" ) -func (a *API) getCoordinator(c *gin.Context) { - // Get bidderAddr - const name = "bidderAddr" - bidderAddr, err := parseParamEthAddr(name, c) - +func (a *API) getCoordinators(c *gin.Context) { + bidderAddr, err := parseQueryEthAddr("bidderAddr", c) if err != nil { retBadReq(err, c) return - } else if bidderAddr == nil { - retBadReq(ErrNillBidderAddr, c) - return } - - coordinator, err := a.h.GetCoordinatorAPI(*bidderAddr) + forgerAddr, err := parseQueryEthAddr("forgerAddr", c) if err != nil { - retSQLErr(err, c) + retBadReq(err, c) return } - - c.JSON(http.StatusOK, coordinator) -} - -func (a *API) getCoordinators(c *gin.Context) { // Pagination fromItem, order, limit, err := parsePagination(c) if err != nil { @@ -38,7 +26,7 @@ func (a *API) getCoordinators(c *gin.Context) { } // Fetch coordinators from historyDB - coordinators, pendingItems, err := a.h.GetCoordinatorsAPI(fromItem, limit, order) + coordinators, pendingItems, err := a.h.GetCoordinatorsAPI(bidderAddr, forgerAddr, fromItem, limit, order) if err != nil { retSQLErr(err, c) return diff --git a/api/coordinator_test.go b/api/coordinator_test.go index 5dcfd3c..0cd8564 100644 --- a/api/coordinator_test.go +++ b/api/coordinator_test.go @@ -68,20 +68,31 @@ func TestGetCoordinators(t *testing.T) { } assertCoordinators(t, reversedCoordinators, fetchedCoordinators) - // Test GetCoordinator - for _, coord := range tc.coordinators { - path = fmt.Sprintf("%s/%s", endpoint, coord.Forger.String()) - fetchedCoordinator := historydb.CoordinatorAPI{} - assert.NoError(t, doGoodReq("GET", path, nil, &fetchedCoordinator)) - assertCoordinator(t, coord, fetchedCoordinator) + for _, filteredCoord := range tc.coordinators { + // By bidder + fetchedCoordinators = []historydb.CoordinatorAPI{} + err = doGoodReqPaginated( + fmt.Sprintf(path+"&bidderAddr=%s", filteredCoord.Bidder.String()), + historydb.OrderAsc, &testCoordinatorsResponse{}, appendIter, + ) + assert.NoError(t, err) + assertCoordinators(t, []historydb.CoordinatorAPI{filteredCoord}, fetchedCoordinators) + // By forger + fetchedCoordinators = []historydb.CoordinatorAPI{} + err = doGoodReqPaginated( + fmt.Sprintf(path+"&forgerAddr=%s", filteredCoord.Forger.String()), + historydb.OrderAsc, &testCoordinatorsResponse{}, appendIter, + ) + assert.NoError(t, err) + assertCoordinators(t, []historydb.CoordinatorAPI{filteredCoord}, fetchedCoordinators) } // 400 - path = fmt.Sprintf("%s/0x001", endpoint) + path = fmt.Sprintf("%s?bidderAddr=0x001", endpoint) err = doBadReq("GET", path, nil, 400) assert.NoError(t, err) // 404 - path = fmt.Sprintf("%s/0xaa942cfcd25ad4d90a62358b0dd84f33b398262a", endpoint) + path = fmt.Sprintf("%s?bidderAddr=0xaa942cfcd25ad4d90a62358b0dd84f33b398262a", endpoint) err = doBadReq("GET", path, nil, 404) assert.NoError(t, err) } diff --git a/api/parsers.go b/api/parsers.go index 45344e8..4519c1f 100644 --- a/api/parsers.go +++ b/api/parsers.go @@ -406,14 +406,6 @@ func parseQueryEthAddr(name string, c querier) (*ethCommon.Address, error) { return parseEthAddr(addrStr) } -func parseParamEthAddr(name string, c paramer) (*ethCommon.Address, error) { - addrStr := c.Param(name) - if addrStr == "" { - return nil, nil - } - return parseEthAddr(addrStr) -} - func parseEthAddr(ethAddrStr string) (*ethCommon.Address, error) { var addr ethCommon.Address err := addr.UnmarshalText([]byte(ethAddrStr)) diff --git a/api/swagger.yml b/api/swagger.yml index 56878c6..8184818 100644 --- a/api/swagger.yml +++ b/api/swagger.yml @@ -1144,6 +1144,18 @@ paths: description: Get information about coordinators. operationId: getCoordinators parameters: + - name: forgerAddr + in: query + required: false + description: Get coordinators by it's forger address. + schema: + $ref: '#/components/schemas/EthereumAddress' + - name: bidderAddr + in: query + required: false + description: Get coordinators by it's bidder address. + schema: + $ref: '#/components/schemas/EthereumAddress' - name: fromItem in: query required: false @@ -1187,45 +1199,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - '/coordinators/{bidderAddr}': - get: - tags: - - Hermez status - summary: Get the information of a coordinator. - description: Get the information of a coordinator. - operationId: getCoordinator - parameters: - - name: bidderAddr - in: path - description: Coordinator identifier - required: true - schema: - $ref: '#/components/schemas/EthereumAddress' - responses: - '200': - description: Successful operation. - content: - application/json: - schema: - $ref: '#/components/schemas/Coordinator' - '400': - description: Bad request. - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '404': - description: Not found. - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal server error. - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' components: schemas: ItemId: diff --git a/db/historydb/historydb.go b/db/historydb/historydb.go index 54e9c5d..c309de2 100644 --- a/db/historydb/historydb.go +++ b/db/historydb/historydb.go @@ -1621,15 +1621,38 @@ func (hdb *HistoryDB) GetCoordinatorAPI(bidderAddr ethCommon.Address) (*Coordina } // GetCoordinatorsAPI returns a list of coordinators from the DB and pagination info -func (hdb *HistoryDB) GetCoordinatorsAPI(fromItem, limit *uint, order string) ([]CoordinatorAPI, uint64, error) { +func (hdb *HistoryDB) GetCoordinatorsAPI( + bidderAddr, forgerAddr *ethCommon.Address, + fromItem, limit *uint, order string, +) ([]CoordinatorAPI, uint64, error) { var query string var args []interface{} queryStr := `SELECT coordinator.*, COUNT(*) OVER() AS total_items FROM coordinator ` // Apply filters + nextIsAnd := false + if bidderAddr != nil { + queryStr += "WHERE bidder_addr = ? " + nextIsAnd = true + args = append(args, bidderAddr) + } + if forgerAddr != nil { + if nextIsAnd { + queryStr += "AND " + } else { + queryStr += "WHERE " + } + queryStr += "forger_addr = ? " + nextIsAnd = true + args = append(args, forgerAddr) + } if fromItem != nil { - queryStr += "WHERE " + if nextIsAnd { + queryStr += "AND " + } else { + queryStr += "WHERE " + } if order == OrderAsc { queryStr += "coordinator.item_id >= ? " } else { diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go index 7a030e4..ebce7b1 100644 --- a/synchronizer/synchronizer.go +++ b/synchronizer/synchronizer.go @@ -358,12 +358,14 @@ func (s *Synchronizer) init() error { } lastBlock := &common.Block{} lastSavedBlock, err := s.historyDB.GetLastBlock() - if err != nil && tracerr.Unwrap(err) != sql.ErrNoRows { + // `s.historyDB.GetLastBlock()` will never return `sql.ErrNoRows` + // because we always have the default block 0 in the DB + if err != nil { return tracerr.Wrap(err) } - // If there's no block in the DB (or we only have the default block 0), + // If we only have the default block 0, // make sure that the stateDB is clean - if tracerr.Unwrap(err) == sql.ErrNoRows || lastSavedBlock.Num == 0 { + if lastSavedBlock.Num == 0 { if err := s.stateDB.Reset(0); err != nil { return tracerr.Wrap(err) } @@ -624,6 +626,14 @@ func (s *Synchronizer) resetState(block *common.Block) error { s.vars.Rollup = *vars.Rollup.Copy() s.vars.Auction = *vars.Auction.Copy() s.vars.WDelayer = *vars.WDelayer.Copy() + // Add initial boot coordinator to HistoryDB + if err := s.historyDB.AddCoordinators([]common.Coordinator{{ + Forger: s.initVars.Auction.BootCoordinator, + URL: s.initVars.Auction.BootCoordinatorURL, + EthBlockNum: s.initVars.Auction.EthBlockNum, + }}); err != nil { + return tracerr.Wrap(err) + } } else if err != nil { return tracerr.Wrap(err) } else { @@ -1035,6 +1045,12 @@ func (s *Synchronizer) auctionSync(ethBlock *common.Block) (*common.AuctionData, s.vars.Auction.BootCoordinator = evt.NewBootCoordinator s.vars.Auction.BootCoordinatorURL = evt.NewBootCoordinatorURL varsUpdate = true + // Add new boot coordinator + auctionData.Coordinators = append(auctionData.Coordinators, common.Coordinator{ + Forger: evt.NewBootCoordinator, + URL: evt.NewBootCoordinatorURL, + EthBlockNum: blockNum, + }) } for _, evt := range auctionEvents.NewOpenAuctionSlots { s.vars.Auction.OpenAuctionSlots = evt.NewOpenAuctionSlots