Merge pull request #262 from hermeznetwork/feature/api-checks ItemID to uint64 & check timestamp
@@ -14,7 +14,7 @@ "github.com/stretchr/testify/assert"
) type testAccount struct { - ItemID int `json:"itemId"` + ItemID uint64 `json:"itemId"` Idx apitypes.HezIdx `json:"accountIndex"` BatchNum common.BatchNum `json:"batchNum"` PublicKey apitypes.HezBJJ `json:"bjj"`@@ -34,7 +34,7 @@ tAccounts := []testAccount{}
for x, account := range accounts { token := getTokenByID(account.TokenID, tokens) tAccount := testAccount{ - ItemID: x + 1, + ItemID: uint64(x + 1), Idx: apitypes.HezIdx(idxToHez(account.Idx, token.Symbol)), PublicKey: apitypes.NewHezBJJ(account.PublicKey), EthAddr: apitypes.NewHezEthAddr(account.EthAddr),
@@ -364,13 +364,13 @@ if order == historydb.OrderAsc {
if pag.LastReturnedItem == pag.LastItem { // No break } else { // Yes - next = pag.LastReturnedItem + 1 + next = int(pag.LastReturnedItem + 1) } } else { if pag.FirstReturnedItem == pag.FirstItem { // No break } else { // Yes - next = pag.FirstReturnedItem - 1 + next = int(pag.FirstReturnedItem - 1) } } }
@@ -15,7 +15,7 @@ "github.com/stretchr/testify/assert"
) type testBatch struct { - ItemID int `json:"itemId"` + ItemID uint64 `json:"itemId"` BatchNum common.BatchNum `json:"batchNum"` EthBlockNum int64 `json:"ethereumBlockNum"` EthBlockHash ethCommon.Hash `json:"ethereumBlockHash"`
@@ -14,7 +14,7 @@ "github.com/stretchr/testify/assert"
) type testBid struct { - ItemID int `json:"itemId"` + ItemID uint64 `json:"itemId"` SlotNum int64 `json:"slotNum"` BidValue string `json:"bidValue"` EthBlockNum int64 `json:"ethereumBlockNum"`
@@ -24,7 +24,7 @@ Fnc int
} type testExit struct { - ItemID int `json:"itemId"` + ItemID uint64 `json:"itemId"` BatchNum common.BatchNum `json:"batchNum"` AccountIdx string `json:"accountIndex"` MerkleProof testCVP `json:"merkleProof"`
@@ -13,15 +13,15 @@ )
// SlotAPI is a repesentation of a slot information type SlotAPI struct { - ItemID int `json:"itemId"` + ItemID uint64 `json:"itemId"` SlotNum int64 `json:"slotNum"` FirstBlock int64 `json:"firstBlock"` LastBlock int64 `json:"lastBlock"` OpenAuction bool `json:"openAuction"` WinnerBid *historydb.BidAPI `json:"winnerBid"` - TotalItems int `json:"-"` - FirstItem int `json:"-"` - LastItem int `json:"-"` + TotalItems uint64 `json:"-"` + FirstItem uint64 `json:"-"` + LastItem uint64 `json:"-"` } func getFirstLastBlock(slotNum int64) (int64, int64) {@@ -49,14 +49,14 @@ }
return false } -func getPagination(totalItems int, minSlotNum, maxSlotNum *int64) *db.Pagination { +func getPagination(totalItems uint64, minSlotNum, maxSlotNum *int64) *db.Pagination { // itemID is slotNum firstItem := *minSlotNum lastItem := *maxSlotNum pagination := &db.Pagination{ - TotalItems: int(totalItems), - FirstItem: int(firstItem), - LastItem: int(lastItem), + TotalItems: totalItems, + FirstItem: uint64(firstItem), + LastItem: uint64(lastItem), } return pagination }@@ -65,7 +65,7 @@ func newSlotAPI(slotNum, currentBlockNum int64, bid *historydb.BidAPI, auctionVars *common.AuctionVariables) SlotAPI {
firstBlock, lastBlock := getFirstLastBlock(slotNum) openAuction := isOpenAuction(currentBlockNum, slotNum, *auctionVars) slot := SlotAPI{ - ItemID: int(slotNum), + ItemID: uint64(slotNum), SlotNum: slotNum, FirstBlock: firstBlock, LastBlock: lastBlock,@@ -80,11 +80,11 @@ for i := range bids {
slotNum := bids[i].SlotNum slot := newSlotAPI(slotNum, currentBlockNum, &bids[i], auctionVars) if order == historydb.OrderAsc { - if slot.ItemID >= int(*fromItem) { + if slot.ItemID >= uint64(*fromItem) { slots = append(slots, slot) } } else { - if slot.ItemID <= int(*fromItem) { + if slot.ItemID <= uint64(*fromItem) { slots = append(slots, slot) } }@@ -95,11 +95,11 @@
func addEmptySlot(slots []SlotAPI, slotNum int64, currentBlockNum int64, auctionVars *common.AuctionVariables, fromItem *uint, order string) ([]SlotAPI, error) { emptySlot := newSlotAPI(slotNum, currentBlockNum, nil, auctionVars) if order == historydb.OrderAsc { - if emptySlot.ItemID >= int(*fromItem) { + if emptySlot.ItemID >= uint64(*fromItem) { slots = append(slots, emptySlot) } } else { - if emptySlot.ItemID <= int(*fromItem) { + if emptySlot.ItemID <= uint64(*fromItem) { slots = append([]SlotAPI{emptySlot}, slots...) } }@@ -263,7 +263,7 @@ // Get bids and pagination according to filters
var slotMinLim, slotMaxLim int64 var bids []historydb.BidAPI var pag *db.Pagination - totalItems := 0 + totalItems := uint64(0) if wonByEthereumAddress == nil { slotMinLim, slotMaxLim = getLimits(minSlotNum, maxSlotNum, fromItem, limit, order) // Get best bids in range maxSlotNum - minSlotNum@@ -272,7 +272,7 @@ if err != nil && err != sql.ErrNoRows {
retSQLErr(err, c) return } - totalItems = int(*maxSlotNum) - int(*minSlotNum) + 1 + totalItems = uint64(*maxSlotNum) - uint64(*minSlotNum) + 1 } else { slotMinLim, slotMaxLim = getLimitsWithAddr(minSlotNum, maxSlotNum, fromItem, limit, order) bids, pag, err = h.GetBestBidsAPI(&slotMinLim, &slotMaxLim, wonByEthereumAddress, limit, order)@@ -281,7 +281,7 @@ retSQLErr(err, c)
return } if len(bids) > 0 { - totalItems = pag.TotalItems + totalItems = uint64(pag.TotalItems) *maxSlotNum = int64(pag.LastItem) *minSlotNum = int64(pag.FirstItem) }@@ -306,11 +306,11 @@ for j := range slotsBids {
if slotsBids[j].SlotNum == i { found = true if order == historydb.OrderAsc { - if slotsBids[j].ItemID >= int(*fromItem) { + if slotsBids[j].ItemID >= uint64(*fromItem) { slots = append(slots, slotsBids[j]) } } else { - if slotsBids[j].ItemID <= int(*fromItem) { + if slotsBids[j].ItemID <= uint64(*fromItem) { slots = append([]SlotAPI{slotsBids[j]}, slots...) } }
@@ -28,11 +28,11 @@ }
func (t testSlotsResponse) GetPagination() *db.Pagination { if t.Slots[0].ItemID < t.Slots[len(t.Slots)-1].ItemID { - t.Pagination.FirstReturnedItem = int(t.Slots[0].ItemID) - t.Pagination.LastReturnedItem = int(t.Slots[len(t.Slots)-1].ItemID) + t.Pagination.FirstReturnedItem = uint64(t.Slots[0].ItemID) + t.Pagination.LastReturnedItem = uint64(t.Slots[len(t.Slots)-1].ItemID) } else { - t.Pagination.LastReturnedItem = int(t.Slots[0].ItemID) - t.Pagination.FirstReturnedItem = int(t.Slots[len(t.Slots)-1].ItemID) + t.Pagination.LastReturnedItem = uint64(t.Slots[0].ItemID) + t.Pagination.FirstReturnedItem = uint64(t.Slots[len(t.Slots)-1].ItemID) } return t.Pagination }
@@ -2488,11 +2488,11 @@ - example: "0x557dc4262BCDbf85190C01c996b4C06a461d2430"
withdrawalDelay: allOf: - $ref: '#/components/schemas/EthBlockNum' - - description: The time that anyone needs to wait until a withdrawal of the funds is allowed, in Ethereum blocks. + - description: The time that anyone needs to wait until a withdrawal of the funds is allowed, in seconds. - example: 539573849 emergencyModeStartingTime: type: integer - description: Ethereum block in which the emergency mode will be activated. + description: Second (since unix epoch) in which the emergency mode has been activated. example: 10 emergencyMode: type: boolean@@ -2716,11 +2716,11 @@ description: Constant configuration of the withdrawal delayer smart contract.
properties: maxWithdrawalDelay: type: integer - description: Maximum time delay in which the tokens can be locked in the contract. Time is measured in Ethereum blocks. + description: Maximum time delay in which the tokens can be locked in the contract. Time is measured in seconds. example: 200 maxEmergencyModeTime: type: integer - description: Maximum amount of time in which the contract can be in emergency mode. Time is measured in Ethereum blocks. + description: Maximum amount of time in which the contract can be in emergency mode. Time is measured in seconds. example: 2000 hermezRollup: allOf:
@@ -34,7 +34,7 @@
type testTx struct { IsL1 string `json:"L1orL2"` TxID common.TxID `json:"id"` - ItemID int `json:"itemId"` + ItemID uint64 `json:"itemId"` Type common.TxType `json:"type"` Position int `json:"position"` FromIdx *string `json:"fromAccountIndex"`
@@ -6,6 +6,7 @@ "math"
"math/big" "os" "testing" + "time" ethCommon "github.com/ethereum/go-ethereum/common" "github.com/hermeznetwork/hermez-node/common"@@ -55,6 +56,9 @@ // Delete peviously created rows (clean previous test execs)
test.WipeDB(historyDB.DB()) // Generate fake blocks blocks := test.GenBlocks(fromBlock, toBlock) + // Save timestamp of a block with UTC and change it without UTC + timestamp := time.Now().Add(time.Second * 13) + blocks[fromBlock].Timestamp = timestamp // Insert blocks into DB for i := 0; i < len(blocks); i++ { err := historyDB.AddBlock(&blocks[i])@@ -68,6 +72,11 @@ assert.NoError(t, err)
for i := range fetchedBlocks { assertEqualBlock(t, &blocks[i], &fetchedBlocks[i]) } + // Compare saved timestamp vs getted + nameZoneUTC, offsetUTC := timestamp.UTC().Zone() + zoneFetchedBlock, offsetFetchedBlock := fetchedBlocks[fromBlock].Timestamp.Zone() + assert.Equal(t, nameZoneUTC, zoneFetchedBlock) + assert.Equal(t, offsetUTC, offsetFetchedBlock) // Get blocks from the DB one by one for i := fromBlock; i < toBlock; i++ { fetchedBlock, err := historyDB.GetBlock(i)@@ -182,7 +191,7 @@ err := historyDB.AddTokens(tokens)
assert.NoError(t, err) tokens = append([]common.Token{ethToken}, tokens...) limit := uint(10) - // Fetch tokens6 + // Fetch tokens fetchedTokens, _, err := historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc) assert.NoError(t, err) // Compare fetched tokens vs generated tokens@@ -195,6 +204,24 @@ assert.Equal(t, tokens[i].Name, token.Name)
assert.Equal(t, tokens[i].Symbol, token.Symbol) assert.Nil(t, token.USD) assert.Nil(t, token.USDUpdate) + } + + // Update token value + for i, token := range tokens { + value := 1.01 * float64(i) + assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value)) + } + // Fetch tokens + fetchedTokens, _, err = historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc) + assert.NoError(t, err) + // Compare fetched tokens vs generated tokens + // All the tokens should have USDUpdate setted by the DB trigger + for i, token := range fetchedTokens { + value := 1.01 * float64(i) + assert.Equal(t, value, *token.USD) + nameZone, offset := token.USDUpdate.Zone() + assert.Equal(t, "UTC", nameZone) + assert.Equal(t, 0, offset) } }
@@ -18,7 +18,7 @@ type TxAPI struct {
// Generic IsL1 bool `meddler:"is_l1"` TxID common.TxID `meddler:"id"` - ItemID int `meddler:"item_id"` + ItemID uint64 `meddler:"item_id"` Type common.TxType `meddler:"type"` Position int `meddler:"position"` FromIdx *apitypes.HezIdx `meddler:"from_idx"`@@ -42,11 +42,11 @@ HistoricFeeUSD *float64 `meddler:"fee_usd"`
Nonce *common.Nonce `meddler:"nonce"` // API extras Timestamp time.Time `meddler:"timestamp,utctime"` - TotalItems int `meddler:"total_items"` - FirstItem int `meddler:"first_item"` - LastItem int `meddler:"last_item"` + TotalItems uint64 `meddler:"total_items"` + FirstItem uint64 `meddler:"first_item"` + LastItem uint64 `meddler:"last_item"` TokenID common.TokenID `meddler:"token_id"` - TokenItemID int `meddler:"token_item_id"` + TokenItemID uint64 `meddler:"token_item_id"` TokenEthBlockNum int64 `meddler:"token_block"` TokenEthAddr ethCommon.Address `meddler:"eth_addr"` TokenName string `meddler:"name"`@@ -137,7 +137,7 @@ }
// TokenWithUSD add USD info to common.Token type TokenWithUSD struct { - ItemID int `json:"itemId" meddler:"item_id"` + ItemID uint64 `json:"itemId" meddler:"item_id"` TokenID common.TokenID `json:"id" meddler:"token_id"` EthBlockNum int64 `json:"ethereumBlockNum" meddler:"eth_block_num"` // Ethereum block number in which this token was registered EthAddr ethCommon.Address `json:"ethereumAddress" meddler:"eth_addr"`@@ -146,15 +146,15 @@ Symbol string `json:"symbol" meddler:"symbol"`
Decimals uint64 `json:"decimals" meddler:"decimals"` USD *float64 `json:"USD" meddler:"usd"` USDUpdate *time.Time `json:"fiatUpdate" meddler:"usd_update,utctime"` - TotalItems int `json:"-" meddler:"total_items"` - FirstItem int `json:"-" meddler:"first_item"` - LastItem int `json:"-" meddler:"last_item"` + TotalItems uint64 `json:"-" meddler:"total_items"` + FirstItem uint64 `json:"-" meddler:"first_item"` + LastItem uint64 `json:"-" meddler:"last_item"` } // ExitAPI is a representation of a exit with additional information // required by the API, and extracted by joining token table type ExitAPI struct { - ItemID int `meddler:"item_id"` + ItemID uint64 `meddler:"item_id"` BatchNum common.BatchNum `meddler:"batch_num"` AccountIdx apitypes.HezIdx `meddler:"account_idx"` MerkleProof *merkletree.CircomVerifierProof `meddler:"merkle_proof,json"`@@ -162,11 +162,11 @@ Balance apitypes.BigIntStr `meddler:"balance"`
InstantWithdrawn *int64 `meddler:"instant_withdrawn"` DelayedWithdrawRequest *int64 `meddler:"delayed_withdraw_request"` DelayedWithdrawn *int64 `meddler:"delayed_withdrawn"` - TotalItems int `meddler:"total_items"` - FirstItem int `meddler:"first_item"` - LastItem int `meddler:"last_item"` + TotalItems uint64 `meddler:"total_items"` + FirstItem uint64 `meddler:"first_item"` + LastItem uint64 `meddler:"last_item"` TokenID common.TokenID `meddler:"token_id"` - TokenItemID int `meddler:"token_item_id"` + TokenItemID uint64 `meddler:"token_item_id"` TokenEthBlockNum int64 `meddler:"token_block"` TokenEthAddr ethCommon.Address `meddler:"eth_addr"` TokenName string `meddler:"name"`@@ -218,29 +218,29 @@
// CoordinatorAPI is a representation of a coordinator with additional information // required by the API type CoordinatorAPI struct { - ItemID int `json:"itemId" meddler:"item_id"` + ItemID uint64 `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"` + TotalItems uint64 `json:"-" meddler:"total_items"` + FirstItem uint64 `json:"-" meddler:"first_item"` + LastItem uint64 `json:"-" meddler:"last_item"` } // AccountAPI is a representation of a account with additional information // required by the API type AccountAPI struct { - ItemID int `meddler:"item_id"` + ItemID uint64 `meddler:"item_id"` Idx apitypes.HezIdx `meddler:"idx"` BatchNum common.BatchNum `meddler:"batch_num"` PublicKey apitypes.HezBJJ `meddler:"bjj"` EthAddr apitypes.HezEthAddr `meddler:"eth_addr"` Nonce common.Nonce `meddler:"-"` // max of 40 bits used Balance *apitypes.BigIntStr `meddler:"-"` // max of 192 bits used - TotalItems int `meddler:"total_items"` - FirstItem int `meddler:"first_item"` - LastItem int `meddler:"last_item"` + TotalItems uint64 `meddler:"total_items"` + FirstItem uint64 `meddler:"first_item"` + LastItem uint64 `meddler:"last_item"` TokenID common.TokenID `meddler:"token_id"` TokenItemID int `meddler:"token_item_id"` TokenEthBlockNum int64 `meddler:"token_block"`@@ -280,7 +280,7 @@
// BatchAPI is a representation of a batch with additional information // required by the API, and extracted by joining block table type BatchAPI struct { - ItemID int `json:"itemId" meddler:"item_id"` + ItemID uint64 `json:"itemId" meddler:"item_id"` BatchNum common.BatchNum `json:"batchNum" meddler:"batch_num"` EthBlockNum int64 `json:"ethereumBlockNum" meddler:"eth_block_num"` EthBlockHash ethCommon.Hash `json:"ethereumBlockHash" meddler:"hash"`@@ -293,9 +293,9 @@ NumAccounts int `json:"numAccounts" meddler:"num_accounts"`
ExitRoot apitypes.BigIntStr `json:"exitRoot" meddler:"exit_root"` ForgeL1TxsNum *int64 `json:"forgeL1TransactionsNum" meddler:"forge_l1_txs_num"` SlotNum int64 `json:"slotNum" meddler:"slot_num"` - TotalItems int `json:"-" meddler:"total_items"` - FirstItem int `json:"-" meddler:"first_item"` - LastItem int `json:"-" meddler:"last_item"` + TotalItems uint64 `json:"-" meddler:"total_items"` + FirstItem uint64 `json:"-" meddler:"first_item"` + LastItem uint64 `json:"-" meddler:"last_item"` } // Network define status of the network@@ -319,7 +319,7 @@
// BidAPI is a representation of a bid with additional information // required by the API type BidAPI struct { - ItemID int `json:"itemId" meddler:"item_id"` + ItemID uint64 `json:"itemId" meddler:"item_id"` SlotNum int64 `json:"slotNum" meddler:"slot_num"` BidValue apitypes.BigIntStr `json:"bidValue" meddler:"bid_value"` EthBlockNum int64 `json:"ethereumBlockNum" meddler:"eth_block_num"`@@ -327,7 +327,7 @@ Bidder ethCommon.Address `json:"bidderAddr" meddler:"bidder_addr"`
Forger ethCommon.Address `json:"forgerAddr" meddler:"forger_addr"` URL string `json:"URL" meddler:"url"` Timestamp time.Time `json:"timestamp" meddler:"timestamp,utctime"` - TotalItems int `json:"-" meddler:"total_items"` - FirstItem int `json:"-" meddler:"first_item"` - LastItem int `json:"-" meddler:"last_item"` + TotalItems uint64 `json:"-" meddler:"total_items"` + FirstItem uint64 `json:"-" meddler:"first_item"` + LastItem uint64 `json:"-" meddler:"last_item"` }
@@ -90,6 +90,9 @@ fetchedTx, err := l2DB.GetTx(tx.TxID)
assert.NoError(t, err) // assertReadTx(t, commonToRead(tx, tokens), fetchedTx) assertTx(t, tx, fetchedTx) + nameZone, offset := fetchedTx.Timestamp.Zone() + assert.Equal(t, "UTC", nameZone) + assert.Equal(t, 0, offset) } }@@ -419,5 +422,8 @@ assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
assert.Equal(t, auths[i].BJJ, auth.BJJ) assert.Equal(t, auths[i].Signature, auth.Signature) assert.Equal(t, auths[i].Timestamp.Unix(), auths[i].Timestamp.Unix()) + nameZone, offset := auths[i].Timestamp.Zone() + assert.Equal(t, "UTC", nameZone) + assert.Equal(t, 0, offset) } }
@@ -62,9 +62,9 @@ Type common.TxType `meddler:"tx_type"`
// Extra read fileds BatchNum *common.BatchNum `meddler:"batch_num"` Timestamp time.Time `meddler:"timestamp,utctime"` - TotalItems int `meddler:"total_items"` + TotalItems uint64 `meddler:"total_items"` TokenID common.TokenID `meddler:"token_id"` - TokenItemID int `meddler:"token_item_id"` + TokenItemID uint64 `meddler:"token_item_id"` TokenEthBlockNum int64 `meddler:"eth_block_num"` TokenEthAddr ethCommon.Address `meddler:"eth_addr"` TokenName string `meddler:"name"`
@@ -181,11 +181,11 @@ }
// Pagination give information on the items of a query type Pagination struct { - TotalItems int `json:"totalItems"` - FirstItem int `json:"firstItem"` - LastItem int `json:"lastItem"` - FirstReturnedItem int `json:"-"` - LastReturnedItem int `json:"-"` + TotalItems uint64 `json:"totalItems"` + FirstItem uint64 `json:"firstItem"` + LastItem uint64 `json:"lastItem"` + FirstReturnedItem uint64 `json:"-"` + LastReturnedItem uint64 `json:"-"` } // Paginationer is an interface that allows getting pagination info on any struct