You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

822 lines
24 KiB

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