Merge pull request #273 from hermeznetwork/feature/api-test

API state endpoint test
This commit is contained in:
Toni Ramírez
2020-11-10 14:51:21 +01:00
committed by GitHub
9 changed files with 351 additions and 271 deletions

View File

@@ -284,13 +284,22 @@ func TestMain(m *testing.M) {
testBids := genTestBids(blocks, coordinators, bids) testBids := genTestBids(blocks, coordinators, bids)
// Vars // Vars
var defaultSlotSetBid [6]*big.Int = [6]*big.Int{big.NewInt(10), big.NewInt(10), big.NewInt(10), big.NewInt(10), big.NewInt(10), big.NewInt(10)}
auctionVars := common.AuctionVariables{ auctionVars := common.AuctionVariables{
EthBlockNum: int64(2),
DonationAddress: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
DefaultSlotSetBid: defaultSlotSetBid,
Outbidding: uint16(1),
SlotDeadline: uint8(20),
BootCoordinator: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"), BootCoordinator: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
ClosedAuctionSlots: uint16(2), ClosedAuctionSlots: uint16(2),
OpenAuctionSlots: uint16(5), OpenAuctionSlots: uint16(5),
} }
rollupVars := common.RollupVariables{ rollupVars := common.RollupVariables{
EthBlockNum: int64(3),
FeeAddToken: big.NewInt(100),
ForgeL1L2BatchTimeout: int64(44),
WithdrawalDelay: uint64(3000), WithdrawalDelay: uint64(3000),
} }

View File

@@ -1,37 +0,0 @@
package api
import (
"encoding/base64"
"strconv"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/hermeznetwork/hermez-node/common"
"github.com/iden3/go-iden3-crypto/babyjub"
)
const exitIdx = "hez:EXIT:1"
type errorMsg struct {
Message string
}
func bjjToString(bjj *babyjub.PublicKey) string {
pkComp := [32]byte(bjj.Compress())
sum := pkComp[0]
for i := 1; i < len(pkComp); i++ {
sum += pkComp[i]
}
bjjSum := append(pkComp[:], sum)
return "hez:" + base64.RawURLEncoding.EncodeToString(bjjSum)
}
func ethAddrToHez(addr ethCommon.Address) string {
return "hez:" + addr.String()
}
func idxToHez(idx common.Idx, tokenSymbol string) string {
if idx == 1 {
return exitIdx
}
return "hez:" + tokenSymbol + ":" + strconv.Itoa(int(idx))
}

View File

@@ -13,6 +13,8 @@ import (
"github.com/iden3/go-iden3-crypto/babyjub" "github.com/iden3/go-iden3-crypto/babyjub"
) )
const exitIdx = "hez:EXIT:1"
// Query parsers // Query parsers
type querier interface { type querier interface {
@@ -428,3 +430,28 @@ func parseParamHezEthAddr(c paramer) (*ethCommon.Address, error) {
addrStr := c.Param(name) addrStr := c.Param(name)
return hezStringToEthAddr(addrStr, name) return hezStringToEthAddr(addrStr, name)
} }
type errorMsg struct {
Message string
}
func bjjToString(bjj *babyjub.PublicKey) string {
pkComp := [32]byte(bjj.Compress())
sum := pkComp[0]
for i := 1; i < len(pkComp); i++ {
sum += pkComp[i]
}
bjjSum := append(pkComp[:], sum)
return "hez:" + base64.RawURLEncoding.EncodeToString(bjjSum)
}
func ethAddrToHez(addr ethCommon.Address) string {
return "hez:" + addr.String()
}
func idxToHez(idx common.Idx, tokenSymbol string) string {
if idx == 1 {
return exitIdx
}
return "hez:" + tokenSymbol + ":" + strconv.Itoa(int(idx))
}

View File

@@ -20,17 +20,17 @@ type Network struct {
// NextForger is a representation of the information of a coordinator and the period will forge // NextForger is a representation of the information of a coordinator and the period will forge
type NextForger struct { type NextForger struct {
Coordinator historydb.CoordinatorAPI Coordinator historydb.CoordinatorAPI `json:"coordinator"`
Period Period Period Period `json:"period"`
} }
// Period is a representation of a period // Period is a representation of a period
type Period struct { type Period struct {
SlotNum int64 SlotNum int64 `json:"slotNum"`
FromBlock int64 FromBlock int64 `json:"fromBlock"`
ToBlock int64 ToBlock int64 `json:"toBlock"`
FromTimestamp time.Time FromTimestamp time.Time `json:"fromTimestamp"`
ToTimestamp time.Time ToTimestamp time.Time `json:"toTimestamp"`
} }
var bootCoordinator historydb.CoordinatorAPI = historydb.CoordinatorAPI{ var bootCoordinator historydb.CoordinatorAPI = historydb.CoordinatorAPI{
@@ -41,6 +41,7 @@ var bootCoordinator historydb.CoordinatorAPI = historydb.CoordinatorAPI{
} }
func (a *API) getState(c *gin.Context) { func (a *API) getState(c *gin.Context) {
// TODO: There are no events for the buckets information, so now this information will be 0
c.JSON(http.StatusOK, a.status) c.JSON(http.StatusOK, a.status)
} }

View File

@@ -5,11 +5,28 @@ import (
"time" "time"
"github.com/hermeznetwork/hermez-node/common" "github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db/historydb"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
const secondsPerBlock = 15 const secondsPerBlock = 15
type testStatus struct {
Network testNetwork `json:"network"`
Metrics historydb.Metrics `json:"metrics"`
Rollup common.RollupVariables `json:"rollup"`
Auction common.AuctionVariables `json:"auction"`
WithdrawalDelayer common.WDelayerVariables `json:"withdrawalDelayer"`
RecommendedFee common.RecommendedFee `json:"recommendedFee"`
}
type testNetwork struct {
LastBlock int64 `json:"lastBlock"`
LastBatch testBatch `json:"lastBatch"`
CurrentSlot int64 `json:"currentSlot"`
NextForgers []NextForger `json:"nextForgers"`
}
func TestSetRollupVariables(t *testing.T) { func TestSetRollupVariables(t *testing.T) {
rollupVars := &common.RollupVariables{} rollupVars := &common.RollupVariables{}
assert.Equal(t, *rollupVars, api.status.Rollup) assert.Equal(t, *rollupVars, api.status.Rollup)
@@ -101,6 +118,46 @@ func TestUpdateRecommendedFee(t *testing.T) {
err := api.UpdateRecommendedFee() err := api.UpdateRecommendedFee()
assert.NoError(t, err) assert.NoError(t, err)
assert.Greater(t, api.status.RecommendedFee.ExistingAccount, float64(0)) assert.Greater(t, api.status.RecommendedFee.ExistingAccount, float64(0))
assert.Equal(t, api.status.RecommendedFee.CreatesAccount, api.status.RecommendedFee.ExistingAccount*createAccountExtraFeePercentage) assert.Equal(t, api.status.RecommendedFee.CreatesAccount,
assert.Equal(t, api.status.RecommendedFee.CreatesAccountAndRegister, api.status.RecommendedFee.ExistingAccount*createAccountInternalExtraFeePercentage) api.status.RecommendedFee.ExistingAccount*createAccountExtraFeePercentage)
assert.Equal(t, api.status.RecommendedFee.CreatesAccountAndRegister,
api.status.RecommendedFee.ExistingAccount*createAccountInternalExtraFeePercentage)
}
func TestGetStatus(t *testing.T) {
lastBlock := tc.blocks[3]
lastBatchNum := common.BatchNum(3)
currentSlotNum := int64(1)
api.SetRollupVariables(tc.rollupVars)
api.SetWDelayerVariables(tc.wdelayerVars)
api.SetAuctionVariables(tc.auctionVars)
err := api.UpdateNetworkInfo(lastBlock, lastBatchNum, currentSlotNum)
assert.NoError(t, err)
err = api.UpdateMetrics()
assert.NoError(t, err)
err = api.UpdateRecommendedFee()
assert.NoError(t, err)
endpoint := apiURL + "state"
var status testStatus
assert.NoError(t, doGoodReq("GET", endpoint, nil, &status))
assert.Equal(t, tc.rollupVars, status.Rollup)
assert.Equal(t, tc.auctionVars, status.Auction)
assert.Equal(t, tc.wdelayerVars, status.WithdrawalDelayer)
assert.Equal(t, lastBlock.EthBlockNum, status.Network.LastBlock)
assert.Equal(t, lastBatchNum, status.Network.LastBatch.BatchNum)
assert.Equal(t, currentSlotNum, status.Network.CurrentSlot)
assert.Equal(t, int(api.status.Auction.ClosedAuctionSlots)+1, len(status.Network.NextForgers))
assert.Greater(t, status.Metrics.TransactionsPerBatch, float64(0))
assert.Greater(t, status.Metrics.BatchFrequency, float64(0))
assert.Greater(t, status.Metrics.TransactionsPerBatch, float64(0))
assert.Greater(t, status.Metrics.TotalAccounts, int64(0))
assert.Greater(t, status.Metrics.TotalBJJs, int64(0))
assert.Greater(t, status.Metrics.AvgTransactionFee, float64(0))
assert.Greater(t, status.RecommendedFee.ExistingAccount, float64(0))
assert.Equal(t, status.RecommendedFee.CreatesAccount,
status.RecommendedFee.ExistingAccount*createAccountExtraFeePercentage)
assert.Equal(t, status.RecommendedFee.CreatesAccountAndRegister,
status.RecommendedFee.ExistingAccount*createAccountInternalExtraFeePercentage)
} }

View File

@@ -2273,6 +2273,8 @@ components:
type: object type: object
description: Time period in which the coordinator will have the ability to forge. Specified both in Ethereum blocks and timestamp description: Time period in which the coordinator will have the ability to forge. Specified both in Ethereum blocks and timestamp
properties: properties:
slotNum:
$ref: '#/components/schemas/SlotNum'
fromBlock: fromBlock:
$ref: '#/components/schemas/EthBlockNum' $ref: '#/components/schemas/EthBlockNum'
toBlock: toBlock:
@@ -2283,21 +2285,47 @@ components:
toTimestamp: toTimestamp:
type: string type: string
format: date-time format: date-time
required:
- slotNum
- fromBlock
- toBlock
- fromTimestamp
- toTimestamp
additionalProperties: false
required:
- coordinator
- period
additionalProperties: false
NextForgers: NextForgers:
type: object
properties:
nextForgers:
type: array type: array
description: List of next coordinators to forge. description: List of next coordinators to forge.
items: items:
$ref: '#/components/schemas/NextForger' $ref: '#/components/schemas/NextForger'
pendingItems:
$ref: '#/components/schemas/PendingItems'
State: State:
type: object type: object
description: Gobal variables of the network description: Gobal variables of the network
properties: properties:
network: network:
$ref: '#/components/schemas/StateNetwork'
metrics:
$ref: '#/components/schemas/StateMetrics'
rollup:
$ref: '#/components/schemas/StateRollup'
auction:
$ref: '#/components/schemas/StateAuction'
withdrawalDelayer:
$ref: '#/components/schemas/StateWithdrawDelayer'
recommendedFee:
$ref: '#/components/schemas/RecommendedFee'
additionalProperties: false
required:
- network
- metrics
- rollup
- auction
- withdrawalDelayer
- recommendedFee
StateNetwork:
type: object type: object
description: Gobal statistics of the network description: Gobal statistics of the network
properties: properties:
@@ -2316,51 +2344,71 @@ components:
nextForgers: nextForgers:
$ref: '#/components/schemas/NextForgers' $ref: '#/components/schemas/NextForgers'
additionalProperties: false additionalProperties: false
require: required:
- lastBlock - lastBlock
- lastBatch - lastBatch
- currentSlot - currentSlot
- nextForgers - nextForgers
metrics: StateAuction:
type: object type: object
description: Metrics of the network description: Auction parameters.
properties: properties:
transactionsPerBatch: ethereumBlockNum:
type: number $ref: '#/components/schemas/EthBlockNum'
description: Average transactions per batch in the last 24 hours. bootCoordinator:
example: 2002.7 allOf:
batchFrequency: - $ref: '#/components/schemas/EthereumAddress'
type: number - description: Ethereum address of the boot coordinator.
description: Average elapsed time between batches in the last 24 hours, in seconds. - example: "0x997dc4262BCDbf85190C01c996b4C06a461d2430"
example: 8.9 slotDeadline:
transactionsPerSecond:
type: number
description: Average transactions per second in the last 24 hours.
example: 302.3
totalAccounts:
type: integer type: integer
description: Number of created accounts. description: Number of blocks after the beginning of a slot after which any coordinator can forge if the winner has not forged any batch in that slot.
example: 90473 example: 3
totalBJJs: closedAuctionSlots:
type: integer type: integer
description: Number of different registered BJJs. description: Amount of slots between the current slot and the slot auction that is closed. Example if the value is 2, when slot 10 begins, the auction of the slot 12 gets closed.
example: 23067 example: 2
avgTransactionFee: openAuctionSlots:
type: integer
description: How many days in advance are auctions opened.
defaultSlotSetBid:
type: array
description: "Initial minimal bid for each auction. Expressed as an array of 6 values. To calculate which value corresponds to each slot: `initialMinimalBidding[slotNum%6]`."
items:
type: integer
example: [32,0,68,21,55,99]
outbidding:
type: number type: number
description: Average fee percentage paid for L2 transactions in the last 24 hours. description: Minimum outbid over the previous one to consider it valid.
example: 1.54 example: 3.64
donationAddress:
allOf:
- $ref: '#/components/schemas/EthereumAddress'
- description: Ethereum address where the donations will go to.
- example: "0x887dc4262BCDbf85190C01c996b4C06a461d2430"
allocationRatio:
type: array
description: Percentage in which fees will be splitted between donations, governance and burning. The sum of the tree values should be 100.
items:
type: integer
example: [80,10,10]
additionalProperties: false additionalProperties: false
require: required:
- transactionsPerBatch - ethereumBlockNum
- batchFrequency - bootCoordinator
- transactionsPerSecond - slotDeadline
- totalAccounts - closedAuctionSlots
- totalBJJs - openAuctionSlots
- avgTransactionFee - defaultSlotSetBid
rollup: - outbidding
- donationAddress
- allocationRatio
StateRollup:
type: object type: object
description: Rollup parameters description: Rollup parameters
properties: properties:
ethereumBlockNum:
$ref: '#/components/schemas/EthBlockNum'
forgeL1L2BatchTimeout: forgeL1L2BatchTimeout:
type: integer type: integer
description: Max ethereum blocks after the last L1-L2-batch, when exceeds the timeout only L1-L2-batch are allowed. description: Max ethereum blocks after the last L1-L2-batch, when exceeds the timeout only L1-L2-batch are allowed.
@@ -2400,78 +2448,25 @@ components:
description: Max withdrawals the bucket can hold description: Max withdrawals the bucket can hold
example: 4 example: 4
additionalProperties: false additionalProperties: false
require: required:
- ceilUSD - ceilUSD
- blockStamp - blockStamp
- withdrawals - withdrawals
- blockWithdrawalRate - blockWithdrawalRate
- maxWithdrawals - maxWithdrawals
additionalProperties: false additionalProperties: false
require: required:
- ethereumBlockNum
- forgeL1L2BatchTimeout - forgeL1L2BatchTimeout
- feeAddToken - feeAddToken
- withdrawalDelay - withdrawalDelay
- buckets - buckets
auction: StateWithdrawDelayer:
type: object
description: Auction parameters.
properties:
bootCoordinator:
allOf:
- $ref: '#/components/schemas/EthereumAddress'
- description: Ethereum address of the boot coordinator.
- example: "0x997dc4262BCDbf85190C01c996b4C06a461d2430"
slotDeadline:
type: integer
description: Number of blocks after the beginning of a slot after which any coordinator can forge if the winner has not forged any batch in that slot.
example: 3
closedAuctionSlots:
type: integer
description: Amount of slots between the current slot and the slot auction that is closed. Example if the value is 2, when slot 10 begins, the auction of the slot 12 gets closed.
example: 2
openAuctionSlots:
type: integer
description: How many days in advance are auctions opened.
defaultSlotSetBid:
type: array
description: "Initial minimal bid for each auction. Expressed as an array of 6 values. To calculate which value corresponds to each slot: `initialMinimalBidding[slotNum%6]`."
items:
type: integer
example: [32,0,68,21,55,99]
outbidding:
type: number
description: Minimum outbid over the previous one to consider it valid.
example: 3.64
donationAddress:
allOf:
- $ref: '#/components/schemas/EthereumAddress'
- description: Ethereum address where the donations will go to.
- example: "0x887dc4262BCDbf85190C01c996b4C06a461d2430"
allocationRatio:
type: array
description: Percentage in which fees will be splitted between donations, governance and burning. The sum of the tree values should be 100.
items:
type: integer
example: [80,10,10]
additionalProperties: false
require:
- bootCoordinator
- slotDeadline
- closedAuctionSlots
- openAuctionSlots
- defaultSlotSetBid
- outbidding
- donationAddress
- allocationRatio
withdrawalDelayer:
type: object type: object
description: Withdrawal delayer parameters description: Withdrawal delayer parameters
properties: properties:
hermezRollupAddress: ethereumBlockNum:
allOf: $ref: '#/components/schemas/EthBlockNum'
- $ref: '#/components/schemas/EthereumAddress'
- description: Ethereum address of the rollup smart contract.
- example: "0x777dc4262BCDbf85190C01c996b4C06a461d2430"
hermezGovernanceDAOAddress: hermezGovernanceDAOAddress:
allOf: allOf:
- $ref: '#/components/schemas/EthereumAddress' - $ref: '#/components/schemas/EthereumAddress'
@@ -2501,24 +2496,50 @@ components:
description: Indicates if emergency mode has been activated. description: Indicates if emergency mode has been activated.
example: false example: false
additionalProperties: false additionalProperties: false
require: required:
- hermezRollupAddress - ethereumBlockNum
- hermezGovernanceDAOAddress - hermezGovernanceDAOAddress
- whiteHackGroupAddress - whiteHackGroupAddress
- hermezKeeperAddress - hermezKeeperAddress
- withdrawalDelay - withdrawalDelay
- emergencyModeStartingTime - emergencyModeStartingTime
- emergencyMode - emergencyMode
recommendedFee: StateMetrics:
$ref: '#/components/schemas/RecommendedFee' type: object
description: Metrics of the network
properties:
transactionsPerBatch:
type: number
description: Average transactions per batch in the last 24 hours.
example: 2002.7
batchFrequency:
type: number
description: Average elapsed time between batches in the last 24 hours, in seconds.
example: 8.9
transactionsPerSecond:
type: number
description: Average transactions per second in the last 24 hours.
example: 302.3
totalAccounts:
type: integer
description: Number of created accounts.
example: 90473
totalBJJs:
type: integer
description: Number of different registered BJJs.
example: 23067
avgTransactionFee:
type: number
description: Average fee percentage paid for L2 transactions in the last 24 hours.
example: 1.54
additionalProperties: false additionalProperties: false
require: required:
- network - transactionsPerBatch
- metrics - batchFrequency
- rollup - transactionsPerSecond
- auction - totalAccounts
- withdrawalDelayer - totalBJJs
- recomendedFee - avgTransactionFee
PendingItems: PendingItems:
type: integer type: integer
description: Amount of items that will be returned in subsequent calls to the endpoint, as long as they are done with same filters. When the value is 0 it means that all items have been sent. description: Amount of items that will be returned in subsequent calls to the endpoint, as long as they are done with same filters. When the value is 0 it means that all items have been sent.

View File

@@ -161,5 +161,5 @@ type RollupVariables struct {
FeeAddToken *big.Int `json:"feeAddToken" meddler:"fee_add_token,bigint" validate:"required"` FeeAddToken *big.Int `json:"feeAddToken" meddler:"fee_add_token,bigint" validate:"required"`
ForgeL1L2BatchTimeout int64 `json:"forgeL1L2BatchTimeout" meddler:"forge_l1_timeout" validate:"required"` ForgeL1L2BatchTimeout int64 `json:"forgeL1L2BatchTimeout" meddler:"forge_l1_timeout" validate:"required"`
WithdrawalDelay uint64 `json:"withdrawalDelay" meddler:"withdrawal_delay" validate:"required"` WithdrawalDelay uint64 `json:"withdrawalDelay" meddler:"withdrawal_delay" validate:"required"`
// Buckets [RollupConstNumBuckets]Bucket `json:"buckets" meddler:"buckets,json"` Buckets [RollupConstNumBuckets]Bucket `json:"buckets" meddler:"buckets,json"`
} }

View File

@@ -469,6 +469,7 @@ func TestSetInitialSCVars(t *testing.T) {
big.NewInt(10), big.NewInt(10),
12, 12,
13, 13,
[5]common.Bucket{},
} }
//nolint:govet //nolint:govet
auction := &common.AuctionVariables{ auction := &common.AuctionVariables{

View File

@@ -520,7 +520,8 @@ CREATE TABLE rollup_vars (
eth_block_num BIGINT PRIMARY KEY REFERENCES block (eth_block_num) ON DELETE CASCADE, eth_block_num BIGINT PRIMARY KEY REFERENCES block (eth_block_num) ON DELETE CASCADE,
fee_add_token BYTEA NOT NULL, fee_add_token BYTEA NOT NULL,
forge_l1_timeout BYTEA NOT NULL, forge_l1_timeout BYTEA NOT NULL,
withdrawal_delay BIGINT NOT NULL withdrawal_delay BIGINT NOT NULL,
buckets BYTEA
); );
CREATE TABLE auction_vars ( CREATE TABLE auction_vars (