arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
Merge pull request #262 from hermeznetwork/feature/api-checks

ItemID to uint64 & check timestamp
Toni Ramírez 58293609+ToniRamirezM@users.noreply.github.com
Fri, 06 Nov 2020 11:45:14 +0100
commit

f662beb2ea6c3f4a38feaf867d31243d84e9a74d

parent

3591e3c2a2fe0bfbad20cc8155c5990dc512738f

M api/account_test.go → api/account_test.go

@@ -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),
M api/api_test.go → api/api_test.go

@@ -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) } } }
M api/batch_test.go → api/batch_test.go

@@ -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"`
M api/bids_test.go → api/bids_test.go

@@ -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"`
M api/exits_test.go → api/exits_test.go

@@ -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"`
M api/slots.go → api/slots.go

@@ -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...) } }
M api/slots_test.go → api/slots_test.go

@@ -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 }
M api/swagger.yml → api/swagger.yml

@@ -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:
M api/txshistory_test.go → api/txshistory_test.go

@@ -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"`
M db/historydb/historydb_test.go → db/historydb/historydb_test.go

@@ -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) } }
M db/historydb/views.go → db/historydb/views.go

@@ -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"` }
M db/l2db/l2db_test.go → db/l2db/l2db_test.go

@@ -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) } }
M db/l2db/views.go → db/l2db/views.go

@@ -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"`
M db/utils.go → db/utils.go

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