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.

880 lines
26 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, 1000.0, 24*time.Hour, nil)
  36. apiConnCon := dbUtils.NewAPIConnectionController(1, time.Second)
  37. l2DBWithACC = NewL2DB(db, db, 10, 1000, 0.0, 1000.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 TestL2DB_GetPoolTxs(t *testing.T) {
  291. err := prepareHistoryDB(historyDB)
  292. if err != nil {
  293. log.Error("Error prepare historyDB", err)
  294. }
  295. poolL2Txs, err := generatePoolL2Txs()
  296. state := common.PoolL2TxState("pend")
  297. idx := common.Idx(256)
  298. var pendingTxs []*common.PoolL2Tx
  299. for i := range poolL2Txs {
  300. if poolL2Txs[i].FromIdx == idx || poolL2Txs[i].ToIdx == idx {
  301. err := l2DB.AddTxTest(&poolL2Txs[i])
  302. require.NoError(t, err)
  303. pendingTxs = append(pendingTxs, &poolL2Txs[i])
  304. }
  305. }
  306. fetchedTxs, err := l2DBWithACC.GetPoolTxs(&idx, &state)
  307. require.NoError(t, err)
  308. assert.Equal(t, len(pendingTxs), len(fetchedTxs))
  309. }
  310. func TestStartForging(t *testing.T) {
  311. // Generate txs
  312. var fakeBatchNum common.BatchNum = 33
  313. err := prepareHistoryDB(historyDB)
  314. if err != nil {
  315. log.Error("Error prepare historyDB", err)
  316. }
  317. poolL2Txs, err := generatePoolL2Txs()
  318. require.NoError(t, err)
  319. var startForgingTxIDs []common.TxID
  320. randomizer := 0
  321. // Add txs to DB
  322. for i := range poolL2Txs {
  323. err := l2DB.AddTxTest(&poolL2Txs[i])
  324. require.NoError(t, err)
  325. if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
  326. startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
  327. }
  328. randomizer++
  329. }
  330. // Start forging txs
  331. err = l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
  332. require.NoError(t, err)
  333. // Fetch txs and check that they've been updated correctly
  334. for _, id := range startForgingTxIDs {
  335. fetchedTx, err := l2DBWithACC.GetTxAPI(id)
  336. require.NoError(t, err)
  337. assert.Equal(t, common.PoolL2TxStateForging, fetchedTx.State)
  338. assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
  339. }
  340. }
  341. func TestDoneForging(t *testing.T) {
  342. // Generate txs
  343. var fakeBatchNum common.BatchNum = 33
  344. err := prepareHistoryDB(historyDB)
  345. if err != nil {
  346. log.Error("Error prepare historyDB", err)
  347. }
  348. poolL2Txs, err := generatePoolL2Txs()
  349. require.NoError(t, err)
  350. var startForgingTxIDs []common.TxID
  351. randomizer := 0
  352. // Add txs to DB
  353. for i := range poolL2Txs {
  354. err := l2DB.AddTxTest(&poolL2Txs[i])
  355. require.NoError(t, err)
  356. if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
  357. startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
  358. }
  359. randomizer++
  360. }
  361. // Start forging txs
  362. err = l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
  363. require.NoError(t, err)
  364. var doneForgingTxIDs []common.TxID
  365. randomizer = 0
  366. for _, txID := range startForgingTxIDs {
  367. if randomizer%2 == 0 {
  368. doneForgingTxIDs = append(doneForgingTxIDs, txID)
  369. }
  370. randomizer++
  371. }
  372. // Done forging txs
  373. err = l2DB.DoneForging(doneForgingTxIDs, fakeBatchNum)
  374. require.NoError(t, err)
  375. // Fetch txs and check that they've been updated correctly
  376. for _, id := range doneForgingTxIDs {
  377. fetchedTx, err := l2DBWithACC.GetTxAPI(id)
  378. require.NoError(t, err)
  379. assert.Equal(t, common.PoolL2TxStateForged, fetchedTx.State)
  380. assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
  381. }
  382. }
  383. func TestInvalidate(t *testing.T) {
  384. // Generate txs
  385. var fakeBatchNum common.BatchNum = 33
  386. err := prepareHistoryDB(historyDB)
  387. if err != nil {
  388. log.Error("Error prepare historyDB", err)
  389. }
  390. poolL2Txs, err := generatePoolL2Txs()
  391. require.NoError(t, err)
  392. var invalidTxIDs []common.TxID
  393. randomizer := 0
  394. // Add txs to DB
  395. for i := range poolL2Txs {
  396. err := l2DB.AddTxTest(&poolL2Txs[i])
  397. require.NoError(t, err)
  398. if poolL2Txs[i].State != common.PoolL2TxStateInvalid && randomizer%2 == 0 {
  399. randomizer++
  400. invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
  401. }
  402. }
  403. // Invalidate txs
  404. err = l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
  405. require.NoError(t, err)
  406. // Fetch txs and check that they've been updated correctly
  407. for _, id := range invalidTxIDs {
  408. fetchedTx, err := l2DBWithACC.GetTxAPI(id)
  409. require.NoError(t, err)
  410. assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
  411. assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
  412. }
  413. }
  414. func TestInvalidateOldNonces(t *testing.T) {
  415. // Generate txs
  416. var fakeBatchNum common.BatchNum = 33
  417. err := prepareHistoryDB(historyDB)
  418. if err != nil {
  419. log.Error("Error prepare historyDB", err)
  420. }
  421. poolL2Txs, err := generatePoolL2Txs()
  422. require.NoError(t, err)
  423. // Update Accounts currentNonce
  424. var updateAccounts []common.IdxNonce
  425. var currentNonce = common.Nonce(1)
  426. for i := range accs {
  427. updateAccounts = append(updateAccounts, common.IdxNonce{
  428. Idx: accs[i].Idx,
  429. Nonce: common.Nonce(currentNonce),
  430. })
  431. }
  432. // Add txs to DB
  433. var invalidTxIDs []common.TxID
  434. for i := range poolL2Txs {
  435. if poolL2Txs[i].Nonce < currentNonce {
  436. invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
  437. }
  438. err := l2DB.AddTxTest(&poolL2Txs[i])
  439. require.NoError(t, err)
  440. }
  441. // sanity check
  442. require.Greater(t, len(invalidTxIDs), 0)
  443. err = l2DB.InvalidateOldNonces(updateAccounts, fakeBatchNum)
  444. require.NoError(t, err)
  445. // Fetch txs and check that they've been updated correctly
  446. for _, id := range invalidTxIDs {
  447. fetchedTx, err := l2DBWithACC.GetTxAPI(id)
  448. require.NoError(t, err)
  449. assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
  450. assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
  451. }
  452. }
  453. // TestReorg: first part of the test with reorg
  454. // With invalidated transactions BEFORE reorgBatch
  455. // And forged transactions in reorgBatch
  456. func TestReorg(t *testing.T) {
  457. // Generate txs
  458. const lastValidBatch common.BatchNum = 20
  459. const reorgBatch common.BatchNum = lastValidBatch + 1
  460. err := prepareHistoryDB(historyDB)
  461. if err != nil {
  462. log.Error("Error prepare historyDB", err)
  463. }
  464. poolL2Txs, err := generatePoolL2Txs()
  465. require.NoError(t, err)
  466. reorgedTxIDs := []common.TxID{}
  467. nonReorgedTxIDs := []common.TxID{}
  468. var startForgingTxIDs []common.TxID
  469. var invalidTxIDs []common.TxID
  470. var allTxRandomize []common.TxID
  471. randomizer := 0
  472. // Add txs to DB
  473. for i := range poolL2Txs {
  474. err := l2DB.AddTxTest(&poolL2Txs[i])
  475. require.NoError(t, err)
  476. if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
  477. startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
  478. allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
  479. } else if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%3 == 0 {
  480. invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
  481. allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
  482. }
  483. randomizer++
  484. }
  485. // Start forging txs
  486. err = l2DB.StartForging(startForgingTxIDs, lastValidBatch)
  487. require.NoError(t, err)
  488. var doneForgingTxIDs []common.TxID
  489. randomizer = 0
  490. for _, txID := range allTxRandomize {
  491. invalidTx := false
  492. for i := range invalidTxIDs {
  493. if invalidTxIDs[i] == txID {
  494. invalidTx = true
  495. nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
  496. }
  497. }
  498. if !invalidTx {
  499. if randomizer%2 == 0 {
  500. doneForgingTxIDs = append(doneForgingTxIDs, txID)
  501. reorgedTxIDs = append(reorgedTxIDs, txID)
  502. } else {
  503. nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
  504. }
  505. randomizer++
  506. }
  507. }
  508. // Invalidate txs BEFORE reorgBatch --> nonReorg
  509. err = l2DB.InvalidateTxs(invalidTxIDs, lastValidBatch)
  510. require.NoError(t, err)
  511. // Done forging txs in reorgBatch --> Reorg
  512. err = l2DB.DoneForging(doneForgingTxIDs, reorgBatch)
  513. require.NoError(t, err)
  514. err = l2DB.Reorg(lastValidBatch)
  515. require.NoError(t, err)
  516. for _, id := range reorgedTxIDs {
  517. tx, err := l2DBWithACC.GetTxAPI(id)
  518. require.NoError(t, err)
  519. assert.Nil(t, tx.BatchNum)
  520. assert.Equal(t, common.PoolL2TxStatePending, tx.State)
  521. }
  522. for _, id := range nonReorgedTxIDs {
  523. fetchedTx, err := l2DBWithACC.GetTxAPI(id)
  524. require.NoError(t, err)
  525. assert.Equal(t, lastValidBatch, *fetchedTx.BatchNum)
  526. }
  527. }
  528. // TestReorg: second part of test with reorg
  529. // With invalidated transactions in reorgBatch
  530. // And forged transactions BEFORE reorgBatch
  531. func TestReorg2(t *testing.T) {
  532. // Generate txs
  533. const lastValidBatch common.BatchNum = 20
  534. const reorgBatch common.BatchNum = lastValidBatch + 1
  535. err := prepareHistoryDB(historyDB)
  536. if err != nil {
  537. log.Error("Error prepare historyDB", err)
  538. }
  539. poolL2Txs, err := generatePoolL2Txs()
  540. require.NoError(t, err)
  541. reorgedTxIDs := []common.TxID{}
  542. nonReorgedTxIDs := []common.TxID{}
  543. var startForgingTxIDs []common.TxID
  544. var invalidTxIDs []common.TxID
  545. var allTxRandomize []common.TxID
  546. randomizer := 0
  547. // Add txs to DB
  548. for i := range poolL2Txs {
  549. err := l2DB.AddTxTest(&poolL2Txs[i])
  550. require.NoError(t, err)
  551. if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
  552. startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
  553. allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
  554. } else if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%3 == 0 {
  555. invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
  556. allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
  557. }
  558. randomizer++
  559. }
  560. // Start forging txs
  561. err = l2DB.StartForging(startForgingTxIDs, lastValidBatch)
  562. require.NoError(t, err)
  563. var doneForgingTxIDs []common.TxID
  564. randomizer = 0
  565. for _, txID := range allTxRandomize {
  566. invalidTx := false
  567. for i := range invalidTxIDs {
  568. if invalidTxIDs[i] == txID {
  569. invalidTx = true
  570. reorgedTxIDs = append(reorgedTxIDs, txID)
  571. }
  572. }
  573. if !invalidTx {
  574. if randomizer%2 == 0 {
  575. doneForgingTxIDs = append(doneForgingTxIDs, txID)
  576. }
  577. nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
  578. randomizer++
  579. }
  580. }
  581. // Done forging txs BEFORE reorgBatch --> nonReorg
  582. err = l2DB.DoneForging(doneForgingTxIDs, lastValidBatch)
  583. require.NoError(t, err)
  584. // Invalidate txs in reorgBatch --> Reorg
  585. err = l2DB.InvalidateTxs(invalidTxIDs, reorgBatch)
  586. require.NoError(t, err)
  587. err = l2DB.Reorg(lastValidBatch)
  588. require.NoError(t, err)
  589. for _, id := range reorgedTxIDs {
  590. tx, err := l2DBWithACC.GetTxAPI(id)
  591. require.NoError(t, err)
  592. assert.Nil(t, tx.BatchNum)
  593. assert.Equal(t, common.PoolL2TxStatePending, tx.State)
  594. }
  595. for _, id := range nonReorgedTxIDs {
  596. fetchedTx, err := l2DBWithACC.GetTxAPI(id)
  597. require.NoError(t, err)
  598. assert.Equal(t, lastValidBatch, *fetchedTx.BatchNum)
  599. }
  600. }
  601. func TestPurge(t *testing.T) {
  602. // Generate txs
  603. err := prepareHistoryDB(historyDB)
  604. if err != nil {
  605. log.Error("Error prepare historyDB", err)
  606. }
  607. // generatePoolL2Txs
  608. generateTx := int(l2DB.maxTxs/8 + 1)
  609. var poolL2Tx []common.PoolL2Tx
  610. for i := 0; i < generateTx; i++ {
  611. poolL2TxAux, err := generatePoolL2Txs()
  612. require.NoError(t, err)
  613. poolL2Tx = append(poolL2Tx, poolL2TxAux...)
  614. }
  615. afterTTLIDs := []common.TxID{}
  616. keepedIDs := []common.TxID{}
  617. var deletedIDs []common.TxID
  618. var invalidTxIDs []common.TxID
  619. var doneForgingTxIDs []common.TxID
  620. const toDeleteBatchNum common.BatchNum = 30
  621. safeBatchNum := toDeleteBatchNum + l2DB.safetyPeriod + 1
  622. // Add txs to the DB
  623. for i := 0; i < len(poolL2Tx); i++ {
  624. tx := poolL2Tx[i]
  625. if i%2 == 0 { // keep tx
  626. keepedIDs = append(keepedIDs, tx.TxID)
  627. } else { // delete after safety period
  628. if i%3 == 0 {
  629. doneForgingTxIDs = append(doneForgingTxIDs, tx.TxID)
  630. } else if i%5 == 0 {
  631. invalidTxIDs = append(invalidTxIDs, tx.TxID)
  632. } else {
  633. afterTTLIDs = append(afterTTLIDs, tx.TxID)
  634. }
  635. deletedIDs = append(deletedIDs, poolL2Tx[i].TxID)
  636. }
  637. err := l2DB.AddTxTest(&tx)
  638. require.NoError(t, err)
  639. }
  640. // Set batchNum keeped txs
  641. for i := range keepedIDs {
  642. _, err = l2DB.dbWrite.Exec(
  643. "UPDATE tx_pool SET batch_num = $1 WHERE tx_id = $2;",
  644. safeBatchNum, keepedIDs[i],
  645. )
  646. require.NoError(t, err)
  647. }
  648. // Start forging txs and set batchNum
  649. err = l2DB.StartForging(doneForgingTxIDs, toDeleteBatchNum)
  650. require.NoError(t, err)
  651. // Done forging txs and set batchNum
  652. err = l2DB.DoneForging(doneForgingTxIDs, toDeleteBatchNum)
  653. require.NoError(t, err)
  654. // Invalidate txs and set batchNum
  655. err = l2DB.InvalidateTxs(invalidTxIDs, toDeleteBatchNum)
  656. require.NoError(t, err)
  657. // Update timestamp of afterTTL txs
  658. deleteTimestamp := time.Unix(time.Now().UTC().Unix()-int64(l2DB.ttl.Seconds()+float64(4*time.Second)), 0)
  659. for _, id := range afterTTLIDs {
  660. // Set timestamp
  661. _, err = l2DB.dbWrite.Exec(
  662. "UPDATE tx_pool SET timestamp = $1, state = $2 WHERE tx_id = $3;",
  663. deleteTimestamp, common.PoolL2TxStatePending, id,
  664. )
  665. require.NoError(t, err)
  666. }
  667. // Purge txs
  668. err = l2DB.Purge(safeBatchNum)
  669. require.NoError(t, err)
  670. // Check results
  671. for _, id := range deletedIDs {
  672. _, err := l2DB.GetTx(id)
  673. assert.Error(t, err)
  674. }
  675. for _, id := range keepedIDs {
  676. _, err := l2DB.GetTx(id)
  677. require.NoError(t, err)
  678. }
  679. }
  680. func TestAuth(t *testing.T) {
  681. test.WipeDB(l2DB.DB())
  682. const nAuths = 5
  683. chainID := uint16(0)
  684. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  685. // Generate authorizations
  686. auths := test.GenAuths(nAuths, chainID, hermezContractAddr)
  687. for i := 0; i < len(auths); i++ {
  688. // Add to the DB
  689. err := l2DB.AddAccountCreationAuth(auths[i])
  690. require.NoError(t, err)
  691. // Fetch from DB
  692. auth, err := l2DB.GetAccountCreationAuth(auths[i].EthAddr)
  693. require.NoError(t, err)
  694. // Check fetched vs generated
  695. assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
  696. assert.Equal(t, auths[i].BJJ, auth.BJJ)
  697. assert.Equal(t, auths[i].Signature, auth.Signature)
  698. assert.Equal(t, auths[i].Timestamp.Unix(), auths[i].Timestamp.Unix())
  699. nameZone, offset := auths[i].Timestamp.Zone()
  700. assert.Equal(t, "UTC", nameZone)
  701. assert.Equal(t, 0, offset)
  702. }
  703. }
  704. func TestManyAuth(t *testing.T) {
  705. test.WipeDB(l2DB.DB())
  706. const nAuths = 5
  707. chainID := uint16(0)
  708. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  709. // Generate authorizations
  710. genAuths := test.GenAuths(nAuths, chainID, hermezContractAddr)
  711. auths := make([]common.AccountCreationAuth, len(genAuths))
  712. // Convert to a non-pointer slice
  713. for i := 0; i < len(genAuths); i++ {
  714. auths[i] = *genAuths[i]
  715. }
  716. // Add a duplicate one to check the not exist condition
  717. err := l2DB.AddAccountCreationAuth(genAuths[0])
  718. require.NoError(t, err)
  719. // Add to the DB
  720. err = l2DB.AddManyAccountCreationAuth(auths)
  721. require.NoError(t, err)
  722. // Assert the result
  723. for i := 0; i < len(auths); i++ {
  724. // Fetch from DB
  725. auth, err := l2DB.GetAccountCreationAuth(auths[i].EthAddr)
  726. require.NoError(t, err)
  727. // Check fetched vs generated
  728. assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
  729. assert.Equal(t, auths[i].BJJ, auth.BJJ)
  730. assert.Equal(t, auths[i].Signature, auth.Signature)
  731. assert.Equal(t, auths[i].Timestamp.Unix(), auths[i].Timestamp.Unix())
  732. nameZone, offset := auths[i].Timestamp.Zone()
  733. assert.Equal(t, "UTC", nameZone)
  734. assert.Equal(t, 0, offset)
  735. }
  736. }
  737. func TestAddGet(t *testing.T) {
  738. err := prepareHistoryDB(historyDB)
  739. if err != nil {
  740. log.Error("Error prepare historyDB", err)
  741. }
  742. poolL2Txs, err := generatePoolL2Txs()
  743. require.NoError(t, err)
  744. // We will work with only 3 txs
  745. require.GreaterOrEqual(t, len(poolL2Txs), 3)
  746. txs := poolL2Txs[:3]
  747. // NOTE: By changing the tx fields, the signature will no longer be
  748. // valid, but we are not checking the signautre here so it's OK.
  749. // 0. Has ToIdx >= 256 && ToEthAddr == 0 && ToBJJ == 0
  750. require.GreaterOrEqual(t, int(txs[0].ToIdx), 256)
  751. txs[0].ToEthAddr = ethCommon.Address{}
  752. txs[0].ToBJJ = babyjub.PublicKeyComp{}
  753. // 1. Has ToIdx >= 256 && ToEthAddr != 0 && ToBJJ != 0
  754. require.GreaterOrEqual(t, int(txs[1].ToIdx), 256)
  755. require.NotEqual(t, txs[1].ToEthAddr, ethCommon.Address{})
  756. require.NotEqual(t, txs[1].ToBJJ, babyjub.PublicKeyComp{})
  757. // 2. Has ToIdx == 0 && ToEthAddr != 0 && ToBJJ != 0
  758. txs[2].ToIdx = 0
  759. require.NotEqual(t, txs[2].ToEthAddr, ethCommon.Address{})
  760. require.NotEqual(t, txs[2].ToBJJ, babyjub.PublicKeyComp{})
  761. for i := 0; i < len(txs); i++ {
  762. require.NoError(t, txs[i].SetID())
  763. require.NoError(t, l2DB.AddTxTest(&txs[i]))
  764. }
  765. // Verify that the inserts haven't altered any field (specially
  766. // ToEthAddr and ToBJJ)
  767. for i := 0; i < len(txs); i++ {
  768. dbTx, err := l2DB.GetTx(txs[i].TxID)
  769. require.NoError(t, err)
  770. // Ignore Timestamp, AbsoluteFee, AbsoluteFeeUpdate
  771. txs[i].Timestamp = dbTx.Timestamp
  772. txs[i].AbsoluteFee = dbTx.AbsoluteFee
  773. txs[i].AbsoluteFeeUpdate = dbTx.AbsoluteFeeUpdate
  774. assert.Equal(t, txs[i], *dbTx)
  775. }
  776. }
  777. func TestPurgeByExternalDelete(t *testing.T) {
  778. err := prepareHistoryDB(historyDB)
  779. if err != nil {
  780. log.Error("Error prepare historyDB", err)
  781. }
  782. txs, err := generatePoolL2Txs()
  783. require.NoError(t, err)
  784. // We will work with 8 txs
  785. require.GreaterOrEqual(t, len(txs), 8)
  786. txs = txs[:8]
  787. for i := range txs {
  788. require.NoError(t, l2DB.AddTxTest(&txs[i]))
  789. }
  790. // We will recreate this scenario:
  791. // tx index, status , external_delete
  792. // 0 , pending, false
  793. // 1 , pending, false
  794. // 2 , pending, true // will be deleted
  795. // 3 , pending, true // will be deleted
  796. // 4 , fging , false
  797. // 5 , fging , false
  798. // 6 , fging , true
  799. // 7 , fging , true
  800. require.NoError(t, l2DB.StartForging(
  801. []common.TxID{txs[4].TxID, txs[5].TxID, txs[6].TxID, txs[7].TxID},
  802. 1))
  803. _, err = l2DB.dbWrite.Exec(
  804. `UPDATE tx_pool SET external_delete = true WHERE
  805. tx_id IN ($1, $2, $3, $4)
  806. ;`,
  807. txs[2].TxID, txs[3].TxID, txs[6].TxID, txs[7].TxID,
  808. )
  809. require.NoError(t, err)
  810. require.NoError(t, l2DB.PurgeByExternalDelete())
  811. // Query txs that are have been not deleted
  812. for _, i := range []int{0, 1, 4, 5, 6, 7} {
  813. txID := txs[i].TxID
  814. _, err := l2DB.GetTx(txID)
  815. require.NoError(t, err)
  816. }
  817. // Query txs that have been deleted
  818. for _, i := range []int{2, 3} {
  819. txID := txs[i].TxID
  820. _, err := l2DB.GetTx(txID)
  821. require.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
  822. }
  823. }