mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Merge pull request #468 from hermeznetwork/fix/repeated-bids
Fix repeated items when coordinator is updated
This commit is contained in:
@@ -353,6 +353,14 @@ func TestMain(m *testing.M) {
|
|||||||
// Generate Coordinators and add them to HistoryDB
|
// Generate Coordinators and add them to HistoryDB
|
||||||
const nCoords = 10
|
const nCoords = 10
|
||||||
commonCoords := test.GenCoordinators(nCoords, commonBlocks)
|
commonCoords := test.GenCoordinators(nCoords, commonBlocks)
|
||||||
|
// Update one coordinator to test behaviour when bidder address is repeated
|
||||||
|
updatedCoordBlock := commonCoords[len(commonCoords)-1].EthBlockNum
|
||||||
|
commonCoords = append(commonCoords, common.Coordinator{
|
||||||
|
Bidder: commonCoords[0].Bidder,
|
||||||
|
Forger: commonCoords[0].Forger,
|
||||||
|
EthBlockNum: updatedCoordBlock,
|
||||||
|
URL: commonCoords[0].URL + ".new",
|
||||||
|
})
|
||||||
if err := api.h.AddCoordinators(commonCoords); err != nil {
|
if err := api.h.AddCoordinators(commonCoords); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -473,7 +481,7 @@ func TestMain(m *testing.M) {
|
|||||||
nonBootForger := historydb.CoordinatorAPI{
|
nonBootForger := historydb.CoordinatorAPI{
|
||||||
Bidder: commonCoords[0].Bidder,
|
Bidder: commonCoords[0].Bidder,
|
||||||
Forger: commonCoords[0].Forger,
|
Forger: commonCoords[0].Forger,
|
||||||
URL: commonCoords[0].URL,
|
URL: commonCoords[0].URL + ".new",
|
||||||
}
|
}
|
||||||
// Slot 4
|
// Slot 4
|
||||||
nextForgers[3].Coordinator = nonBootForger
|
nextForgers[3].Coordinator = nonBootForger
|
||||||
@@ -762,10 +770,16 @@ func getBlockByNum(ethBlockNum int64, blocks []common.Block) common.Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getCoordinatorByBidder(bidder ethCommon.Address, coordinators []historydb.CoordinatorAPI) historydb.CoordinatorAPI {
|
func getCoordinatorByBidder(bidder ethCommon.Address, coordinators []historydb.CoordinatorAPI) historydb.CoordinatorAPI {
|
||||||
|
var coordLastUpdate historydb.CoordinatorAPI
|
||||||
|
found := false
|
||||||
for _, c := range coordinators {
|
for _, c := range coordinators {
|
||||||
if c.Bidder == bidder {
|
if c.Bidder == bidder {
|
||||||
return c
|
coordLastUpdate = c
|
||||||
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("coordinator not found")
|
if !found {
|
||||||
|
panic("coordinator not found")
|
||||||
|
}
|
||||||
|
return coordLastUpdate
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,12 +31,27 @@ func (t testCoordinatorsResponse) New() Pendinger { return &testCoordinatorsResp
|
|||||||
func genTestCoordinators(coordinators []common.Coordinator) []historydb.CoordinatorAPI {
|
func genTestCoordinators(coordinators []common.Coordinator) []historydb.CoordinatorAPI {
|
||||||
testCoords := []historydb.CoordinatorAPI{}
|
testCoords := []historydb.CoordinatorAPI{}
|
||||||
for i := 0; i < len(coordinators); i++ {
|
for i := 0; i < len(coordinators); i++ {
|
||||||
testCoords = append(testCoords, historydb.CoordinatorAPI{
|
alreadyRegistered := false
|
||||||
Bidder: coordinators[i].Bidder,
|
for j := 0; j < len(testCoords); j++ {
|
||||||
Forger: coordinators[i].Forger,
|
// coordinator already registered
|
||||||
EthBlockNum: coordinators[i].EthBlockNum,
|
if coordinators[i].Bidder == testCoords[j].Bidder {
|
||||||
URL: coordinators[i].URL,
|
alreadyRegistered = true
|
||||||
})
|
if coordinators[i].EthBlockNum > testCoords[j].EthBlockNum {
|
||||||
|
// This occurrence is more updated, delete current and append new
|
||||||
|
testCoords = append(testCoords[:j], testCoords[j+1:]...)
|
||||||
|
alreadyRegistered = false
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !alreadyRegistered {
|
||||||
|
testCoords = append(testCoords, historydb.CoordinatorAPI{
|
||||||
|
Bidder: coordinators[i].Bidder,
|
||||||
|
Forger: coordinators[i].Forger,
|
||||||
|
EthBlockNum: coordinators[i].EthBlockNum,
|
||||||
|
URL: coordinators[i].URL,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return testCoords
|
return testCoords
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||||
"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/mitchellh/copystructure"
|
"github.com/mitchellh/copystructure"
|
||||||
@@ -148,7 +149,12 @@ func TestGetSlots(t *testing.T) {
|
|||||||
// maxSlotNum & wonByEthereumAddress
|
// maxSlotNum & wonByEthereumAddress
|
||||||
fetchedSlots = []testSlot{}
|
fetchedSlots = []testSlot{}
|
||||||
limit = 1
|
limit = 1
|
||||||
bidderAddr := tc.coordinators[0].Bidder
|
var bidderAddr ethCommon.Address
|
||||||
|
for i := 0; i < len(tc.slots); i++ {
|
||||||
|
if tc.slots[i].WinnerBid != nil {
|
||||||
|
bidderAddr = tc.slots[i].WinnerBid.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)
|
||||||
|
|||||||
@@ -380,8 +380,12 @@ func (hdb *HistoryDB) GetBestBidAPI(slotNum *int64) (BidAPI, error) {
|
|||||||
bid := &BidAPI{}
|
bid := &BidAPI{}
|
||||||
err := meddler.QueryRow(
|
err := meddler.QueryRow(
|
||||||
hdb.db, bid, `SELECT bid.*, block.timestamp, coordinator.forger_addr, coordinator.url
|
hdb.db, bid, `SELECT bid.*, block.timestamp, coordinator.forger_addr, coordinator.url
|
||||||
FROM bid INNER JOIN block ON bid.eth_block_num = block.eth_block_num
|
FROM bid INNER JOIN block ON bid.eth_block_num = block.eth_block_num
|
||||||
INNER JOIN coordinator ON bid.bidder_addr = coordinator.bidder_addr
|
INNER JOIN (
|
||||||
|
SELECT bidder_addr, MAX(item_id) AS item_id FROM coordinator
|
||||||
|
GROUP BY bidder_addr
|
||||||
|
) c ON bid.bidder_addr = c.bidder_addr
|
||||||
|
INNER JOIN coordinator ON c.item_id = coordinator.item_id
|
||||||
WHERE slot_num = $1 ORDER BY item_id DESC LIMIT 1;`, slotNum,
|
WHERE slot_num = $1 ORDER BY item_id DESC LIMIT 1;`, slotNum,
|
||||||
)
|
)
|
||||||
return *bid, tracerr.Wrap(err)
|
return *bid, tracerr.Wrap(err)
|
||||||
@@ -397,11 +401,15 @@ func (hdb *HistoryDB) GetBestBidCoordinator(slotNum int64) (*common.BidCoordinat
|
|||||||
FROM auction_vars
|
FROM auction_vars
|
||||||
WHERE default_slot_set_bid_slot_num <= $1
|
WHERE default_slot_set_bid_slot_num <= $1
|
||||||
ORDER BY eth_block_num DESC LIMIT 1
|
ORDER BY eth_block_num DESC LIMIT 1
|
||||||
),
|
),
|
||||||
bid.slot_num, bid.bid_value, bid.bidder_addr,
|
bid.slot_num, bid.bid_value, bid.bidder_addr,
|
||||||
coordinator.forger_addr, coordinator.url
|
coordinator.forger_addr, coordinator.url
|
||||||
FROM bid
|
FROM bid
|
||||||
INNER JOIN coordinator ON bid.bidder_addr = coordinator.bidder_addr
|
INNER JOIN (
|
||||||
|
SELECT bidder_addr, MAX(item_id) AS item_id FROM coordinator
|
||||||
|
GROUP BY bidder_addr
|
||||||
|
) c ON bid.bidder_addr = c.bidder_addr
|
||||||
|
INNER JOIN coordinator ON c.item_id = coordinator.item_id
|
||||||
WHERE bid.slot_num = $1 ORDER BY bid.item_id DESC LIMIT 1;`,
|
WHERE bid.slot_num = $1 ORDER BY bid.item_id DESC LIMIT 1;`,
|
||||||
slotNum)
|
slotNum)
|
||||||
|
|
||||||
@@ -416,14 +424,19 @@ func (hdb *HistoryDB) GetBestBidsAPI(
|
|||||||
) ([]BidAPI, uint64, error) {
|
) ([]BidAPI, uint64, error) {
|
||||||
var query string
|
var query string
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
|
// JOIN the best bid of each slot with the latest update of each coordinator
|
||||||
queryStr := `SELECT b.*, block.timestamp, coordinator.forger_addr, coordinator.url,
|
queryStr := `SELECT b.*, block.timestamp, coordinator.forger_addr, coordinator.url,
|
||||||
COUNT(*) OVER() AS total_items FROM (
|
COUNT(*) OVER() AS total_items FROM (
|
||||||
SELECT slot_num, MAX(item_id) as maxitem
|
SELECT slot_num, MAX(item_id) as maxitem
|
||||||
FROM bid GROUP BY slot_num
|
FROM bid GROUP BY slot_num
|
||||||
)
|
)
|
||||||
AS x INNER JOIN bid AS b ON b.item_id = x.maxitem
|
AS x INNER JOIN bid AS b ON b.item_id = x.maxitem
|
||||||
INNER JOIN block ON b.eth_block_num = block.eth_block_num
|
INNER JOIN block ON b.eth_block_num = block.eth_block_num
|
||||||
INNER JOIN coordinator ON b.bidder_addr = coordinator.bidder_addr
|
INNER JOIN (
|
||||||
|
SELECT bidder_addr, MAX(item_id) AS item_id FROM coordinator
|
||||||
|
GROUP BY bidder_addr
|
||||||
|
) c ON b.bidder_addr = c.bidder_addr
|
||||||
|
INNER JOIN coordinator ON c.item_id = coordinator.item_id
|
||||||
WHERE (b.slot_num >= ? AND b.slot_num <= ?)`
|
WHERE (b.slot_num >= ? AND b.slot_num <= ?)`
|
||||||
args = append(args, minSlotNum)
|
args = append(args, minSlotNum)
|
||||||
args = append(args, maxSlotNum)
|
args = append(args, maxSlotNum)
|
||||||
@@ -456,15 +469,20 @@ func (hdb *HistoryDB) GetBestBidsAPI(
|
|||||||
|
|
||||||
// GetBidsAPI return the bids applying the given filters
|
// GetBidsAPI return the bids applying the given filters
|
||||||
func (hdb *HistoryDB) GetBidsAPI(
|
func (hdb *HistoryDB) GetBidsAPI(
|
||||||
slotNum *int64, forgerAddr *ethCommon.Address,
|
slotNum *int64, bidderAddr *ethCommon.Address,
|
||||||
fromItem, limit *uint, order string,
|
fromItem, limit *uint, order string,
|
||||||
) ([]BidAPI, uint64, error) {
|
) ([]BidAPI, uint64, error) {
|
||||||
var query string
|
var query string
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
queryStr := `SELECT bid.*, block.timestamp, coordinator.forger_addr, coordinator.url,
|
// JOIN each bid with the latest update of each coordinator
|
||||||
|
queryStr := `SELECT bid.*, block.timestamp, coord.forger_addr, coord.url,
|
||||||
COUNT(*) OVER() AS total_items
|
COUNT(*) OVER() AS total_items
|
||||||
FROM bid INNER JOIN block ON bid.eth_block_num = block.eth_block_num
|
FROM bid INNER JOIN block ON bid.eth_block_num = block.eth_block_num
|
||||||
INNER JOIN coordinator ON bid.bidder_addr = coordinator.bidder_addr `
|
INNER JOIN (
|
||||||
|
SELECT bidder_addr, MAX(item_id) AS item_id FROM coordinator
|
||||||
|
GROUP BY bidder_addr
|
||||||
|
) c ON bid.bidder_addr = c.bidder_addr
|
||||||
|
INNER JOIN coordinator coord ON c.item_id = coord.item_id `
|
||||||
// Apply filters
|
// Apply filters
|
||||||
nextIsAnd := false
|
nextIsAnd := false
|
||||||
// slotNum filter
|
// slotNum filter
|
||||||
@@ -478,15 +496,15 @@ func (hdb *HistoryDB) GetBidsAPI(
|
|||||||
args = append(args, slotNum)
|
args = append(args, slotNum)
|
||||||
nextIsAnd = true
|
nextIsAnd = true
|
||||||
}
|
}
|
||||||
// slotNum filter
|
// bidder filter
|
||||||
if forgerAddr != nil {
|
if bidderAddr != nil {
|
||||||
if nextIsAnd {
|
if nextIsAnd {
|
||||||
queryStr += "AND "
|
queryStr += "AND "
|
||||||
} else {
|
} else {
|
||||||
queryStr += "WHERE "
|
queryStr += "WHERE "
|
||||||
}
|
}
|
||||||
queryStr += "bid.bidder_addr = ? "
|
queryStr += "bid.bidder_addr = ? "
|
||||||
args = append(args, forgerAddr)
|
args = append(args, bidderAddr)
|
||||||
nextIsAnd = true
|
nextIsAnd = true
|
||||||
}
|
}
|
||||||
if fromItem != nil {
|
if fromItem != nil {
|
||||||
@@ -1647,7 +1665,11 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *common.BlockData) (err error) {
|
|||||||
// GetCoordinatorAPI returns a coordinator by its bidderAddr
|
// GetCoordinatorAPI returns a coordinator by its bidderAddr
|
||||||
func (hdb *HistoryDB) GetCoordinatorAPI(bidderAddr ethCommon.Address) (*CoordinatorAPI, error) {
|
func (hdb *HistoryDB) GetCoordinatorAPI(bidderAddr ethCommon.Address) (*CoordinatorAPI, error) {
|
||||||
coordinator := &CoordinatorAPI{}
|
coordinator := &CoordinatorAPI{}
|
||||||
err := meddler.QueryRow(hdb.db, coordinator, "SELECT * FROM coordinator WHERE bidder_addr = $1;", bidderAddr)
|
err := meddler.QueryRow(
|
||||||
|
hdb.db, coordinator,
|
||||||
|
"SELECT * FROM coordinator WHERE bidder_addr = $1 ORDER BY item_id DESC LIMIT 1;",
|
||||||
|
bidderAddr,
|
||||||
|
)
|
||||||
return coordinator, tracerr.Wrap(err)
|
return coordinator, tracerr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1658,9 +1680,11 @@ func (hdb *HistoryDB) GetCoordinatorsAPI(
|
|||||||
) ([]CoordinatorAPI, uint64, error) {
|
) ([]CoordinatorAPI, uint64, error) {
|
||||||
var query string
|
var query string
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
queryStr := `SELECT coordinator.*,
|
queryStr := `SELECT coordinator.*, COUNT(*) OVER() AS total_items
|
||||||
COUNT(*) OVER() AS total_items
|
FROM coordinator INNER JOIN (
|
||||||
FROM coordinator `
|
SELECT MAX(item_id) AS item_id FROM coordinator
|
||||||
|
GROUP BY bidder_addr
|
||||||
|
) c ON coordinator.item_id = c.item_id `
|
||||||
// Apply filters
|
// Apply filters
|
||||||
nextIsAnd := false
|
nextIsAnd := false
|
||||||
if bidderAddr != nil {
|
if bidderAddr != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user