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.

395 lines
12 KiB

  1. package historydb
  2. import (
  3. "math"
  4. "math/big"
  5. "os"
  6. "testing"
  7. "github.com/hermeznetwork/hermez-node/common"
  8. dbUtils "github.com/hermeznetwork/hermez-node/db"
  9. "github.com/hermeznetwork/hermez-node/log"
  10. "github.com/hermeznetwork/hermez-node/test"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. var historyDB *HistoryDB
  14. // In order to run the test you need to run a Posgres DB with
  15. // a database named "history" that is accessible by
  16. // user: "hermez"
  17. // pass: set it using the env var POSTGRES_PASS
  18. // This can be achieved by running: POSTGRES_PASS=your_strong_pass && sudo docker run --rm --name hermez-db-test -p 5432:5432 -e POSTGRES_DB=history -e POSTGRES_USER=hermez -e POSTGRES_PASSWORD=$POSTGRES_PASS -d postgres && sleep 2s && sudo docker exec -it hermez-db-test psql -a history -U hermez -c "CREATE DATABASE l2;"
  19. // After running the test you can stop the container by running: sudo docker kill hermez-db-test
  20. // If you already did that for the L2DB you don't have to do it again
  21. func TestMain(m *testing.M) {
  22. // init DB
  23. pass := os.Getenv("POSTGRES_PASS")
  24. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  25. if err != nil {
  26. panic(err)
  27. }
  28. historyDB = NewHistoryDB(db)
  29. if err != nil {
  30. panic(err)
  31. }
  32. // Run tests
  33. result := m.Run()
  34. // Close DB
  35. if err := db.Close(); err != nil {
  36. log.Error("Error closing the history DB:", err)
  37. }
  38. os.Exit(result)
  39. }
  40. func TestBlocks(t *testing.T) {
  41. var fromBlock, toBlock int64
  42. fromBlock = 1
  43. toBlock = 5
  44. // Delete peviously created rows (clean previous test execs)
  45. assert.NoError(t, historyDB.Reorg(fromBlock-1))
  46. // Generate fake blocks
  47. blocks := test.GenBlocks(fromBlock, toBlock)
  48. // Insert blocks into DB
  49. for i := 0; i < len(blocks); i++ {
  50. err := historyDB.AddBlock(&blocks[i])
  51. assert.NoError(t, err)
  52. }
  53. // Get all blocks from DB
  54. fetchedBlocks, err := historyDB.GetBlocks(fromBlock, toBlock)
  55. assert.Equal(t, len(blocks), len(fetchedBlocks))
  56. // Compare generated vs getted blocks
  57. assert.NoError(t, err)
  58. for i := range fetchedBlocks {
  59. assertEqualBlock(t, &blocks[i], &fetchedBlocks[i])
  60. }
  61. // Get blocks from the DB one by one
  62. for i := fromBlock; i < toBlock; i++ {
  63. fetchedBlock, err := historyDB.GetBlock(i)
  64. assert.NoError(t, err)
  65. assertEqualBlock(t, &blocks[i-1], fetchedBlock)
  66. }
  67. // Get last block
  68. lastBlock, err := historyDB.GetLastBlock()
  69. assert.NoError(t, err)
  70. assertEqualBlock(t, &blocks[len(blocks)-1], lastBlock)
  71. }
  72. func assertEqualBlock(t *testing.T, expected *common.Block, actual *common.Block) {
  73. assert.Equal(t, expected.EthBlockNum, actual.EthBlockNum)
  74. assert.Equal(t, expected.Hash, actual.Hash)
  75. assert.Equal(t, expected.Timestamp.Unix(), actual.Timestamp.Unix())
  76. }
  77. func TestBatches(t *testing.T) {
  78. const fromBlock int64 = 1
  79. const toBlock int64 = 3
  80. // Prepare blocks in the DB
  81. blocks := setTestBlocks(fromBlock, toBlock)
  82. // Generate fake batches
  83. const nBatches = 9
  84. batches := test.GenBatches(nBatches, blocks)
  85. // Test GetLastL1TxsNum with no batches
  86. fetchedLastL1TxsNum, err := historyDB.GetLastL1TxsNum()
  87. assert.NoError(t, err)
  88. assert.Nil(t, fetchedLastL1TxsNum)
  89. // Add batches to the DB
  90. err = historyDB.AddBatches(batches)
  91. assert.NoError(t, err)
  92. // Get batches from the DB
  93. fetchedBatches, err := historyDB.GetBatches(0, common.BatchNum(nBatches))
  94. assert.NoError(t, err)
  95. for i, fetchedBatch := range fetchedBatches {
  96. assert.Equal(t, batches[i], fetchedBatch)
  97. }
  98. // Test GetLastBatchNum
  99. fetchedLastBatchNum, err := historyDB.GetLastBatchNum()
  100. assert.NoError(t, err)
  101. assert.Equal(t, batches[len(batches)-1].BatchNum, fetchedLastBatchNum)
  102. // Test GetLastL1TxsNum
  103. fetchedLastL1TxsNum, err = historyDB.GetLastL1TxsNum()
  104. assert.NoError(t, err)
  105. assert.Equal(t, *batches[nBatches-1].ForgeL1TxsNum, *fetchedLastL1TxsNum)
  106. // Test total fee
  107. // Generate fake tokens
  108. const nTokens = 5
  109. tokens := test.GenTokens(nTokens, blocks)
  110. err = historyDB.AddTokens(tokens)
  111. assert.NoError(t, err)
  112. feeBatch := batches[0]
  113. feeBatch.BatchNum = 9999
  114. feeBatch.CollectedFees = make(map[common.TokenID]*big.Int)
  115. var total float64
  116. for i, token := range tokens {
  117. value := 3.019237 * float64(i)
  118. assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
  119. bigAmount := big.NewInt(345000000)
  120. feeBatch.CollectedFees[token.TokenID] = bigAmount
  121. f := new(big.Float).SetInt(bigAmount)
  122. amount, _ := f.Float64()
  123. total += value * (amount / math.Pow(10, float64(token.Decimals)))
  124. }
  125. err = historyDB.AddBatch(&feeBatch)
  126. assert.NoError(t, err)
  127. fetchedBatches, err = historyDB.GetBatches(feeBatch.BatchNum-1, feeBatch.BatchNum+1)
  128. assert.NoError(t, err)
  129. for _, fetchedBatch := range fetchedBatches {
  130. if fetchedBatch.BatchNum == feeBatch.BatchNum {
  131. assert.Equal(t, total, *fetchedBatch.TotalFeesUSD)
  132. }
  133. }
  134. }
  135. func TestBids(t *testing.T) {
  136. const fromBlock int64 = 1
  137. const toBlock int64 = 5
  138. // Prepare blocks in the DB
  139. blocks := setTestBlocks(fromBlock, toBlock)
  140. // Generate fake coordinators
  141. const nCoords = 5
  142. coords := test.GenCoordinators(nCoords, blocks)
  143. err := historyDB.AddCoordinators(coords)
  144. assert.NoError(t, err)
  145. // Generate fake bids
  146. const nBids = 20
  147. bids := test.GenBids(nBids, blocks, coords)
  148. err = historyDB.AddBids(bids)
  149. assert.NoError(t, err)
  150. // Fetch bids
  151. fetchedBids, err := historyDB.GetBids()
  152. assert.NoError(t, err)
  153. // Compare fetched bids vs generated bids
  154. for i, bid := range fetchedBids {
  155. assert.Equal(t, bids[i], bid)
  156. }
  157. }
  158. func TestTokens(t *testing.T) {
  159. const fromBlock int64 = 1
  160. const toBlock int64 = 5
  161. // Prepare blocks in the DB
  162. blocks := setTestBlocks(fromBlock, toBlock)
  163. // Generate fake tokens
  164. const nTokens = 5
  165. tokens := test.GenTokens(nTokens, blocks)
  166. err := historyDB.AddTokens(tokens)
  167. assert.NoError(t, err)
  168. limit := uint(10)
  169. // Fetch tokens6
  170. fetchedTokens, _, err := historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
  171. assert.NoError(t, err)
  172. // Compare fetched tokens vs generated tokens
  173. // All the tokens should have USDUpdate setted by the DB trigger
  174. for i, token := range fetchedTokens {
  175. assert.Equal(t, tokens[i].TokenID, token.TokenID)
  176. assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
  177. assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
  178. assert.Equal(t, tokens[i].Name, token.Name)
  179. assert.Equal(t, tokens[i].Symbol, token.Symbol)
  180. assert.Nil(t, token.USD)
  181. assert.Nil(t, token.USDUpdate)
  182. }
  183. }
  184. func TestAccounts(t *testing.T) {
  185. const fromBlock int64 = 1
  186. const toBlock int64 = 5
  187. // Prepare blocks in the DB
  188. blocks := setTestBlocks(fromBlock, toBlock)
  189. // Generate fake tokens
  190. const nTokens = 5
  191. tokens := test.GenTokens(nTokens, blocks)
  192. err := historyDB.AddTokens(tokens)
  193. assert.NoError(t, err)
  194. // Generate fake batches
  195. const nBatches = 10
  196. batches := test.GenBatches(nBatches, blocks)
  197. err = historyDB.AddBatches(batches)
  198. assert.NoError(t, err)
  199. // Generate fake accounts
  200. const nAccounts = 3
  201. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  202. err = historyDB.AddAccounts(accs)
  203. assert.NoError(t, err)
  204. // Fetch accounts
  205. fetchedAccs, err := historyDB.GetAccounts()
  206. assert.NoError(t, err)
  207. // Compare fetched accounts vs generated accounts
  208. for i, acc := range fetchedAccs {
  209. accs[i].Balance = nil
  210. assert.Equal(t, accs[i], acc)
  211. }
  212. }
  213. func TestTxs(t *testing.T) {
  214. const fromBlock int64 = 1
  215. const toBlock int64 = 5
  216. // Prepare blocks in the DB
  217. blocks := setTestBlocks(fromBlock, toBlock)
  218. // Generate fake tokens
  219. const nTokens = 500
  220. tokens := test.GenTokens(nTokens, blocks)
  221. err := historyDB.AddTokens(tokens)
  222. assert.NoError(t, err)
  223. // Generate fake batches
  224. const nBatches = 10
  225. batches := test.GenBatches(nBatches, blocks)
  226. err = historyDB.AddBatches(batches)
  227. assert.NoError(t, err)
  228. // Generate fake accounts
  229. const nAccounts = 3
  230. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  231. err = historyDB.AddAccounts(accs)
  232. assert.NoError(t, err)
  233. /*
  234. Uncomment once the transaction generation is fixed
  235. !! test that batches that forge user L1s !!
  236. !! Missing tests to check that historic USD is not set if USDUpdate is too old (24h) !!
  237. // Generate fake L1 txs
  238. const nL1s = 64
  239. _, l1txs := test.GenL1Txs(256, nL1s, 0, nil, accs, tokens, blocks, batches)
  240. err = historyDB.AddL1Txs(l1txs)
  241. assert.NoError(t, err)
  242. // Generate fake L2 txs
  243. const nL2s = 2048 - nL1s
  244. _, l2txs := test.GenL2Txs(256, nL2s, 0, nil, accs, tokens, blocks, batches)
  245. err = historyDB.AddL2Txs(l2txs)
  246. assert.NoError(t, err)
  247. // Compare fetched txs vs generated txs.
  248. fetchAndAssertTxs(t, l1txs, l2txs)
  249. // Test trigger: L1 integrity
  250. // from_eth_addr can't be null
  251. l1txs[0].FromEthAddr = ethCommon.Address{}
  252. err = historyDB.AddL1Txs(l1txs)
  253. assert.Error(t, err)
  254. l1txs[0].FromEthAddr = ethCommon.BigToAddress(big.NewInt(int64(5)))
  255. // from_bjj can't be null
  256. l1txs[0].FromBJJ = nil
  257. err = historyDB.AddL1Txs(l1txs)
  258. assert.Error(t, err)
  259. privK := babyjub.NewRandPrivKey()
  260. l1txs[0].FromBJJ = privK.Public()
  261. // load_amount can't be null
  262. l1txs[0].LoadAmount = nil
  263. err = historyDB.AddL1Txs(l1txs)
  264. assert.Error(t, err)
  265. // Test trigger: L2 integrity
  266. // batch_num can't be null
  267. l2txs[0].BatchNum = 0
  268. err = historyDB.AddL2Txs(l2txs)
  269. assert.Error(t, err)
  270. l2txs[0].BatchNum = 1
  271. // nonce can't be null
  272. l2txs[0].Nonce = 0
  273. err = historyDB.AddL2Txs(l2txs)
  274. assert.Error(t, err)
  275. // Test trigger: forge L1 txs
  276. // add next batch to DB
  277. batchNum, toForgeL1TxsNum := test.GetNextToForgeNumAndBatch(batches)
  278. batch := batches[0]
  279. batch.BatchNum = batchNum
  280. batch.ForgeL1TxsNum = toForgeL1TxsNum
  281. assert.NoError(t, historyDB.AddBatch(&batch)) // This should update nL1s / 2 rows
  282. // Set batch num in txs that should have been marked as forged in the DB
  283. for i := 0; i < len(l1txs); i++ {
  284. fetchedTx, err := historyDB.GetTx(l1txs[i].TxID)
  285. assert.NoError(t, err)
  286. if l1txs[i].ToForgeL1TxsNum == toForgeL1TxsNum {
  287. assert.Equal(t, batchNum, *fetchedTx.BatchNum)
  288. } else {
  289. if fetchedTx.BatchNum != nil {
  290. assert.NotEqual(t, batchNum, *fetchedTx.BatchNum)
  291. }
  292. }
  293. }
  294. // Test helper functions for Synchronizer
  295. // GetLastTxsPosition
  296. expectedPosition := -1
  297. var choosenToForgeL1TxsNum int64 = -1
  298. for _, tx := range l1txs {
  299. if choosenToForgeL1TxsNum == -1 && tx.ToForgeL1TxsNum > 0 {
  300. choosenToForgeL1TxsNum = tx.ToForgeL1TxsNum
  301. expectedPosition = tx.Position
  302. } else if choosenToForgeL1TxsNum == tx.ToForgeL1TxsNum && expectedPosition < tx.Position {
  303. expectedPosition = tx.Position
  304. }
  305. }
  306. position, err := historyDB.GetLastTxsPosition(choosenToForgeL1TxsNum)
  307. assert.NoError(t, err)
  308. assert.Equal(t, expectedPosition, position)
  309. // GetL1UserTxs: not needed? tests were broken
  310. // txs, err := historyDB.GetL1UserTxs(2)
  311. // assert.NoError(t, err)
  312. // assert.NotZero(t, len(txs))
  313. // assert.NoError(t, err)
  314. // assert.Equal(t, 22, position)
  315. // // Test Update L1 TX Batch_num
  316. // assert.Equal(t, common.BatchNum(0), txs[0].BatchNum)
  317. // txs[0].BatchNum = common.BatchNum(1)
  318. // txs, err = historyDB.GetL1UserTxs(2)
  319. // assert.NoError(t, err)
  320. // assert.NotZero(t, len(txs))
  321. // assert.Equal(t, common.BatchNum(1), txs[0].BatchNum)
  322. */
  323. }
  324. /*
  325. func fetchAndAssertTxs(t *testing.T, l1txs []common.L1Tx, l2txs []common.L2Tx) {
  326. for i := 0; i < len(l1txs); i++ {
  327. tx := l1txs[i].Tx()
  328. fmt.Println("ASDF", i, tx.TxID)
  329. fetchedTx, err := historyDB.GetTx(tx.TxID)
  330. require.NoError(t, err)
  331. test.AssertUSD(t, tx.USD, fetchedTx.USD)
  332. test.AssertUSD(t, tx.LoadAmountUSD, fetchedTx.LoadAmountUSD)
  333. assert.Equal(t, tx, fetchedTx)
  334. }
  335. for i := 0; i < len(l2txs); i++ {
  336. tx := l2txs[i].Tx()
  337. fetchedTx, err := historyDB.GetTx(tx.TxID)
  338. tx.TokenID = fetchedTx.TokenID
  339. assert.NoError(t, err)
  340. test.AssertUSD(t, fetchedTx.USD, tx.USD)
  341. test.AssertUSD(t, fetchedTx.FeeUSD, tx.FeeUSD)
  342. assert.Equal(t, tx, fetchedTx)
  343. }
  344. }
  345. */
  346. func TestExitTree(t *testing.T) {
  347. nBatches := 17
  348. blocks := setTestBlocks(0, 10)
  349. batches := test.GenBatches(nBatches, blocks)
  350. err := historyDB.AddBatches(batches)
  351. const nTokens = 50
  352. tokens := test.GenTokens(nTokens, blocks)
  353. assert.NoError(t, historyDB.AddTokens(tokens))
  354. assert.NoError(t, err)
  355. const nAccounts = 3
  356. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  357. assert.NoError(t, historyDB.AddAccounts(accs))
  358. exitTree := test.GenExitTree(nBatches, batches, accs)
  359. err = historyDB.AddExitTree(exitTree)
  360. assert.NoError(t, err)
  361. }
  362. // setTestBlocks WARNING: this will delete the blocks and recreate them
  363. func setTestBlocks(from, to int64) []common.Block {
  364. if err := cleanHistoryDB(); err != nil {
  365. panic(err)
  366. }
  367. blocks := test.GenBlocks(from, to)
  368. if err := historyDB.AddBlocks(blocks); err != nil {
  369. panic(err)
  370. }
  371. return blocks
  372. }
  373. func cleanHistoryDB() error {
  374. return historyDB.Reorg(-1)
  375. }