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.

361 lines
11 KiB

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