Browse Source

Merge pull request #235 from hermeznetwork/feature/api-coordinator-refactor

API Coordinator Refactor
feature/sql-semaphore1
laisolizq 4 years ago
committed by GitHub
parent
commit
decc4996ee
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 175 additions and 166 deletions
  1. +3
    -56
      api/api_test.go
  2. +57
    -0
      api/coordinator.go
  3. +93
    -0
      api/coordinator_test.go
  4. +0
    -42
      api/dbtoapistructs.go
  5. +0
    -46
      api/handlers.go
  6. +1
    -1
      api/token_test.go
  7. +7
    -7
      db/historydb/historydb.go
  8. +14
    -14
      db/historydb/views.go

+ 3
- 56
api/api_test.go

@ -41,7 +41,7 @@ type testCommon struct {
blocks []common.Block blocks []common.Block
tokens []historydb.TokenWithUSD tokens []historydb.TokenWithUSD
batches []testBatch batches []testBatch
coordinators []coordinatorAPI
coordinators []historydb.CoordinatorAPI
usrAddr string usrAddr string
usrBjj string usrBjj string
accs []common.Account accs []common.Account
@ -633,8 +633,7 @@ func TestMain(m *testing.M) {
} }
fromItem := uint(0) fromItem := uint(0)
limit := uint(99999) 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 { if err != nil {
panic(err) panic(err)
} }
@ -652,7 +651,7 @@ func TestMain(m *testing.M) {
blocks: blocks, blocks: blocks,
tokens: tokensUSD, tokens: tokensUSD,
batches: genTestBatches(blocks, batches), batches: genTestBatches(blocks, batches),
coordinators: apiCoordinators,
coordinators: coordinators,
usrAddr: ethAddrToHez(usrAddr), usrAddr: ethAddrToHez(usrAddr),
usrBjj: bjjToString(usrBjj), usrBjj: bjjToString(usrBjj),
accs: accs, accs: accs,
@ -1162,58 +1161,6 @@ func assertPoolTx(t *testing.T, expected, actual sendPoolTx) {
assert.Equal(t, expected, actual) 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) { func TestAccountCreationAuth(t *testing.T) {
// POST // POST
endpoint := apiURL + "account-creation-authorization" endpoint := apiURL + "account-creation-authorization"

+ 57
- 0
api/coordinator.go

@ -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
- 0
api/coordinator_test.go

@ -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)
}

+ 0
- 42
api/dbtoapistructs.go

@ -578,48 +578,6 @@ func poolL2TxReadToSend(dbTx *l2db.PoolL2TxRead) *sendPoolTx {
return tx 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 // AccountCreationAuth
type accountCreationAuthAPI struct { type accountCreationAuthAPI struct {

+ 0
- 46
api/handlers.go

@ -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) { func retSQLErr(err error, c *gin.Context) {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
c.JSON(http.StatusNotFound, errorMsg{ c.JSON(http.StatusNotFound, errorMsg{

+ 1
- 1
api/token_test.go

@ -145,7 +145,7 @@ func assertTokensAPIs(t *testing.T, expected, actual []historydb.TokenWithUSD) {
if expected[i].USDUpdate == nil { if expected[i].USDUpdate == nil {
assert.Equal(t, expected[i].USDUpdate, actual[i].USDUpdate) assert.Equal(t, expected[i].USDUpdate, actual[i].USDUpdate)
} else { } 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 expected[i].USDUpdate = actual[i].USDUpdate
} }
assert.Equal(t, expected[i], actual[i]) assert.Equal(t, expected[i], actual[i])

+ 7
- 7
db/historydb/historydb.go

@ -1100,17 +1100,17 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *common.BlockData) (err error) {
return txn.Commit() 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( err := meddler.QueryRow(
hdb.db, coordinator, `SELECT * FROM coordinator WHERE bidder_addr = $1;`, bidderAddr, hdb.db, coordinator, `SELECT * FROM coordinator WHERE bidder_addr = $1;`, bidderAddr,
) )
return coordinator, err 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 query string
var args []interface{} var args []interface{}
queryStr := `SELECT coordinator.*, queryStr := `SELECT coordinator.*,
@ -1136,14 +1136,14 @@ func (hdb *HistoryDB) GetCoordinators(fromItem, limit *uint, order string) ([]Hi
queryStr += fmt.Sprintf("LIMIT %d;", *limit) queryStr += fmt.Sprintf("LIMIT %d;", *limit)
query = hdb.db.Rebind(queryStr) query = hdb.db.Rebind(queryStr)
coordinators := []*HistoryCoordinator{}
coordinators := []*CoordinatorAPI{}
if err := meddler.QueryAll(hdb.db, &coordinators, query, args...); err != nil { if err := meddler.QueryAll(hdb.db, &coordinators, query, args...); err != nil {
return nil, nil, err return nil, nil, err
} }
if len(coordinators) == 0 { if len(coordinators) == 0 {
return nil, nil, sql.ErrNoRows return nil, nil, sql.ErrNoRows
} }
return db.SlicePtrsToSlice(coordinators).([]HistoryCoordinator), &db.Pagination{
return db.SlicePtrsToSlice(coordinators).([]CoordinatorAPI), &db.Pagination{
TotalItems: coordinators[0].TotalItems, TotalItems: coordinators[0].TotalItems,
FirstItem: coordinators[0].FirstItem, FirstItem: coordinators[0].FirstItem,
LastItem: coordinators[0].LastItem, LastItem: coordinators[0].LastItem,

+ 14
- 14
db/historydb/views.go

@ -120,17 +120,17 @@ type HistoryExit struct {
TokenUSDUpdate *time.Time `meddler:"usd_update"` 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 // 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 // BatchAPI is a representation of a batch with additional information
@ -157,10 +157,10 @@ type BatchAPI struct {
// Network define status of the network // Network define status of the network
type Network struct { 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 // Metrics define metrics of the network

Loading…
Cancel
Save