hermez-node/synchronizer/synchronizer_test.go
synchronizer/synchronizer_test.goRaw
1package synchronizer
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "io/ioutil"
8 "math/big"
9 "os"
10 "sort"
11 "testing"
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/db/historydb"
17 "github.com/hermeznetwork/hermez-node/db/statedb"
18 "github.com/hermeznetwork/hermez-node/eth"
19 "github.com/hermeznetwork/hermez-node/test"
20 "github.com/hermeznetwork/hermez-node/test/til"
21 "github.com/jinzhu/copier"
22 "github.com/stretchr/testify/assert"
23 "github.com/stretchr/testify/require"
24)
25
26var tokenConsts = map[common.TokenID]eth.ERC20Consts{}
27
28type timer struct {
29 time int64
30}
31
32func (t *timer) Time() int64 {
33 currentTime := t.time
34 t.time++
35 return currentTime
36}
37
38func accountsCmp(accounts []common.Account) func(i, j int) bool {
39 return func(i, j int) bool { return accounts[i].Idx < accounts[j].Idx }
40}
41
42// Check Sync output and HistoryDB state against expected values generated by
43// til
44func checkSyncBlock(t *testing.T, s *Synchronizer, blockNum int, block, syncBlock *common.BlockData) {
45 // Check Blocks
46 dbBlocks, err := s.historyDB.GetAllBlocks()
47 require.Nil(t, err)
48 dbBlocks = dbBlocks[1:] // ignore block 0, added by default in the DB
49 assert.Equal(t, blockNum, len(dbBlocks))
50 assert.Equal(t, int64(blockNum), dbBlocks[blockNum-1].EthBlockNum)
51 assert.NotEqual(t, dbBlocks[blockNum-1].Hash, dbBlocks[blockNum-2].Hash)
52 assert.Greater(t, dbBlocks[blockNum-1].Timestamp.Unix(), dbBlocks[blockNum-2].Timestamp.Unix())
53
54 // Check Tokens
55 assert.Equal(t, len(block.Rollup.AddedTokens), len(syncBlock.Rollup.AddedTokens))
56 dbTokens, err := s.historyDB.GetAllTokens()
57 require.Nil(t, err)
58 dbTokens = dbTokens[1:] // ignore token 0, added by default in the DB
59 for i, token := range block.Rollup.AddedTokens {
60 dbToken := dbTokens[i]
61 syncToken := syncBlock.Rollup.AddedTokens[i]
62
63 assert.Equal(t, block.Block.EthBlockNum, syncToken.EthBlockNum)
64 assert.Equal(t, token.TokenID, syncToken.TokenID)
65 assert.Equal(t, token.EthAddr, syncToken.EthAddr)
66 tokenConst := tokenConsts[token.TokenID]
67 assert.Equal(t, tokenConst.Name, syncToken.Name)
68 assert.Equal(t, tokenConst.Symbol, syncToken.Symbol)
69 assert.Equal(t, tokenConst.Decimals, syncToken.Decimals)
70
71 var tokenCpy historydb.TokenWithUSD
72 //nolint:gosec
73 require.Nil(t, copier.Copy(&tokenCpy, &token)) // copy common.Token to historydb.TokenWithUSD
74 require.Nil(t, copier.Copy(&tokenCpy, &tokenConst)) // copy common.Token to historydb.TokenWithUSD
75 tokenCpy.ItemID = dbToken.ItemID // we don't care about ItemID
76 assert.Equal(t, tokenCpy, dbToken)
77 }
78
79 // Check L1UserTxs
80 assert.Equal(t, len(block.Rollup.L1UserTxs), len(syncBlock.Rollup.L1UserTxs))
81 dbL1UserTxs, err := s.historyDB.GetAllL1UserTxs()
82 require.Nil(t, err)
83 // Ignore BatchNum in syncBlock.L1UserTxs because this value is set by the HistoryDB
84 for i := range syncBlock.Rollup.L1UserTxs {
85 syncBlock.Rollup.L1UserTxs[i].BatchNum = block.Rollup.L1UserTxs[i].BatchNum
86 }
87 assert.Equal(t, block.Rollup.L1UserTxs, syncBlock.Rollup.L1UserTxs)
88 for _, tx := range block.Rollup.L1UserTxs {
89 var dbTx *common.L1Tx
90 // Find tx in DB output
91 for _, _dbTx := range dbL1UserTxs {
92 if *tx.ToForgeL1TxsNum == *_dbTx.ToForgeL1TxsNum &&
93 tx.Position == _dbTx.Position {
94 dbTx = new(common.L1Tx)
95 *dbTx = _dbTx
96 break
97 }
98 }
99 assert.Equal(t, &tx, dbTx) //nolint:gosec
100 }
101
102 // Check Batches
103 assert.Equal(t, len(block.Rollup.Batches), len(syncBlock.Rollup.Batches))
104 dbBatches, err := s.historyDB.GetAllBatches()
105 require.Nil(t, err)
106
107 dbL1CoordinatorTxs, err := s.historyDB.GetAllL1CoordinatorTxs()
108 require.Nil(t, err)
109 dbL2Txs, err := s.historyDB.GetAllL2Txs()
110 require.Nil(t, err)
111 dbExits, err := s.historyDB.GetAllExits()
112 require.Nil(t, err)
113 // dbL1CoordinatorTxs := []common.L1Tx{}
114 for i, batch := range block.Rollup.Batches {
115 var dbBatch *common.Batch
116 // Find batch in DB output
117 for _, _dbBatch := range dbBatches {
118 if batch.Batch.BatchNum == _dbBatch.BatchNum {
119 dbBatch = new(common.Batch)
120 *dbBatch = _dbBatch
121 break
122 }
123 }
124 syncBatch := syncBlock.Rollup.Batches[i]
125
126 // We don't care about TotalFeesUSD. Use the syncBatch that
127 // has a TotalFeesUSD inserted by the HistoryDB
128 batch.Batch.TotalFeesUSD = syncBatch.Batch.TotalFeesUSD
129 assert.Equal(t, batch.CreatedAccounts, syncBatch.CreatedAccounts)
130 batch.Batch.NumAccounts = len(batch.CreatedAccounts)
131
132 // Test field by field to facilitate debugging of errors
133 assert.Equal(t, batch.L1CoordinatorTxs, syncBatch.L1CoordinatorTxs)
134 assert.Equal(t, batch.L2Txs, syncBatch.L2Txs)
135 // In exit tree, we only check AccountIdx and Balance, because
136 // it's what we have precomputed before.
137 for j := range batch.ExitTree {
138 exit := &batch.ExitTree[j]
139 assert.Equal(t, exit.AccountIdx, syncBatch.ExitTree[j].AccountIdx)
140 assert.Equal(t, exit.Balance, syncBatch.ExitTree[j].Balance)
141 *exit = syncBatch.ExitTree[j]
142 }
143 assert.Equal(t, batch.Batch, syncBatch.Batch)
144 assert.Equal(t, batch, syncBatch)
145 assert.Equal(t, &batch.Batch, dbBatch) //nolint:gosec
146
147 // Check L1CoordinatorTxs from DB
148 for _, tx := range batch.L1CoordinatorTxs {
149 var dbTx *common.L1Tx
150 // Find tx in DB output
151 for _, _dbTx := range dbL1CoordinatorTxs {
152 if *tx.BatchNum == *_dbTx.BatchNum &&
153 tx.Position == _dbTx.Position {
154 dbTx = new(common.L1Tx)
155 *dbTx = _dbTx
156 break
157 }
158 }
159 assert.Equal(t, &tx, dbTx) //nolint:gosec
160 }
161
162 // Check L2Txs from DB
163 for _, tx := range batch.L2Txs {
164 var dbTx *common.L2Tx
165 // Find tx in DB output
166 for _, _dbTx := range dbL2Txs {
167 if tx.BatchNum == _dbTx.BatchNum &&
168 tx.Position == _dbTx.Position {
169 dbTx = new(common.L2Tx)
170 *dbTx = _dbTx
171 break
172 }
173 }
174 assert.Equal(t, &tx, dbTx) //nolint:gosec
175 }
176
177 // Check Exits from DB
178 for _, exit := range batch.ExitTree {
179 var dbExit *common.ExitInfo
180 // Find exit in DB output
181 for _, _dbExit := range dbExits {
182 if exit.BatchNum == _dbExit.BatchNum &&
183 exit.AccountIdx == _dbExit.AccountIdx {
184 dbExit = new(common.ExitInfo)
185 *dbExit = _dbExit
186 break
187 }
188 }
189 // Compare MerkleProof in JSON because unmarshaled 0
190 // big.Int leaves the internal big.Int array at nil,
191 // and gives trouble when comparing big.Int with
192 // internal big.Int array != nil but empty.
193 mtp, err := json.Marshal(exit.MerkleProof)
194 require.Nil(t, err)
195 dbMtp, err := json.Marshal(dbExit.MerkleProof)
196 require.Nil(t, err)
197 assert.Equal(t, mtp, dbMtp)
198 dbExit.MerkleProof = exit.MerkleProof
199 assert.Equal(t, &exit, dbExit) //nolint:gosec
200 }
201 }
202
203 // Compare accounts from HistoryDB with StateDB (they should match)
204 dbAccounts, err := s.historyDB.GetAllAccounts()
205 require.Nil(t, err)
206 sdbAccounts, err := s.stateDB.GetAccounts()
207 require.Nil(t, err)
208 assertEqualAccountsHistoryDBStateDB(t, dbAccounts, sdbAccounts)
209}
210
211func assertEqualAccountsHistoryDBStateDB(t *testing.T, hdbAccs, sdbAccs []common.Account) {
212 assert.Equal(t, len(hdbAccs), len(sdbAccs))
213 sort.SliceStable(hdbAccs, accountsCmp(hdbAccs))
214 sort.SliceStable(sdbAccs, accountsCmp(sdbAccs))
215 for i := range hdbAccs {
216 hdbAcc := hdbAccs[i]
217 sdbAcc := sdbAccs[i]
218 assert.Equal(t, hdbAcc.Idx, sdbAcc.Idx)
219 assert.Equal(t, hdbAcc.TokenID, sdbAcc.TokenID)
220 assert.Equal(t, hdbAcc.EthAddr, sdbAcc.EthAddr)
221 assert.Equal(t, hdbAcc.PublicKey, sdbAcc.PublicKey)
222 }
223}
224
225// ethAddTokens adds the tokens from the blocks to the blockchain
226func ethAddTokens(blocks []common.BlockData, client *test.Client) {
227 for _, block := range blocks {
228 for _, token := range block.Rollup.AddedTokens {
229 consts := eth.ERC20Consts{
230 Name: fmt.Sprintf("Token %d", token.TokenID),
231 Symbol: fmt.Sprintf("TK%d", token.TokenID),
232 Decimals: 18,
233 }
234 tokenConsts[token.TokenID] = consts
235 client.CtlAddERC20(token.EthAddr, consts)
236 }
237 }
238}
239
240// ethAddBlocks adds block data to the smart contracts
241func ethAddBlocks(t *testing.T, blocks []common.BlockData,
242 client *test.Client, clientSetup *test.ClientSetup) {
243 for _, block := range blocks {
244 for _, token := range block.Rollup.AddedTokens {
245 _, err := client.RollupAddTokenSimple(token.EthAddr, clientSetup.RollupVariables.FeeAddToken)
246 require.Nil(t, err)
247 }
248 for _, tx := range block.Rollup.L1UserTxs {
249 client.CtlSetAddr(tx.FromEthAddr)
250 _, err := client.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.LoadAmount, tx.Amount,
251 uint32(tx.TokenID), int64(tx.ToIdx))
252 require.Nil(t, err)
253 }
254 client.CtlSetAddr(clientSetup.AuctionVariables.BootCoordinator)
255 for _, batch := range block.Rollup.Batches {
256 _, err := client.RollupForgeBatch(ð.RollupForgeBatchArgs{
257 NewLastIdx: batch.Batch.LastIdx,
258 NewStRoot: batch.Batch.StateRoot,
259 NewExitRoot: batch.Batch.ExitRoot,
260 L1CoordinatorTxs: batch.L1CoordinatorTxs,
261 L1CoordinatorTxsAuths: [][]byte{}, // Intentionally empty
262 L2TxsData: batch.L2Txs,
263 FeeIdxCoordinator: batch.Batch.FeeIdxsCoordinator,
264 // Circuit selector
265 VerifierIdx: 0, // Intentionally empty
266 L1Batch: batch.L1Batch,
267 ProofA: [2]*big.Int{}, // Intentionally empty
268 ProofB: [2][2]*big.Int{}, // Intentionally empty
269 ProofC: [2]*big.Int{}, // Intentionally empty
270 })
271 require.Nil(t, err)
272 }
273 // Mine block and sync
274 client.CtlMineBlock()
275 }
276}
277
278func TestSync(t *testing.T) {
279 //
280 // Setup
281 //
282
283 ctx := context.Background()
284 // Int State DB
285 dir, err := ioutil.TempDir("", "tmpdb")
286 require.Nil(t, err)
287 defer assert.Nil(t, os.RemoveAll(dir))
288
289 stateDB, err := statedb.NewStateDB(dir, statedb.TypeSynchronizer, 32)
290 assert.Nil(t, err)
291
292 // Init History DB
293 pass := os.Getenv("POSTGRES_PASS")
294 db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
295 require.Nil(t, err)
296 historyDB := historydb.NewHistoryDB(db)
297 // Clear DB
298 test.WipeDB(historyDB.DB())
299
300 // Init eth client
301 var timer timer
302 clientSetup := test.NewClientSetupExample()
303 bootCoordAddr := clientSetup.AuctionVariables.BootCoordinator
304 client := test.NewClient(true, &timer, ðCommon.Address{}, clientSetup)
305
306 // Create Synchronizer
307 s, err := NewSynchronizer(client, historyDB, stateDB, Config{
308 StartBlockNum: ConfigStartBlockNum{
309 Rollup: 1,
310 Auction: 1,
311 WDelayer: 1,
312 },
313 InitialVariables: SCVariables{
314 Rollup: *clientSetup.RollupVariables,
315 Auction: *clientSetup.AuctionVariables,
316 WDelayer: *clientSetup.WDelayerVariables,
317 },
318 })
319 require.Nil(t, err)
320
321 //
322 // First Sync from an initial state
323 //
324
325 // Test Sync for rollup genesis block
326 syncBlock, discards, err := s.Sync2(ctx, nil)
327 require.Nil(t, err)
328 require.Nil(t, discards)
329 require.NotNil(t, syncBlock)
330 assert.Equal(t, int64(1), syncBlock.Block.EthBlockNum)
331 dbBlocks, err := s.historyDB.GetAllBlocks()
332 require.Nil(t, err)
333 assert.Equal(t, 2, len(dbBlocks))
334 assert.Equal(t, int64(1), dbBlocks[1].EthBlockNum)
335
336 // Sync again and expect no new blocks
337 syncBlock, discards, err = s.Sync2(ctx, nil)
338 require.Nil(t, err)
339 require.Nil(t, discards)
340 require.Nil(t, syncBlock)
341
342 //
343 // Generate blockchain and smart contract data, and fill the test smart contracts
344 //
345
346 // Generate blockchain data with til
347 set1 := `
348 Type: Blockchain
349
350 AddToken(1)
351 AddToken(2)
352 AddToken(3)
353
354 CreateAccountDeposit(1) C: 2000 // Idx=256+2=258
355 CreateAccountDeposit(2) A: 2000 // Idx=256+3=259
356 CreateAccountDeposit(1) D: 500 // Idx=256+4=260
357 CreateAccountDeposit(2) B: 500 // Idx=256+5=261
358 CreateAccountDeposit(2) C: 500 // Idx=256+6=262
359
360 CreateAccountCoordinator(1) A // Idx=256+0=256
361 CreateAccountCoordinator(1) B // Idx=256+1=257
362
363 > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{5}
364 > batchL1 // forge defined L1UserTxs{5}, freeze L1UserTxs{nil}
365 > block // blockNum=2
366
367 CreateAccountDepositTransfer(1) E-A: 1000, 200 // Idx=256+7=263
368 ForceExit(1) A: 100
369 ForceExit(1) B: 80
370 ForceTransfer(1) A-D: 100
371
372 Transfer(1) C-A: 100 (200)
373 Exit(1) C: 50 (200)
374 Exit(1) D: 30 (200)
375
376 > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{3}
377 > batchL1 // forge L1UserTxs{3}, freeze defined L1UserTxs{nil}
378 > block // blockNum=3
379 `
380 tc := til.NewContext(common.RollupConstMaxL1UserTx)
381 tilCfgExtra := til.ConfigExtra{
382 BootCoordAddr: bootCoordAddr,
383 CoordUser: "A",
384 }
385 blocks, err := tc.GenerateBlocks(set1)
386 require.Nil(t, err)
387 // Sanity check
388 require.Equal(t, 2, len(blocks))
389 // blocks 0 (blockNum=2)
390 i := 0
391 require.Equal(t, 2, int(blocks[i].Block.EthBlockNum))
392 require.Equal(t, 3, len(blocks[i].Rollup.AddedTokens))
393 require.Equal(t, 5, len(blocks[i].Rollup.L1UserTxs))
394 require.Equal(t, 2, len(blocks[i].Rollup.Batches))
395 require.Equal(t, 2, len(blocks[i].Rollup.Batches[0].L1CoordinatorTxs))
396 // blocks 1 (blockNum=3)
397 i = 1
398 require.Equal(t, 3, int(blocks[i].Block.EthBlockNum))
399 require.Equal(t, 4, len(blocks[i].Rollup.L1UserTxs))
400 require.Equal(t, 2, len(blocks[i].Rollup.Batches))
401 require.Equal(t, 3, len(blocks[i].Rollup.Batches[0].L2Txs))
402
403 // Generate extra required data
404 ethAddTokens(blocks, client)
405
406 err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
407 assert.Nil(t, err)
408 tc.FillBlocksL1UserTxsBatchNum(blocks)
409
410 // Add block data to the smart contracts
411 ethAddBlocks(t, blocks, client, clientSetup)
412
413 //
414 // Sync to synchronize the current state from the test smart contracts,
415 // and check the outcome
416 //
417
418 // Block 2
419
420 syncBlock, discards, err = s.Sync2(ctx, nil)
421 require.Nil(t, err)
422 require.Nil(t, discards)
423 require.NotNil(t, syncBlock)
424 assert.Equal(t, int64(2), syncBlock.Block.EthBlockNum)
425
426 checkSyncBlock(t, s, 2, &blocks[0], syncBlock)
427
428 // Block 3
429
430 syncBlock, discards, err = s.Sync2(ctx, nil)
431 require.Nil(t, err)
432 require.Nil(t, discards)
433 require.NotNil(t, syncBlock)
434 assert.Equal(t, int64(3), syncBlock.Block.EthBlockNum)
435
436 checkSyncBlock(t, s, 3, &blocks[1], syncBlock)
437
438 // Block 4
439 // Generate 2 withdraws manually
440 _, err = client.RollupWithdrawMerkleProof(tc.Users["A"].BJJ.Public(), 1, 4, 256, big.NewInt(100), []*big.Int{}, true)
441 require.Nil(t, err)
442 _, err = client.RollupWithdrawMerkleProof(tc.Users["C"].BJJ.Public(), 1, 3, 258, big.NewInt(50), []*big.Int{}, false)
443 require.Nil(t, err)
444 client.CtlMineBlock()
445
446 syncBlock, discards, err = s.Sync2(ctx, nil)
447 require.Nil(t, err)
448 require.Nil(t, discards)
449 require.NotNil(t, syncBlock)
450 assert.Equal(t, int64(4), syncBlock.Block.EthBlockNum)
451 dbExits, err := s.historyDB.GetAllExits()
452 require.Nil(t, err)
453 foundA1, foundC1 := false, false
454 for _, exit := range dbExits {
455 if exit.AccountIdx == 256 && exit.BatchNum == 4 {
456 foundA1 = true
457 assert.Equal(t, int64(4), *exit.InstantWithdrawn)
458 }
459 if exit.AccountIdx == 258 && exit.BatchNum == 3 {
460 foundC1 = true
461 assert.Equal(t, int64(4), *exit.DelayedWithdrawRequest)
462 }
463 }
464 assert.True(t, foundA1)
465 assert.True(t, foundC1)
466
467 // Block 5
468 // Update variables manually
469 rollupVars, auctionVars, wDelayerVars, err := s.historyDB.GetSCVars()
470 require.Nil(t, err)
471 rollupVars.ForgeL1L2BatchTimeout = 42
472 _, err = client.RollupUpdateForgeL1L2BatchTimeout(rollupVars.ForgeL1L2BatchTimeout)
473 require.Nil(t, err)
474
475 auctionVars.OpenAuctionSlots = 17
476 _, err = client.AuctionSetOpenAuctionSlots(auctionVars.OpenAuctionSlots)
477 require.Nil(t, err)
478
479 wDelayerVars.WithdrawalDelay = 99
480 _, err = client.WDelayerChangeWithdrawalDelay(wDelayerVars.WithdrawalDelay)
481 require.Nil(t, err)
482
483 client.CtlMineBlock()
484
485 syncBlock, discards, err = s.Sync2(ctx, nil)
486 require.Nil(t, err)
487 require.Nil(t, discards)
488 require.NotNil(t, syncBlock)
489 assert.Equal(t, int64(5), syncBlock.Block.EthBlockNum)
490
491 dbRollupVars, dbAuctionVars, dbWDelayerVars, err := s.historyDB.GetSCVars()
492 require.Nil(t, err)
493 // Set EthBlockNum for Vars to the blockNum in which they were updated (should be 5)
494 rollupVars.EthBlockNum = syncBlock.Block.EthBlockNum
495 auctionVars.EthBlockNum = syncBlock.Block.EthBlockNum
496 wDelayerVars.EthBlockNum = syncBlock.Block.EthBlockNum
497 assert.Equal(t, rollupVars, dbRollupVars)
498 assert.Equal(t, auctionVars, dbAuctionVars)
499 assert.Equal(t, wDelayerVars, dbWDelayerVars)
500
501 //
502 // Reorg test
503 //
504
505 // Redo blocks 2-5 (as a reorg) only leaving:
506 // - 2 create account transactions
507 // - 2 add tokens
508 // We add a 6th block so that the synchronizer can detect the reorg
509 set2 := `
510 Type: Blockchain
511
512 AddToken(1)
513 AddToken(2)
514
515 CreateAccountDeposit(1) C: 2000 // Idx=256+1=257
516
517 CreateAccountCoordinator(1) A // Idx=256+0=256
518
519 > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{1}
520 > batchL1 // forge defined L1UserTxs{1}, freeze L1UserTxs{nil}
521 > block // blockNum=2
522 > block // blockNum=3
523 > block // blockNum=4
524 > block // blockNum=5
525 > block // blockNum=6
526 `
527 tc = til.NewContext(common.RollupConstMaxL1UserTx)
528 tilCfgExtra = til.ConfigExtra{
529 BootCoordAddr: bootCoordAddr,
530 CoordUser: "A",
531 }
532 blocks, err = tc.GenerateBlocks(set2)
533 require.Nil(t, err)
534
535 for i := 0; i < 4; i++ {
536 client.CtlRollback()
537 }
538 blockNum := client.CtlLastBlock()
539 require.Equal(t, int64(1), blockNum)
540
541 // Generate extra required data
542 ethAddTokens(blocks, client)
543
544 err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
545 assert.Nil(t, err)
546 tc.FillBlocksL1UserTxsBatchNum(blocks)
547
548 // Add block data to the smart contracts
549 ethAddBlocks(t, blocks, client, clientSetup)
550
551 // First sync detects the reorg and discards 4 blocks
552 syncBlock, discards, err = s.Sync2(ctx, nil)
553 require.Nil(t, err)
554 expetedDiscards := int64(4)
555 require.Equal(t, &expetedDiscards, discards)
556 require.Nil(t, syncBlock)
557
558 // At this point, the DB only has data up to block 1
559 dbBlock, err := s.historyDB.GetLastBlock()
560 require.Nil(t, err)
561 assert.Equal(t, int64(1), dbBlock.EthBlockNum)
562
563 // Accounts in HistoryDB and StateDB must be empty
564 dbAccounts, err := s.historyDB.GetAllAccounts()
565 require.Nil(t, err)
566 sdbAccounts, err := s.stateDB.GetAccounts()
567 require.Nil(t, err)
568 assert.Equal(t, 0, len(dbAccounts))
569 assertEqualAccountsHistoryDBStateDB(t, dbAccounts, sdbAccounts)
570
571 // Sync blocks 2-6
572 for i := 0; i < 5; i++ {
573 syncBlock, discards, err = s.Sync2(ctx, nil)
574 require.Nil(t, err)
575 require.Nil(t, discards)
576 require.NotNil(t, syncBlock)
577 assert.Equal(t, int64(2+i), syncBlock.Block.EthBlockNum)
578 }
579
580 dbBlock, err = s.historyDB.GetLastBlock()
581 require.Nil(t, err)
582 assert.Equal(t, int64(6), dbBlock.EthBlockNum)
583
584 // Accounts in HistoryDB and StateDB is only 2 entries
585 dbAccounts, err = s.historyDB.GetAllAccounts()
586 require.Nil(t, err)
587 sdbAccounts, err = s.stateDB.GetAccounts()
588 require.Nil(t, err)
589 assert.Equal(t, 2, len(dbAccounts))
590 assertEqualAccountsHistoryDBStateDB(t, dbAccounts, sdbAccounts)
591}