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