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.

352 lines
11 KiB

4 years ago
  1. package historydb
  2. import (
  3. "fmt"
  4. "math/big"
  5. "os"
  6. "testing"
  7. "time"
  8. ethCommon "github.com/ethereum/go-ethereum/common"
  9. "github.com/hermeznetwork/hermez-node/common"
  10. "github.com/hermeznetwork/hermez-node/test"
  11. "github.com/iden3/go-iden3-crypto/babyjub"
  12. "github.com/stretchr/testify/assert"
  13. )
  14. var historyDB *HistoryDB
  15. // In order to run the test you need to run a Posgres DB with
  16. // a database named "history" that is accessible by
  17. // user: "hermez"
  18. // pass: set it using the env var POSTGRES_PASS
  19. // 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;"
  20. // After running the test you can stop the container by running: sudo docker kill hermez-db-test
  21. // If you already did that for the L2DB you don't have to do it again
  22. func TestMain(m *testing.M) {
  23. // init DB
  24. var err error
  25. pass := os.Getenv("POSTGRES_PASS")
  26. historyDB, err = NewHistoryDB(5432, "localhost", "hermez", pass, "history")
  27. if err != nil {
  28. panic(err)
  29. }
  30. // Run tests
  31. result := m.Run()
  32. // Close DB
  33. if err := historyDB.Close(); err != nil {
  34. fmt.Println("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, fetchedBlock := range fetchedBlocks {
  57. assertEqualBlock(t, &blocks[i], fetchedBlock)
  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. // Update price of generated tokens without price
  139. for i := 0; i < len(tokens); i++ {
  140. if tokens[i].USD == 0 {
  141. value := 3.33 + float64(i)
  142. tokens[i].USD = value
  143. err := historyDB.UpdateTokenValue(tokens[i].TokenID, value)
  144. assert.NoError(t, err)
  145. }
  146. }
  147. // Fetch tokens
  148. fetchedTokens, err := historyDB.GetTokens()
  149. assert.NoError(t, err)
  150. // Compare fetched tokens vs generated tokens
  151. // All the tokens should have USDUpdate setted by the DB trigger
  152. for i, token := range fetchedTokens {
  153. assert.Equal(t, tokens[i].TokenID, token.TokenID)
  154. assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
  155. assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
  156. assert.Equal(t, tokens[i].Name, token.Name)
  157. assert.Equal(t, tokens[i].Symbol, token.Symbol)
  158. assert.Equal(t, tokens[i].USD, token.USD)
  159. assert.Greater(t, int64(1*time.Second), int64(time.Since(token.USDUpdate)))
  160. }
  161. }
  162. func TestAccounts(t *testing.T) {
  163. const fromBlock int64 = 1
  164. const toBlock int64 = 5
  165. // Prepare blocks in the DB
  166. blocks := setTestBlocks(fromBlock, toBlock)
  167. // Generate fake tokens
  168. const nTokens = 5
  169. tokens := test.GenTokens(nTokens, blocks)
  170. err := historyDB.AddTokens(tokens)
  171. assert.NoError(t, err)
  172. // Generate fake batches
  173. const nBatches = 10
  174. batches := test.GenBatches(nBatches, blocks)
  175. err = historyDB.AddBatches(batches)
  176. assert.NoError(t, err)
  177. // Generate fake accounts
  178. const nAccounts = 3
  179. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  180. err = historyDB.AddAccounts(accs)
  181. assert.NoError(t, err)
  182. // Fetch accounts
  183. fetchedAccs, err := historyDB.GetAccounts()
  184. assert.NoError(t, err)
  185. // Compare fetched accounts vs generated accounts
  186. for i, acc := range fetchedAccs {
  187. assert.Equal(t, accs[i], *acc)
  188. }
  189. }
  190. func TestTxs(t *testing.T) {
  191. const fromBlock int64 = 1
  192. const toBlock int64 = 5
  193. // Prepare blocks in the DB
  194. blocks := setTestBlocks(fromBlock, toBlock)
  195. // Generate fake tokens
  196. const nTokens = 5
  197. const tokenValue = 1.23456
  198. tokens := test.GenTokens(nTokens, blocks)
  199. for i := 0; i < len(tokens); i++ {
  200. tokens[i].USD = tokenValue
  201. }
  202. err := historyDB.AddTokens(tokens)
  203. assert.NoError(t, err)
  204. // Generate fake batches
  205. const nBatches = 10
  206. batches := test.GenBatches(nBatches, blocks)
  207. err = historyDB.AddBatches(batches)
  208. assert.NoError(t, err)
  209. // Generate fake accounts
  210. const nAccounts = 3
  211. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  212. err = historyDB.AddAccounts(accs)
  213. assert.NoError(t, err)
  214. // Generate fake L1 txs
  215. const nL1s = 30
  216. _, l1txs := test.GenL1Txs(0, nL1s, 0, nil, accs, tokens, blocks, batches)
  217. err = historyDB.AddL1Txs(l1txs)
  218. assert.NoError(t, err)
  219. // Generate fake L2 txs
  220. const nL2s = 20
  221. _, l2txs := test.GenL2Txs(0, nL2s, 0, nil, accs, tokens, blocks, batches)
  222. err = historyDB.AddL2Txs(l2txs)
  223. assert.NoError(t, err)
  224. // Compare fetched txs vs generated txs.
  225. for i := 0; i < len(l1txs); i++ {
  226. tx := l1txs[i].Tx()
  227. fetchedTx, err := historyDB.GetTx(tx.TxID)
  228. assert.NoError(t, err)
  229. tx.USD = tokenValue * tx.AmountFloat
  230. if fetchedTx.USD > tx.USD {
  231. assert.Less(t, 0.999, tx.USD/fetchedTx.USD)
  232. } else {
  233. assert.Less(t, 0.999, fetchedTx.USD/tx.USD)
  234. }
  235. tx.LoadAmountUSD = tokenValue * tx.LoadAmountFloat
  236. if fetchedTx.LoadAmountUSD > tx.LoadAmountUSD {
  237. assert.Less(t, 0.999, tx.LoadAmountUSD/fetchedTx.LoadAmountUSD)
  238. } else {
  239. assert.Less(t, 0.999, fetchedTx.LoadAmountUSD/tx.LoadAmountUSD)
  240. }
  241. tx.LoadAmountUSD = 0
  242. tx.USD = 0
  243. fetchedTx.LoadAmountUSD = 0
  244. fetchedTx.USD = 0
  245. assert.Equal(t, tx, fetchedTx)
  246. }
  247. for i := 0; i < len(l2txs); i++ {
  248. tx := l2txs[i].Tx()
  249. fetchedTx, err := historyDB.GetTx(tx.TxID)
  250. assert.NoError(t, err)
  251. tx.USD = tokenValue * tx.AmountFloat
  252. if fetchedTx.USD > tx.USD {
  253. assert.Less(t, 0.999, tx.USD/fetchedTx.USD)
  254. } else {
  255. assert.Less(t, 0.999, fetchedTx.USD/tx.USD)
  256. }
  257. tx.FeeUSD = tx.USD * tx.Fee.Percentage()
  258. if fetchedTx.FeeUSD > tx.FeeUSD {
  259. assert.Less(t, 0.999, tx.FeeUSD/fetchedTx.FeeUSD)
  260. } else if fetchedTx.FeeUSD < tx.FeeUSD {
  261. assert.Less(t, 0.999, fetchedTx.FeeUSD/tx.FeeUSD)
  262. }
  263. tx.FeeUSD = 0
  264. tx.USD = 0
  265. fetchedTx.FeeUSD = 0
  266. fetchedTx.USD = 0
  267. assert.Equal(t, tx, fetchedTx)
  268. }
  269. // Test trigger: L1 integrity
  270. // from_eth_addr can't be null
  271. l1txs[0].FromEthAddr = ethCommon.Address{}
  272. err = historyDB.AddL1Txs(l1txs)
  273. assert.Error(t, err)
  274. l1txs[0].FromEthAddr = ethCommon.BigToAddress(big.NewInt(int64(5)))
  275. // from_bjj can't be null
  276. l1txs[0].FromBJJ = nil
  277. err = historyDB.AddL1Txs(l1txs)
  278. assert.Error(t, err)
  279. privK := babyjub.NewRandPrivKey()
  280. l1txs[0].FromBJJ = privK.Public()
  281. // load_amount can't be null
  282. l1txs[0].LoadAmount = nil
  283. err = historyDB.AddL1Txs(l1txs)
  284. assert.Error(t, err)
  285. // Test trigger: L2 integrity
  286. // batch_num can't be null
  287. l2txs[0].BatchNum = 0
  288. err = historyDB.AddL2Txs(l2txs)
  289. assert.Error(t, err)
  290. l2txs[0].BatchNum = 1
  291. // nonce can't be null
  292. l2txs[0].Nonce = 0
  293. err = historyDB.AddL2Txs(l2txs)
  294. assert.Error(t, err)
  295. // Test helper functions for Synchronizer
  296. txs, err := historyDB.GetL1UserTxs(2)
  297. assert.NoError(t, err)
  298. assert.NotZero(t, len(txs))
  299. position, err := historyDB.GetLastTxsPosition(2)
  300. assert.NoError(t, err)
  301. assert.Equal(t, 22, position)
  302. // Test Update L1 TX Batch_num
  303. assert.Equal(t, common.BatchNum(0), txs[0].BatchNum)
  304. txs[0].BatchNum = common.BatchNum(1)
  305. // err = historyDB.UpdateTxsBatchNum(txs)
  306. err = historyDB.SetBatchNumL1UserTxs(2, 1)
  307. assert.NoError(t, err)
  308. txs, err = historyDB.GetL1UserTxs(2)
  309. assert.NoError(t, err)
  310. assert.NotZero(t, len(txs))
  311. assert.Equal(t, common.BatchNum(1), txs[0].BatchNum)
  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. }