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.

357 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. // Fetch tokens
  139. fetchedTokens, err := historyDB.GetTokens()
  140. assert.NoError(t, err)
  141. // Compare fetched tokens vs generated tokens
  142. // All the tokens should have USDUpdate setted by the DB trigger
  143. for i, token := range fetchedTokens {
  144. assert.Equal(t, tokens[i].TokenID, token.TokenID)
  145. assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
  146. assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
  147. assert.Equal(t, tokens[i].Name, token.Name)
  148. assert.Equal(t, tokens[i].Symbol, token.Symbol)
  149. assert.Nil(t, token.USD)
  150. assert.Nil(t, token.USDUpdate)
  151. }
  152. }
  153. func TestAccounts(t *testing.T) {
  154. const fromBlock int64 = 1
  155. const toBlock int64 = 5
  156. // Prepare blocks in the DB
  157. blocks := setTestBlocks(fromBlock, toBlock)
  158. // Generate fake tokens
  159. const nTokens = 5
  160. tokens := test.GenTokens(nTokens, blocks)
  161. err := historyDB.AddTokens(tokens)
  162. assert.NoError(t, err)
  163. // Generate fake batches
  164. const nBatches = 10
  165. batches := test.GenBatches(nBatches, blocks)
  166. err = historyDB.AddBatches(batches)
  167. assert.NoError(t, err)
  168. // Generate fake accounts
  169. const nAccounts = 3
  170. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  171. err = historyDB.AddAccounts(accs)
  172. assert.NoError(t, err)
  173. // Fetch accounts
  174. fetchedAccs, err := historyDB.GetAccounts()
  175. assert.NoError(t, err)
  176. // Compare fetched accounts vs generated accounts
  177. for i, acc := range fetchedAccs {
  178. assert.Equal(t, accs[i], acc)
  179. }
  180. }
  181. func TestTxs(t *testing.T) {
  182. const fromBlock int64 = 1
  183. const toBlock int64 = 5
  184. // Prepare blocks in the DB
  185. blocks := setTestBlocks(fromBlock, toBlock)
  186. // Generate fake tokens
  187. const nTokens = 500
  188. tokens := test.GenTokens(nTokens, blocks)
  189. err := historyDB.AddTokens(tokens)
  190. assert.NoError(t, err)
  191. // Generate fake batches
  192. const nBatches = 10
  193. batches := test.GenBatches(nBatches, blocks)
  194. err = historyDB.AddBatches(batches)
  195. assert.NoError(t, err)
  196. // Generate fake accounts
  197. const nAccounts = 3
  198. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  199. err = historyDB.AddAccounts(accs)
  200. assert.NoError(t, err)
  201. /*
  202. Uncomment once the transaction generation is fixed
  203. !! Missing tests to check that historic USD is not set if USDUpdate is too old (24h) !!
  204. // Generate fake L1 txs
  205. const nL1s = 64
  206. _, l1txs := test.GenL1Txs(256, nL1s, 0, nil, accs, tokens, blocks, batches)
  207. err = historyDB.AddL1Txs(l1txs)
  208. assert.NoError(t, err)
  209. // Generate fake L2 txs
  210. const nL2s = 2048 - nL1s
  211. _, l2txs := test.GenL2Txs(256, nL2s, 0, nil, accs, tokens, blocks, batches)
  212. err = historyDB.AddL2Txs(l2txs)
  213. assert.NoError(t, err)
  214. // Compare fetched txs vs generated txs.
  215. fetchAndAssertTxs(t, l1txs, l2txs)
  216. // Test trigger: L1 integrity
  217. // from_eth_addr can't be null
  218. l1txs[0].FromEthAddr = ethCommon.Address{}
  219. err = historyDB.AddL1Txs(l1txs)
  220. assert.Error(t, err)
  221. l1txs[0].FromEthAddr = ethCommon.BigToAddress(big.NewInt(int64(5)))
  222. // from_bjj can't be null
  223. l1txs[0].FromBJJ = nil
  224. err = historyDB.AddL1Txs(l1txs)
  225. assert.Error(t, err)
  226. privK := babyjub.NewRandPrivKey()
  227. l1txs[0].FromBJJ = privK.Public()
  228. // load_amount can't be null
  229. l1txs[0].LoadAmount = nil
  230. err = historyDB.AddL1Txs(l1txs)
  231. assert.Error(t, err)
  232. // Test trigger: L2 integrity
  233. // batch_num can't be null
  234. l2txs[0].BatchNum = 0
  235. err = historyDB.AddL2Txs(l2txs)
  236. assert.Error(t, err)
  237. l2txs[0].BatchNum = 1
  238. // nonce can't be null
  239. l2txs[0].Nonce = 0
  240. err = historyDB.AddL2Txs(l2txs)
  241. assert.Error(t, err)
  242. // Test trigger: forge L1 txs
  243. // add next batch to DB
  244. batchNum, toForgeL1TxsNum := test.GetNextToForgeNumAndBatch(batches)
  245. batch := batches[0]
  246. batch.BatchNum = batchNum
  247. batch.ForgeL1TxsNum = toForgeL1TxsNum
  248. assert.NoError(t, historyDB.AddBatch(&batch)) // This should update nL1s / 2 rows
  249. // Set batch num in txs that should have been marked as forged in the DB
  250. for i := 0; i < len(l1txs); i++ {
  251. fetchedTx, err := historyDB.GetTx(l1txs[i].TxID)
  252. assert.NoError(t, err)
  253. if l1txs[i].ToForgeL1TxsNum == toForgeL1TxsNum {
  254. assert.Equal(t, batchNum, *fetchedTx.BatchNum)
  255. } else {
  256. if fetchedTx.BatchNum != nil {
  257. assert.NotEqual(t, batchNum, *fetchedTx.BatchNum)
  258. }
  259. }
  260. }
  261. // Test helper functions for Synchronizer
  262. // GetLastTxsPosition
  263. expectedPosition := -1
  264. var choosenToForgeL1TxsNum int64 = -1
  265. for _, tx := range l1txs {
  266. if choosenToForgeL1TxsNum == -1 && tx.ToForgeL1TxsNum > 0 {
  267. choosenToForgeL1TxsNum = tx.ToForgeL1TxsNum
  268. expectedPosition = tx.Position
  269. } else if choosenToForgeL1TxsNum == tx.ToForgeL1TxsNum && expectedPosition < tx.Position {
  270. expectedPosition = tx.Position
  271. }
  272. }
  273. position, err := historyDB.GetLastTxsPosition(choosenToForgeL1TxsNum)
  274. assert.NoError(t, err)
  275. assert.Equal(t, expectedPosition, position)
  276. // GetL1UserTxs: not needed? tests were broken
  277. // txs, err := historyDB.GetL1UserTxs(2)
  278. // assert.NoError(t, err)
  279. // assert.NotZero(t, len(txs))
  280. // assert.NoError(t, err)
  281. // assert.Equal(t, 22, position)
  282. // // Test Update L1 TX Batch_num
  283. // assert.Equal(t, common.BatchNum(0), txs[0].BatchNum)
  284. // txs[0].BatchNum = common.BatchNum(1)
  285. // txs, err = historyDB.GetL1UserTxs(2)
  286. // assert.NoError(t, err)
  287. // assert.NotZero(t, len(txs))
  288. // assert.Equal(t, common.BatchNum(1), txs[0].BatchNum)
  289. */
  290. }
  291. /*
  292. func fetchAndAssertTxs(t *testing.T, l1txs []common.L1Tx, l2txs []common.L2Tx) {
  293. for i := 0; i < len(l1txs); i++ {
  294. tx := l1txs[i].Tx()
  295. fmt.Println("ASDF", i, tx.TxID)
  296. fetchedTx, err := historyDB.GetTx(tx.TxID)
  297. require.NoError(t, err)
  298. test.AssertUSD(t, tx.USD, fetchedTx.USD)
  299. test.AssertUSD(t, tx.LoadAmountUSD, fetchedTx.LoadAmountUSD)
  300. assert.Equal(t, tx, fetchedTx)
  301. }
  302. for i := 0; i < len(l2txs); i++ {
  303. tx := l2txs[i].Tx()
  304. fetchedTx, err := historyDB.GetTx(tx.TxID)
  305. tx.TokenID = fetchedTx.TokenID
  306. assert.NoError(t, err)
  307. test.AssertUSD(t, fetchedTx.USD, tx.USD)
  308. test.AssertUSD(t, fetchedTx.FeeUSD, tx.FeeUSD)
  309. assert.Equal(t, tx, fetchedTx)
  310. }
  311. }
  312. */
  313. func TestExitTree(t *testing.T) {
  314. nBatches := 17
  315. blocks := setTestBlocks(0, 10)
  316. batches := test.GenBatches(nBatches, blocks)
  317. err := historyDB.AddBatches(batches)
  318. assert.NoError(t, err)
  319. exitTree := test.GenExitTree(nBatches)
  320. err = historyDB.AddExitTree(exitTree)
  321. assert.NoError(t, err)
  322. }
  323. // setTestBlocks WARNING: this will delete the blocks and recreate them
  324. func setTestBlocks(from, to int64) []common.Block {
  325. if err := cleanHistoryDB(); err != nil {
  326. panic(err)
  327. }
  328. blocks := test.GenBlocks(from, to)
  329. if err := historyDB.AddBlocks(blocks); err != nil {
  330. panic(err)
  331. }
  332. return blocks
  333. }
  334. func cleanHistoryDB() error {
  335. return historyDB.Reorg(-1)
  336. }