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.

365 lines
11 KiB

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