mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Merge pull request #428 from hermeznetwork/fix/api-next-forgers
Fix next forgers api response
This commit is contained in:
137
api/api_test.go
137
api/api_test.go
@@ -177,6 +177,7 @@ type testCommon struct {
|
|||||||
auctionVars common.AuctionVariables
|
auctionVars common.AuctionVariables
|
||||||
rollupVars common.RollupVariables
|
rollupVars common.RollupVariables
|
||||||
wdelayerVars common.WDelayerVariables
|
wdelayerVars common.WDelayerVariables
|
||||||
|
nextForgers []NextForger
|
||||||
}
|
}
|
||||||
|
|
||||||
var tc testCommon
|
var tc testCommon
|
||||||
@@ -218,7 +219,6 @@ func TestMain(m *testing.M) {
|
|||||||
// L2DB
|
// L2DB
|
||||||
l2DB := l2db.NewL2DB(database, 10, 100, 24*time.Hour)
|
l2DB := l2db.NewL2DB(database, 10, 100, 24*time.Hour)
|
||||||
test.WipeDB(l2DB.DB()) // this will clean HistoryDB and L2DB
|
test.WipeDB(l2DB.DB()) // this will clean HistoryDB and L2DB
|
||||||
|
|
||||||
// Config (smart contract constants)
|
// Config (smart contract constants)
|
||||||
chainID := uint16(0)
|
chainID := uint16(0)
|
||||||
_config := getConfigTest(chainID)
|
_config := getConfigTest(chainID)
|
||||||
@@ -357,26 +357,128 @@ func TestMain(m *testing.M) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate Bids and add them to HistoryDB
|
// Test next forgers
|
||||||
const nBids = 20
|
// Set auction vars
|
||||||
commonBids := test.GenBids(nBids, commonBlocks, commonCoords)
|
// Slots 3 and 6 will have bids that will be invalidated because of minBid update
|
||||||
if err = api.h.AddBids(commonBids); err != nil {
|
// Slots 4 and 7 will have valid bids, the rest will be cordinator slots
|
||||||
panic(err)
|
var slot3MinBid int64 = 3
|
||||||
|
var slot4MinBid int64 = 4
|
||||||
|
var slot6MinBid int64 = 6
|
||||||
|
var slot7MinBid int64 = 7
|
||||||
|
// First update will indicate how things behave from slot 0
|
||||||
|
var defaultSlotSetBid [6]*big.Int = [6]*big.Int{
|
||||||
|
big.NewInt(10), // Slot 0 min bid
|
||||||
|
big.NewInt(10), // Slot 1 min bid
|
||||||
|
big.NewInt(10), // Slot 2 min bid
|
||||||
|
big.NewInt(slot3MinBid), // Slot 3 min bid
|
||||||
|
big.NewInt(slot4MinBid), // Slot 4 min bid
|
||||||
|
big.NewInt(10), // Slot 5 min bid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate SC vars and add them to HistoryDB (if needed)
|
|
||||||
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),
|
EthBlockNum: int64(2),
|
||||||
DonationAddress: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
|
DonationAddress: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
|
||||||
DefaultSlotSetBid: defaultSlotSetBid,
|
DefaultSlotSetBid: defaultSlotSetBid,
|
||||||
|
DefaultSlotSetBidSlotNum: 0,
|
||||||
Outbidding: uint16(1),
|
Outbidding: uint16(1),
|
||||||
SlotDeadline: uint8(20),
|
SlotDeadline: uint8(20),
|
||||||
BootCoordinator: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
|
BootCoordinator: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
|
||||||
BootCoordinatorURL: "https://boot.coordinator.io",
|
BootCoordinatorURL: "https://boot.coordinator.io",
|
||||||
ClosedAuctionSlots: uint16(2),
|
ClosedAuctionSlots: uint16(10),
|
||||||
OpenAuctionSlots: uint16(5),
|
OpenAuctionSlots: uint16(20),
|
||||||
}
|
}
|
||||||
|
if err := api.h.AddAuctionVars(&auctionVars); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// Last update in auction vars will indicate how things will behave from slot 5
|
||||||
|
defaultSlotSetBid = [6]*big.Int{
|
||||||
|
big.NewInt(10), // Slot 5 min bid
|
||||||
|
big.NewInt(slot6MinBid), // Slot 6 min bid
|
||||||
|
big.NewInt(slot7MinBid), // Slot 7 min bid
|
||||||
|
big.NewInt(10), // Slot 8 min bid
|
||||||
|
big.NewInt(10), // Slot 9 min bid
|
||||||
|
big.NewInt(10), // Slot 10 min bid
|
||||||
|
}
|
||||||
|
auctionVars = common.AuctionVariables{
|
||||||
|
EthBlockNum: int64(3),
|
||||||
|
DonationAddress: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
|
||||||
|
DefaultSlotSetBid: defaultSlotSetBid,
|
||||||
|
DefaultSlotSetBidSlotNum: 5,
|
||||||
|
Outbidding: uint16(1),
|
||||||
|
SlotDeadline: uint8(20),
|
||||||
|
BootCoordinator: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
|
||||||
|
BootCoordinatorURL: "https://boot.coordinator.io",
|
||||||
|
ClosedAuctionSlots: uint16(10),
|
||||||
|
OpenAuctionSlots: uint16(20),
|
||||||
|
}
|
||||||
|
if err := api.h.AddAuctionVars(&auctionVars); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate Bids and add them to HistoryDB
|
||||||
|
bids := []common.Bid{}
|
||||||
|
// Slot 1 and 2, no bids, wins boot coordinator
|
||||||
|
// Slot 3, below what's going to be the minimum (wins boot coordinator)
|
||||||
|
bids = append(bids, common.Bid{
|
||||||
|
SlotNum: 3,
|
||||||
|
BidValue: big.NewInt(slot3MinBid - 1),
|
||||||
|
EthBlockNum: commonBlocks[0].Num,
|
||||||
|
Bidder: commonCoords[0].Bidder,
|
||||||
|
})
|
||||||
|
// Slot 4, valid bid (wins bidder)
|
||||||
|
bids = append(bids, common.Bid{
|
||||||
|
SlotNum: 4,
|
||||||
|
BidValue: big.NewInt(slot4MinBid),
|
||||||
|
EthBlockNum: commonBlocks[0].Num,
|
||||||
|
Bidder: commonCoords[0].Bidder,
|
||||||
|
})
|
||||||
|
// Slot 5 no bids, wins boot coordinator
|
||||||
|
// Slot 6, below what's going to be the minimum (wins boot coordinator)
|
||||||
|
bids = append(bids, common.Bid{
|
||||||
|
SlotNum: 6,
|
||||||
|
BidValue: big.NewInt(slot6MinBid - 1),
|
||||||
|
EthBlockNum: commonBlocks[0].Num,
|
||||||
|
Bidder: commonCoords[0].Bidder,
|
||||||
|
})
|
||||||
|
// Slot 7, valid bid (wins bidder)
|
||||||
|
bids = append(bids, common.Bid{
|
||||||
|
SlotNum: 7,
|
||||||
|
BidValue: big.NewInt(slot7MinBid),
|
||||||
|
EthBlockNum: commonBlocks[0].Num,
|
||||||
|
Bidder: commonCoords[0].Bidder,
|
||||||
|
})
|
||||||
|
if err = api.h.AddBids(bids); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
bootForger := NextForger{
|
||||||
|
Coordinator: historydb.CoordinatorAPI{
|
||||||
|
Bidder: ethCommon.HexToAddress("0x0111111111111111111111111111111111111111"),
|
||||||
|
Forger: ethCommon.HexToAddress("0x0111111111111111111111111111111111111111"),
|
||||||
|
URL: "https://bootCoordinator",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// Set next forgers: set all as boot coordinator then replace the non boot coordinators
|
||||||
|
nextForgers := []NextForger{}
|
||||||
|
var initBlock int64 = 140
|
||||||
|
var deltaBlocks int64 = 40
|
||||||
|
for i := 1; i < int(auctionVars.ClosedAuctionSlots)+2; i++ {
|
||||||
|
fromBlock := initBlock + deltaBlocks*int64(i-1)
|
||||||
|
bootForger.Period = Period{
|
||||||
|
SlotNum: int64(i),
|
||||||
|
FromBlock: fromBlock,
|
||||||
|
ToBlock: fromBlock + deltaBlocks - 1,
|
||||||
|
}
|
||||||
|
nextForgers = append(nextForgers, bootForger)
|
||||||
|
}
|
||||||
|
// Set next forgers that aren't the boot coordinator
|
||||||
|
nonBootForger := historydb.CoordinatorAPI{
|
||||||
|
Bidder: commonCoords[0].Bidder,
|
||||||
|
Forger: commonCoords[0].Forger,
|
||||||
|
URL: commonCoords[0].URL,
|
||||||
|
}
|
||||||
|
// Slot 4
|
||||||
|
nextForgers[3].Coordinator = nonBootForger
|
||||||
|
// Slot 7
|
||||||
|
nextForgers[6].Coordinator = nonBootForger
|
||||||
|
|
||||||
var buckets [common.RollupConstNumBuckets]common.BucketParams
|
var buckets [common.RollupConstNumBuckets]common.BucketParams
|
||||||
for i := range buckets {
|
for i := range buckets {
|
||||||
@@ -386,6 +488,7 @@ func TestMain(m *testing.M) {
|
|||||||
buckets[i].MaxWithdrawals = big.NewInt(int64(i) * 10000)
|
buckets[i].MaxWithdrawals = big.NewInt(int64(i) * 10000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate SC vars and add them to HistoryDB (if needed)
|
||||||
rollupVars := common.RollupVariables{
|
rollupVars := common.RollupVariables{
|
||||||
EthBlockNum: int64(3),
|
EthBlockNum: int64(3),
|
||||||
FeeAddToken: big.NewInt(100),
|
FeeAddToken: big.NewInt(100),
|
||||||
@@ -399,14 +502,9 @@ func TestMain(m *testing.M) {
|
|||||||
WithdrawalDelay: uint64(3000),
|
WithdrawalDelay: uint64(3000),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = api.h.AddAuctionVars(&auctionVars)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate test data, as expected to be received/sended from/to the API
|
// Generate test data, as expected to be received/sended from/to the API
|
||||||
testCoords := genTestCoordinators(commonCoords)
|
testCoords := genTestCoordinators(commonCoords)
|
||||||
testBids := genTestBids(commonBlocks, testCoords, commonBids)
|
testBids := genTestBids(commonBlocks, testCoords, bids)
|
||||||
testExits := genTestExits(commonExitTree, testTokens, commonAccounts)
|
testExits := genTestExits(commonExitTree, testTokens, commonAccounts)
|
||||||
testTxs := genTestTxs(commonL1Txs, commonL2Txs, commonAccounts, testTokens, commonBlocks)
|
testTxs := genTestTxs(commonL1Txs, commonL2Txs, commonAccounts, testTokens, commonBlocks)
|
||||||
testBatches, testFullBatches := genTestBatches(commonBlocks, commonBatches, testTxs)
|
testBatches, testFullBatches := genTestBatches(commonBlocks, commonBatches, testTxs)
|
||||||
@@ -434,8 +532,11 @@ func TestMain(m *testing.M) {
|
|||||||
auctionVars: auctionVars,
|
auctionVars: auctionVars,
|
||||||
rollupVars: rollupVars,
|
rollupVars: rollupVars,
|
||||||
wdelayerVars: wdelayerVars,
|
wdelayerVars: wdelayerVars,
|
||||||
|
nextForgers: nextForgers,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run tests
|
||||||
|
result := m.Run()
|
||||||
// Fake server
|
// Fake server
|
||||||
if os.Getenv("FAKE_SERVER") == "yes" {
|
if os.Getenv("FAKE_SERVER") == "yes" {
|
||||||
for {
|
for {
|
||||||
@@ -443,8 +544,6 @@ func TestMain(m *testing.M) {
|
|||||||
time.Sleep(30 * time.Second)
|
time.Sleep(30 * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Run tests
|
|
||||||
result := m.Run()
|
|
||||||
// Stop server
|
// Stop server
|
||||||
if err := server.Shutdown(context.Background()); err != nil {
|
if err := server.Shutdown(context.Background()); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ func TestGetBids(t *testing.T) {
|
|||||||
err = doBadReq("GET", path, nil, 400)
|
err = doBadReq("GET", path, nil, 400)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// 404
|
// 404
|
||||||
path = fmt.Sprintf("%s?slotNum=%d&bidderAddr=%s", endpoint, tc.bids[0].SlotNum, tc.bids[1].Bidder.String())
|
path = fmt.Sprintf("%s?slotNum=%d&bidderAddr=%s", endpoint, 5, tc.bids[1].Bidder.String())
|
||||||
err = doBadReq("GET", path, nil, 404)
|
err = doBadReq("GET", path, nil, 404)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ func (a *API) genTestSlots(nSlots int, lastBlockNum int64, bids []testBid, aucti
|
|||||||
return tSlots
|
return tSlots
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) getEmptyTestSlot(slotNum int64) testSlot {
|
func (a *API) getEmptyTestSlot(slotNum, lastBlock int64, auctionVars common.AuctionVariables) testSlot {
|
||||||
firstBlock, lastBlock := a.getFirstLastBlock(slotNum)
|
firstSlotBlock, lastSlotBlock := a.getFirstLastBlock(slotNum)
|
||||||
slot := testSlot{
|
slot := testSlot{
|
||||||
SlotNum: slotNum,
|
SlotNum: slotNum,
|
||||||
FirstBlock: firstBlock,
|
FirstBlock: firstSlotBlock,
|
||||||
LastBlock: lastBlock,
|
LastBlock: lastSlotBlock,
|
||||||
OpenAuction: false,
|
OpenAuction: a.isOpenAuction(lastBlock, slotNum, auctionVars),
|
||||||
WinnerBid: nil,
|
WinnerBid: nil,
|
||||||
}
|
}
|
||||||
return slot
|
return slot
|
||||||
@@ -98,7 +98,7 @@ func TestGetSlot(t *testing.T) {
|
|||||||
nil, &fetchedSlot,
|
nil, &fetchedSlot,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
emptySlot := api.getEmptyTestSlot(slotNum)
|
emptySlot := api.getEmptyTestSlot(slotNum, api.status.Network.LastSyncBlock, tc.auctionVars)
|
||||||
assertSlot(t, emptySlot, fetchedSlot)
|
assertSlot(t, emptySlot, fetchedSlot)
|
||||||
|
|
||||||
// Invalid slotNum
|
// Invalid slotNum
|
||||||
@@ -127,7 +127,7 @@ func TestGetSlots(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
allSlots := tc.slots
|
allSlots := tc.slots
|
||||||
for i := tc.slots[len(tc.slots)-1].SlotNum; i < maxSlotNum; i++ {
|
for i := tc.slots[len(tc.slots)-1].SlotNum; i < maxSlotNum; i++ {
|
||||||
emptySlot := api.getEmptyTestSlot(i + 1)
|
emptySlot := api.getEmptyTestSlot(i+1, api.status.Network.LastSyncBlock, tc.auctionVars)
|
||||||
allSlots = append(allSlots, emptySlot)
|
allSlots = append(allSlots, emptySlot)
|
||||||
}
|
}
|
||||||
assertSlots(t, allSlots, fetchedSlots)
|
assertSlots(t, allSlots, fetchedSlots)
|
||||||
@@ -148,7 +148,7 @@ func TestGetSlots(t *testing.T) {
|
|||||||
// maxSlotNum & wonByEthereumAddress
|
// maxSlotNum & wonByEthereumAddress
|
||||||
fetchedSlots = []testSlot{}
|
fetchedSlots = []testSlot{}
|
||||||
limit = 1
|
limit = 1
|
||||||
bidderAddr := tc.coordinators[2].Bidder
|
bidderAddr := tc.coordinators[0].Bidder
|
||||||
path = fmt.Sprintf("%s?maxSlotNum=%d&wonByEthereumAddress=%s&limit=%d", endpoint, maxSlotNum, bidderAddr.String(), limit)
|
path = fmt.Sprintf("%s?maxSlotNum=%d&wonByEthereumAddress=%s&limit=%d", endpoint, maxSlotNum, bidderAddr.String(), limit)
|
||||||
err = doGoodReqPaginated(path, historydb.OrderAsc, &testSlotsResponse{}, appendIter)
|
err = doGoodReqPaginated(path, historydb.OrderAsc, &testSlotsResponse{}, appendIter)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|||||||
48
api/state.go
48
api/state.go
@@ -2,6 +2,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"math/big"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -122,6 +123,21 @@ func (a *API) getNextForgers(lastBlock common.Block, currentSlot, lastClosedSlot
|
|||||||
return nil, tracerr.Wrap(err)
|
return nil, tracerr.Wrap(err)
|
||||||
}
|
}
|
||||||
nextForgers := []NextForger{}
|
nextForgers := []NextForger{}
|
||||||
|
// Get min bid info
|
||||||
|
var minBidInfo []historydb.MinBidInfo
|
||||||
|
if currentSlot >= a.status.Auction.DefaultSlotSetBidSlotNum {
|
||||||
|
// All min bids can be calculated with the last update of AuctionVariables
|
||||||
|
minBidInfo = []historydb.MinBidInfo{{
|
||||||
|
DefaultSlotSetBid: a.status.Auction.DefaultSlotSetBid,
|
||||||
|
DefaultSlotSetBidSlotNum: a.status.Auction.DefaultSlotSetBidSlotNum,
|
||||||
|
}}
|
||||||
|
} else {
|
||||||
|
// Get all the relevant updates from the DB
|
||||||
|
minBidInfo, err = a.h.GetAuctionVarsUntilSetSlotNum(lastClosedSlot, int(lastClosedSlot-currentSlot)+1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, tracerr.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Create nextForger for each slot
|
// Create nextForger for each slot
|
||||||
for i := currentSlot; i <= lastClosedSlot; i++ {
|
for i := currentSlot; i <= lastClosedSlot; i++ {
|
||||||
fromBlock := i*int64(a.cg.AuctionConstants.BlocksPerSlot) + a.cg.AuctionConstants.GenesisBlockNum
|
fromBlock := i*int64(a.cg.AuctionConstants.BlocksPerSlot) + a.cg.AuctionConstants.GenesisBlockNum
|
||||||
@@ -135,11 +151,35 @@ func (a *API) getNextForgers(lastBlock common.Block, currentSlot, lastClosedSlot
|
|||||||
ToTimestamp: lastBlock.Timestamp.Add(time.Second * time.Duration(secondsPerBlock*(toBlock-lastBlock.Num))),
|
ToTimestamp: lastBlock.Timestamp.Add(time.Second * time.Duration(secondsPerBlock*(toBlock-lastBlock.Num))),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
foundBid := false
|
foundForger := false
|
||||||
// If there is a bid for a slot, get forger (coordinator)
|
// If there is a bid for a slot, get forger (coordinator)
|
||||||
for j := range bids {
|
for j := range bids {
|
||||||
if bids[j].SlotNum == i {
|
slotNum := bids[j].SlotNum
|
||||||
foundBid = true
|
if slotNum == i {
|
||||||
|
// There's a bid for the slot
|
||||||
|
// Check if the bid is greater than the minimum required
|
||||||
|
for i := 0; i < len(minBidInfo); i++ {
|
||||||
|
// Find the most recent update
|
||||||
|
if slotNum >= minBidInfo[i].DefaultSlotSetBidSlotNum {
|
||||||
|
// Get min bid
|
||||||
|
minBidSelector := slotNum % int64(len(a.status.Auction.DefaultSlotSetBid))
|
||||||
|
minBid := minBidInfo[i].DefaultSlotSetBid[minBidSelector]
|
||||||
|
// Check if the bid has beaten the minimum
|
||||||
|
bid, ok := new(big.Int).SetString(string(bids[j].BidValue), 10)
|
||||||
|
if !ok {
|
||||||
|
return nil, tracerr.New("Wrong bid value, error parsing it as big.Int")
|
||||||
|
}
|
||||||
|
if minBid.Cmp(bid) == 1 {
|
||||||
|
// Min bid is greater than bid, the slot will be forged by boot coordinator
|
||||||
|
break
|
||||||
|
}
|
||||||
|
foundForger = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !foundForger { // There is no bid or it's smaller than the minimum
|
||||||
|
break
|
||||||
|
}
|
||||||
coordinator, err := a.h.GetCoordinatorAPI(bids[j].Bidder)
|
coordinator, err := a.h.GetCoordinatorAPI(bids[j].Bidder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, tracerr.Wrap(err)
|
return nil, tracerr.Wrap(err)
|
||||||
@@ -149,7 +189,7 @@ func (a *API) getNextForgers(lastBlock common.Block, currentSlot, lastClosedSlot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If there is no bid, the coordinator that will forge is boot coordinator
|
// If there is no bid, the coordinator that will forge is boot coordinator
|
||||||
if !foundBid {
|
if !foundForger {
|
||||||
nextForger.Coordinator = bootCoordinator
|
nextForger.Coordinator = bootCoordinator
|
||||||
}
|
}
|
||||||
nextForgers = append(nextForgers, nextForger)
|
nextForgers = append(nextForgers, nextForger)
|
||||||
|
|||||||
@@ -2,15 +2,12 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hermeznetwork/hermez-node/common"
|
"github.com/hermeznetwork/hermez-node/common"
|
||||||
"github.com/hermeznetwork/hermez-node/db/historydb"
|
"github.com/hermeznetwork/hermez-node/db/historydb"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
const secondsPerBlock = 15
|
|
||||||
|
|
||||||
type testStatus struct {
|
type testStatus struct {
|
||||||
Network testNetwork `json:"network"`
|
Network testNetwork `json:"network"`
|
||||||
Metrics historydb.Metrics `json:"metrics"`
|
Metrics historydb.Metrics `json:"metrics"`
|
||||||
@@ -49,36 +46,6 @@ func TestSetAuctionVariables(t *testing.T) {
|
|||||||
assert.Equal(t, tc.auctionVars, api.status.Auction)
|
assert.Equal(t, tc.auctionVars, api.status.Auction)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextForgers(t *testing.T) {
|
|
||||||
// It's assumed that bids for each slot will be received in increasing order
|
|
||||||
bestBids := make(map[int64]testBid)
|
|
||||||
for j := range tc.bids {
|
|
||||||
bestBids[tc.bids[j].SlotNum] = tc.bids[j]
|
|
||||||
}
|
|
||||||
lastBlock := tc.blocks[len(tc.blocks)-1]
|
|
||||||
for i := int64(0); i < tc.slots[len(tc.slots)-1].SlotNum; i++ {
|
|
||||||
lastClosedSlot := i + int64(api.status.Auction.ClosedAuctionSlots)
|
|
||||||
nextForgers, err := api.getNextForgers(tc.blocks[len(tc.blocks)-1], i, lastClosedSlot)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for j := i; j <= lastClosedSlot; j++ {
|
|
||||||
for q := range nextForgers {
|
|
||||||
if nextForgers[q].Period.SlotNum == j {
|
|
||||||
if nextForgers[q].Coordinator.ItemID != 0 {
|
|
||||||
assert.Equal(t, bestBids[j].Bidder, nextForgers[q].Coordinator.Bidder)
|
|
||||||
} else {
|
|
||||||
assert.Equal(t, bootCoordinator.Bidder, nextForgers[q].Coordinator.Bidder)
|
|
||||||
}
|
|
||||||
firstBlockSlot, lastBlockSlot := api.getFirstLastBlock(j)
|
|
||||||
fromTimestamp := lastBlock.Timestamp.Add(time.Second * time.Duration(secondsPerBlock*(firstBlockSlot-lastBlock.Num)))
|
|
||||||
toTimestamp := lastBlock.Timestamp.Add(time.Second * time.Duration(secondsPerBlock*(lastBlockSlot-lastBlock.Num)))
|
|
||||||
assert.Equal(t, fromTimestamp.Unix(), nextForgers[q].Period.FromTimestamp.Unix())
|
|
||||||
assert.Equal(t, toTimestamp.Unix(), nextForgers[q].Period.ToTimestamp.Unix())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdateNetworkInfo(t *testing.T) {
|
func TestUpdateNetworkInfo(t *testing.T) {
|
||||||
status := &Network{}
|
status := &Network{}
|
||||||
assert.Equal(t, status.LastSyncBlock, api.status.Network.LastSyncBlock)
|
assert.Equal(t, status.LastSyncBlock, api.status.Network.LastSyncBlock)
|
||||||
@@ -143,23 +110,43 @@ func TestGetState(t *testing.T) {
|
|||||||
var status testStatus
|
var status testStatus
|
||||||
|
|
||||||
assert.NoError(t, doGoodReq("GET", endpoint, nil, &status))
|
assert.NoError(t, doGoodReq("GET", endpoint, nil, &status))
|
||||||
|
|
||||||
|
// SC vars
|
||||||
assert.Equal(t, tc.rollupVars, status.Rollup)
|
assert.Equal(t, tc.rollupVars, status.Rollup)
|
||||||
assert.Equal(t, tc.auctionVars, status.Auction)
|
assert.Equal(t, tc.auctionVars, status.Auction)
|
||||||
assert.Equal(t, tc.wdelayerVars, status.WithdrawalDelayer)
|
assert.Equal(t, tc.wdelayerVars, status.WithdrawalDelayer)
|
||||||
|
// Network
|
||||||
assert.Equal(t, lastBlock.Num, status.Network.LastEthBlock)
|
assert.Equal(t, lastBlock.Num, status.Network.LastEthBlock)
|
||||||
assert.Equal(t, lastBlock.Num, status.Network.LastSyncBlock)
|
assert.Equal(t, lastBlock.Num, status.Network.LastSyncBlock)
|
||||||
|
// TODO: assert all the batch, not just the batch num
|
||||||
assert.Equal(t, lastBatchNum, status.Network.LastBatch.BatchNum)
|
assert.Equal(t, lastBatchNum, status.Network.LastBatch.BatchNum)
|
||||||
assert.Equal(t, currentSlotNum, status.Network.CurrentSlot)
|
assert.Equal(t, currentSlotNum, status.Network.CurrentSlot)
|
||||||
assert.Equal(t, int(api.status.Auction.ClosedAuctionSlots)+1, len(status.Network.NextForgers))
|
assertNextForgers(t, tc.nextForgers, status.Network.NextForgers)
|
||||||
|
// Metrics
|
||||||
|
// TODO: perform real asserts (not just greater than 0)
|
||||||
assert.Greater(t, status.Metrics.TransactionsPerBatch, float64(0))
|
assert.Greater(t, status.Metrics.TransactionsPerBatch, float64(0))
|
||||||
assert.Greater(t, status.Metrics.BatchFrequency, float64(0))
|
assert.Greater(t, status.Metrics.BatchFrequency, float64(0))
|
||||||
assert.Greater(t, status.Metrics.TransactionsPerBatch, float64(0))
|
assert.Greater(t, status.Metrics.TransactionsPerBatch, float64(0))
|
||||||
assert.Greater(t, status.Metrics.TotalAccounts, int64(0))
|
assert.Greater(t, status.Metrics.TotalAccounts, int64(0))
|
||||||
assert.Greater(t, status.Metrics.TotalBJJs, int64(0))
|
assert.Greater(t, status.Metrics.TotalBJJs, int64(0))
|
||||||
assert.Greater(t, status.Metrics.AvgTransactionFee, float64(0))
|
assert.Greater(t, status.Metrics.AvgTransactionFee, float64(0))
|
||||||
|
// Recommended fee
|
||||||
|
// TODO: perform real asserts (not just greater than 0)
|
||||||
assert.Greater(t, status.RecommendedFee.ExistingAccount, float64(0))
|
assert.Greater(t, status.RecommendedFee.ExistingAccount, float64(0))
|
||||||
assert.Equal(t, status.RecommendedFee.CreatesAccount,
|
assert.Equal(t, status.RecommendedFee.CreatesAccount,
|
||||||
status.RecommendedFee.ExistingAccount*createAccountExtraFeePercentage)
|
status.RecommendedFee.ExistingAccount*createAccountExtraFeePercentage)
|
||||||
assert.Equal(t, status.RecommendedFee.CreatesAccountAndRegister,
|
assert.Equal(t, status.RecommendedFee.CreatesAccountAndRegister,
|
||||||
status.RecommendedFee.ExistingAccount*createAccountInternalExtraFeePercentage)
|
status.RecommendedFee.ExistingAccount*createAccountInternalExtraFeePercentage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assertNextForgers(t *testing.T, expected, actual []NextForger) {
|
||||||
|
assert.Equal(t, len(expected), len(actual))
|
||||||
|
for i := range expected {
|
||||||
|
// ignore timestamps and other metadata
|
||||||
|
actual[i].Period.FromTimestamp = expected[i].Period.FromTimestamp
|
||||||
|
actual[i].Period.ToTimestamp = expected[i].Period.ToTimestamp
|
||||||
|
actual[i].Coordinator.ItemID = expected[i].Coordinator.ItemID
|
||||||
|
actual[i].Coordinator.EthBlockNum = expected[i].Coordinator.EthBlockNum
|
||||||
|
assert.Equal(t, expected[i], actual[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2714,6 +2714,9 @@ components:
|
|||||||
items:
|
items:
|
||||||
type: integer
|
type: integer
|
||||||
example: [32,0,68,21,55,99]
|
example: [32,0,68,21,55,99]
|
||||||
|
defaultSlotSetBidSlotNum:
|
||||||
|
type: integer
|
||||||
|
description: Slot in which the changes will be applied for the first time.
|
||||||
outbidding:
|
outbidding:
|
||||||
type: number
|
type: number
|
||||||
description: Minimum outbid over the previous one to consider it valid.
|
description: Minimum outbid over the previous one to consider it valid.
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ type AuctionVariables struct {
|
|||||||
// The minimum bid value in a series of 6 slots
|
// The minimum bid value in a series of 6 slots
|
||||||
DefaultSlotSetBid [6]*big.Int `json:"defaultSlotSetBid" meddler:"default_slot_set_bid,json" validate:"required"`
|
DefaultSlotSetBid [6]*big.Int `json:"defaultSlotSetBid" meddler:"default_slot_set_bid,json" validate:"required"`
|
||||||
// SlotNum at which the new default_slot_set_bid applies
|
// SlotNum at which the new default_slot_set_bid applies
|
||||||
DefaultSlotSetBidSlotNum int64 `json:"-" meddler:"default_slot_set_bid_slot_num"`
|
DefaultSlotSetBidSlotNum int64 `json:"defaultSlotSetBidSlotNum" meddler:"default_slot_set_bid_slot_num"`
|
||||||
// Distance (#slots) to the closest slot to which you can bid ( 2 Slots = 2 * 40 Blocks = 20 min )
|
// Distance (#slots) to the closest slot to which you can bid ( 2 Slots = 2 * 40 Blocks = 20 min )
|
||||||
ClosedAuctionSlots uint16 `json:"closedAuctionSlots" meddler:"closed_auction_slots" validate:"required"`
|
ClosedAuctionSlots uint16 `json:"closedAuctionSlots" meddler:"closed_auction_slots" validate:"required"`
|
||||||
// Distance (#slots) to the farthest slot to which you can bid (30 days = 4320 slots )
|
// Distance (#slots) to the farthest slot to which you can bid (30 days = 4320 slots )
|
||||||
|
|||||||
@@ -1706,6 +1706,23 @@ func (hdb *HistoryDB) GetAuctionVars() (*common.AuctionVariables, error) {
|
|||||||
return auctionVars, tracerr.Wrap(err)
|
return auctionVars, tracerr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAuctionVarsUntilSetSlotNum returns all the updates of the auction vars
|
||||||
|
// from the last entry in which DefaultSlotSetBidSlotNum <= slotNum
|
||||||
|
func (hdb *HistoryDB) GetAuctionVarsUntilSetSlotNum(slotNum int64, maxItems int) ([]MinBidInfo, error) {
|
||||||
|
auctionVars := []*MinBidInfo{}
|
||||||
|
query := `
|
||||||
|
SELECT DISTINCT default_slot_set_bid, default_slot_set_bid_slot_num FROM auction_vars
|
||||||
|
WHERE default_slot_set_bid_slot_num < $1
|
||||||
|
ORDER BY default_slot_set_bid_slot_num DESC
|
||||||
|
LIMIT $2;
|
||||||
|
`
|
||||||
|
err := meddler.QueryAll(hdb.db, &auctionVars, query, slotNum, maxItems)
|
||||||
|
if err != nil {
|
||||||
|
return nil, tracerr.Wrap(err)
|
||||||
|
}
|
||||||
|
return db.SlicePtrsToSlice(auctionVars).([]MinBidInfo), nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetAccountAPI returns an account by its index
|
// GetAccountAPI returns an account by its index
|
||||||
func (hdb *HistoryDB) GetAccountAPI(idx common.Idx) (*AccountAPI, error) {
|
func (hdb *HistoryDB) GetAccountAPI(idx common.Idx) (*AccountAPI, error) {
|
||||||
account := &AccountAPI{}
|
account := &AccountAPI{}
|
||||||
|
|||||||
@@ -331,3 +331,9 @@ type BidAPI struct {
|
|||||||
FirstItem uint64 `json:"-" meddler:"first_item"`
|
FirstItem uint64 `json:"-" meddler:"first_item"`
|
||||||
LastItem uint64 `json:"-" meddler:"last_item"`
|
LastItem uint64 `json:"-" meddler:"last_item"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MinBidInfo gives information of the minum bid for specific slot(s)
|
||||||
|
type MinBidInfo struct {
|
||||||
|
DefaultSlotSetBid [6]*big.Int `json:"defaultSlotSetBid" meddler:"default_slot_set_bid,json" validate:"required"`
|
||||||
|
DefaultSlotSetBidSlotNum int64 `json:"-" meddler:"default_slot_set_bid_slot_num"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ func GenCoordinators(nCoords int, blocks []common.Block) []common.Coordinator {
|
|||||||
EthBlockNum: blocks[i%len(blocks)].Num,
|
EthBlockNum: blocks[i%len(blocks)].Num,
|
||||||
Forger: ethCommon.BigToAddress(big.NewInt(int64(i))),
|
Forger: ethCommon.BigToAddress(big.NewInt(int64(i))),
|
||||||
Bidder: ethCommon.BigToAddress(big.NewInt(int64(i))),
|
Bidder: ethCommon.BigToAddress(big.NewInt(int64(i))),
|
||||||
URL: "https://foo.bar",
|
URL: fmt.Sprintf("https://%d.coord", i),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return coords
|
return coords
|
||||||
|
|||||||
Reference in New Issue
Block a user