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.

499 lines
14 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
  1. package l2db
  2. import (
  3. "math/big"
  4. "os"
  5. "testing"
  6. "time"
  7. ethCommon "github.com/ethereum/go-ethereum/common"
  8. "github.com/hermeznetwork/hermez-node/common"
  9. dbUtils "github.com/hermeznetwork/hermez-node/db"
  10. "github.com/hermeznetwork/hermez-node/db/historydb"
  11. "github.com/hermeznetwork/hermez-node/log"
  12. "github.com/hermeznetwork/hermez-node/test"
  13. "github.com/jmoiron/sqlx"
  14. "github.com/stretchr/testify/assert"
  15. )
  16. var l2DB *L2DB
  17. var tokens []common.Token
  18. var tokensUSD []historydb.TokenWithUSD
  19. func TestMain(m *testing.M) {
  20. // init DB
  21. pass := os.Getenv("POSTGRES_PASS")
  22. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  23. if err != nil {
  24. panic(err)
  25. }
  26. l2DB = NewL2DB(db, 10, 100, 24*time.Hour)
  27. tokens, tokensUSD = prepareHistoryDB(db)
  28. if err != nil {
  29. panic(err)
  30. }
  31. // Run tests
  32. result := m.Run()
  33. // Close DB
  34. if err := db.Close(); err != nil {
  35. log.Error("Error closing the history DB:", err)
  36. }
  37. os.Exit(result)
  38. }
  39. func prepareHistoryDB(db *sqlx.DB) ([]common.Token, []historydb.TokenWithUSD) {
  40. historyDB := historydb.NewHistoryDB(db)
  41. const fromBlock int64 = 1
  42. const toBlock int64 = 5
  43. // Clean historyDB
  44. if err := historyDB.Reorg(-1); err != nil {
  45. panic(err)
  46. }
  47. // Store blocks to historyDB
  48. blocks := test.GenBlocks(fromBlock, toBlock)
  49. if err := historyDB.AddBlocks(blocks); err != nil {
  50. panic(err)
  51. }
  52. // Store tokens to historyDB
  53. const nTokens = 5
  54. tokens := test.GenTokens(nTokens, blocks)
  55. if err := historyDB.AddTokens(tokens); err != nil {
  56. panic(err)
  57. }
  58. readTokens := []historydb.TokenWithUSD{}
  59. for i, token := range tokens {
  60. readToken := historydb.TokenWithUSD{
  61. TokenID: token.TokenID,
  62. EthBlockNum: token.EthBlockNum,
  63. EthAddr: token.EthAddr,
  64. Name: token.Name,
  65. Symbol: token.Symbol,
  66. Decimals: token.Decimals,
  67. }
  68. if i%2 != 0 {
  69. value := float64(i) * 5.4321
  70. if err := historyDB.UpdateTokenValue(token.Symbol, value); err != nil {
  71. panic(err)
  72. }
  73. now := time.Now().UTC()
  74. readToken.USDUpdate = &now
  75. readToken.USD = &value
  76. }
  77. readTokens = append(readTokens, readToken)
  78. }
  79. return tokens, readTokens
  80. }
  81. func TestAddTxTest(t *testing.T) {
  82. // Gen poolTxs
  83. const nInserts = 20
  84. test.CleanL2DB(l2DB.DB())
  85. txs := test.GenPoolTxs(nInserts, tokens)
  86. for _, tx := range txs {
  87. err := l2DB.AddTxTest(tx)
  88. assert.NoError(t, err)
  89. fetchedTx, err := l2DB.GetTx(tx.TxID)
  90. assert.NoError(t, err)
  91. assertReadTx(t, commonToRead(tx, tokens), fetchedTx)
  92. }
  93. }
  94. func commonToRead(commonTx *common.PoolL2Tx, tokens []common.Token) *PoolL2TxRead {
  95. readTx := &PoolL2TxRead{
  96. TxID: commonTx.TxID,
  97. FromIdx: commonTx.FromIdx,
  98. ToBJJ: commonTx.ToBJJ,
  99. Amount: commonTx.Amount,
  100. Fee: commonTx.Fee,
  101. Nonce: commonTx.Nonce,
  102. State: commonTx.State,
  103. Signature: commonTx.Signature,
  104. RqToBJJ: commonTx.RqToBJJ,
  105. RqAmount: commonTx.RqAmount,
  106. Type: commonTx.Type,
  107. Timestamp: commonTx.Timestamp,
  108. TokenID: commonTx.TokenID,
  109. }
  110. // token related fields
  111. // find token
  112. token := historydb.TokenWithUSD{}
  113. for _, tkn := range tokensUSD {
  114. if tkn.TokenID == readTx.TokenID {
  115. token = tkn
  116. break
  117. }
  118. }
  119. // set token related fields
  120. readTx.TokenEthBlockNum = token.EthBlockNum
  121. readTx.TokenEthAddr = token.EthAddr
  122. readTx.TokenName = token.Name
  123. readTx.TokenSymbol = token.Symbol
  124. readTx.TokenDecimals = token.Decimals
  125. readTx.TokenUSD = token.USD
  126. readTx.TokenUSDUpdate = token.USDUpdate
  127. // nullable fields
  128. if commonTx.ToIdx != 0 {
  129. readTx.ToIdx = &commonTx.ToIdx
  130. }
  131. nilAddr := ethCommon.BigToAddress(big.NewInt(0))
  132. if commonTx.ToEthAddr != nilAddr {
  133. readTx.ToEthAddr = &commonTx.ToEthAddr
  134. }
  135. if commonTx.RqFromIdx != 0 {
  136. readTx.RqFromIdx = &commonTx.RqFromIdx
  137. }
  138. if commonTx.RqToIdx != 0 { // if true, all Rq... fields must be different to nil
  139. readTx.RqToIdx = &commonTx.RqToIdx
  140. readTx.RqTokenID = &commonTx.RqTokenID
  141. readTx.RqFee = &commonTx.RqFee
  142. readTx.RqNonce = &commonTx.RqNonce
  143. }
  144. if commonTx.RqToEthAddr != nilAddr {
  145. readTx.RqToEthAddr = &commonTx.RqToEthAddr
  146. }
  147. return readTx
  148. }
  149. func assertReadTx(t *testing.T, expected, actual *PoolL2TxRead) {
  150. // Check that timestamp has been set within the last 3 seconds
  151. assert.Less(t, time.Now().UTC().Unix()-3, actual.Timestamp.Unix())
  152. assert.GreaterOrEqual(t, time.Now().UTC().Unix(), actual.Timestamp.Unix())
  153. expected.Timestamp = actual.Timestamp
  154. // Check token related stuff
  155. if expected.TokenUSDUpdate != nil {
  156. // Check that TokenUSDUpdate has been set within the last 3 seconds
  157. assert.Less(t, time.Now().UTC().Unix()-3, actual.TokenUSDUpdate.Unix())
  158. assert.GreaterOrEqual(t, time.Now().UTC().Unix(), actual.TokenUSDUpdate.Unix())
  159. expected.TokenUSDUpdate = actual.TokenUSDUpdate
  160. }
  161. assert.Equal(t, expected, actual)
  162. }
  163. func assertTx(t *testing.T, expected, actual *common.PoolL2Tx) {
  164. // Check that timestamp has been set within the last 3 seconds
  165. assert.Less(t, time.Now().UTC().Unix()-3, actual.Timestamp.Unix())
  166. assert.GreaterOrEqual(t, time.Now().UTC().Unix(), actual.Timestamp.Unix())
  167. expected.Timestamp = actual.Timestamp
  168. // Check absolute fee
  169. // find token
  170. token := historydb.TokenWithUSD{}
  171. for _, tkn := range tokensUSD {
  172. if expected.TokenID == tkn.TokenID {
  173. token = tkn
  174. break
  175. }
  176. }
  177. // If the token has value in USD setted
  178. if token.USDUpdate != nil {
  179. assert.Equal(t, token.USDUpdate.Unix(), actual.AbsoluteFeeUpdate.Unix())
  180. expected.AbsoluteFeeUpdate = actual.AbsoluteFeeUpdate
  181. // Set expected fee
  182. f := new(big.Float).SetInt(expected.Amount)
  183. amountF, _ := f.Float64()
  184. expected.AbsoluteFee = *token.USD * amountF * expected.Fee.Percentage()
  185. test.AssertUSD(t, &expected.AbsoluteFee, &actual.AbsoluteFee)
  186. }
  187. assert.Equal(t, expected, actual)
  188. }
  189. func BenchmarkAddTxTest(b *testing.B) {
  190. const nInserts = 20
  191. test.CleanL2DB(l2DB.DB())
  192. txs := test.GenPoolTxs(nInserts, tokens)
  193. now := time.Now()
  194. for _, tx := range txs {
  195. _ = l2DB.AddTxTest(tx)
  196. }
  197. elapsedTime := time.Since(now)
  198. log.Info("Time to insert 2048 txs:", elapsedTime)
  199. }
  200. func TestGetPending(t *testing.T) {
  201. const nInserts = 20
  202. test.CleanL2DB(l2DB.DB())
  203. txs := test.GenPoolTxs(nInserts, tokens)
  204. var pendingTxs []*common.PoolL2Tx
  205. for _, tx := range txs {
  206. err := l2DB.AddTxTest(tx)
  207. assert.NoError(t, err)
  208. if tx.State == common.PoolL2TxStatePending {
  209. pendingTxs = append(pendingTxs, tx)
  210. }
  211. }
  212. fetchedTxs, err := l2DB.GetPendingTxs()
  213. assert.NoError(t, err)
  214. assert.Equal(t, len(pendingTxs), len(fetchedTxs))
  215. for i := range fetchedTxs {
  216. assertTx(t, pendingTxs[i], &fetchedTxs[i])
  217. }
  218. }
  219. /*
  220. WARNING: this should be fixed once transaktio is ready
  221. func TestStartForging(t *testing.T) {
  222. // Generate txs
  223. const nInserts = 60
  224. const fakeBatchNum common.BatchNum = 33
  225. test.CleanL2DB(l2DB.DB())
  226. txs := test.GenPoolTxs(nInserts, tokens)
  227. var startForgingTxIDs []common.TxID
  228. randomizer := 0
  229. // Add txs to DB
  230. for _, tx := range txs {
  231. err := l2DB.AddTxTest(tx)
  232. assert.NoError(t, err)
  233. if tx.State == common.PoolL2TxStatePending && randomizer%2 == 0 {
  234. randomizer++
  235. startForgingTxIDs = append(startForgingTxIDs, tx.TxID)
  236. }
  237. }
  238. // Start forging txs
  239. err := l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
  240. assert.NoError(t, err)
  241. // Fetch txs and check that they've been updated correctly
  242. for _, id := range startForgingTxIDs {
  243. fetchedTx, err := l2DB.GetTx(id)
  244. assert.NoError(t, err)
  245. assert.Equal(t, common.PoolL2TxStateForging, fetchedTx.State)
  246. assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
  247. }
  248. }
  249. */
  250. /*
  251. WARNING: this should be fixed once transaktio is ready
  252. func TestDoneForging(t *testing.T) {
  253. // Generate txs
  254. const nInserts = 60
  255. const fakeBatchNum common.BatchNum = 33
  256. test.CleanL2DB(l2DB.DB())
  257. txs := test.GenPoolTxs(nInserts, tokens)
  258. var doneForgingTxIDs []common.TxID
  259. randomizer := 0
  260. // Add txs to DB
  261. for _, tx := range txs {
  262. err := l2DB.AddTxTest(tx)
  263. assert.NoError(t, err)
  264. if tx.State == common.PoolL2TxStateForging && randomizer%2 == 0 {
  265. randomizer++
  266. doneForgingTxIDs = append(doneForgingTxIDs, tx.TxID)
  267. }
  268. }
  269. // Start forging txs
  270. err := l2DB.DoneForging(doneForgingTxIDs, fakeBatchNum)
  271. assert.NoError(t, err)
  272. // Fetch txs and check that they've been updated correctly
  273. for _, id := range doneForgingTxIDs {
  274. fetchedTx, err := l2DB.GetTx(id)
  275. assert.NoError(t, err)
  276. assert.Equal(t, common.PoolL2TxStateForged, fetchedTx.State)
  277. assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
  278. }
  279. }
  280. */
  281. /*
  282. WARNING: this should be fixed once transaktio is ready
  283. func TestInvalidate(t *testing.T) {
  284. // Generate txs
  285. const nInserts = 60
  286. const fakeBatchNum common.BatchNum = 33
  287. test.CleanL2DB(l2DB.DB())
  288. txs := test.GenPoolTxs(nInserts, tokens)
  289. var invalidTxIDs []common.TxID
  290. randomizer := 0
  291. // Add txs to DB
  292. for _, tx := range txs {
  293. err := l2DB.AddTxTest(tx)
  294. assert.NoError(t, err)
  295. if tx.State != common.PoolL2TxStateInvalid && randomizer%2 == 0 {
  296. randomizer++
  297. invalidTxIDs = append(invalidTxIDs, tx.TxID)
  298. }
  299. }
  300. // Start forging txs
  301. err := l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
  302. assert.NoError(t, err)
  303. // Fetch txs and check that they've been updated correctly
  304. for _, id := range invalidTxIDs {
  305. fetchedTx, err := l2DB.GetTx(id)
  306. assert.NoError(t, err)
  307. assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
  308. assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
  309. }
  310. }
  311. */
  312. /*
  313. WARNING: this should be fixed once transaktio is ready
  314. func TestCheckNonces(t *testing.T) {
  315. // Generate txs
  316. const nInserts = 60
  317. const fakeBatchNum common.BatchNum = 33
  318. test.CleanL2DB(l2DB.DB())
  319. txs := test.GenPoolTxs(nInserts, tokens)
  320. var invalidTxIDs []common.TxID
  321. // Generate accounts
  322. const nAccoutns = 2
  323. const currentNonce = 2
  324. accs := []common.Account{}
  325. for i := 0; i < nAccoutns; i++ {
  326. accs = append(accs, common.Account{
  327. Idx: common.Idx(i),
  328. Nonce: currentNonce,
  329. })
  330. }
  331. // Add txs to DB
  332. for i := 0; i < len(txs); i++ {
  333. if txs[i].State != common.PoolL2TxStateInvalid {
  334. if i%2 == 0 { // Ensure transaction will be marked as invalid due to old nonce
  335. txs[i].Nonce = accs[i%len(accs)].Nonce
  336. txs[i].FromIdx = accs[i%len(accs)].Idx
  337. invalidTxIDs = append(invalidTxIDs, txs[i].TxID)
  338. } else { // Ensure transaction will NOT be marked as invalid due to old nonce
  339. txs[i].Nonce = currentNonce + 1
  340. }
  341. }
  342. err := l2DB.AddTxTest(txs[i])
  343. assert.NoError(t, err)
  344. }
  345. // Start forging txs
  346. err := l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
  347. assert.NoError(t, err)
  348. // Fetch txs and check that they've been updated correctly
  349. for _, id := range invalidTxIDs {
  350. fetchedTx, err := l2DB.GetTx(id)
  351. assert.NoError(t, err)
  352. assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
  353. assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
  354. }
  355. }
  356. */
  357. func TestReorg(t *testing.T) {
  358. // Generate txs
  359. const nInserts = 20
  360. const lastValidBatch common.BatchNum = 20
  361. const reorgBatch common.BatchNum = lastValidBatch + 1
  362. test.CleanL2DB(l2DB.DB())
  363. txs := test.GenPoolTxs(nInserts, tokens)
  364. // Add txs to the DB
  365. reorgedTxIDs := []common.TxID{}
  366. nonReorgedTxIDs := []common.TxID{}
  367. for i := 0; i < len(txs); i++ {
  368. err := l2DB.AddTxTest(txs[i])
  369. assert.NoError(t, err)
  370. var batchNum common.BatchNum
  371. if txs[i].State == common.PoolL2TxStateForged || txs[i].State == common.PoolL2TxStateInvalid {
  372. reorgedTxIDs = append(reorgedTxIDs, txs[i].TxID)
  373. batchNum = reorgBatch
  374. } else {
  375. nonReorgedTxIDs = append(nonReorgedTxIDs, txs[i].TxID)
  376. batchNum = lastValidBatch
  377. }
  378. _, err = l2DB.db.Exec(
  379. "UPDATE tx_pool SET batch_num = $1 WHERE tx_id = $2;",
  380. batchNum, txs[i].TxID,
  381. )
  382. assert.NoError(t, err)
  383. }
  384. err := l2DB.Reorg(lastValidBatch)
  385. assert.NoError(t, err)
  386. for _, id := range reorgedTxIDs {
  387. tx, err := l2DB.GetTx(id)
  388. assert.NoError(t, err)
  389. assert.Nil(t, tx.BatchNum)
  390. assert.Equal(t, common.PoolL2TxStatePending, tx.State)
  391. }
  392. for _, id := range nonReorgedTxIDs {
  393. fetchedTx, err := l2DB.GetTx(id)
  394. assert.NoError(t, err)
  395. assert.Equal(t, lastValidBatch, *fetchedTx.BatchNum)
  396. }
  397. }
  398. func TestPurge(t *testing.T) {
  399. /*
  400. WARNING: this should be fixed once transaktio is ready
  401. // Generate txs
  402. nInserts := l2DB.maxTxs + 20
  403. test.CleanL2DB(l2DB.DB())
  404. txs := test.GenPoolTxs(int(nInserts), tokens)
  405. deletedIDs := []common.TxID{}
  406. keepedIDs := []common.TxID{}
  407. const toDeleteBatchNum common.BatchNum = 30
  408. safeBatchNum := toDeleteBatchNum + l2DB.safetyPeriod + 1
  409. // Add txs to the DB
  410. for i := 0; i < int(l2DB.maxTxs); i++ {
  411. var batchNum common.BatchNum
  412. if i%2 == 0 { // keep tx
  413. batchNum = safeBatchNum
  414. keepedIDs = append(keepedIDs, txs[i].TxID)
  415. } else { // delete after safety period
  416. batchNum = toDeleteBatchNum
  417. if i%3 == 0 {
  418. txs[i].State = common.PoolL2TxStateForged
  419. } else {
  420. txs[i].State = common.PoolL2TxStateInvalid
  421. }
  422. deletedIDs = append(deletedIDs, txs[i].TxID)
  423. }
  424. err := l2DB.AddTxTest(txs[i])
  425. assert.NoError(t, err)
  426. // Set batchNum
  427. _, err = l2DB.db.Exec(
  428. "UPDATE tx_pool SET batch_num = $1 WHERE tx_id = $2;",
  429. batchNum, txs[i].TxID,
  430. )
  431. assert.NoError(t, err)
  432. }
  433. for i := int(l2DB.maxTxs); i < len(txs); i++ {
  434. // Delete after TTL
  435. deletedIDs = append(deletedIDs, txs[i].TxID)
  436. err := l2DB.AddTxTest(txs[i])
  437. assert.NoError(t, err)
  438. // Set timestamp
  439. deleteTimestamp := time.Unix(time.Now().UTC().Unix()-int64(l2DB.ttl.Seconds()+float64(4*time.Second)), 0)
  440. _, err = l2DB.db.Exec(
  441. "UPDATE tx_pool SET timestamp = $1 WHERE tx_id = $2;",
  442. deleteTimestamp, txs[i].TxID,
  443. )
  444. assert.NoError(t, err)
  445. }
  446. // Purge txs
  447. err := l2DB.Purge(safeBatchNum)
  448. assert.NoError(t, err)
  449. // Check results
  450. for _, id := range deletedIDs {
  451. tx, err := l2DB.GetTx(id)
  452. if err == nil {
  453. log.Debug(tx)
  454. }
  455. assert.Error(t, err)
  456. }
  457. for _, id := range keepedIDs {
  458. _, err := l2DB.GetTx(id)
  459. assert.NoError(t, err)
  460. }
  461. */
  462. }
  463. func TestAuth(t *testing.T) {
  464. test.CleanL2DB(l2DB.DB())
  465. const nAuths = 5
  466. // Generate authorizations
  467. auths := test.GenAuths(nAuths)
  468. for i := 0; i < len(auths); i++ {
  469. // Add to the DB
  470. err := l2DB.AddAccountCreationAuth(auths[i])
  471. assert.NoError(t, err)
  472. // Fetch from DB
  473. auth, err := l2DB.GetAccountCreationAuth(auths[i].EthAddr)
  474. assert.NoError(t, err)
  475. // Check fetched vs generated
  476. assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
  477. assert.Equal(t, auths[i].BJJ, auth.BJJ)
  478. assert.Equal(t, auths[i].Signature, auth.Signature)
  479. assert.Equal(t, auths[i].Timestamp.Unix(), auths[i].Timestamp.Unix())
  480. }
  481. }