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.

330 lines
10 KiB

4 years ago
  1. package historydb
  2. import (
  3. "fmt"
  4. "math"
  5. "math/big"
  6. "os"
  7. "testing"
  8. "time"
  9. ethCommon "github.com/ethereum/go-ethereum/common"
  10. "github.com/hermeznetwork/hermez-node/common"
  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. var err error
  26. pass := os.Getenv("POSTGRES_PASS")
  27. historyDB, err = NewHistoryDB(5432, "localhost", "hermez", pass, "history")
  28. if err != nil {
  29. panic(err)
  30. }
  31. // Run tests
  32. result := m.Run()
  33. // Close DB
  34. if err := historyDB.Close(); err != nil {
  35. fmt.Println("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, fetchedBlock := range fetchedBlocks {
  58. assertEqualBlock(t, &blocks[i], fetchedBlock)
  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. // Generate fake bids
  115. const nBids = 20
  116. bids := test.GenBids(nBids, blocks, coords)
  117. err := historyDB.addBids(bids)
  118. assert.NoError(t, err)
  119. // Fetch bids
  120. fetchedBids, err := historyDB.GetBids()
  121. assert.NoError(t, err)
  122. // Compare fetched bids vs generated bids
  123. for i, bid := range fetchedBids {
  124. assert.Equal(t, bids[i], *bid)
  125. }
  126. }
  127. func TestTokens(t *testing.T) {
  128. const fromBlock int64 = 1
  129. const toBlock int64 = 5
  130. // Prepare blocks in the DB
  131. blocks := setTestBlocks(fromBlock, toBlock)
  132. // Generate fake tokens
  133. const nTokens = 5
  134. tokens := test.GenTokens(nTokens, blocks)
  135. err := historyDB.AddTokens(tokens)
  136. assert.NoError(t, err)
  137. // Update price of generated tokens without price
  138. for i := 0; i < len(tokens); i++ {
  139. if tokens[i].USD == 0 {
  140. value := 3.33 + float64(i)
  141. tokens[i].USD = value
  142. err := historyDB.UpdateTokenValue(tokens[i].TokenID, value)
  143. assert.NoError(t, err)
  144. }
  145. }
  146. // Fetch tokens
  147. fetchedTokens, err := historyDB.GetTokens()
  148. assert.NoError(t, err)
  149. // Compare fetched tokens vs generated tokens
  150. // All the tokens should have USDUpdate setted by the DB trigger
  151. for i, token := range fetchedTokens {
  152. assert.Equal(t, tokens[i].TokenID, token.TokenID)
  153. assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
  154. assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
  155. assert.Equal(t, tokens[i].Name, token.Name)
  156. assert.Equal(t, tokens[i].Symbol, token.Symbol)
  157. assert.Equal(t, tokens[i].USD, token.USD)
  158. assert.Greater(t, int64(1*time.Second), int64(time.Since(token.USDUpdate)))
  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, 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 = 5
  196. const tokenValue = 1.23456
  197. tokens := test.GenTokens(nTokens, blocks)
  198. for i := 0; i < len(tokens); i++ {
  199. tokens[i].USD = tokenValue
  200. }
  201. err := historyDB.AddTokens(tokens)
  202. assert.NoError(t, err)
  203. // Generate fake batches
  204. const nBatches = 10
  205. batches := test.GenBatches(nBatches, blocks)
  206. err = historyDB.AddBatches(batches)
  207. assert.NoError(t, err)
  208. // Generate fake accounts
  209. const nAccounts = 3
  210. accs := test.GenAccounts(nAccounts, 0, tokens, nil, batches)
  211. err = historyDB.AddAccounts(accs)
  212. assert.NoError(t, err)
  213. // Generate fake L1 txs
  214. const nL1s = 30
  215. _, l1txs := test.GenL1Txs(0, nL1s, 0, nil, accs, tokens, blocks, batches)
  216. err = historyDB.AddL1Txs(l1txs)
  217. assert.NoError(t, err)
  218. // Generate fake L2 txs
  219. const nL2s = 20
  220. _, l2txs := test.GenL2Txs(0, nL2s, 0, nil, accs, tokens, blocks, batches)
  221. err = historyDB.AddL2Txs(l2txs)
  222. assert.NoError(t, err)
  223. // Compare fetched txs vs generated txs.
  224. for i := 0; i < len(l1txs); i++ {
  225. tx := l1txs[i].Tx()
  226. fetchedTx, err := historyDB.GetTx(tx.TxID)
  227. assert.NoError(t, err)
  228. tx.USD = tokenValue * tx.AmountFloat
  229. if fetchedTx.USD > tx.USD {
  230. assert.Less(t, 0.999, tx.USD/fetchedTx.USD)
  231. } else {
  232. assert.Less(t, 0.999, fetchedTx.USD/tx.USD)
  233. }
  234. tx.LoadAmountUSD = tokenValue * tx.LoadAmountFloat
  235. if fetchedTx.LoadAmountUSD > tx.LoadAmountUSD {
  236. assert.Less(t, 0.999, tx.LoadAmountUSD/fetchedTx.LoadAmountUSD)
  237. } else {
  238. assert.Less(t, 0.999, fetchedTx.LoadAmountUSD/tx.LoadAmountUSD)
  239. }
  240. tx.LoadAmountUSD = 0
  241. tx.USD = 0
  242. fetchedTx.LoadAmountUSD = 0
  243. fetchedTx.USD = 0
  244. assert.Equal(t, tx, fetchedTx)
  245. }
  246. for i := 0; i < len(l2txs); i++ {
  247. tx := l2txs[i].Tx()
  248. fetchedTx, err := historyDB.GetTx(tx.TxID)
  249. assert.NoError(t, err)
  250. tx.USD = tokenValue * tx.AmountFloat
  251. if fetchedTx.USD > tx.USD {
  252. assert.Less(t, 0.999, tx.USD/fetchedTx.USD)
  253. } else {
  254. assert.Less(t, 0.999, fetchedTx.USD/tx.USD)
  255. }
  256. if tx.Fee == 0 {
  257. tx.FeeUSD = 0
  258. } else if tx.Fee <= 32 {
  259. tx.FeeUSD = tx.USD * math.Pow(10, -24+(float64(tx.Fee)/2))
  260. } else if tx.Fee <= 223 {
  261. tx.FeeUSD = tx.USD * math.Pow(10, -8+(0.041666666666667*(float64(tx.Fee)-32)))
  262. } else {
  263. tx.FeeUSD = tx.USD * math.Pow(10, float64(tx.Fee)-224)
  264. }
  265. if fetchedTx.FeeUSD > tx.FeeUSD {
  266. assert.Less(t, 0.999, tx.FeeUSD/fetchedTx.FeeUSD)
  267. } else if fetchedTx.FeeUSD < tx.FeeUSD {
  268. assert.Less(t, 0.999, fetchedTx.FeeUSD/tx.FeeUSD)
  269. }
  270. tx.FeeUSD = 0
  271. tx.USD = 0
  272. fetchedTx.FeeUSD = 0
  273. fetchedTx.USD = 0
  274. assert.Equal(t, tx, fetchedTx)
  275. }
  276. // Test trigger: L1 integrity
  277. // from_eth_addr can't be null
  278. l1txs[0].FromEthAddr = ethCommon.Address{}
  279. err = historyDB.AddL1Txs(l1txs)
  280. assert.Error(t, err)
  281. l1txs[0].FromEthAddr = ethCommon.BigToAddress(big.NewInt(int64(5)))
  282. // from_bjj can't be null
  283. l1txs[0].FromBJJ = nil
  284. err = historyDB.AddL1Txs(l1txs)
  285. assert.Error(t, err)
  286. privK := babyjub.NewRandPrivKey()
  287. l1txs[0].FromBJJ = privK.Public()
  288. // load_amount can't be null
  289. l1txs[0].LoadAmount = nil
  290. err = historyDB.AddL1Txs(l1txs)
  291. assert.Error(t, err)
  292. // Test trigger: L2 integrity
  293. // batch_num can't be null
  294. l2txs[0].BatchNum = 0
  295. err = historyDB.AddL2Txs(l2txs)
  296. assert.Error(t, err)
  297. l2txs[0].BatchNum = 1
  298. // nonce can't be null
  299. l2txs[0].Nonce = 0
  300. err = historyDB.AddL2Txs(l2txs)
  301. assert.Error(t, err)
  302. }
  303. // setTestBlocks WARNING: this will delete the blocks and recreate them
  304. func setTestBlocks(from, to int64) []common.Block {
  305. if err := cleanHistoryDB(); err != nil {
  306. panic(err)
  307. }
  308. blocks := test.GenBlocks(from, to)
  309. if err := historyDB.AddBlocks(blocks); err != nil {
  310. panic(err)
  311. }
  312. return blocks
  313. }
  314. func cleanHistoryDB() error {
  315. return historyDB.Reorg(0)
  316. }