mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Update missing parts, improve til, and more
- Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
This commit is contained in:
@@ -33,49 +33,6 @@ type HistoryDB struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
// BlockData contains the information of a Block
|
||||
type BlockData struct {
|
||||
Block *common.Block
|
||||
// Rollup
|
||||
// L1UserTxs that were submitted in the block
|
||||
L1UserTxs []common.L1Tx
|
||||
Batches []BatchData
|
||||
RegisteredTokens []common.Token
|
||||
RollupVars *common.RollupVars
|
||||
// Auction
|
||||
Bids []common.Bid
|
||||
Coordinators []common.Coordinator
|
||||
AuctionVars *common.AuctionVars
|
||||
WithdrawDelayerVars *common.WithdrawDelayerVars
|
||||
// TODO: enable when common.WithdrawalDelayerVars is Merged from Synchronizer PR
|
||||
// WithdrawalDelayerVars *common.WithdrawalDelayerVars
|
||||
}
|
||||
|
||||
// BatchData contains the information of a Batch
|
||||
type BatchData struct {
|
||||
// L1UserTxs that were forged in the batch
|
||||
L1Batch bool // TODO: Remove once Batch.ForgeL1TxsNum is a pointer
|
||||
L1UserTxs []common.L1Tx
|
||||
L1CoordinatorTxs []common.L1Tx
|
||||
L2Txs []common.L2Tx
|
||||
CreatedAccounts []common.Account
|
||||
ExitTree []common.ExitInfo
|
||||
Batch *common.Batch
|
||||
}
|
||||
|
||||
// NewBatchData creates an empty BatchData with the slices initialized.
|
||||
func NewBatchData() *BatchData {
|
||||
return &BatchData{
|
||||
L1Batch: false,
|
||||
L1UserTxs: make([]common.L1Tx, 0),
|
||||
L1CoordinatorTxs: make([]common.L1Tx, 0),
|
||||
L2Txs: make([]common.L2Tx, 0),
|
||||
CreatedAccounts: make([]common.Account, 0),
|
||||
ExitTree: make([]common.ExitInfo, 0),
|
||||
Batch: &common.Batch{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewHistoryDB initialize the DB
|
||||
func NewHistoryDB(db *sqlx.DB) *HistoryDB {
|
||||
return &HistoryDB{db: db}
|
||||
@@ -149,19 +106,21 @@ func (hdb *HistoryDB) addBatch(d meddler.DB, batch *common.Batch) error {
|
||||
USD *float64 `meddler:"usd"`
|
||||
Decimals int `meddler:"decimals"`
|
||||
}
|
||||
query, args, err := sqlx.In(
|
||||
"SELECT token_id, usd, decimals FROM token WHERE token_id IN (?)",
|
||||
tokenIDs,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
query = hdb.db.Rebind(query)
|
||||
var tokenPrices []*tokenPrice
|
||||
if err := meddler.QueryAll(
|
||||
hdb.db, &tokenPrices, query, args...,
|
||||
); err != nil {
|
||||
return err
|
||||
if len(tokenIDs) > 0 {
|
||||
query, args, err := sqlx.In(
|
||||
"SELECT token_id, usd, decimals FROM token WHERE token_id IN (?)",
|
||||
tokenIDs,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
query = hdb.db.Rebind(query)
|
||||
if err := meddler.QueryAll(
|
||||
hdb.db, &tokenPrices, query, args...,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Calculate total collected
|
||||
var total float64
|
||||
@@ -209,8 +168,8 @@ func (hdb *HistoryDB) GetLastBatchNum() (common.BatchNum, error) {
|
||||
return batchNum, row.Scan(&batchNum)
|
||||
}
|
||||
|
||||
// GetLastL1TxsNum returns the greatest ForgeL1TxsNum in the DB. If there's no
|
||||
// batch in the DB (nil, nil) is returned.
|
||||
// GetLastL1TxsNum returns the greatest ForgeL1TxsNum in the DB from forged
|
||||
// batches. If there's no batch in the DB (nil, nil) is returned.
|
||||
func (hdb *HistoryDB) GetLastL1TxsNum() (*int64, error) {
|
||||
row := hdb.db.QueryRow("SELECT MAX(forge_l1_txs_num) FROM batch;")
|
||||
lastL1TxsNum := new(int64)
|
||||
@@ -326,6 +285,16 @@ func (hdb *HistoryDB) GetToken(tokenID common.TokenID) (*TokenRead, error) {
|
||||
return token, err
|
||||
}
|
||||
|
||||
// GetAllTokens returns all tokens from the DB
|
||||
func (hdb *HistoryDB) GetAllTokens() ([]TokenRead, error) {
|
||||
var tokens []*TokenRead
|
||||
err := meddler.QueryAll(
|
||||
hdb.db, &tokens,
|
||||
"SELECT * FROM token ORDER BY token_id;",
|
||||
)
|
||||
return db.SlicePtrsToSlice(tokens).([]TokenRead), err
|
||||
}
|
||||
|
||||
// GetTokens returns a list of tokens from the DB
|
||||
func (hdb *HistoryDB) GetTokens(ids []common.TokenID, symbols []string, name string, fromItem, limit *uint, order string) ([]TokenRead, *db.Pagination, error) {
|
||||
var query string
|
||||
@@ -822,17 +791,19 @@ func (hdb *HistoryDB) GetExits(
|
||||
// )
|
||||
// }
|
||||
|
||||
// // GetL1UserTxs gets L1 User Txs to be forged in a batch that will create an account
|
||||
// // TODO: This is currently not used. Figure out if it should be used somewhere or removed.
|
||||
// func (hdb *HistoryDB) GetL1UserTxs(toForgeL1TxsNum int64) ([]*common.Tx, error) {
|
||||
// var txs []*common.Tx
|
||||
// err := meddler.QueryAll(
|
||||
// hdb.db, &txs,
|
||||
// "SELECT * FROM tx WHERE to_forge_l1_txs_num = $1 AND is_l1 = TRUE AND user_origin = TRUE;",
|
||||
// toForgeL1TxsNum,
|
||||
// )
|
||||
// return txs, err
|
||||
// }
|
||||
// GetL1UserTxs gets L1 User Txs to be forged in the L1Batch with toForgeL1TxsNum.
|
||||
func (hdb *HistoryDB) GetL1UserTxs(toForgeL1TxsNum int64) ([]common.L1Tx, error) {
|
||||
var txs []*common.L1Tx
|
||||
err := meddler.QueryAll(
|
||||
hdb.db, &txs,
|
||||
`SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin,
|
||||
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id, tx.amount,
|
||||
tx.load_amount, tx.eth_block_num, tx.type, tx.batch_num
|
||||
FROM tx WHERE to_forge_l1_txs_num = $1 AND is_l1 = TRUE AND user_origin = TRUE;`,
|
||||
toForgeL1TxsNum,
|
||||
)
|
||||
return db.SlicePtrsToSlice(txs).([]common.L1Tx), err
|
||||
}
|
||||
|
||||
// TODO: Think about chaning all the queries that return a last value, to queries that return the next valid value.
|
||||
|
||||
@@ -843,8 +814,11 @@ func (hdb *HistoryDB) GetLastTxsPosition(toForgeL1TxsNum int64) (int, error) {
|
||||
return lastL1TxsPosition, row.Scan(&lastL1TxsPosition)
|
||||
}
|
||||
|
||||
// AddBlockSCData stores all the information of a block retrieved by the Synchronizer
|
||||
func (hdb *HistoryDB) AddBlockSCData(blockData *BlockData) (err error) {
|
||||
// AddBlockSCData stores all the information of a block retrieved by the
|
||||
// Synchronizer. Blocks should be inserted in order, leaving no gaps because
|
||||
// the pagination system of the API/DB depends on this. Within blocks, all
|
||||
// items should also be in the correct order (Accounts, Tokens, Txs, etc.)
|
||||
func (hdb *HistoryDB) AddBlockSCData(blockData *common.BlockData) (err error) {
|
||||
txn, err := hdb.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -859,7 +833,7 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *BlockData) (err error) {
|
||||
}()
|
||||
|
||||
// Add block
|
||||
err = hdb.addBlock(txn, blockData.Block)
|
||||
err = hdb.addBlock(txn, &blockData.Block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -881,8 +855,8 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *BlockData) (err error) {
|
||||
}
|
||||
|
||||
// Add Tokens
|
||||
if len(blockData.RegisteredTokens) > 0 {
|
||||
err = hdb.addTokens(txn, blockData.RegisteredTokens)
|
||||
if len(blockData.AddedTokens) > 0 {
|
||||
err = hdb.addTokens(txn, blockData.AddedTokens)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -897,10 +871,11 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *BlockData) (err error) {
|
||||
}
|
||||
|
||||
// Add Batches
|
||||
for _, batch := range blockData.Batches {
|
||||
for i := range blockData.Batches {
|
||||
batch := &blockData.Batches[i]
|
||||
// Add Batch: this will trigger an update on the DB
|
||||
// that will set the batch num of forged L1 txs in this batch
|
||||
err = hdb.addBatch(txn, batch.Batch)
|
||||
err = hdb.addBatch(txn, &batch.Batch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,11 +6,14 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
dbUtils "github.com/hermeznetwork/hermez-node/db"
|
||||
"github.com/hermeznetwork/hermez-node/log"
|
||||
"github.com/hermeznetwork/hermez-node/test"
|
||||
"github.com/hermeznetwork/hermez-node/test/til"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var historyDB *HistoryDB
|
||||
@@ -378,6 +381,91 @@ func TestExitTree(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGetL1UserTxs(t *testing.T) {
|
||||
require.NoError(t, cleanHistoryDB())
|
||||
|
||||
set := `
|
||||
Type: Blockchain
|
||||
AddToken(1)
|
||||
AddToken(2)
|
||||
AddToken(3)
|
||||
|
||||
CreateAccountDeposit(1) A: 10
|
||||
CreateAccountDeposit(2) A: 20
|
||||
CreateAccountDeposit(1) B: 5
|
||||
CreateAccountDeposit(1) C: 5
|
||||
CreateAccountDepositTransfer(1) D-A: 15, 10 (3)
|
||||
|
||||
> batchL1 // freeze open l1UserTxs queue
|
||||
> batchL1 // forge current l1UserTxs queue
|
||||
> block
|
||||
`
|
||||
tc := til.NewContext(128)
|
||||
blocks, err := tc.GenerateBlocks(set)
|
||||
require.Nil(t, err)
|
||||
// Sanity check
|
||||
require.Equal(t, 1, len(blocks))
|
||||
require.Equal(t, 5, len(blocks[0].L1UserTxs))
|
||||
require.Equal(t, 2, len(blocks[0].Batches))
|
||||
// fmt.Printf("DBG Blocks: %+v\n", blocks)
|
||||
|
||||
// TODO: Move this logic to `func (tc *TestContext) GenerateBlocks(set string) ([]common.BlockData, error)`
|
||||
toForgeL1TxsNum := int64(1)
|
||||
for i := range blocks {
|
||||
block := &blocks[i]
|
||||
block.Block.EthBlockNum = int64(i)
|
||||
for j := range block.AddedTokens {
|
||||
token := &block.AddedTokens[j]
|
||||
token.EthAddr = ethCommon.BigToAddress(big.NewInt(int64(i*len(blocks) + j)))
|
||||
}
|
||||
for j := range block.L1UserTxs {
|
||||
l1Tx := &block.L1UserTxs[j]
|
||||
l1Tx.UserOrigin = true
|
||||
l1Tx.Position = j
|
||||
l1Tx.ToForgeL1TxsNum = &toForgeL1TxsNum
|
||||
}
|
||||
}
|
||||
|
||||
for i := range blocks {
|
||||
// fmt.Printf("DBG %+v\n", blocks[i])
|
||||
// fmt.Printf("DBG Batches %+v\n", blocks[i].Batches)
|
||||
// for _, l1Tx := range blocks[i].L1UserTxs {
|
||||
// fmt.Printf("DBG l1UserTx %+v\n", l1Tx)
|
||||
// }
|
||||
err = historyDB.AddBlockSCData(&blocks[i])
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
// // TODO: Use til to generate a set with some L1UserTxs
|
||||
// l1Txs := []common.L1Tx{}
|
||||
// l1Tx, err := common.NewL1Tx(&common.L1Tx{
|
||||
// ToForgeL1TxsNum: &toForgeL1TxsNum,
|
||||
// Position: 0,
|
||||
// UserOrigin: true,
|
||||
// FromIdx: 0,
|
||||
// FromEthAddr: ethCommon.Address{}, // ethCommon.HexToAddress("0xff"),
|
||||
// FromBJJ: nil,
|
||||
// ToIdx: 0,
|
||||
// TokenID: 1,
|
||||
// Amount: big.NewInt(0),
|
||||
// LoadAmount: big.NewInt(0),
|
||||
// })
|
||||
// require.Nil(t, err)
|
||||
// l1Txs = append(l1Txs, *l1Tx)
|
||||
|
||||
// require.Nil(t, historyDB.AddL1Txs(l1Txs))
|
||||
|
||||
l1UserTxs, err := historyDB.GetL1UserTxs(toForgeL1TxsNum)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 5, len(l1UserTxs))
|
||||
assert.Equal(t, blocks[0].L1UserTxs, l1UserTxs)
|
||||
|
||||
// No l1UserTxs for this toForgeL1TxsNum
|
||||
l1UserTxs, err = historyDB.GetL1UserTxs(2)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 0, len(l1UserTxs))
|
||||
}
|
||||
|
||||
// setTestBlocks WARNING: this will delete the blocks and recreate them
|
||||
func setTestBlocks(from, to int64) []common.Block {
|
||||
if err := cleanHistoryDB(); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user