Browse Source

Merge pull request #428 from hermeznetwork/fix/api-next-forgers

Fix next forgers api response
feature/sql-semaphore1
Eduard S 3 years ago
committed by GitHub
parent
commit
890b94a41a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 226 additions and 74 deletions
  1. +124
    -25
      api/api_test.go
  2. +1
    -1
      api/bids_test.go
  3. +8
    -8
      api/slots_test.go
  4. +44
    -4
      api/state.go
  5. +21
    -34
      api/state_test.go
  6. +3
    -0
      api/swagger.yml
  7. +1
    -1
      common/ethauction.go
  8. +17
    -0
      db/historydb/historydb.go
  9. +6
    -0
      db/historydb/views.go
  10. +1
    -1
      test/historydb.go

+ 124
- 25
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
const nBids = 20
commonBids := test.GenBids(nBids, commonBlocks, commonCoords)
if err = api.h.AddBids(commonBids); err != nil {
// Test next forgers
// Set auction vars
// Slots 3 and 6 will have bids that will be invalidated because of minBid update
// Slots 4 and 7 will have valid bids, the rest will be cordinator slots
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
}
auctionVars := common.AuctionVariables{
EthBlockNum: int64(2),
DonationAddress: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
DefaultSlotSetBid: defaultSlotSetBid,
DefaultSlotSetBidSlotNum: 0,
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)
}
// 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) panic(err)
} }
// 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{
EthBlockNum: int64(2),
DonationAddress: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
DefaultSlotSetBid: defaultSlotSetBid,
Outbidding: uint16(1),
SlotDeadline: uint8(20),
BootCoordinator: ethCommon.HexToAddress("0x1111111111111111111111111111111111111111"),
BootCoordinatorURL: "https://boot.coordinator.io",
ClosedAuctionSlots: uint16(2),
OpenAuctionSlots: uint16(5),
// 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)

+ 1
- 1
api/bids_test.go

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

+ 8
- 8
api/slots_test.go

@ -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 {
firstBlock, lastBlock := a.getFirstLastBlock(slotNum)
func (a *API) getEmptyTestSlot(slotNum, lastBlock int64, auctionVars common.AuctionVariables) testSlot {
firstSlotBlock, lastSlotBlock := a.getFirstLastBlock(slotNum)
slot := testSlot{ slot := testSlot{
SlotNum: slotNum, SlotNum: slotNum,
FirstBlock: firstBlock,
LastBlock: lastBlock,
OpenAuction: false,
FirstBlock: firstSlotBlock,
LastBlock: lastSlotBlock,
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)

+ 44
- 4
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 {
foundBid = true
slotNum := bids[j].SlotNum
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)

+ 21
- 34
api/state_test.go

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

+ 3
- 0
api/swagger.yml

@ -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.

+ 1
- 1
common/ethauction.go

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

+ 17
- 0
db/historydb/historydb.go

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

+ 6
- 0
db/historydb/views.go

@ -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"`
}

+ 1
- 1
test/historydb.go

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

Loading…
Cancel
Save