arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/db/historydb/historydb_test.go
db/historydb/historydb_test.goRaw
   1package historydb
   2
   3import (
   4	"database/sql"
   5	"fmt"
   6	"math"
   7	"math/big"
   8	"os"
   9	"strings"
  10	"testing"
  11	"time"
  12
  13	ethCommon "github.com/ethereum/go-ethereum/common"
  14	"github.com/hermeznetwork/hermez-node/api/apitypes"
  15	"github.com/hermeznetwork/hermez-node/common"
  16	dbUtils "github.com/hermeznetwork/hermez-node/db"
  17	"github.com/hermeznetwork/hermez-node/log"
  18	"github.com/hermeznetwork/hermez-node/test"
  19	"github.com/hermeznetwork/hermez-node/test/til"
  20	"github.com/hermeznetwork/tracerr"
  21	"github.com/stretchr/testify/assert"
  22	"github.com/stretchr/testify/require"
  23)
  24
  25var historyDB *HistoryDB
  26var historyDBWithACC *HistoryDB
  27
  28// In order to run the test you need to run a Posgres DB with
  29// a database named "history" that is accessible by
  30// user: "hermez"
  31// pass: set it using the env var POSTGRES_PASS
  32// This can be achieved by running: POSTGRES_PASS=your_strong_pass && sudo docker run --rm --name hermez-db-test -p 5432:5432 -e POSTGRES_DB=history -e POSTGRES_USER=hermez -e POSTGRES_PASSWORD=$POSTGRES_PASS -d postgres && sleep 2s && sudo docker exec -it hermez-db-test psql -a history -U hermez -c "CREATE DATABASE l2;"
  33// After running the test you can stop the container by running: sudo docker kill hermez-db-test
  34// If you already did that for the L2DB you don't have to do it again
  35
  36func TestMain(m *testing.M) {
  37	// init DB
  38	pass := os.Getenv("POSTGRES_PASS")
  39	db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  40	if err != nil {
  41		panic(err)
  42	}
  43	historyDB = NewHistoryDB(db, db, nil)
  44	if err != nil {
  45		panic(err)
  46	}
  47	apiConnCon := dbUtils.NewAPIConnectionController(1, time.Second)
  48	historyDBWithACC = NewHistoryDB(db, db, apiConnCon)
  49	// Run tests
  50	result := m.Run()
  51	// Close DB
  52	if err := db.Close(); err != nil {
  53		log.Error("Error closing the history DB:", err)
  54	}
  55	os.Exit(result)
  56}
  57
  58func TestBlocks(t *testing.T) {
  59	var fromBlock, toBlock int64
  60	fromBlock = 0
  61	toBlock = 7
  62	// Reset DB
  63	test.WipeDB(historyDB.DB())
  64	// Generate blocks using til
  65	set1 := `
  66		Type: Blockchain
  67		// block 0 is stored as default in the DB
  68		// block 1 does not exist
  69		> block // blockNum=2
  70		> block // blockNum=3 
  71		> block // blockNum=4
  72		> block // blockNum=5
  73		> block // blockNum=6
  74	`
  75	tc := til.NewContext(uint16(0), 1)
  76	blocks, err := tc.GenerateBlocks(set1)
  77	require.NoError(t, err)
  78	// Save timestamp of a block with UTC and change it without UTC
  79	timestamp := time.Now().Add(time.Second * 13)
  80	blocks[fromBlock].Block.Timestamp = timestamp
  81	// Insert blocks into DB
  82	for i := 0; i < len(blocks); i++ {
  83		err := historyDB.AddBlock(&blocks[i].Block)
  84		assert.NoError(t, err)
  85	}
  86	// Add block 0 to the generated blocks
  87	blocks = append(
  88		[]common.BlockData{{Block: test.Block0}}, //nolint:gofmt
  89		blocks...,
  90	)
  91	// Get all blocks from DB
  92	fetchedBlocks, err := historyDB.getBlocks(fromBlock, toBlock)
  93	assert.Equal(t, len(blocks), len(fetchedBlocks))
  94	// Compare generated vs getted blocks
  95	assert.NoError(t, err)
  96	for i := range fetchedBlocks {
  97		assertEqualBlock(t, &blocks[i].Block, &fetchedBlocks[i])
  98	}
  99	// Compare saved timestamp vs getted
 100	nameZoneUTC, offsetUTC := timestamp.UTC().Zone()
 101	zoneFetchedBlock, offsetFetchedBlock := fetchedBlocks[fromBlock].Timestamp.Zone()
 102	assert.Equal(t, nameZoneUTC, zoneFetchedBlock)
 103	assert.Equal(t, offsetUTC, offsetFetchedBlock)
 104	// Get blocks from the DB one by one
 105	for i := int64(2); i < toBlock; i++ { // avoid block 0 for simplicity
 106		fetchedBlock, err := historyDB.GetBlock(i)
 107		assert.NoError(t, err)
 108		assertEqualBlock(t, &blocks[i-1].Block, fetchedBlock)
 109	}
 110	// Get last block
 111	lastBlock, err := historyDB.GetLastBlock()
 112	assert.NoError(t, err)
 113	assertEqualBlock(t, &blocks[len(blocks)-1].Block, lastBlock)
 114}
 115
 116func assertEqualBlock(t *testing.T, expected *common.Block, actual *common.Block) {
 117	assert.Equal(t, expected.Num, actual.Num)
 118	assert.Equal(t, expected.Hash, actual.Hash)
 119	assert.Equal(t, expected.Timestamp.Unix(), actual.Timestamp.Unix())
 120}
 121
 122func TestBatches(t *testing.T) {
 123	// Reset DB
 124	test.WipeDB(historyDB.DB())
 125	// Generate batches using til (and blocks for foreign key)
 126	set := `
 127		Type: Blockchain
 128		
 129		AddToken(1) // Will have value in USD
 130		AddToken(2) // Will NOT have value in USD
 131		CreateAccountDeposit(1) A: 2000
 132		CreateAccountDeposit(2) A: 2000
 133		CreateAccountDeposit(1) B: 1000
 134		CreateAccountDeposit(2) B: 1000
 135		> batchL1 
 136		> batchL1 
 137		Transfer(1) A-B: 100 (5)
 138		Transfer(2) B-A: 100 (199)
 139		> batch   // batchNum=2, L2 only batch, forges transfers (mixed case of with(out) USD value)
 140		> block
 141		Transfer(1) A-B: 100 (5)
 142		> batch   // batchNum=3, L2 only batch, forges transfer (with USD value)
 143		Transfer(2) B-A: 100 (199)
 144		> batch   // batchNum=4, L2 only batch, forges transfer (without USD value)
 145		> block
 146	`
 147	tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
 148	tilCfgExtra := til.ConfigExtra{
 149		BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
 150		CoordUser:     "A",
 151	}
 152	blocks, err := tc.GenerateBlocks(set)
 153	require.NoError(t, err)
 154	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
 155	require.NoError(t, err)
 156	// Insert to DB
 157	batches := []common.Batch{}
 158	tokensValue := make(map[common.TokenID]float64)
 159	lastL1TxsNum := new(int64)
 160	lastL1BatchBlockNum := int64(0)
 161	for _, block := range blocks {
 162		// Insert block
 163		assert.NoError(t, historyDB.AddBlock(&block.Block))
 164		// Insert tokens
 165		for i, token := range block.Rollup.AddedTokens {
 166			assert.NoError(t, historyDB.AddToken(&token)) //nolint:gosec
 167			if i%2 != 0 {
 168				// Set value to the token
 169				value := (float64(i) + 5) * 5.389329
 170				assert.NoError(t, historyDB.UpdateTokenValue(token.EthAddr, value))
 171				tokensValue[token.TokenID] = value / math.Pow(10, float64(token.Decimals))
 172			}
 173		}
 174		// Combine all generated batches into single array
 175		for _, batch := range block.Rollup.Batches {
 176			batches = append(batches, batch.Batch)
 177			forgeTxsNum := batch.Batch.ForgeL1TxsNum
 178			if forgeTxsNum != nil && (lastL1TxsNum == nil || *lastL1TxsNum < *forgeTxsNum) {
 179				*lastL1TxsNum = *forgeTxsNum
 180				lastL1BatchBlockNum = batch.Batch.EthBlockNum
 181			}
 182		}
 183	}
 184	// Insert batches
 185	assert.NoError(t, historyDB.AddBatches(batches))
 186	// Set expected total fee
 187	for _, batch := range batches {
 188		total := .0
 189		for tokenID, amount := range batch.CollectedFees {
 190			af := new(big.Float).SetInt(amount)
 191			amountFloat, _ := af.Float64()
 192			total += tokensValue[tokenID] * amountFloat
 193		}
 194		batch.TotalFeesUSD = &total
 195	}
 196	// Get batches from the DB
 197	fetchedBatches, err := historyDB.GetBatches(0, common.BatchNum(len(batches)+1))
 198	assert.NoError(t, err)
 199	assert.Equal(t, len(batches), len(fetchedBatches))
 200	for i, fetchedBatch := range fetchedBatches {
 201		assert.Equal(t, batches[i], fetchedBatch)
 202	}
 203	// Test GetLastBatchNum
 204	fetchedLastBatchNum, err := historyDB.GetLastBatchNum()
 205	assert.NoError(t, err)
 206	assert.Equal(t, batches[len(batches)-1].BatchNum, fetchedLastBatchNum)
 207	// Test GetLastBatch
 208	fetchedLastBatch, err := historyDB.GetLastBatch()
 209	assert.NoError(t, err)
 210	assert.Equal(t, &batches[len(batches)-1], fetchedLastBatch)
 211	// Test GetLastL1TxsNum
 212	fetchedLastL1TxsNum, err := historyDB.GetLastL1TxsNum()
 213	assert.NoError(t, err)
 214	assert.Equal(t, lastL1TxsNum, fetchedLastL1TxsNum)
 215	// Test GetLastL1BatchBlockNum
 216	fetchedLastL1BatchBlockNum, err := historyDB.GetLastL1BatchBlockNum()
 217	assert.NoError(t, err)
 218	assert.Equal(t, lastL1BatchBlockNum, fetchedLastL1BatchBlockNum)
 219	// Test GetBatch
 220	fetchedBatch, err := historyDB.GetBatch(1)
 221	require.NoError(t, err)
 222	assert.Equal(t, &batches[0], fetchedBatch)
 223	_, err = historyDB.GetBatch(common.BatchNum(len(batches) + 1))
 224	assert.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
 225}
 226
 227func TestBids(t *testing.T) {
 228	const fromBlock int64 = 1
 229	const toBlock int64 = 5
 230	// Prepare blocks in the DB
 231	blocks := setTestBlocks(fromBlock, toBlock)
 232	// Generate fake coordinators
 233	const nCoords = 5
 234	coords := test.GenCoordinators(nCoords, blocks)
 235	err := historyDB.AddCoordinators(coords)
 236	assert.NoError(t, err)
 237	// Generate fake bids
 238	const nBids = 20
 239	bids := test.GenBids(nBids, blocks, coords)
 240	err = historyDB.AddBids(bids)
 241	assert.NoError(t, err)
 242	// Fetch bids
 243	fetchedBids, err := historyDB.GetAllBids()
 244	assert.NoError(t, err)
 245	// Compare fetched bids vs generated bids
 246	for i, bid := range fetchedBids {
 247		assert.Equal(t, bids[i], bid)
 248	}
 249}
 250
 251func TestTokens(t *testing.T) {
 252	const fromBlock int64 = 1
 253	const toBlock int64 = 5
 254	// Prepare blocks in the DB
 255	blocks := setTestBlocks(fromBlock, toBlock)
 256	// Generate fake tokens
 257	const nTokens = 5
 258	tokens, ethToken := test.GenTokens(nTokens, blocks)
 259	err := historyDB.AddTokens(tokens)
 260	assert.NoError(t, err)
 261	tokens = append([]common.Token{ethToken}, tokens...)
 262	// Fetch tokens
 263	fetchedTokens, err := historyDB.GetTokensTest()
 264	assert.NoError(t, err)
 265	// Compare fetched tokens vs generated tokens
 266	// All the tokens should have USDUpdate setted by the DB trigger
 267	for i, token := range fetchedTokens {
 268		assert.Equal(t, tokens[i].TokenID, token.TokenID)
 269		assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
 270		assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
 271		assert.Equal(t, tokens[i].Name, token.Name)
 272		assert.Equal(t, tokens[i].Symbol, token.Symbol)
 273		assert.Nil(t, token.USD)
 274		assert.Nil(t, token.USDUpdate)
 275	}
 276
 277	// Update token value
 278	for i, token := range tokens {
 279		value := 1.01 * float64(i)
 280		assert.NoError(t, historyDB.UpdateTokenValue(token.EthAddr, value))
 281	}
 282	// Fetch tokens
 283	fetchedTokens, err = historyDB.GetTokensTest()
 284	assert.NoError(t, err)
 285	// Compare fetched tokens vs generated tokens
 286	// All the tokens should have USDUpdate setted by the DB trigger
 287	for i, token := range fetchedTokens {
 288		value := 1.01 * float64(i)
 289		assert.Equal(t, value, *token.USD)
 290		nameZone, offset := token.USDUpdate.Zone()
 291		assert.Equal(t, "UTC", nameZone)
 292		assert.Equal(t, 0, offset)
 293	}
 294}
 295
 296func TestTokensUTF8(t *testing.T) {
 297	// Reset DB
 298	test.WipeDB(historyDB.DB())
 299	const fromBlock int64 = 1
 300	const toBlock int64 = 5
 301	// Prepare blocks in the DB
 302	blocks := setTestBlocks(fromBlock, toBlock)
 303	// Generate fake tokens
 304	const nTokens = 5
 305	tokens, ethToken := test.GenTokens(nTokens, blocks)
 306	nonUTFTokens := make([]common.Token, len(tokens))
 307	// Force token.name and token.symbol to be non UTF-8 Strings
 308	for i, token := range tokens {
 309		token.Name = fmt.Sprint("NON-UTF8-NAME-\xc5-", i)
 310		token.Symbol = fmt.Sprint("S-\xc5-", i)
 311		tokens[i] = token
 312		nonUTFTokens[i] = token
 313	}
 314	err := historyDB.AddTokens(tokens)
 315	assert.NoError(t, err)
 316	// Work with nonUTFTokens as tokens one gets updated and non UTF-8 characters are lost
 317	nonUTFTokens = append([]common.Token{ethToken}, nonUTFTokens...)
 318	// Fetch tokens
 319	fetchedTokens, err := historyDB.GetTokensTest()
 320	assert.NoError(t, err)
 321	// Compare fetched tokens vs generated tokens
 322	// All the tokens should have USDUpdate setted by the DB trigger
 323	for i, token := range fetchedTokens {
 324		assert.Equal(t, nonUTFTokens[i].TokenID, token.TokenID)
 325		assert.Equal(t, nonUTFTokens[i].EthBlockNum, token.EthBlockNum)
 326		assert.Equal(t, nonUTFTokens[i].EthAddr, token.EthAddr)
 327		assert.Equal(t, strings.ToValidUTF8(nonUTFTokens[i].Name, " "), token.Name)
 328		assert.Equal(t, strings.ToValidUTF8(nonUTFTokens[i].Symbol, " "), token.Symbol)
 329		assert.Nil(t, token.USD)
 330		assert.Nil(t, token.USDUpdate)
 331	}
 332
 333	// Update token value
 334	for i, token := range nonUTFTokens {
 335		value := 1.01 * float64(i)
 336		assert.NoError(t, historyDB.UpdateTokenValue(token.EthAddr, value))
 337	}
 338	// Fetch tokens
 339	fetchedTokens, err = historyDB.GetTokensTest()
 340	assert.NoError(t, err)
 341	// Compare fetched tokens vs generated tokens
 342	// All the tokens should have USDUpdate setted by the DB trigger
 343	for i, token := range fetchedTokens {
 344		value := 1.01 * float64(i)
 345		assert.Equal(t, value, *token.USD)
 346		nameZone, offset := token.USDUpdate.Zone()
 347		assert.Equal(t, "UTC", nameZone)
 348		assert.Equal(t, 0, offset)
 349	}
 350}
 351
 352func TestAccounts(t *testing.T) {
 353	const fromBlock int64 = 1
 354	const toBlock int64 = 5
 355	// Prepare blocks in the DB
 356	blocks := setTestBlocks(fromBlock, toBlock)
 357	// Generate fake tokens
 358	const nTokens = 5
 359	tokens, ethToken := test.GenTokens(nTokens, blocks)
 360	err := historyDB.AddTokens(tokens)
 361	assert.NoError(t, err)
 362	tokens = append([]common.Token{ethToken}, tokens...)
 363	// Generate fake batches
 364	const nBatches = 10
 365	batches := test.GenBatches(nBatches, blocks)
 366	err = historyDB.AddBatches(batches)
 367	assert.NoError(t, err)
 368	// Generate fake accounts
 369	const nAccounts = 3
 370	accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
 371	err = historyDB.AddAccounts(accs)
 372	assert.NoError(t, err)
 373	// Fetch accounts
 374	fetchedAccs, err := historyDB.GetAllAccounts()
 375	assert.NoError(t, err)
 376	// Compare fetched accounts vs generated accounts
 377	for i, acc := range fetchedAccs {
 378		accs[i].Balance = nil
 379		assert.Equal(t, accs[i], acc)
 380	}
 381	// Test AccountBalances
 382	accUpdates := make([]common.AccountUpdate, len(accs))
 383	for i, acc := range accs {
 384		accUpdates[i] = common.AccountUpdate{
 385			EthBlockNum: batches[acc.BatchNum-1].EthBlockNum,
 386			BatchNum:    acc.BatchNum,
 387			Idx:         acc.Idx,
 388			Nonce:       common.Nonce(i),
 389			Balance:     big.NewInt(int64(i)),
 390		}
 391	}
 392	err = historyDB.AddAccountUpdates(accUpdates)
 393	require.NoError(t, err)
 394	fetchedAccBalances, err := historyDB.GetAllAccountUpdates()
 395	require.NoError(t, err)
 396	assert.Equal(t, accUpdates, fetchedAccBalances)
 397}
 398
 399func TestTxs(t *testing.T) {
 400	// Reset DB
 401	test.WipeDB(historyDB.DB())
 402
 403	set := `
 404		Type: Blockchain
 405		
 406		AddToken(1)
 407		AddToken(2)
 408		CreateAccountDeposit(1) A: 10
 409		CreateAccountDeposit(1) B: 10
 410		> batchL1
 411		> batchL1
 412		> block
 413				
 414		CreateAccountDepositTransfer(1) C-A: 20, 10
 415		CreateAccountCoordinator(1) User0
 416		> batchL1
 417		> batchL1
 418		> block
 419
 420		Deposit(1) B: 10
 421		Deposit(1) C: 10
 422		Transfer(1) C-A : 10 (1)
 423		Transfer(1) B-C : 10 (1)
 424		Transfer(1) A-B : 10 (1)
 425		Exit(1) A: 10 (1)
 426		> batch
 427		> block
 428		
 429		DepositTransfer(1) A-B: 10, 10
 430		> batchL1
 431		> block
 432
 433		ForceTransfer(1) A-B: 10
 434		ForceExit(1) A: 5
 435		> batchL1
 436		> batchL1
 437		> block
 438
 439		CreateAccountDeposit(2) D: 10
 440		> batchL1
 441		> block
 442
 443		CreateAccountDeposit(2) E: 10
 444		> batchL1
 445		> batchL1
 446		> block
 447
 448	`
 449	tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
 450	tilCfgExtra := til.ConfigExtra{
 451		BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
 452		CoordUser:     "A",
 453	}
 454	blocks, err := tc.GenerateBlocks(set)
 455	require.NoError(t, err)
 456	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
 457	require.NoError(t, err)
 458
 459	// Sanity check
 460	require.Equal(t, 7, len(blocks))
 461	require.Equal(t, 2, len(blocks[0].Rollup.L1UserTxs))
 462	require.Equal(t, 1, len(blocks[1].Rollup.L1UserTxs))
 463	require.Equal(t, 2, len(blocks[2].Rollup.L1UserTxs))
 464	require.Equal(t, 1, len(blocks[3].Rollup.L1UserTxs))
 465	require.Equal(t, 2, len(blocks[4].Rollup.L1UserTxs))
 466	require.Equal(t, 1, len(blocks[5].Rollup.L1UserTxs))
 467	require.Equal(t, 1, len(blocks[6].Rollup.L1UserTxs))
 468
 469	var null *common.BatchNum = nil
 470	var txID common.TxID
 471
 472	// Insert blocks into DB
 473	for i := range blocks {
 474		if i == len(blocks)-1 {
 475			blocks[i].Block.Timestamp = time.Now()
 476			dbL1Txs, err := historyDB.GetAllL1UserTxs()
 477			assert.NoError(t, err)
 478			// Check batch_num is nil before forging
 479			assert.Equal(t, null, dbL1Txs[len(dbL1Txs)-1].BatchNum)
 480			// Save this TxId
 481			txID = dbL1Txs[len(dbL1Txs)-1].TxID
 482		}
 483		err = historyDB.AddBlockSCData(&blocks[i])
 484		assert.NoError(t, err)
 485	}
 486
 487	// Check blocks
 488	dbBlocks, err := historyDB.GetAllBlocks()
 489	assert.NoError(t, err)
 490	assert.Equal(t, len(blocks)+1, len(dbBlocks))
 491
 492	// Check batches
 493	batches, err := historyDB.GetAllBatches()
 494	assert.NoError(t, err)
 495	assert.Equal(t, 11, len(batches))
 496
 497	// Check L1 Transactions
 498	dbL1Txs, err := historyDB.GetAllL1UserTxs()
 499	assert.NoError(t, err)
 500	assert.Equal(t, 10, len(dbL1Txs))
 501
 502	// Tx Type
 503	assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[0].Type)
 504	assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[1].Type)
 505	assert.Equal(t, common.TxTypeCreateAccountDepositTransfer, dbL1Txs[2].Type)
 506	assert.Equal(t, common.TxTypeDeposit, dbL1Txs[3].Type)
 507	assert.Equal(t, common.TxTypeDeposit, dbL1Txs[4].Type)
 508	assert.Equal(t, common.TxTypeDepositTransfer, dbL1Txs[5].Type)
 509	assert.Equal(t, common.TxTypeForceTransfer, dbL1Txs[6].Type)
 510	assert.Equal(t, common.TxTypeForceExit, dbL1Txs[7].Type)
 511	assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[8].Type)
 512	assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[9].Type)
 513
 514	// Tx ID
 515	assert.Equal(t, "0x00e979da4b80d60a17ce56fa19278c6f3a7e1b43359fb8a8ea46d0264de7d653ab", dbL1Txs[0].TxID.String())
 516	assert.Equal(t, "0x00af9bf96eb60f2d618519402a2f6b07057a034fa2baefd379fe8e1c969f1c5cf4", dbL1Txs[1].TxID.String())
 517	assert.Equal(t, "0x00a256ee191905243320ea830840fd666a73c7b4e6f89ce4bd47ddf998dfee627a", dbL1Txs[2].TxID.String())
 518	assert.Equal(t, "0x00930696d03ae0a1e6150b6ccb88043cb539a4e06a7f8baf213029ce9a0600197e", dbL1Txs[3].TxID.String())
 519	assert.Equal(t, "0x00de8e41d49f23832f66364e8702c4b78237eb0c95542a94d34188e51696e74fc8", dbL1Txs[4].TxID.String())
 520	assert.Equal(t, "0x007a44d6d60b15f3789d4ff49d62377a70255bf13a8d42e41ef49bf4c7b77d2c1b", dbL1Txs[5].TxID.String())
 521	assert.Equal(t, "0x00c33f316240f8d33a973db2d0e901e4ac1c96de30b185fcc6b63dac4d0e147bd4", dbL1Txs[6].TxID.String())
 522	assert.Equal(t, "0x00b55f0882c5229d1be3d9d3c1a076290f249cd0bae5ae6e609234606befb91233", dbL1Txs[7].TxID.String())
 523	assert.Equal(t, "0x009133d4c8a412ca45f50bccdbcfdb8393b0dd8efe953d0cc3bcc82796b7a581b6", dbL1Txs[8].TxID.String())
 524	assert.Equal(t, "0x00f5e8ab141ac16d673e654ba7747c2f12e93ea2c50ba6c05563752ca531968c62", dbL1Txs[9].TxID.String())
 525
 526	// Tx From IDx
 527	assert.Equal(t, common.Idx(0), dbL1Txs[0].FromIdx)
 528	assert.Equal(t, common.Idx(0), dbL1Txs[1].FromIdx)
 529	assert.Equal(t, common.Idx(0), dbL1Txs[2].FromIdx)
 530	assert.NotEqual(t, common.Idx(0), dbL1Txs[3].FromIdx)
 531	assert.NotEqual(t, common.Idx(0), dbL1Txs[4].FromIdx)
 532	assert.NotEqual(t, common.Idx(0), dbL1Txs[5].FromIdx)
 533	assert.NotEqual(t, common.Idx(0), dbL1Txs[6].FromIdx)
 534	assert.NotEqual(t, common.Idx(0), dbL1Txs[7].FromIdx)
 535	assert.Equal(t, common.Idx(0), dbL1Txs[8].FromIdx)
 536	assert.Equal(t, common.Idx(0), dbL1Txs[9].FromIdx)
 537	assert.Equal(t, common.Idx(0), dbL1Txs[9].FromIdx)
 538	assert.Equal(t, dbL1Txs[5].FromIdx, dbL1Txs[6].FromIdx)
 539	assert.Equal(t, dbL1Txs[5].FromIdx, dbL1Txs[7].FromIdx)
 540
 541	// Tx to IDx
 542	assert.Equal(t, dbL1Txs[2].ToIdx, dbL1Txs[5].FromIdx)
 543	assert.Equal(t, dbL1Txs[5].ToIdx, dbL1Txs[3].FromIdx)
 544	assert.Equal(t, dbL1Txs[6].ToIdx, dbL1Txs[3].FromIdx)
 545
 546	// Token ID
 547	assert.Equal(t, common.TokenID(1), dbL1Txs[0].TokenID)
 548	assert.Equal(t, common.TokenID(1), dbL1Txs[1].TokenID)
 549	assert.Equal(t, common.TokenID(1), dbL1Txs[2].TokenID)
 550	assert.Equal(t, common.TokenID(1), dbL1Txs[3].TokenID)
 551	assert.Equal(t, common.TokenID(1), dbL1Txs[4].TokenID)
 552	assert.Equal(t, common.TokenID(1), dbL1Txs[5].TokenID)
 553	assert.Equal(t, common.TokenID(1), dbL1Txs[6].TokenID)
 554	assert.Equal(t, common.TokenID(1), dbL1Txs[7].TokenID)
 555	assert.Equal(t, common.TokenID(2), dbL1Txs[8].TokenID)
 556	assert.Equal(t, common.TokenID(2), dbL1Txs[9].TokenID)
 557
 558	// Batch Number
 559	var bn common.BatchNum = common.BatchNum(2)
 560
 561	assert.Equal(t, &bn, dbL1Txs[0].BatchNum)
 562	assert.Equal(t, &bn, dbL1Txs[1].BatchNum)
 563
 564	bn = common.BatchNum(4)
 565	assert.Equal(t, &bn, dbL1Txs[2].BatchNum)
 566
 567	bn = common.BatchNum(7)
 568	assert.Equal(t, &bn, dbL1Txs[3].BatchNum)
 569	assert.Equal(t, &bn, dbL1Txs[4].BatchNum)
 570	assert.Equal(t, &bn, dbL1Txs[5].BatchNum)
 571
 572	bn = common.BatchNum(8)
 573	assert.Equal(t, &bn, dbL1Txs[6].BatchNum)
 574	assert.Equal(t, &bn, dbL1Txs[7].BatchNum)
 575
 576	bn = common.BatchNum(10)
 577	assert.Equal(t, &bn, dbL1Txs[8].BatchNum)
 578
 579	bn = common.BatchNum(11)
 580	assert.Equal(t, &bn, dbL1Txs[9].BatchNum)
 581
 582	// eth_block_num
 583	assert.Equal(t, int64(2), dbL1Txs[0].EthBlockNum)
 584	assert.Equal(t, int64(2), dbL1Txs[1].EthBlockNum)
 585	assert.Equal(t, int64(3), dbL1Txs[2].EthBlockNum)
 586	assert.Equal(t, int64(4), dbL1Txs[3].EthBlockNum)
 587	assert.Equal(t, int64(4), dbL1Txs[4].EthBlockNum)
 588	assert.Equal(t, int64(5), dbL1Txs[5].EthBlockNum)
 589	assert.Equal(t, int64(6), dbL1Txs[6].EthBlockNum)
 590	assert.Equal(t, int64(6), dbL1Txs[7].EthBlockNum)
 591	assert.Equal(t, int64(7), dbL1Txs[8].EthBlockNum)
 592	assert.Equal(t, int64(8), dbL1Txs[9].EthBlockNum)
 593
 594	// User Origin
 595	assert.Equal(t, true, dbL1Txs[0].UserOrigin)
 596	assert.Equal(t, true, dbL1Txs[1].UserOrigin)
 597	assert.Equal(t, true, dbL1Txs[2].UserOrigin)
 598	assert.Equal(t, true, dbL1Txs[3].UserOrigin)
 599	assert.Equal(t, true, dbL1Txs[4].UserOrigin)
 600	assert.Equal(t, true, dbL1Txs[5].UserOrigin)
 601	assert.Equal(t, true, dbL1Txs[6].UserOrigin)
 602	assert.Equal(t, true, dbL1Txs[7].UserOrigin)
 603	assert.Equal(t, true, dbL1Txs[8].UserOrigin)
 604	assert.Equal(t, true, dbL1Txs[9].UserOrigin)
 605
 606	// Deposit Amount
 607	assert.Equal(t, big.NewInt(10), dbL1Txs[0].DepositAmount)
 608	assert.Equal(t, big.NewInt(10), dbL1Txs[1].DepositAmount)
 609	assert.Equal(t, big.NewInt(20), dbL1Txs[2].DepositAmount)
 610	assert.Equal(t, big.NewInt(10), dbL1Txs[3].DepositAmount)
 611	assert.Equal(t, big.NewInt(10), dbL1Txs[4].DepositAmount)
 612	assert.Equal(t, big.NewInt(10), dbL1Txs[5].DepositAmount)
 613	assert.Equal(t, big.NewInt(0), dbL1Txs[6].DepositAmount)
 614	assert.Equal(t, big.NewInt(0), dbL1Txs[7].DepositAmount)
 615	assert.Equal(t, big.NewInt(10), dbL1Txs[8].DepositAmount)
 616	assert.Equal(t, big.NewInt(10), dbL1Txs[9].DepositAmount)
 617
 618	// Check saved txID's batch_num is not nil
 619	assert.Equal(t, txID, dbL1Txs[len(dbL1Txs)-2].TxID)
 620	assert.NotEqual(t, null, dbL1Txs[len(dbL1Txs)-2].BatchNum)
 621
 622	// Check Coordinator TXs
 623	coordTxs, err := historyDB.GetAllL1CoordinatorTxs()
 624	assert.NoError(t, err)
 625	assert.Equal(t, 1, len(coordTxs))
 626	assert.Equal(t, common.TxTypeCreateAccountDeposit, coordTxs[0].Type)
 627	assert.Equal(t, false, coordTxs[0].UserOrigin)
 628
 629	// Check L2 TXs
 630	dbL2Txs, err := historyDB.GetAllL2Txs()
 631	assert.NoError(t, err)
 632	assert.Equal(t, 4, len(dbL2Txs))
 633
 634	// Tx Type
 635	assert.Equal(t, common.TxTypeTransfer, dbL2Txs[0].Type)
 636	assert.Equal(t, common.TxTypeTransfer, dbL2Txs[1].Type)
 637	assert.Equal(t, common.TxTypeTransfer, dbL2Txs[2].Type)
 638	assert.Equal(t, common.TxTypeExit, dbL2Txs[3].Type)
 639
 640	// Tx ID
 641	assert.Equal(t, "0x024e555248100b69a8aabf6d31719b9fe8a60dcc6c3407904a93c8d2d9ade18ee5", dbL2Txs[0].TxID.String())
 642	assert.Equal(t, "0x021ae87ca34d50ff35d98dfc0d7c95f2bf2e4ffeebb82ea71f43a8b0dfa5d36d89", dbL2Txs[1].TxID.String())
 643	assert.Equal(t, "0x024abce7f3f2382dc520ed557593f11dea1ee197e55b60402e664facc27aa19774", dbL2Txs[2].TxID.String())
 644	assert.Equal(t, "0x02f921ad9e7a6e59606570fe12a7dde0e36014197de0363b9b45e5097d6f2b1dd0", dbL2Txs[3].TxID.String())
 645
 646	// Tx From and To IDx
 647	assert.Equal(t, dbL2Txs[0].ToIdx, dbL2Txs[2].FromIdx)
 648	assert.Equal(t, dbL2Txs[1].ToIdx, dbL2Txs[0].FromIdx)
 649	assert.Equal(t, dbL2Txs[2].ToIdx, dbL2Txs[1].FromIdx)
 650
 651	// Batch Number
 652	assert.Equal(t, common.BatchNum(5), dbL2Txs[0].BatchNum)
 653	assert.Equal(t, common.BatchNum(5), dbL2Txs[1].BatchNum)
 654	assert.Equal(t, common.BatchNum(5), dbL2Txs[2].BatchNum)
 655	assert.Equal(t, common.BatchNum(5), dbL2Txs[3].BatchNum)
 656
 657	// eth_block_num
 658	assert.Equal(t, int64(4), dbL2Txs[0].EthBlockNum)
 659	assert.Equal(t, int64(4), dbL2Txs[1].EthBlockNum)
 660	assert.Equal(t, int64(4), dbL2Txs[2].EthBlockNum)
 661
 662	// Amount
 663	assert.Equal(t, big.NewInt(10), dbL2Txs[0].Amount)
 664	assert.Equal(t, big.NewInt(10), dbL2Txs[1].Amount)
 665	assert.Equal(t, big.NewInt(10), dbL2Txs[2].Amount)
 666	assert.Equal(t, big.NewInt(10), dbL2Txs[3].Amount)
 667}
 668
 669func TestExitTree(t *testing.T) {
 670	nBatches := 17
 671	blocks := setTestBlocks(1, 10)
 672	batches := test.GenBatches(nBatches, blocks)
 673	err := historyDB.AddBatches(batches)
 674	assert.NoError(t, err)
 675	const nTokens = 50
 676	tokens, ethToken := test.GenTokens(nTokens, blocks)
 677	err = historyDB.AddTokens(tokens)
 678	assert.NoError(t, err)
 679	tokens = append([]common.Token{ethToken}, tokens...)
 680	const nAccounts = 3
 681	accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
 682	assert.NoError(t, historyDB.AddAccounts(accs))
 683	exitTree := test.GenExitTree(nBatches, batches, accs, blocks)
 684	err = historyDB.AddExitTree(exitTree)
 685	assert.NoError(t, err)
 686}
 687
 688func TestGetUnforgedL1UserTxs(t *testing.T) {
 689	test.WipeDB(historyDB.DB())
 690
 691	set := `
 692		Type: Blockchain
 693		AddToken(1)
 694		AddToken(2)
 695		AddToken(3)
 696
 697		CreateAccountDeposit(1) A: 20
 698		CreateAccountDeposit(2) A: 20
 699		CreateAccountDeposit(1) B: 5
 700		CreateAccountDeposit(1) C: 5
 701		CreateAccountDeposit(1) D: 5
 702
 703		> block
 704	`
 705	tc := til.NewContext(uint16(0), 128)
 706	blocks, err := tc.GenerateBlocks(set)
 707	require.NoError(t, err)
 708	// Sanity check
 709	require.Equal(t, 1, len(blocks))
 710	require.Equal(t, 5, len(blocks[0].Rollup.L1UserTxs))
 711
 712	toForgeL1TxsNum := int64(1)
 713
 714	for i := range blocks {
 715		err = historyDB.AddBlockSCData(&blocks[i])
 716		require.NoError(t, err)
 717	}
 718
 719	l1UserTxs, err := historyDB.GetUnforgedL1UserTxs(toForgeL1TxsNum)
 720	require.NoError(t, err)
 721	assert.Equal(t, 5, len(l1UserTxs))
 722	assert.Equal(t, blocks[0].Rollup.L1UserTxs, l1UserTxs)
 723
 724	count, err := historyDB.GetUnforgedL1UserTxsCount()
 725	require.NoError(t, err)
 726	assert.Equal(t, 5, count)
 727
 728	// No l1UserTxs for this toForgeL1TxsNum
 729	l1UserTxs, err = historyDB.GetUnforgedL1UserTxs(2)
 730	require.NoError(t, err)
 731	assert.Equal(t, 0, len(l1UserTxs))
 732}
 733
 734func exampleInitSCVars() (*common.RollupVariables, *common.AuctionVariables, *common.WDelayerVariables) {
 735	//nolint:govet
 736	rollup := &common.RollupVariables{
 737		0,
 738		big.NewInt(10),
 739		12,
 740		13,
 741		[5]common.BucketParams{},
 742		false,
 743	}
 744	//nolint:govet
 745	auction := &common.AuctionVariables{
 746		0,
 747		ethCommon.BigToAddress(big.NewInt(2)),
 748		ethCommon.BigToAddress(big.NewInt(3)),
 749		"https://boot.coord.com",
 750		[6]*big.Int{
 751			big.NewInt(1), big.NewInt(2), big.NewInt(3),
 752			big.NewInt(4), big.NewInt(5), big.NewInt(6),
 753		},
 754		0,
 755		2,
 756		4320,
 757		[3]uint16{10, 11, 12},
 758		1000,
 759		20,
 760	}
 761	//nolint:govet
 762	wDelayer := &common.WDelayerVariables{
 763		0,
 764		ethCommon.BigToAddress(big.NewInt(2)),
 765		ethCommon.BigToAddress(big.NewInt(3)),
 766		13,
 767		14,
 768		false,
 769	}
 770	return rollup, auction, wDelayer
 771}
 772
 773func TestSetInitialSCVars(t *testing.T) {
 774	test.WipeDB(historyDB.DB())
 775	_, _, _, err := historyDB.GetSCVars()
 776	assert.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
 777	rollup, auction, wDelayer := exampleInitSCVars()
 778	err = historyDB.SetInitialSCVars(rollup, auction, wDelayer)
 779	require.NoError(t, err)
 780	dbRollup, dbAuction, dbWDelayer, err := historyDB.GetSCVars()
 781	require.NoError(t, err)
 782	require.Equal(t, rollup, dbRollup)
 783	require.Equal(t, auction, dbAuction)
 784	require.Equal(t, wDelayer, dbWDelayer)
 785}
 786
 787func TestSetExtraInfoForgedL1UserTxs(t *testing.T) {
 788	test.WipeDB(historyDB.DB())
 789
 790	set := `
 791		Type: Blockchain
 792
 793		AddToken(1)
 794
 795		CreateAccountDeposit(1) A: 2000
 796		CreateAccountDeposit(1) B: 500
 797		CreateAccountDeposit(1) C: 500
 798
 799		> batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{*}
 800		> block // blockNum=2
 801
 802		> batchL1 // forge defined L1UserTxs{*}
 803		> block // blockNum=3
 804	`
 805
 806	tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
 807	tilCfgExtra := til.ConfigExtra{
 808		BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
 809		CoordUser:     "A",
 810	}
 811	blocks, err := tc.GenerateBlocks(set)
 812	require.NoError(t, err)
 813	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
 814	require.NoError(t, err)
 815	err = tc.FillBlocksForgedL1UserTxs(blocks)
 816	require.NoError(t, err)
 817
 818	// Add only first block so that the L1UserTxs are not marked as forged
 819	for i := range blocks[:1] {
 820		err = historyDB.AddBlockSCData(&blocks[i])
 821		require.NoError(t, err)
 822	}
 823	// Add second batch to trigger the update of the batch_num,
 824	// while avoiding the implicit call of setExtraInfoForgedL1UserTxs
 825	err = historyDB.addBlock(historyDB.dbWrite, &blocks[1].Block)
 826	require.NoError(t, err)
 827	err = historyDB.addBatch(historyDB.dbWrite, &blocks[1].Rollup.Batches[0].Batch)
 828	require.NoError(t, err)
 829	err = historyDB.addAccounts(historyDB.dbWrite, blocks[1].Rollup.Batches[0].CreatedAccounts)
 830	require.NoError(t, err)
 831
 832	// Set the Effective{Amount,DepositAmount} of the L1UserTxs that are forged in the second block
 833	l1Txs := blocks[1].Rollup.Batches[0].L1UserTxs
 834	require.Equal(t, 3, len(l1Txs))
 835	// Change some values to test all cases
 836	l1Txs[1].EffectiveAmount = big.NewInt(0)
 837	l1Txs[2].EffectiveDepositAmount = big.NewInt(0)
 838	l1Txs[2].EffectiveAmount = big.NewInt(0)
 839	err = historyDB.setExtraInfoForgedL1UserTxs(historyDB.dbWrite, l1Txs)
 840	require.NoError(t, err)
 841
 842	dbL1Txs, err := historyDB.GetAllL1UserTxs()
 843	require.NoError(t, err)
 844	for i, tx := range dbL1Txs {
 845		log.Infof("%d %v %v", i, tx.EffectiveAmount, tx.EffectiveDepositAmount)
 846		assert.NotNil(t, tx.EffectiveAmount)
 847		assert.NotNil(t, tx.EffectiveDepositAmount)
 848		switch tx.TxID {
 849		case l1Txs[0].TxID:
 850			assert.Equal(t, l1Txs[0].DepositAmount, tx.EffectiveDepositAmount)
 851			assert.Equal(t, l1Txs[0].Amount, tx.EffectiveAmount)
 852		case l1Txs[1].TxID:
 853			assert.Equal(t, l1Txs[1].DepositAmount, tx.EffectiveDepositAmount)
 854			assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 855		case l1Txs[2].TxID:
 856			assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
 857			assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 858		}
 859	}
 860}
 861
 862func TestUpdateExitTree(t *testing.T) {
 863	test.WipeDB(historyDB.DB())
 864
 865	set := `
 866		Type: Blockchain
 867
 868		AddToken(1)
 869
 870		CreateAccountDeposit(1) C: 2000 // Idx=256+2=258
 871		CreateAccountDeposit(1) D: 500  // Idx=256+3=259
 872
 873		CreateAccountCoordinator(1) A // Idx=256+0=256
 874		CreateAccountCoordinator(1) B // Idx=256+1=257
 875
 876		> batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{5}
 877		> batchL1 // forge defined L1UserTxs{5}, freeze L1UserTxs{nil}
 878		> block // blockNum=2
 879
 880		ForceExit(1) A: 100
 881		ForceExit(1) B: 80
 882
 883		Exit(1) C: 50 (172)
 884		Exit(1) D: 30 (172)
 885
 886		> batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{3}
 887		> batchL1 // forge L1UserTxs{3}, freeze defined L1UserTxs{nil}
 888		> block // blockNum=3
 889
 890		> block // blockNum=4 (empty block)
 891		> block // blockNum=5 (empty block)
 892	`
 893
 894	tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
 895	tilCfgExtra := til.ConfigExtra{
 896		BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
 897		CoordUser:     "A",
 898	}
 899	blocks, err := tc.GenerateBlocks(set)
 900	require.NoError(t, err)
 901	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
 902	require.NoError(t, err)
 903
 904	// Add all blocks except for the last two
 905	for i := range blocks[:len(blocks)-2] {
 906		err = historyDB.AddBlockSCData(&blocks[i])
 907		require.NoError(t, err)
 908	}
 909
 910	// Add withdraws to the second-to-last block, and insert block into the DB
 911	block := &blocks[len(blocks)-2]
 912	require.Equal(t, int64(4), block.Block.Num)
 913	tokenAddr := blocks[0].Rollup.AddedTokens[0].EthAddr
 914	// block.WDelayer.Deposits = append(block.WDelayer.Deposits,
 915	// 	common.WDelayerTransfer{Owner: tc.UsersByIdx[257].Addr, Token: tokenAddr, Amount: big.NewInt(80)}, // 257
 916	// 	common.WDelayerTransfer{Owner: tc.UsersByIdx[259].Addr, Token: tokenAddr, Amount: big.NewInt(15)}, // 259
 917	// )
 918	block.Rollup.Withdrawals = append(block.Rollup.Withdrawals,
 919		common.WithdrawInfo{Idx: 256, NumExitRoot: 4, InstantWithdraw: true},
 920		common.WithdrawInfo{Idx: 257, NumExitRoot: 4, InstantWithdraw: false,
 921			Owner: tc.UsersByIdx[257].Addr, Token: tokenAddr},
 922		common.WithdrawInfo{Idx: 258, NumExitRoot: 3, InstantWithdraw: true},
 923		common.WithdrawInfo{Idx: 259, NumExitRoot: 3, InstantWithdraw: false,
 924			Owner: tc.UsersByIdx[259].Addr, Token: tokenAddr},
 925	)
 926	err = historyDB.addBlock(historyDB.dbWrite, &block.Block)
 927	require.NoError(t, err)
 928
 929	err = historyDB.updateExitTree(historyDB.dbWrite, block.Block.Num,
 930		block.Rollup.Withdrawals, block.WDelayer.Withdrawals)
 931	require.NoError(t, err)
 932
 933	// Check that exits in DB match with the expected values
 934	dbExits, err := historyDB.GetAllExits()
 935	require.NoError(t, err)
 936	assert.Equal(t, 4, len(dbExits))
 937	dbExitsByIdx := make(map[common.Idx]common.ExitInfo)
 938	for _, dbExit := range dbExits {
 939		dbExitsByIdx[dbExit.AccountIdx] = dbExit
 940	}
 941	for _, withdraw := range block.Rollup.Withdrawals {
 942		assert.Equal(t, withdraw.NumExitRoot, dbExitsByIdx[withdraw.Idx].BatchNum)
 943		if withdraw.InstantWithdraw {
 944			assert.Equal(t, &block.Block.Num, dbExitsByIdx[withdraw.Idx].InstantWithdrawn)
 945		} else {
 946			assert.Equal(t, &block.Block.Num, dbExitsByIdx[withdraw.Idx].DelayedWithdrawRequest)
 947		}
 948	}
 949
 950	// Add delayed withdraw to the last block, and insert block into the DB
 951	block = &blocks[len(blocks)-1]
 952	require.Equal(t, int64(5), block.Block.Num)
 953	block.WDelayer.Withdrawals = append(block.WDelayer.Withdrawals,
 954		common.WDelayerTransfer{
 955			Owner:  tc.UsersByIdx[257].Addr,
 956			Token:  tokenAddr,
 957			Amount: big.NewInt(80),
 958		})
 959	err = historyDB.addBlock(historyDB.dbWrite, &block.Block)
 960	require.NoError(t, err)
 961
 962	err = historyDB.updateExitTree(historyDB.dbWrite, block.Block.Num,
 963		block.Rollup.Withdrawals, block.WDelayer.Withdrawals)
 964	require.NoError(t, err)
 965
 966	// Check that delayed withdrawn has been set
 967	dbExits, err = historyDB.GetAllExits()
 968	require.NoError(t, err)
 969	for _, dbExit := range dbExits {
 970		dbExitsByIdx[dbExit.AccountIdx] = dbExit
 971	}
 972	require.Equal(t, &block.Block.Num, dbExitsByIdx[257].DelayedWithdrawn)
 973}
 974
 975func TestGetBestBidCoordinator(t *testing.T) {
 976	test.WipeDB(historyDB.DB())
 977
 978	rollup, auction, wDelayer := exampleInitSCVars()
 979	err := historyDB.SetInitialSCVars(rollup, auction, wDelayer)
 980	require.NoError(t, err)
 981
 982	tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
 983	blocks, err := tc.GenerateBlocks(`
 984		Type: Blockchain
 985		> block // blockNum=2
 986	`)
 987	require.NoError(t, err)
 988	err = historyDB.AddBlockSCData(&blocks[0])
 989	require.NoError(t, err)
 990
 991	coords := []common.Coordinator{
 992		{
 993			Bidder:      ethCommon.BigToAddress(big.NewInt(1)),
 994			Forger:      ethCommon.BigToAddress(big.NewInt(2)),
 995			EthBlockNum: 2,
 996			URL:         "foo",
 997		},
 998		{
 999			Bidder:      ethCommon.BigToAddress(big.NewInt(3)),
1000			Forger:      ethCommon.BigToAddress(big.NewInt(4)),
1001			EthBlockNum: 2,
1002			URL:         "bar",
1003		},
1004	}
1005	err = historyDB.addCoordinators(historyDB.dbWrite, coords)
1006	require.NoError(t, err)
1007
1008	bids := []common.Bid{
1009		{
1010			SlotNum:     10,
1011			BidValue:    big.NewInt(10),
1012			EthBlockNum: 2,
1013			Bidder:      coords[0].Bidder,
1014		},
1015		{
1016			SlotNum:     10,
1017			BidValue:    big.NewInt(20),
1018			EthBlockNum: 2,
1019			Bidder:      coords[1].Bidder,
1020		},
1021	}
1022
1023	err = historyDB.addBids(historyDB.dbWrite, bids)
1024	require.NoError(t, err)
1025
1026	forger10, err := historyDB.GetBestBidCoordinator(10)
1027	require.NoError(t, err)
1028	require.Equal(t, coords[1].Forger, forger10.Forger)
1029	require.Equal(t, coords[1].Bidder, forger10.Bidder)
1030	require.Equal(t, coords[1].URL, forger10.URL)
1031	require.Equal(t, bids[1].SlotNum, forger10.SlotNum)
1032	require.Equal(t, bids[1].BidValue, forger10.BidValue)
1033	for i := range forger10.DefaultSlotSetBid {
1034		require.Equal(t, auction.DefaultSlotSetBid[i], forger10.DefaultSlotSetBid[i])
1035	}
1036
1037	_, err = historyDB.GetBestBidCoordinator(11)
1038	require.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
1039}
1040
1041func TestAddBucketUpdates(t *testing.T) {
1042	test.WipeDB(historyDB.DB())
1043	const fromBlock int64 = 1
1044	const toBlock int64 = 5 + 1
1045	setTestBlocks(fromBlock, toBlock)
1046
1047	bucketUpdates := []common.BucketUpdate{
1048		{
1049			EthBlockNum: 4,
1050			NumBucket:   0,
1051			BlockStamp:  4,
1052			Withdrawals: big.NewInt(123),
1053		},
1054		{
1055			EthBlockNum: 5,
1056			NumBucket:   2,
1057			BlockStamp:  5,
1058			Withdrawals: big.NewInt(42),
1059		},
1060	}
1061	err := historyDB.addBucketUpdates(historyDB.dbWrite, bucketUpdates)
1062	require.NoError(t, err)
1063	dbBucketUpdates, err := historyDB.GetAllBucketUpdates()
1064	require.NoError(t, err)
1065	assert.Equal(t, bucketUpdates, dbBucketUpdates)
1066}
1067
1068func TestAddTokenExchanges(t *testing.T) {
1069	test.WipeDB(historyDB.DB())
1070	const fromBlock int64 = 1
1071	const toBlock int64 = 5 + 1
1072	setTestBlocks(fromBlock, toBlock)
1073
1074	tokenExchanges := []common.TokenExchange{
1075		{
1076			EthBlockNum: 4,
1077			Address:     ethCommon.BigToAddress(big.NewInt(111)),
1078			ValueUSD:    12345,
1079		},
1080		{
1081			EthBlockNum: 5,
1082			Address:     ethCommon.BigToAddress(big.NewInt(222)),
1083			ValueUSD:    67890,
1084		},
1085	}
1086	err := historyDB.addTokenExchanges(historyDB.dbWrite, tokenExchanges)
1087	require.NoError(t, err)
1088	dbTokenExchanges, err := historyDB.GetAllTokenExchanges()
1089	require.NoError(t, err)
1090	assert.Equal(t, tokenExchanges, dbTokenExchanges)
1091}
1092
1093func TestAddEscapeHatchWithdrawals(t *testing.T) {
1094	test.WipeDB(historyDB.DB())
1095	const fromBlock int64 = 1
1096	const toBlock int64 = 5 + 1
1097	setTestBlocks(fromBlock, toBlock)
1098
1099	escapeHatchWithdrawals := []common.WDelayerEscapeHatchWithdrawal{
1100		{
1101			EthBlockNum: 4,
1102			Who:         ethCommon.BigToAddress(big.NewInt(111)),
1103			To:          ethCommon.BigToAddress(big.NewInt(222)),
1104			TokenAddr:   ethCommon.BigToAddress(big.NewInt(333)),
1105			Amount:      big.NewInt(10002),
1106		},
1107		{
1108			EthBlockNum: 5,
1109			Who:         ethCommon.BigToAddress(big.NewInt(444)),
1110			To:          ethCommon.BigToAddress(big.NewInt(555)),
1111			TokenAddr:   ethCommon.BigToAddress(big.NewInt(666)),
1112			Amount:      big.NewInt(20003),
1113		},
1114	}
1115	err := historyDB.addEscapeHatchWithdrawals(historyDB.dbWrite, escapeHatchWithdrawals)
1116	require.NoError(t, err)
1117	dbEscapeHatchWithdrawals, err := historyDB.GetAllEscapeHatchWithdrawals()
1118	require.NoError(t, err)
1119	assert.Equal(t, escapeHatchWithdrawals, dbEscapeHatchWithdrawals)
1120}
1121
1122func TestGetMetricsAPI(t *testing.T) {
1123	test.WipeDB(historyDB.DB())
1124	set := `
1125		Type: Blockchain
1126
1127		AddToken(1)
1128
1129		CreateAccountDeposit(1) A: 1000 // numTx=1
1130		CreateAccountDeposit(1) B: 2000 // numTx=2
1131		CreateAccountDeposit(1) C: 3000 //numTx=3
1132
1133		// block 0 is stored as default in the DB
1134		// block 1 does not exist
1135		> batchL1 // numBatches=1
1136		> batchL1 // numBatches=2
1137		> block // blockNum=2
1138
1139		Transfer(1) C-A : 10 (1) // numTx=4
1140		> batch // numBatches=3
1141		> block // blockNum=3
1142		Transfer(1) B-C : 10 (1) // numTx=5
1143		> batch // numBatches=5
1144		> block // blockNum=4
1145		Transfer(1) A-B : 10 (1) // numTx=6
1146		> batch // numBatches=5
1147		> block // blockNum=5
1148		Transfer(1) A-B : 10 (1) // numTx=7
1149		> batch // numBatches=6
1150		> block // blockNum=6
1151	`
1152
1153	const numBatches int = 6
1154	const numTx int = 7
1155	const blockNum = 6 - 1
1156
1157	tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
1158	tilCfgExtra := til.ConfigExtra{
1159		BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
1160		CoordUser:     "A",
1161	}
1162	blocks, err := tc.GenerateBlocks(set)
1163	require.NoError(t, err)
1164	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
1165	require.NoError(t, err)
1166
1167	// Sanity check
1168	require.Equal(t, blockNum, len(blocks))
1169
1170	// Adding one batch per block
1171	// batch frequency can be chosen
1172	const frequency int = 15
1173
1174	for i := range blocks {
1175		blocks[i].Block.Timestamp = time.Now().Add(-time.Second * time.Duration(frequency*(len(blocks)-i)))
1176		err = historyDB.AddBlockSCData(&blocks[i])
1177		assert.NoError(t, err)
1178	}
1179
1180	res, _, err := historyDB.GetMetricsInternalAPI(common.BatchNum(numBatches))
1181	assert.NoError(t, err)
1182
1183	assert.Equal(t, float64(numTx)/float64(numBatches), res.TransactionsPerBatch)
1184
1185	// Frequency is not exactly the desired one, some decimals may appear
1186	// There is a -2 as time for first and last batch is not taken into account
1187	assert.InEpsilon(t, float64(frequency)*float64(numBatches-2)/float64(numBatches), res.BatchFrequency, 0.01)
1188	assert.InEpsilon(t, float64(numTx)/float64(frequency*blockNum-frequency), res.TransactionsPerSecond, 0.01)
1189	assert.Equal(t, int64(3), res.TokenAccounts)
1190	assert.Equal(t, int64(3), res.Wallets)
1191	// Til does not set fees
1192	assert.Equal(t, float64(0), res.AvgTransactionFee)
1193}
1194
1195func TestGetMetricsAPIMoreThan24Hours(t *testing.T) {
1196	test.WipeDB(historyDB.DB())
1197
1198	testUsersLen := 3
1199	var set []til.Instruction
1200	for user := 0; user < testUsersLen; user++ {
1201		set = append(set, til.Instruction{
1202			Typ:           common.TxTypeCreateAccountDeposit,
1203			TokenID:       common.TokenID(0),
1204			DepositAmount: big.NewInt(1000000),
1205			Amount:        big.NewInt(0),
1206			From:          fmt.Sprintf("User%02d", user),
1207		})
1208		set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1209	}
1210	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1211	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1212	set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1213
1214	// Transfers
1215	const numBlocks int = 30
1216	for x := 0; x < numBlocks; x++ {
1217		set = append(set, til.Instruction{
1218			Typ:           common.TxTypeTransfer,
1219			TokenID:       common.TokenID(0),
1220			DepositAmount: big.NewInt(1),
1221			Amount:        big.NewInt(0),
1222			From:          "User00",
1223			To:            "User01",
1224		})
1225		set = append(set, til.Instruction{Typ: til.TypeNewBatch})
1226		set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1227	}
1228
1229	var chainID uint16 = 0
1230	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
1231	blocks, err := tc.GenerateBlocksFromInstructions(set)
1232	assert.NoError(t, err)
1233
1234	tilCfgExtra := til.ConfigExtra{
1235		CoordUser: "A",
1236	}
1237	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
1238	require.NoError(t, err)
1239
1240	const numBatches int = 2 + numBlocks
1241	const blockNum = 4 + numBlocks
1242
1243	// Sanity check
1244	require.Equal(t, blockNum, len(blocks))
1245
1246	// Adding one batch per block
1247	// batch frequency can be chosen
1248	const blockTime time.Duration = 3600 * time.Second
1249	now := time.Now()
1250	require.NoError(t, err)
1251
1252	for i := range blocks {
1253		blocks[i].Block.Timestamp = now.Add(-time.Duration(len(blocks)-1-i) * blockTime)
1254		err = historyDB.AddBlockSCData(&blocks[i])
1255		assert.NoError(t, err)
1256	}
1257
1258	res, _, err := historyDBWithACC.GetMetricsInternalAPI(common.BatchNum(numBatches))
1259	assert.NoError(t, err)
1260
1261	assert.InEpsilon(t, 1.0, res.TransactionsPerBatch, 0.1)
1262
1263	assert.InEpsilon(t, res.BatchFrequency, float64(blockTime/time.Second), 0.1)
1264	assert.InEpsilon(t, 1.0/float64(blockTime/time.Second), res.TransactionsPerSecond, 0.1)
1265	assert.Equal(t, int64(3), res.TokenAccounts)
1266	assert.Equal(t, int64(3), res.Wallets)
1267	// Til does not set fees
1268	assert.Equal(t, float64(0), res.AvgTransactionFee)
1269}
1270
1271func TestGetMetricsAPIEmpty(t *testing.T) {
1272	test.WipeDB(historyDB.DB())
1273	_, _, err := historyDBWithACC.GetMetricsInternalAPI(0)
1274	assert.NoError(t, err)
1275}
1276
1277func TestGetLastL1TxsNum(t *testing.T) {
1278	test.WipeDB(historyDB.DB())
1279	_, err := historyDB.GetLastL1TxsNum()
1280	assert.NoError(t, err)
1281}
1282
1283func TestGetLastTxsPosition(t *testing.T) {
1284	test.WipeDB(historyDB.DB())
1285	_, err := historyDB.GetLastTxsPosition(0)
1286	assert.Equal(t, sql.ErrNoRows.Error(), err.Error())
1287}
1288
1289func TestGetFirstBatchBlockNumBySlot(t *testing.T) {
1290	test.WipeDB(historyDB.DB())
1291
1292	set := `
1293		Type: Blockchain
1294
1295		// Slot = 0
1296
1297		> block // 2
1298		> block // 3
1299		> block // 4
1300		> block // 5
1301
1302		// Slot = 1
1303
1304		> block // 6
1305		> block // 7
1306		> batch
1307		> block // 8
1308		> block // 9
1309
1310		// Slot = 2
1311
1312		> batch
1313		> block // 10
1314		> block // 11
1315		> block // 12
1316		> block // 13
1317
1318	`
1319	tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
1320	blocks, err := tc.GenerateBlocks(set)
1321	assert.NoError(t, err)
1322
1323	tilCfgExtra := til.ConfigExtra{
1324		CoordUser: "A",
1325	}
1326	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
1327	require.NoError(t, err)
1328
1329	for i := range blocks {
1330		for j := range blocks[i].Rollup.Batches {
1331			blocks[i].Rollup.Batches[j].Batch.SlotNum = int64(i) / 4
1332		}
1333	}
1334
1335	// Add all blocks
1336	for i := range blocks {
1337		err = historyDB.AddBlockSCData(&blocks[i])
1338		require.NoError(t, err)
1339	}
1340
1341	_, err = historyDB.GetFirstBatchBlockNumBySlot(0)
1342	require.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
1343
1344	bn1, err := historyDB.GetFirstBatchBlockNumBySlot(1)
1345	require.NoError(t, err)
1346	assert.Equal(t, int64(8), bn1)
1347
1348	bn2, err := historyDB.GetFirstBatchBlockNumBySlot(2)
1349	require.NoError(t, err)
1350	assert.Equal(t, int64(10), bn2)
1351}
1352
1353func TestTxItemID(t *testing.T) {
1354	test.WipeDB(historyDB.DB())
1355	testUsersLen := 10
1356	var set []til.Instruction
1357	for user := 0; user < testUsersLen; user++ {
1358		set = append(set, til.Instruction{
1359			Typ:           common.TxTypeCreateAccountDeposit,
1360			TokenID:       common.TokenID(0),
1361			DepositAmount: big.NewInt(1000000),
1362			Amount:        big.NewInt(0),
1363			From:          fmt.Sprintf("User%02d", user),
1364		})
1365		set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1366	}
1367	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1368	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1369	set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1370	for user := 0; user < testUsersLen; user++ {
1371		set = append(set, til.Instruction{
1372			Typ:           common.TxTypeDeposit,
1373			TokenID:       common.TokenID(0),
1374			DepositAmount: big.NewInt(100000),
1375			Amount:        big.NewInt(0),
1376			From:          fmt.Sprintf("User%02d", user),
1377		})
1378		set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1379	}
1380	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1381	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1382	set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1383	for user := 0; user < testUsersLen; user++ {
1384		set = append(set, til.Instruction{
1385			Typ:           common.TxTypeDepositTransfer,
1386			TokenID:       common.TokenID(0),
1387			DepositAmount: big.NewInt(10000 * int64(user+1)),
1388			Amount:        big.NewInt(1000 * int64(user+1)),
1389			From:          fmt.Sprintf("User%02d", user),
1390			To:            fmt.Sprintf("User%02d", (user+1)%testUsersLen),
1391		})
1392		set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1393	}
1394	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1395	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1396	set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1397	for user := 0; user < testUsersLen; user++ {
1398		set = append(set, til.Instruction{
1399			Typ:           common.TxTypeForceTransfer,
1400			TokenID:       common.TokenID(0),
1401			Amount:        big.NewInt(100 * int64(user+1)),
1402			DepositAmount: big.NewInt(0),
1403			From:          fmt.Sprintf("User%02d", user),
1404			To:            fmt.Sprintf("User%02d", (user+1)%testUsersLen),
1405		})
1406		set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1407	}
1408	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1409	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1410	set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1411	for user := 0; user < testUsersLen; user++ {
1412		set = append(set, til.Instruction{
1413			Typ:           common.TxTypeForceExit,
1414			TokenID:       common.TokenID(0),
1415			Amount:        big.NewInt(10 * int64(user+1)),
1416			DepositAmount: big.NewInt(0),
1417			From:          fmt.Sprintf("User%02d", user),
1418		})
1419		set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1420	}
1421	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1422	set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
1423	set = append(set, til.Instruction{Typ: til.TypeNewBlock})
1424	var chainID uint16 = 0
1425	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
1426	blocks, err := tc.GenerateBlocksFromInstructions(set)
1427	assert.NoError(t, err)
1428
1429	tilCfgExtra := til.ConfigExtra{
1430		CoordUser: "A",
1431	}
1432	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
1433	require.NoError(t, err)
1434
1435	// Add all blocks
1436	for i := range blocks {
1437		err = historyDB.AddBlockSCData(&blocks[i])
1438		require.NoError(t, err)
1439	}
1440
1441	txs, err := historyDB.GetAllL1UserTxs()
1442	require.NoError(t, err)
1443	position := 0
1444	for _, tx := range txs {
1445		if tx.Position == 0 {
1446			position = 0
1447		}
1448		assert.Equal(t, position, tx.Position)
1449		position++
1450	}
1451}
1452
1453// setTestBlocks WARNING: this will delete the blocks and recreate them
1454func setTestBlocks(from, to int64) []common.Block {
1455	test.WipeDB(historyDB.DB())
1456	blocks := test.GenBlocks(from, to)
1457	if err := historyDB.AddBlocks(blocks); err != nil {
1458		panic(err)
1459	}
1460	return blocks
1461}
1462
1463func TestNodeInfo(t *testing.T) {
1464	test.WipeDB(historyDB.DB())
1465
1466	err := historyDB.SetStateInternalAPI(&StateAPI{})
1467	require.NoError(t, err)
1468
1469	clientSetup := test.NewClientSetupExample()
1470	constants := &Constants{
1471		SCConsts: common.SCConsts{
1472			Rollup:   *clientSetup.RollupConstants,
1473			Auction:  *clientSetup.AuctionConstants,
1474			WDelayer: *clientSetup.WDelayerConstants,
1475		},
1476		ChainID:       42,
1477		HermezAddress: clientSetup.AuctionConstants.HermezRollup,
1478	}
1479	err = historyDB.SetConstants(constants)
1480	require.NoError(t, err)
1481
1482	// Test parameters
1483	var f64 float64 = 1.2
1484	var i64 int64 = 8888
1485	addr := ethCommon.HexToAddress("0x1234")
1486	hash := ethCommon.HexToHash("0x5678")
1487	stateAPI := &StateAPI{
1488		NodePublicInfo: NodePublicInfo{
1489			ForgeDelay: 3.1,
1490		},
1491		Network: NetworkAPI{
1492			LastEthBlock:  12,
1493			LastSyncBlock: 34,
1494			LastBatch: &BatchAPI{
1495				ItemID:       123,
1496				BatchNum:     456,
1497				EthBlockNum:  789,
1498				EthBlockHash: hash,
1499				Timestamp:    time.Now(),
1500				ForgerAddr:   addr,
1501				// CollectedFeesDB: map[common.TokenID]*big.Int{
1502				// 	0: big.NewInt(11111),
1503				// 	1: big.NewInt(21111),
1504				// 	2: big.NewInt(31111),
1505				// },
1506				CollectedFeesAPI: apitypes.CollectedFeesAPI(map[common.TokenID]apitypes.BigIntStr{
1507					0: apitypes.BigIntStr("11111"),
1508					1: apitypes.BigIntStr("21111"),
1509					2: apitypes.BigIntStr("31111"),
1510				}),
1511				TotalFeesUSD:  &f64,
1512				StateRoot:     apitypes.BigIntStr("1234"),
1513				NumAccounts:   11,
1514				ExitRoot:      apitypes.BigIntStr("5678"),
1515				ForgeL1TxsNum: &i64,
1516				SlotNum:       44,
1517				ForgedTxs:     23,
1518				TotalItems:    0,
1519				FirstItem:     0,
1520				LastItem:      0,
1521			},
1522			CurrentSlot: 22,
1523			NextForgers: []NextForgerAPI{
1524				{
1525					Coordinator: CoordinatorAPI{
1526						ItemID:      111,
1527						Bidder:      addr,
1528						Forger:      addr,
1529						EthBlockNum: 566,
1530						URL:         "asd",
1531						TotalItems:  0,
1532						FirstItem:   0,
1533						LastItem:    0,
1534					},
1535					Period: Period{
1536						SlotNum:       33,
1537						FromBlock:     55,
1538						ToBlock:       66,
1539						FromTimestamp: time.Now(),
1540						ToTimestamp:   time.Now(),
1541					},
1542				},
1543			},
1544		},
1545		Metrics: MetricsAPI{
1546			TransactionsPerBatch: 1.1,
1547			TokenAccounts:        42,
1548		},
1549		Rollup:            *NewRollupVariablesAPI(clientSetup.RollupVariables),
1550		Auction:           *NewAuctionVariablesAPI(clientSetup.AuctionVariables),
1551		WithdrawalDelayer: *clientSetup.WDelayerVariables,
1552		RecommendedFee: common.RecommendedFee{
1553			ExistingAccount: 0.15,
1554		},
1555	}
1556	err = historyDB.SetStateInternalAPI(stateAPI)
1557	require.NoError(t, err)
1558
1559	nodeConfig := &NodeConfig{
1560		MaxPoolTxs: 123,
1561		MinFeeUSD:  0.5,
1562	}
1563	err = historyDB.SetNodeConfig(nodeConfig)
1564	require.NoError(t, err)
1565
1566	dbConstants, err := historyDB.GetConstants()
1567	require.NoError(t, err)
1568	assert.Equal(t, constants, dbConstants)
1569
1570	dbNodeConfig, err := historyDB.GetNodeConfig()
1571	require.NoError(t, err)
1572	assert.Equal(t, nodeConfig, dbNodeConfig)
1573
1574	dbStateAPI, err := historyDB.getStateAPI(historyDB.dbRead)
1575	require.NoError(t, err)
1576	assert.Equal(t, stateAPI.Network.LastBatch.Timestamp.Unix(),
1577		dbStateAPI.Network.LastBatch.Timestamp.Unix())
1578	dbStateAPI.Network.LastBatch.Timestamp = stateAPI.Network.LastBatch.Timestamp
1579	assert.Equal(t, stateAPI.Network.NextForgers[0].Period.FromTimestamp.Unix(),
1580		dbStateAPI.Network.NextForgers[0].Period.FromTimestamp.Unix())
1581	dbStateAPI.Network.NextForgers[0].Period.FromTimestamp = stateAPI.Network.NextForgers[0].Period.FromTimestamp
1582	assert.Equal(t, stateAPI.Network.NextForgers[0].Period.ToTimestamp.Unix(),
1583		dbStateAPI.Network.NextForgers[0].Period.ToTimestamp.Unix())
1584	dbStateAPI.Network.NextForgers[0].Period.ToTimestamp = stateAPI.Network.NextForgers[0].Period.ToTimestamp
1585	assert.Equal(t, stateAPI, dbStateAPI)
1586}