mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Merge pull request #235 from hermeznetwork/feature/api-coordinator-refactor
API Coordinator Refactor
This commit is contained in:
@@ -41,7 +41,7 @@ type testCommon struct {
|
||||
blocks []common.Block
|
||||
tokens []historydb.TokenWithUSD
|
||||
batches []testBatch
|
||||
coordinators []coordinatorAPI
|
||||
coordinators []historydb.CoordinatorAPI
|
||||
usrAddr string
|
||||
usrBjj string
|
||||
accs []common.Account
|
||||
@@ -633,8 +633,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
fromItem := uint(0)
|
||||
limit := uint(99999)
|
||||
coordinators, _, err := hdb.GetCoordinators(&fromItem, &limit, historydb.OrderAsc)
|
||||
apiCoordinators := coordinatorsToAPI(coordinators)
|
||||
coordinators, _, err := hdb.GetCoordinatorsAPI(&fromItem, &limit, historydb.OrderAsc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -652,7 +651,7 @@ func TestMain(m *testing.M) {
|
||||
blocks: blocks,
|
||||
tokens: tokensUSD,
|
||||
batches: genTestBatches(blocks, batches),
|
||||
coordinators: apiCoordinators,
|
||||
coordinators: coordinators,
|
||||
usrAddr: ethAddrToHez(usrAddr),
|
||||
usrBjj: bjjToString(usrBjj),
|
||||
accs: accs,
|
||||
@@ -1162,58 +1161,6 @@ func assertPoolTx(t *testing.T, expected, actual sendPoolTx) {
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestGetCoordinators(t *testing.T) {
|
||||
endpoint := apiURL + "coordinators"
|
||||
fetchedCoordinators := []coordinatorAPI{}
|
||||
|
||||
appendIter := func(intr interface{}) {
|
||||
for i := 0; i < len(intr.(*coordinatorsAPI).Coordinators); i++ {
|
||||
tmp, err := copystructure.Copy(intr.(*coordinatorsAPI).Coordinators[i])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fetchedCoordinators = append(fetchedCoordinators, tmp.(coordinatorAPI))
|
||||
}
|
||||
}
|
||||
|
||||
limit := 5
|
||||
|
||||
path := fmt.Sprintf("%s?limit=%d&fromItem=", endpoint, limit)
|
||||
err := doGoodReqPaginated(path, historydb.OrderAsc, &coordinatorsAPI{}, appendIter)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.coordinators, fetchedCoordinators)
|
||||
|
||||
// Reverse Order
|
||||
reversedCoordinators := []coordinatorAPI{}
|
||||
appendIter = func(intr interface{}) {
|
||||
for i := 0; i < len(intr.(*coordinatorsAPI).Coordinators); i++ {
|
||||
tmp, err := copystructure.Copy(intr.(*coordinatorsAPI).Coordinators[i])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
reversedCoordinators = append(reversedCoordinators, tmp.(coordinatorAPI))
|
||||
}
|
||||
}
|
||||
err = doGoodReqPaginated(path, historydb.OrderDesc, &coordinatorsAPI{}, appendIter)
|
||||
assert.NoError(t, err)
|
||||
for i := 0; i < len(fetchedCoordinators); i++ {
|
||||
assert.Equal(t, reversedCoordinators[i], fetchedCoordinators[len(fetchedCoordinators)-1-i])
|
||||
}
|
||||
|
||||
// Test GetCoordinator
|
||||
path = fmt.Sprintf("%s/%s", endpoint, fetchedCoordinators[2].Forger.String())
|
||||
coordinator := coordinatorAPI{}
|
||||
assert.NoError(t, doGoodReq("GET", path, nil, &coordinator))
|
||||
assert.Equal(t, fetchedCoordinators[2], coordinator)
|
||||
// 400
|
||||
path = fmt.Sprintf("%s/0x001", endpoint)
|
||||
err = doBadReq("GET", path, nil, 400)
|
||||
assert.NoError(t, err)
|
||||
// 404
|
||||
path = fmt.Sprintf("%s/0xaa942cfcd25ad4d90a62358b0dd84f33b398262a", endpoint)
|
||||
err = doBadReq("GET", path, nil, 404)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
func TestAccountCreationAuth(t *testing.T) {
|
||||
// POST
|
||||
endpoint := apiURL + "account-creation-authorization"
|
||||
|
||||
57
api/coordinator.go
Normal file
57
api/coordinator.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/hermeznetwork/hermez-node/db"
|
||||
"github.com/hermeznetwork/hermez-node/db/historydb"
|
||||
)
|
||||
|
||||
func getCoordinator(c *gin.Context) {
|
||||
// Get bidderAddr
|
||||
const name = "bidderAddr"
|
||||
bidderAddr, err := parseParamEthAddr(name, c)
|
||||
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
} else if bidderAddr == nil {
|
||||
retBadReq(ErrNillBidderAddr, c)
|
||||
return
|
||||
}
|
||||
|
||||
coordinator, err := h.GetCoordinatorAPI(*bidderAddr)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, coordinator)
|
||||
}
|
||||
|
||||
func getCoordinators(c *gin.Context) {
|
||||
// Pagination
|
||||
fromItem, order, limit, err := parsePagination(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch coordinators from historyDB
|
||||
coordinators, pagination, err := h.GetCoordinatorsAPI(fromItem, limit, order)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Build succesfull response
|
||||
type coordinatorsResponse struct {
|
||||
Coordinators []historydb.CoordinatorAPI `json:"coordinators"`
|
||||
Pagination *db.Pagination `json:"pagination"`
|
||||
}
|
||||
c.JSON(http.StatusOK, &coordinatorsResponse{
|
||||
Coordinators: coordinators,
|
||||
Pagination: pagination,
|
||||
})
|
||||
}
|
||||
93
api/coordinator_test.go
Normal file
93
api/coordinator_test.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hermeznetwork/hermez-node/db"
|
||||
"github.com/hermeznetwork/hermez-node/db/historydb"
|
||||
"github.com/mitchellh/copystructure"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type testCoordinatorsResponse struct {
|
||||
Coordinators []historydb.CoordinatorAPI `json:"coordinators"`
|
||||
Pagination *db.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
func (t *testCoordinatorsResponse) GetPagination() *db.Pagination {
|
||||
if t.Coordinators[0].ItemID < t.Coordinators[len(t.Coordinators)-1].ItemID {
|
||||
t.Pagination.FirstReturnedItem = t.Coordinators[0].ItemID
|
||||
t.Pagination.LastReturnedItem = t.Coordinators[len(t.Coordinators)-1].ItemID
|
||||
} else {
|
||||
t.Pagination.LastReturnedItem = t.Coordinators[0].ItemID
|
||||
t.Pagination.FirstReturnedItem = t.Coordinators[len(t.Coordinators)-1].ItemID
|
||||
}
|
||||
return t.Pagination
|
||||
}
|
||||
|
||||
func (t *testCoordinatorsResponse) Len() int { return len(t.Coordinators) }
|
||||
|
||||
func TestGetCoordinators(t *testing.T) {
|
||||
endpoint := apiURL + "coordinators"
|
||||
fetchedCoordinators := []historydb.CoordinatorAPI{}
|
||||
|
||||
appendIter := func(intr interface{}) {
|
||||
for i := 0; i < len(intr.(*testCoordinatorsResponse).Coordinators); i++ {
|
||||
tmp, err := copystructure.Copy(intr.(*testCoordinatorsResponse).Coordinators[i])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fetchedCoordinators = append(fetchedCoordinators, tmp.(historydb.CoordinatorAPI))
|
||||
}
|
||||
}
|
||||
|
||||
limit := 5
|
||||
|
||||
path := fmt.Sprintf("%s?limit=%d&fromItem=", endpoint, limit)
|
||||
err := doGoodReqPaginated(path, historydb.OrderAsc, &testCoordinatorsResponse{}, appendIter)
|
||||
assert.NoError(t, err)
|
||||
for i := 0; i < len(fetchedCoordinators); i++ {
|
||||
assert.Equal(t, tc.coordinators[i].ItemID, fetchedCoordinators[i].ItemID)
|
||||
assert.Equal(t, tc.coordinators[i].Bidder, fetchedCoordinators[i].Bidder)
|
||||
assert.Equal(t, tc.coordinators[i].Forger, fetchedCoordinators[i].Forger)
|
||||
assert.Equal(t, tc.coordinators[i].EthBlockNum, fetchedCoordinators[i].EthBlockNum)
|
||||
assert.Equal(t, tc.coordinators[i].URL, fetchedCoordinators[i].URL)
|
||||
}
|
||||
|
||||
// Reverse Order
|
||||
reversedCoordinators := []historydb.CoordinatorAPI{}
|
||||
appendIter = func(intr interface{}) {
|
||||
for i := 0; i < len(intr.(*testCoordinatorsResponse).Coordinators); i++ {
|
||||
tmp, err := copystructure.Copy(intr.(*testCoordinatorsResponse).Coordinators[i])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
reversedCoordinators = append(reversedCoordinators, tmp.(historydb.CoordinatorAPI))
|
||||
}
|
||||
}
|
||||
err = doGoodReqPaginated(path, historydb.OrderDesc, &testCoordinatorsResponse{}, appendIter)
|
||||
assert.NoError(t, err)
|
||||
for i := 0; i < len(fetchedCoordinators); i++ {
|
||||
assert.Equal(t, reversedCoordinators[i].ItemID, fetchedCoordinators[len(fetchedCoordinators)-1-i].ItemID)
|
||||
assert.Equal(t, reversedCoordinators[i].Bidder, fetchedCoordinators[len(fetchedCoordinators)-1-i].Bidder)
|
||||
assert.Equal(t, reversedCoordinators[i].Forger, fetchedCoordinators[len(fetchedCoordinators)-1-i].Forger)
|
||||
assert.Equal(t, reversedCoordinators[i].EthBlockNum, fetchedCoordinators[len(fetchedCoordinators)-1-i].EthBlockNum)
|
||||
assert.Equal(t, reversedCoordinators[i].URL, fetchedCoordinators[len(fetchedCoordinators)-1-i].URL)
|
||||
}
|
||||
|
||||
// Test GetCoordinator
|
||||
path = fmt.Sprintf("%s/%s", endpoint, fetchedCoordinators[2].Forger.String())
|
||||
coordinator := historydb.CoordinatorAPI{}
|
||||
assert.NoError(t, doGoodReq("GET", path, nil, &coordinator))
|
||||
assert.Equal(t, fetchedCoordinators[2], coordinator)
|
||||
|
||||
// 400
|
||||
path = fmt.Sprintf("%s/0x001", endpoint)
|
||||
err = doBadReq("GET", path, nil, 400)
|
||||
assert.NoError(t, err)
|
||||
// 404
|
||||
path = fmt.Sprintf("%s/0xaa942cfcd25ad4d90a62358b0dd84f33b398262a", endpoint)
|
||||
err = doBadReq("GET", path, nil, 404)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@@ -578,48 +578,6 @@ func poolL2TxReadToSend(dbTx *l2db.PoolL2TxRead) *sendPoolTx {
|
||||
return tx
|
||||
}
|
||||
|
||||
// Coordinators
|
||||
|
||||
type coordinatorAPI struct {
|
||||
ItemID int `json:"itemId"`
|
||||
Bidder ethCommon.Address `json:"bidderAddr"`
|
||||
Forger ethCommon.Address `json:"forgerAddr"`
|
||||
EthBlockNum int64 `json:"ethereumBlock"`
|
||||
URL string `json:"URL"`
|
||||
}
|
||||
|
||||
type coordinatorsAPI struct {
|
||||
Coordinators []coordinatorAPI `json:"coordinators"`
|
||||
Pagination *db.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
func (t *coordinatorsAPI) GetPagination() *db.Pagination {
|
||||
if t.Coordinators[0].ItemID < t.Coordinators[len(t.Coordinators)-1].ItemID {
|
||||
t.Pagination.FirstReturnedItem = t.Coordinators[0].ItemID
|
||||
t.Pagination.LastReturnedItem = t.Coordinators[len(t.Coordinators)-1].ItemID
|
||||
} else {
|
||||
t.Pagination.LastReturnedItem = t.Coordinators[0].ItemID
|
||||
t.Pagination.FirstReturnedItem = t.Coordinators[len(t.Coordinators)-1].ItemID
|
||||
}
|
||||
return t.Pagination
|
||||
}
|
||||
|
||||
func (t *coordinatorsAPI) Len() int { return len(t.Coordinators) }
|
||||
|
||||
func coordinatorsToAPI(dbCoordinators []historydb.HistoryCoordinator) []coordinatorAPI {
|
||||
apiCoordinators := []coordinatorAPI{}
|
||||
for i := 0; i < len(dbCoordinators); i++ {
|
||||
apiCoordinators = append(apiCoordinators, coordinatorAPI{
|
||||
ItemID: dbCoordinators[i].ItemID,
|
||||
Bidder: dbCoordinators[i].Bidder,
|
||||
Forger: dbCoordinators[i].Forger,
|
||||
EthBlockNum: dbCoordinators[i].EthBlockNum,
|
||||
URL: dbCoordinators[i].URL,
|
||||
})
|
||||
}
|
||||
return apiCoordinators
|
||||
}
|
||||
|
||||
// AccountCreationAuth
|
||||
|
||||
type accountCreationAuthAPI struct {
|
||||
|
||||
@@ -219,52 +219,6 @@ func getRecommendedFee(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
func getCoordinators(c *gin.Context) {
|
||||
// Pagination
|
||||
fromItem, order, limit, err := parsePagination(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch coordinators from historyDB
|
||||
coordinators, pagination, err := h.GetCoordinators(fromItem, limit, order)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Build succesfull response
|
||||
apiCoordinators := coordinatorsToAPI(coordinators)
|
||||
c.JSON(http.StatusOK, &coordinatorsAPI{
|
||||
Coordinators: apiCoordinators,
|
||||
Pagination: pagination,
|
||||
})
|
||||
}
|
||||
|
||||
func getCoordinator(c *gin.Context) {
|
||||
// Get bidderAddr
|
||||
const name = "bidderAddr"
|
||||
bidderAddr, err := parseParamEthAddr(name, c)
|
||||
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
} else if bidderAddr == nil {
|
||||
retBadReq(ErrNillBidderAddr, c)
|
||||
return
|
||||
}
|
||||
|
||||
coordinator, err := h.GetCoordinator(*bidderAddr)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
apiCoordinator := coordinatorsToAPI([]historydb.HistoryCoordinator{*coordinator})
|
||||
c.JSON(http.StatusOK, apiCoordinator[0])
|
||||
}
|
||||
|
||||
func retSQLErr(err error, c *gin.Context) {
|
||||
if err == sql.ErrNoRows {
|
||||
c.JSON(http.StatusNotFound, errorMsg{
|
||||
|
||||
@@ -145,7 +145,7 @@ func assertTokensAPIs(t *testing.T, expected, actual []historydb.TokenWithUSD) {
|
||||
if expected[i].USDUpdate == nil {
|
||||
assert.Equal(t, expected[i].USDUpdate, actual[i].USDUpdate)
|
||||
} else {
|
||||
assert.Equal(t, expected[i].USDUpdate.Unix(), actual[i].USDUpdate.Unix())
|
||||
assert.Less(t, expected[i].USDUpdate.Unix()-3, actual[i].USDUpdate.Unix())
|
||||
expected[i].USDUpdate = actual[i].USDUpdate
|
||||
}
|
||||
assert.Equal(t, expected[i], actual[i])
|
||||
|
||||
@@ -1100,17 +1100,17 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *common.BlockData) (err error) {
|
||||
return txn.Commit()
|
||||
}
|
||||
|
||||
// GetCoordinator returns a coordinator by its bidderAddr
|
||||
func (hdb *HistoryDB) GetCoordinator(bidderAddr ethCommon.Address) (*HistoryCoordinator, error) {
|
||||
coordinator := &HistoryCoordinator{}
|
||||
// GetCoordinatorAPI returns a coordinator by its bidderAddr
|
||||
func (hdb *HistoryDB) GetCoordinatorAPI(bidderAddr ethCommon.Address) (*CoordinatorAPI, error) {
|
||||
coordinator := &CoordinatorAPI{}
|
||||
err := meddler.QueryRow(
|
||||
hdb.db, coordinator, `SELECT * FROM coordinator WHERE bidder_addr = $1;`, bidderAddr,
|
||||
)
|
||||
return coordinator, err
|
||||
}
|
||||
|
||||
// GetCoordinators returns a list of coordinators from the DB and pagination info
|
||||
func (hdb *HistoryDB) GetCoordinators(fromItem, limit *uint, order string) ([]HistoryCoordinator, *db.Pagination, error) {
|
||||
// GetCoordinatorsAPI returns a list of coordinators from the DB and pagination info
|
||||
func (hdb *HistoryDB) GetCoordinatorsAPI(fromItem, limit *uint, order string) ([]CoordinatorAPI, *db.Pagination, error) {
|
||||
var query string
|
||||
var args []interface{}
|
||||
queryStr := `SELECT coordinator.*,
|
||||
@@ -1136,14 +1136,14 @@ func (hdb *HistoryDB) GetCoordinators(fromItem, limit *uint, order string) ([]Hi
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query = hdb.db.Rebind(queryStr)
|
||||
|
||||
coordinators := []*HistoryCoordinator{}
|
||||
coordinators := []*CoordinatorAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &coordinators, query, args...); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(coordinators) == 0 {
|
||||
return nil, nil, sql.ErrNoRows
|
||||
}
|
||||
return db.SlicePtrsToSlice(coordinators).([]HistoryCoordinator), &db.Pagination{
|
||||
return db.SlicePtrsToSlice(coordinators).([]CoordinatorAPI), &db.Pagination{
|
||||
TotalItems: coordinators[0].TotalItems,
|
||||
FirstItem: coordinators[0].FirstItem,
|
||||
LastItem: coordinators[0].LastItem,
|
||||
|
||||
@@ -120,17 +120,17 @@ type HistoryExit struct {
|
||||
TokenUSDUpdate *time.Time `meddler:"usd_update"`
|
||||
}
|
||||
|
||||
// HistoryCoordinator is a representation of a coordinator with additional information
|
||||
// CoordinatorAPI is a representation of a coordinator with additional information
|
||||
// required by the API
|
||||
type HistoryCoordinator struct {
|
||||
ItemID int `meddler:"item_id"`
|
||||
Bidder ethCommon.Address `meddler:"bidder_addr"`
|
||||
Forger ethCommon.Address `meddler:"forger_addr"`
|
||||
EthBlockNum int64 `meddler:"eth_block_num"`
|
||||
URL string `meddler:"url"`
|
||||
TotalItems int `meddler:"total_items"`
|
||||
FirstItem int `meddler:"first_item"`
|
||||
LastItem int `meddler:"last_item"`
|
||||
type CoordinatorAPI struct {
|
||||
ItemID int `json:"itemId" meddler:"item_id"`
|
||||
Bidder ethCommon.Address `json:"bidderAddr" meddler:"bidder_addr"`
|
||||
Forger ethCommon.Address `json:"forgerAddr" meddler:"forger_addr"`
|
||||
EthBlockNum int64 `json:"ethereumBlock" meddler:"eth_block_num"`
|
||||
URL string `json:"URL" meddler:"url"`
|
||||
TotalItems int `json:"-" meddler:"total_items"`
|
||||
FirstItem int `json:"-" meddler:"first_item"`
|
||||
LastItem int `json:"-" meddler:"last_item"`
|
||||
}
|
||||
|
||||
// BatchAPI is a representation of a batch with additional information
|
||||
@@ -157,10 +157,10 @@ type BatchAPI struct {
|
||||
|
||||
// Network define status of the network
|
||||
type Network struct {
|
||||
LastBlock int64 `json:"lastBlock"`
|
||||
LastBatch BatchAPI `json:"lastBatch"`
|
||||
CurrentSlot int64 `json:"currentSlot"`
|
||||
NextForgers []HistoryCoordinator `json:"nextForgers"`
|
||||
LastBlock int64 `json:"lastBlock"`
|
||||
LastBatch BatchAPI `json:"lastBatch"`
|
||||
CurrentSlot int64 `json:"currentSlot"`
|
||||
NextForgers []CoordinatorAPI `json:"nextForgers"`
|
||||
}
|
||||
|
||||
// Metrics define metrics of the network
|
||||
|
||||
Reference in New Issue
Block a user