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.

356 lines
11 KiB

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