hermez-node/db/l2db/l2db_test.go
db/l2db/l2db_test.goRaw
1package l2db
2
3import (
4 "database/sql"
5 "math"
6 "math/big"
7 "os"
8 "testing"
9 "time"
10
11 ethCommon "github.com/ethereum/go-ethereum/common"
12 "github.com/hermeznetwork/hermez-node/common"
13 dbUtils "github.com/hermeznetwork/hermez-node/db"
14 "github.com/hermeznetwork/hermez-node/db/historydb"
15 "github.com/hermeznetwork/hermez-node/log"
16 "github.com/hermeznetwork/hermez-node/test"
17 "github.com/hermeznetwork/hermez-node/test/til"
18 "github.com/hermeznetwork/tracerr"
19 "github.com/iden3/go-iden3-crypto/babyjub"
20 "github.com/stretchr/testify/assert"
21 "github.com/stretchr/testify/require"
22)
23
24var l2DB *L2DB
25var l2DBWithACC *L2DB
26var historyDB *historydb.HistoryDB
27var tc *til.Context
28var tokens map[common.TokenID]historydb.TokenWithUSD
29var tokensValue map[common.TokenID]float64
30var accs map[common.Idx]common.Account
31
32func TestMain(m *testing.M) {
33 // init DB
34 pass := os.Getenv("POSTGRES_PASS")
35 db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
36 if err != nil {
37 panic(err)
38 }
39 l2DB = NewL2DB(db, 10, 1000, 24*time.Hour, nil)
40 apiConnCon := dbUtils.NewAPICnnectionController(1, time.Second)
41 l2DBWithACC = NewL2DB(db, 10, 1000, 24*time.Hour, apiConnCon)
42 test.WipeDB(l2DB.DB())
43 historyDB = historydb.NewHistoryDB(db, nil)
44 // Run tests
45 result := m.Run()
46 // Close DB
47 if err := db.Close(); err != nil {
48 log.Error("Error closing the history DB:", err)
49 }
50 os.Exit(result)
51}
52
53func prepareHistoryDB(historyDB *historydb.HistoryDB) error {
54 // Reset DB
55 test.WipeDB(l2DB.DB())
56 // Generate pool txs using til
57 setBlockchain := `
58 Type: Blockchain
59
60 AddToken(1)
61 AddToken(2)
62 CreateAccountDeposit(1) A: 2000
63 CreateAccountDeposit(2) A: 2000
64 CreateAccountDeposit(1) B: 1000
65 CreateAccountDeposit(2) B: 1000
66 > batchL1
67 > batchL1
68 > block
69 > block
70 `
71
72 tc = til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
73 tilCfgExtra := til.ConfigExtra{
74 BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
75 CoordUser: "A",
76 }
77 blocks, err := tc.GenerateBlocks(setBlockchain)
78 if err != nil {
79 return tracerr.Wrap(err)
80 }
81
82 err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
83 if err != nil {
84 return tracerr.Wrap(err)
85 }
86 tokens = make(map[common.TokenID]historydb.TokenWithUSD)
87 tokensValue = make(map[common.TokenID]float64)
88 accs = make(map[common.Idx]common.Account)
89 value := 5 * 5.389329
90 now := time.Now().UTC()
91 // Add all blocks except for the last one
92 for i := range blocks[:len(blocks)-1] {
93 err = historyDB.AddBlockSCData(&blocks[i])
94 if err != nil {
95 return tracerr.Wrap(err)
96 }
97 for _, batch := range blocks[i].Rollup.Batches {
98 for _, account := range batch.CreatedAccounts {
99 accs[account.Idx] = account
100 }
101 }
102 for _, token := range blocks[i].Rollup.AddedTokens {
103 readToken := historydb.TokenWithUSD{
104 TokenID: token.TokenID,
105 EthBlockNum: token.EthBlockNum,
106 EthAddr: token.EthAddr,
107 Name: token.Name,
108 Symbol: token.Symbol,
109 Decimals: token.Decimals,
110 }
111 tokensValue[token.TokenID] = value / math.Pow(10, float64(token.Decimals))
112 readToken.USDUpdate = &now
113 readToken.USD = &value
114 tokens[token.TokenID] = readToken
115 }
116 // Set value to the tokens (tokens have no symbol)
117 tokenSymbol := ""
118 err := historyDB.UpdateTokenValue(tokenSymbol, value)
119 if err != nil {
120 return tracerr.Wrap(err)
121 }
122 }
123 return nil
124}
125
126func generatePoolL2Txs() ([]common.PoolL2Tx, error) {
127 setPool := `
128 Type: PoolL2
129 PoolTransfer(1) A-B: 6 (4)
130 PoolTransfer(2) A-B: 3 (1)
131 PoolTransfer(1) B-A: 5 (2)
132 PoolTransfer(2) B-A: 10 (3)
133 PoolTransfer(1) A-B: 7 (2)
134 PoolTransfer(2) A-B: 2 (1)
135 PoolTransfer(1) B-A: 8 (2)
136 PoolTransfer(2) B-A: 1 (1)
137 PoolTransfer(1) A-B: 3 (1)
138 PoolTransferToEthAddr(2) B-A: 5 (2)
139 PoolTransferToBJJ(2) B-A: 5 (2)
140
141 PoolExit(1) A: 5 (2)
142 PoolExit(2) B: 3 (1)
143 `
144 poolL2Txs, err := tc.GeneratePoolL2Txs(setPool)
145 if err != nil {
146 return nil, tracerr.Wrap(err)
147 }
148 return poolL2Txs, nil
149}
150
151func TestAddTxTest(t *testing.T) {
152 err := prepareHistoryDB(historyDB)
153 if err != nil {
154 log.Error("Error prepare historyDB", err)
155 }
156 poolL2Txs, err := generatePoolL2Txs()
157 assert.NoError(t, err)
158 for i := range poolL2Txs {
159 err := l2DB.AddTxTest(&poolL2Txs[i])
160 assert.NoError(t, err)
161 fetchedTx, err := l2DB.GetTx(poolL2Txs[i].TxID)
162 assert.NoError(t, err)
163 assertTx(t, &poolL2Txs[i], fetchedTx)
164 nameZone, offset := fetchedTx.Timestamp.Zone()
165 assert.Equal(t, "UTC", nameZone)
166 assert.Equal(t, 0, offset)
167 }
168}
169func TestUpdateTxsInfo(t *testing.T) {
170 err := prepareHistoryDB(historyDB)
171 if err != nil {
172 log.Error("Error prepare historyDB", err)
173 }
174 poolL2Txs, err := generatePoolL2Txs()
175 assert.NoError(t, err)
176 for i := range poolL2Txs {
177 err := l2DB.AddTxTest(&poolL2Txs[i])
178 require.NoError(t, err)
179
180 // once added, change the Info parameter
181 poolL2Txs[i].Info = "test"
182 }
183 // update the txs
184 err = l2DB.UpdateTxsInfo(poolL2Txs)
185 require.NoError(t, err)
186
187 for i := range poolL2Txs {
188 fetchedTx, err := l2DB.GetTx(poolL2Txs[i].TxID)
189 assert.NoError(t, err)
190 assert.Equal(t, "test", fetchedTx.Info)
191 }
192}
193
194func assertTx(t *testing.T, expected, actual *common.PoolL2Tx) {
195 // Check that timestamp has been set within the last 3 seconds
196 assert.Less(t, time.Now().UTC().Unix()-3, actual.Timestamp.Unix())
197 assert.GreaterOrEqual(t, time.Now().UTC().Unix(), actual.Timestamp.Unix())
198 expected.Timestamp = actual.Timestamp
199 // Check absolute fee
200 // find token
201 token := tokens[expected.TokenID]
202 // If the token has value in USD setted
203 if token.USDUpdate != nil {
204 assert.Less(t, token.USDUpdate.Unix()-3, actual.AbsoluteFeeUpdate.Unix())
205 expected.AbsoluteFeeUpdate = actual.AbsoluteFeeUpdate
206 // Set expected fee
207 f := new(big.Float).SetInt(expected.Amount)
208 amountF, _ := f.Float64()
209 expected.AbsoluteFee = *token.USD * amountF * expected.Fee.Percentage()
210 test.AssertUSD(t, &expected.AbsoluteFee, &actual.AbsoluteFee)
211 }
212 assert.Equal(t, expected, actual)
213}
214
215// NO UPDATE: benchmarks will be done after impl is finished
216// func BenchmarkAddTxTest(b *testing.B) {
217// const nInserts = 20
218// test.WipeDB(l2DB.DB())
219// txs := test.GenPoolTxs(nInserts, tokens)
220// now := time.Now()
221// for _, tx := range txs {
222// _ = l2DB.AddTxTest(tx)
223// }
224// elapsedTime := time.Since(now)
225// log.Info("Time to insert 2048 txs:", elapsedTime)
226// }
227
228func TestGetPending(t *testing.T) {
229 err := prepareHistoryDB(historyDB)
230 if err != nil {
231 log.Error("Error prepare historyDB", err)
232 }
233 poolL2Txs, err := generatePoolL2Txs()
234 assert.NoError(t, err)
235 var pendingTxs []*common.PoolL2Tx
236 for i := range poolL2Txs {
237 err := l2DB.AddTxTest(&poolL2Txs[i])
238 assert.NoError(t, err)
239 pendingTxs = append(pendingTxs, &poolL2Txs[i])
240 }
241 fetchedTxs, err := l2DB.GetPendingTxs()
242 assert.NoError(t, err)
243 assert.Equal(t, len(pendingTxs), len(fetchedTxs))
244 for i := range fetchedTxs {
245 assertTx(t, pendingTxs[i], &fetchedTxs[i])
246 }
247}
248
249func TestStartForging(t *testing.T) {
250 // Generate txs
251 var fakeBatchNum common.BatchNum = 33
252 err := prepareHistoryDB(historyDB)
253 if err != nil {
254 log.Error("Error prepare historyDB", err)
255 }
256 poolL2Txs, err := generatePoolL2Txs()
257 assert.NoError(t, err)
258 var startForgingTxIDs []common.TxID
259 randomizer := 0
260 // Add txs to DB
261 for i := range poolL2Txs {
262 err := l2DB.AddTxTest(&poolL2Txs[i])
263 assert.NoError(t, err)
264 if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
265 startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
266 }
267 randomizer++
268 }
269 // Start forging txs
270 err = l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
271 assert.NoError(t, err)
272 // Fetch txs and check that they've been updated correctly
273 for _, id := range startForgingTxIDs {
274 fetchedTx, err := l2DBWithACC.GetTxAPI(id)
275 assert.NoError(t, err)
276 assert.Equal(t, common.PoolL2TxStateForging, fetchedTx.State)
277 assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
278 }
279}
280
281func TestDoneForging(t *testing.T) {
282 // Generate txs
283 var fakeBatchNum common.BatchNum = 33
284 err := prepareHistoryDB(historyDB)
285 if err != nil {
286 log.Error("Error prepare historyDB", err)
287 }
288 poolL2Txs, err := generatePoolL2Txs()
289 assert.NoError(t, err)
290 var startForgingTxIDs []common.TxID
291 randomizer := 0
292 // Add txs to DB
293 for i := range poolL2Txs {
294 err := l2DB.AddTxTest(&poolL2Txs[i])
295 assert.NoError(t, err)
296 if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
297 startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
298 }
299 randomizer++
300 }
301 // Start forging txs
302 err = l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
303 assert.NoError(t, err)
304
305 var doneForgingTxIDs []common.TxID
306 randomizer = 0
307 for _, txID := range startForgingTxIDs {
308 if randomizer%2 == 0 {
309 doneForgingTxIDs = append(doneForgingTxIDs, txID)
310 }
311 randomizer++
312 }
313 // Done forging txs
314 err = l2DB.DoneForging(doneForgingTxIDs, fakeBatchNum)
315 assert.NoError(t, err)
316
317 // Fetch txs and check that they've been updated correctly
318 for _, id := range doneForgingTxIDs {
319 fetchedTx, err := l2DBWithACC.GetTxAPI(id)
320 assert.NoError(t, err)
321 assert.Equal(t, common.PoolL2TxStateForged, fetchedTx.State)
322 assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
323 }
324}
325
326func TestInvalidate(t *testing.T) {
327 // Generate txs
328 var fakeBatchNum common.BatchNum = 33
329 err := prepareHistoryDB(historyDB)
330 if err != nil {
331 log.Error("Error prepare historyDB", err)
332 }
333 poolL2Txs, err := generatePoolL2Txs()
334 assert.NoError(t, err)
335 var invalidTxIDs []common.TxID
336 randomizer := 0
337 // Add txs to DB
338 for i := range poolL2Txs {
339 err := l2DB.AddTxTest(&poolL2Txs[i])
340 assert.NoError(t, err)
341 if poolL2Txs[i].State != common.PoolL2TxStateInvalid && randomizer%2 == 0 {
342 randomizer++
343 invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
344 }
345 }
346 // Invalidate txs
347 err = l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
348 assert.NoError(t, err)
349 // Fetch txs and check that they've been updated correctly
350 for _, id := range invalidTxIDs {
351 fetchedTx, err := l2DBWithACC.GetTxAPI(id)
352 assert.NoError(t, err)
353 assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
354 assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
355 }
356}
357
358func TestInvalidateOldNonces(t *testing.T) {
359 // Generate txs
360 var fakeBatchNum common.BatchNum = 33
361 err := prepareHistoryDB(historyDB)
362 if err != nil {
363 log.Error("Error prepare historyDB", err)
364 }
365 poolL2Txs, err := generatePoolL2Txs()
366 assert.NoError(t, err)
367 // Update Accounts currentNonce
368 var updateAccounts []common.IdxNonce
369 var currentNonce = common.Nonce(1)
370 for i := range accs {
371 updateAccounts = append(updateAccounts, common.IdxNonce{
372 Idx: accs[i].Idx,
373 Nonce: common.Nonce(currentNonce),
374 })
375 }
376 // Add txs to DB
377 var invalidTxIDs []common.TxID
378 for i := range poolL2Txs {
379 if poolL2Txs[i].Nonce < currentNonce {
380 invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
381 }
382 err := l2DB.AddTxTest(&poolL2Txs[i])
383 assert.NoError(t, err)
384 }
385 // sanity check
386 require.Greater(t, len(invalidTxIDs), 0)
387
388 err = l2DB.InvalidateOldNonces(updateAccounts, fakeBatchNum)
389 assert.NoError(t, err)
390 // Fetch txs and check that they've been updated correctly
391 for _, id := range invalidTxIDs {
392 fetchedTx, err := l2DBWithACC.GetTxAPI(id)
393 require.NoError(t, err)
394 assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
395 assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
396 }
397}
398
399// TestReorg: first part of the test with reorg
400// With invalidated transactions BEFORE reorgBatch
401// And forged transactions in reorgBatch
402func TestReorg(t *testing.T) {
403 // Generate txs
404 const lastValidBatch common.BatchNum = 20
405 const reorgBatch common.BatchNum = lastValidBatch + 1
406 err := prepareHistoryDB(historyDB)
407 if err != nil {
408 log.Error("Error prepare historyDB", err)
409 }
410 poolL2Txs, err := generatePoolL2Txs()
411 assert.NoError(t, err)
412
413 reorgedTxIDs := []common.TxID{}
414 nonReorgedTxIDs := []common.TxID{}
415 var startForgingTxIDs []common.TxID
416 var invalidTxIDs []common.TxID
417 var allTxRandomize []common.TxID
418 randomizer := 0
419 // Add txs to DB
420 for i := range poolL2Txs {
421 err := l2DB.AddTxTest(&poolL2Txs[i])
422 assert.NoError(t, err)
423 if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
424 startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
425 allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
426 } else if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%3 == 0 {
427 invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
428 allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
429 }
430 randomizer++
431 }
432 // Start forging txs
433 err = l2DB.StartForging(startForgingTxIDs, lastValidBatch)
434 assert.NoError(t, err)
435
436 var doneForgingTxIDs []common.TxID
437 randomizer = 0
438 for _, txID := range allTxRandomize {
439 invalidTx := false
440 for i := range invalidTxIDs {
441 if invalidTxIDs[i] == txID {
442 invalidTx = true
443 nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
444 }
445 }
446 if !invalidTx {
447 if randomizer%2 == 0 {
448 doneForgingTxIDs = append(doneForgingTxIDs, txID)
449 reorgedTxIDs = append(reorgedTxIDs, txID)
450 } else {
451 nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
452 }
453 randomizer++
454 }
455 }
456
457 // Invalidate txs BEFORE reorgBatch --> nonReorg
458 err = l2DB.InvalidateTxs(invalidTxIDs, lastValidBatch)
459 assert.NoError(t, err)
460 // Done forging txs in reorgBatch --> Reorg
461 err = l2DB.DoneForging(doneForgingTxIDs, reorgBatch)
462 assert.NoError(t, err)
463
464 err = l2DB.Reorg(lastValidBatch)
465 assert.NoError(t, err)
466 for _, id := range reorgedTxIDs {
467 tx, err := l2DBWithACC.GetTxAPI(id)
468 assert.NoError(t, err)
469 assert.Nil(t, tx.BatchNum)
470 assert.Equal(t, common.PoolL2TxStatePending, tx.State)
471 }
472 for _, id := range nonReorgedTxIDs {
473 fetchedTx, err := l2DBWithACC.GetTxAPI(id)
474 assert.NoError(t, err)
475 assert.Equal(t, lastValidBatch, *fetchedTx.BatchNum)
476 }
477}
478
479// TestReorg: second part of test with reorg
480// With invalidated transactions in reorgBatch
481// And forged transactions BEFORE reorgBatch
482func TestReorg2(t *testing.T) {
483 // Generate txs
484 const lastValidBatch common.BatchNum = 20
485 const reorgBatch common.BatchNum = lastValidBatch + 1
486 err := prepareHistoryDB(historyDB)
487 if err != nil {
488 log.Error("Error prepare historyDB", err)
489 }
490 poolL2Txs, err := generatePoolL2Txs()
491 assert.NoError(t, err)
492
493 reorgedTxIDs := []common.TxID{}
494 nonReorgedTxIDs := []common.TxID{}
495 var startForgingTxIDs []common.TxID
496 var invalidTxIDs []common.TxID
497 var allTxRandomize []common.TxID
498 randomizer := 0
499 // Add txs to DB
500 for i := range poolL2Txs {
501 err := l2DB.AddTxTest(&poolL2Txs[i])
502 assert.NoError(t, err)
503 if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
504 startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
505 allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
506 } else if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%3 == 0 {
507 invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
508 allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
509 }
510 randomizer++
511 }
512 // Start forging txs
513 err = l2DB.StartForging(startForgingTxIDs, lastValidBatch)
514 assert.NoError(t, err)
515
516 var doneForgingTxIDs []common.TxID
517 randomizer = 0
518 for _, txID := range allTxRandomize {
519 invalidTx := false
520 for i := range invalidTxIDs {
521 if invalidTxIDs[i] == txID {
522 invalidTx = true
523 reorgedTxIDs = append(reorgedTxIDs, txID)
524 }
525 }
526 if !invalidTx {
527 if randomizer%2 == 0 {
528 doneForgingTxIDs = append(doneForgingTxIDs, txID)
529 }
530 nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
531 randomizer++
532 }
533 }
534 // Done forging txs BEFORE reorgBatch --> nonReorg
535 err = l2DB.DoneForging(doneForgingTxIDs, lastValidBatch)
536 assert.NoError(t, err)
537 // Invalidate txs in reorgBatch --> Reorg
538 err = l2DB.InvalidateTxs(invalidTxIDs, reorgBatch)
539 assert.NoError(t, err)
540
541 err = l2DB.Reorg(lastValidBatch)
542 assert.NoError(t, err)
543 for _, id := range reorgedTxIDs {
544 tx, err := l2DBWithACC.GetTxAPI(id)
545 assert.NoError(t, err)
546 assert.Nil(t, tx.BatchNum)
547 assert.Equal(t, common.PoolL2TxStatePending, tx.State)
548 }
549 for _, id := range nonReorgedTxIDs {
550 fetchedTx, err := l2DBWithACC.GetTxAPI(id)
551 assert.NoError(t, err)
552 assert.Equal(t, lastValidBatch, *fetchedTx.BatchNum)
553 }
554}
555
556func TestPurge(t *testing.T) {
557 // Generate txs
558 err := prepareHistoryDB(historyDB)
559 if err != nil {
560 log.Error("Error prepare historyDB", err)
561 }
562 // generatePoolL2Txs
563 generateTx := int(l2DB.maxTxs/8 + 1)
564 var poolL2Tx []common.PoolL2Tx
565 for i := 0; i < generateTx; i++ {
566 poolL2TxAux, err := generatePoolL2Txs()
567 assert.NoError(t, err)
568 poolL2Tx = append(poolL2Tx, poolL2TxAux...)
569 }
570
571 afterTTLIDs := []common.TxID{}
572 keepedIDs := []common.TxID{}
573 var deletedIDs []common.TxID
574 var invalidTxIDs []common.TxID
575 var doneForgingTxIDs []common.TxID
576 const toDeleteBatchNum common.BatchNum = 30
577 safeBatchNum := toDeleteBatchNum + l2DB.safetyPeriod + 1
578 // Add txs to the DB
579 for i := 0; i < len(poolL2Tx); i++ {
580 tx := poolL2Tx[i]
581 if i%2 == 0 { // keep tx
582 keepedIDs = append(keepedIDs, tx.TxID)
583 } else { // delete after safety period
584 if i%3 == 0 {
585 doneForgingTxIDs = append(doneForgingTxIDs, tx.TxID)
586 } else if i%5 == 0 {
587 invalidTxIDs = append(invalidTxIDs, tx.TxID)
588 } else {
589 afterTTLIDs = append(afterTTLIDs, tx.TxID)
590 }
591 deletedIDs = append(deletedIDs, poolL2Tx[i].TxID)
592 }
593 err := l2DB.AddTxTest(&tx)
594 assert.NoError(t, err)
595 }
596 // Set batchNum keeped txs
597 for i := range keepedIDs {
598 _, err = l2DB.db.Exec(
599 "UPDATE tx_pool SET batch_num = $1 WHERE tx_id = $2;",
600 safeBatchNum, keepedIDs[i],
601 )
602 assert.NoError(t, err)
603 }
604 // Start forging txs and set batchNum
605 err = l2DB.StartForging(doneForgingTxIDs, toDeleteBatchNum)
606 assert.NoError(t, err)
607 // Done forging txs and set batchNum
608 err = l2DB.DoneForging(doneForgingTxIDs, toDeleteBatchNum)
609 assert.NoError(t, err)
610 // Invalidate txs and set batchNum
611 err = l2DB.InvalidateTxs(invalidTxIDs, toDeleteBatchNum)
612 assert.NoError(t, err)
613 // Update timestamp of afterTTL txs
614 deleteTimestamp := time.Unix(time.Now().UTC().Unix()-int64(l2DB.ttl.Seconds()+float64(4*time.Second)), 0)
615 for _, id := range afterTTLIDs {
616 // Set timestamp
617 _, err = l2DB.db.Exec(
618 "UPDATE tx_pool SET timestamp = $1, state = $2 WHERE tx_id = $3;",
619 deleteTimestamp, common.PoolL2TxStatePending, id,
620 )
621 assert.NoError(t, err)
622 }
623
624 // Purge txs
625 err = l2DB.Purge(safeBatchNum)
626 assert.NoError(t, err)
627 // Check results
628 for _, id := range deletedIDs {
629 _, err := l2DB.GetTx(id)
630 assert.Error(t, err)
631 }
632 for _, id := range keepedIDs {
633 _, err := l2DB.GetTx(id)
634 assert.NoError(t, err)
635 }
636}
637
638func TestAuth(t *testing.T) {
639 test.WipeDB(l2DB.DB())
640 const nAuths = 5
641 chainID := uint16(0)
642 hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
643 // Generate authorizations
644 auths := test.GenAuths(nAuths, chainID, hermezContractAddr)
645 for i := 0; i < len(auths); i++ {
646 // Add to the DB
647 err := l2DB.AddAccountCreationAuth(auths[i])
648 assert.NoError(t, err)
649 // Fetch from DB
650 auth, err := l2DB.GetAccountCreationAuth(auths[i].EthAddr)
651 assert.NoError(t, err)
652 // Check fetched vs generated
653 assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
654 assert.Equal(t, auths[i].BJJ, auth.BJJ)
655 assert.Equal(t, auths[i].Signature, auth.Signature)
656 assert.Equal(t, auths[i].Timestamp.Unix(), auths[i].Timestamp.Unix())
657 nameZone, offset := auths[i].Timestamp.Zone()
658 assert.Equal(t, "UTC", nameZone)
659 assert.Equal(t, 0, offset)
660 }
661}
662
663func TestAddGet(t *testing.T) {
664 err := prepareHistoryDB(historyDB)
665 if err != nil {
666 log.Error("Error prepare historyDB", err)
667 }
668 poolL2Txs, err := generatePoolL2Txs()
669 assert.NoError(t, err)
670
671 // We will work with only 3 txs
672 require.GreaterOrEqual(t, len(poolL2Txs), 3)
673 txs := poolL2Txs[:3]
674 // NOTE: By changing the tx fields, the signature will no longer be
675 // valid, but we are not checking the signautre here so it's OK.
676 // 0. Has ToIdx >= 256 && ToEthAddr == 0 && ToBJJ == 0
677 require.GreaterOrEqual(t, int(txs[0].ToIdx), 256)
678 txs[0].ToEthAddr = ethCommon.Address{}
679 txs[0].ToBJJ = babyjub.PublicKeyComp{}
680 // 1. Has ToIdx >= 256 && ToEthAddr != 0 && ToBJJ != 0
681 require.GreaterOrEqual(t, int(txs[1].ToIdx), 256)
682 require.NotEqual(t, txs[1].ToEthAddr, ethCommon.Address{})
683 require.NotEqual(t, txs[1].ToBJJ, babyjub.PublicKeyComp{})
684 // 2. Has ToIdx == 0 && ToEthAddr != 0 && ToBJJ != 0
685 txs[2].ToIdx = 0
686 require.NotEqual(t, txs[2].ToEthAddr, ethCommon.Address{})
687 require.NotEqual(t, txs[2].ToBJJ, babyjub.PublicKeyComp{})
688
689 for i := 0; i < len(txs); i++ {
690 require.NoError(t, txs[i].SetID())
691 require.NoError(t, l2DB.AddTxTest(&txs[i]))
692 }
693 // Verify that the inserts haven't altered any field (specially
694 // ToEthAddr and ToBJJ)
695 for i := 0; i < len(txs); i++ {
696 dbTx, err := l2DB.GetTx(txs[i].TxID)
697 require.NoError(t, err)
698 // Ignore Timestamp, AbsoluteFee, AbsoluteFeeUpdate
699 txs[i].Timestamp = dbTx.Timestamp
700 txs[i].AbsoluteFee = dbTx.AbsoluteFee
701 txs[i].AbsoluteFeeUpdate = dbTx.AbsoluteFeeUpdate
702 assert.Equal(t, txs[i], *dbTx)
703 }
704}
705
706func TestPurgeByExternalDelete(t *testing.T) {
707 err := prepareHistoryDB(historyDB)
708 if err != nil {
709 log.Error("Error prepare historyDB", err)
710 }
711 txs, err := generatePoolL2Txs()
712 assert.NoError(t, err)
713
714 // We will work with 8 txs
715 require.GreaterOrEqual(t, len(txs), 8)
716 txs = txs[:8]
717 for i := range txs {
718 require.NoError(t, l2DB.AddTxTest(&txs[i]))
719 }
720
721 // We will recreate this scenario:
722 // tx index, status , external_delete
723 // 0 , pending, false
724 // 1 , pending, false
725 // 2 , pending, true // will be deleted
726 // 3 , pending, true // will be deleted
727 // 4 , fging , false
728 // 5 , fging , false
729 // 6 , fging , true
730 // 7 , fging , true
731
732 require.NoError(t, l2DB.StartForging(
733 []common.TxID{txs[4].TxID, txs[5].TxID, txs[6].TxID, txs[7].TxID},
734 1))
735 _, err = l2DB.db.Exec(
736 `UPDATE tx_pool SET external_delete = true WHERE
737 tx_id IN ($1, $2, $3, $4)
738 ;`,
739 txs[2].TxID, txs[3].TxID, txs[6].TxID, txs[7].TxID,
740 )
741 require.NoError(t, err)
742 require.NoError(t, l2DB.PurgeByExternalDelete())
743
744 // Query txs that are have been not deleted
745 for _, i := range []int{0, 1, 4, 5, 6, 7} {
746 txID := txs[i].TxID
747 _, err := l2DB.GetTx(txID)
748 require.NoError(t, err)
749 }
750
751 // Query txs that have been deleted
752 for _, i := range []int{2, 3} {
753 txID := txs[i].TxID
754 _, err := l2DB.GetTx(txID)
755 require.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
756 }
757}