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.

488 lines
15 KiB

Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
  1. package historydb
  2. import (
  3. "database/sql"
  4. "math"
  5. "math/big"
  6. "os"
  7. "testing"
  8. ethCommon "github.com/ethereum/go-ethereum/common"
  9. "github.com/hermeznetwork/hermez-node/common"
  10. dbUtils "github.com/hermeznetwork/hermez-node/db"
  11. "github.com/hermeznetwork/hermez-node/log"
  12. "github.com/hermeznetwork/hermez-node/test"
  13. "github.com/hermeznetwork/hermez-node/test/til"
  14. "github.com/stretchr/testify/assert"
  15. "github.com/stretchr/testify/require"
  16. )
  17. var historyDB *HistoryDB
  18. // In order to run the test you need to run a Posgres DB with
  19. // a database named "history" that is accessible by
  20. // user: "hermez"
  21. // pass: set it using the env var POSTGRES_PASS
  22. // 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;"
  23. // After running the test you can stop the container by running: sudo docker kill hermez-db-test
  24. // If you already did that for the L2DB you don't have to do it again
  25. func TestMain(m *testing.M) {
  26. // init DB
  27. pass := os.Getenv("POSTGRES_PASS")
  28. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  29. if err != nil {
  30. panic(err)
  31. }
  32. historyDB = NewHistoryDB(db)
  33. if err != nil {
  34. panic(err)
  35. }
  36. // Run tests
  37. result := m.Run()
  38. // Close DB
  39. if err := db.Close(); err != nil {
  40. log.Error("Error closing the history DB:", err)
  41. }
  42. os.Exit(result)
  43. }
  44. func TestBlocks(t *testing.T) {
  45. var fromBlock, toBlock int64
  46. fromBlock = 1
  47. toBlock = 5
  48. // Delete peviously created rows (clean previous test execs)
  49. test.WipeDB(historyDB.DB())
  50. // Generate fake blocks
  51. blocks := test.GenBlocks(fromBlock, toBlock)
  52. // Insert blocks into DB
  53. for i := 0; i < len(blocks); i++ {
  54. err := historyDB.AddBlock(&blocks[i])
  55. assert.NoError(t, err)
  56. }
  57. // Get all blocks from DB
  58. fetchedBlocks, err := historyDB.GetBlocks(fromBlock, toBlock)
  59. assert.Equal(t, len(blocks), len(fetchedBlocks))
  60. // Compare generated vs getted blocks
  61. assert.NoError(t, err)
  62. for i := range fetchedBlocks {
  63. assertEqualBlock(t, &blocks[i], &fetchedBlocks[i])
  64. }
  65. // Get blocks from the DB one by one
  66. for i := fromBlock; i < toBlock; i++ {
  67. fetchedBlock, err := historyDB.GetBlock(i)
  68. assert.NoError(t, err)
  69. assertEqualBlock(t, &blocks[i-1], fetchedBlock)
  70. }
  71. // Get last block
  72. lastBlock, err := historyDB.GetLastBlock()
  73. assert.NoError(t, err)
  74. assertEqualBlock(t, &blocks[len(blocks)-1], lastBlock)
  75. }
  76. func assertEqualBlock(t *testing.T, expected *common.Block, actual *common.Block) {
  77. assert.Equal(t, expected.EthBlockNum, actual.EthBlockNum)
  78. assert.Equal(t, expected.Hash, actual.Hash)
  79. assert.Equal(t, expected.Timestamp.Unix(), actual.Timestamp.Unix())
  80. }
  81. func TestBatches(t *testing.T) {
  82. const fromBlock int64 = 1
  83. const toBlock int64 = 3
  84. // Prepare blocks in the DB
  85. blocks := setTestBlocks(fromBlock, toBlock)
  86. // Generate fake batches
  87. const nBatches = 9
  88. batches := test.GenBatches(nBatches, blocks)
  89. // Test GetLastL1TxsNum with no batches
  90. fetchedLastL1TxsNum, err := historyDB.GetLastL1TxsNum()
  91. assert.NoError(t, err)
  92. assert.Nil(t, fetchedLastL1TxsNum)
  93. // Add batches to the DB
  94. err = historyDB.AddBatches(batches)
  95. assert.NoError(t, err)
  96. // Get batches from the DB
  97. fetchedBatches, err := historyDB.GetBatches(0, common.BatchNum(nBatches))
  98. assert.NoError(t, err)
  99. for i, fetchedBatch := range fetchedBatches {
  100. assert.Equal(t, batches[i], fetchedBatch)
  101. }
  102. // Test GetLastBatchNum
  103. fetchedLastBatchNum, err := historyDB.GetLastBatchNum()
  104. assert.NoError(t, err)
  105. assert.Equal(t, batches[len(batches)-1].BatchNum, fetchedLastBatchNum)
  106. // Test GetLastL1TxsNum
  107. fetchedLastL1TxsNum, err = historyDB.GetLastL1TxsNum()
  108. assert.NoError(t, err)
  109. assert.Equal(t, *batches[nBatches-1].ForgeL1TxsNum, *fetchedLastL1TxsNum)
  110. // Test total fee
  111. // Generate fake tokens
  112. const nTokens = 5
  113. tokens, ethToken := test.GenTokens(nTokens, blocks)
  114. err = historyDB.AddTokens(tokens)
  115. assert.NoError(t, err)
  116. tokens = append([]common.Token{ethToken}, tokens...)
  117. feeBatch := batches[0]
  118. feeBatch.BatchNum = 9999
  119. feeBatch.CollectedFees = make(map[common.TokenID]*big.Int)
  120. var total float64
  121. for i, token := range tokens {
  122. value := 3.019237 * float64(i)
  123. assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
  124. bigAmount := big.NewInt(345000000)
  125. feeBatch.CollectedFees[token.TokenID] = bigAmount
  126. f := new(big.Float).SetInt(bigAmount)
  127. amount, _ := f.Float64()
  128. total += value * (amount / math.Pow(10, float64(token.Decimals)))
  129. }
  130. err = historyDB.AddBatch(&feeBatch)
  131. assert.NoError(t, err)
  132. fetchedBatches, err = historyDB.GetBatches(feeBatch.BatchNum-1, feeBatch.BatchNum+1)
  133. assert.NoError(t, err)
  134. for _, fetchedBatch := range fetchedBatches {
  135. if fetchedBatch.BatchNum == feeBatch.BatchNum {
  136. assert.Equal(t, total, *fetchedBatch.TotalFeesUSD)
  137. }
  138. }
  139. }
  140. func TestBids(t *testing.T) {
  141. const fromBlock int64 = 1
  142. const toBlock int64 = 5
  143. // Prepare blocks in the DB
  144. blocks := setTestBlocks(fromBlock, toBlock)
  145. // Generate fake coordinators
  146. const nCoords = 5
  147. coords := test.GenCoordinators(nCoords, blocks)
  148. err := historyDB.AddCoordinators(coords)
  149. assert.NoError(t, err)
  150. // Generate fake bids
  151. const nBids = 20
  152. bids := test.GenBids(nBids, blocks, coords)
  153. err = historyDB.AddBids(bids)
  154. assert.NoError(t, err)
  155. // Fetch bids
  156. fetchedBids, err := historyDB.GetAllBids()
  157. assert.NoError(t, err)
  158. // Compare fetched bids vs generated bids
  159. for i, bid := range fetchedBids {
  160. assert.Equal(t, bids[i], bid)
  161. }
  162. }
  163. func TestTokens(t *testing.T) {
  164. const fromBlock int64 = 1
  165. const toBlock int64 = 5
  166. // Prepare blocks in the DB
  167. blocks := setTestBlocks(fromBlock, toBlock)
  168. // Generate fake tokens
  169. const nTokens = 5
  170. tokens, ethToken := test.GenTokens(nTokens, blocks)
  171. err := historyDB.AddTokens(tokens)
  172. assert.NoError(t, err)
  173. tokens = append([]common.Token{ethToken}, tokens...)
  174. limit := uint(10)
  175. // Fetch tokens6
  176. fetchedTokens, _, err := historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
  177. assert.NoError(t, err)
  178. // Compare fetched tokens vs generated tokens
  179. // All the tokens should have USDUpdate setted by the DB trigger
  180. for i, token := range fetchedTokens {
  181. assert.Equal(t, tokens[i].TokenID, token.TokenID)
  182. assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
  183. assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
  184. assert.Equal(t, tokens[i].Name, token.Name)
  185. assert.Equal(t, tokens[i].Symbol, token.Symbol)
  186. assert.Nil(t, token.USD)
  187. assert.Nil(t, token.USDUpdate)
  188. }
  189. }
  190. func TestAccounts(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. tokens, ethToken := test.GenTokens(nTokens, blocks)
  198. err := historyDB.AddTokens(tokens)
  199. assert.NoError(t, err)
  200. tokens = append([]common.Token{ethToken}, tokens...)
  201. // Generate fake batches
  202. const nBatches = 10
  203. batches := test.GenBatches(nBatches, blocks)
  204. err = historyDB.AddBatches(batches)
  205. assert.NoError(t, err)
  206. // Generate fake accounts
  207. const nAccounts = 3
  208. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  209. err = historyDB.AddAccounts(accs)
  210. assert.NoError(t, err)
  211. // Fetch accounts
  212. fetchedAccs, err := historyDB.GetAccounts()
  213. assert.NoError(t, err)
  214. // Compare fetched accounts vs generated accounts
  215. for i, acc := range fetchedAccs {
  216. accs[i].Balance = nil
  217. assert.Equal(t, accs[i], acc)
  218. }
  219. }
  220. func TestTxs(t *testing.T) {
  221. const fromBlock int64 = 1
  222. const toBlock int64 = 5
  223. // Prepare blocks in the DB
  224. blocks := setTestBlocks(fromBlock, toBlock)
  225. // Generate fake tokens
  226. const nTokens = 500
  227. tokens, ethToken := test.GenTokens(nTokens, blocks)
  228. err := historyDB.AddTokens(tokens)
  229. assert.NoError(t, err)
  230. tokens = append([]common.Token{ethToken}, tokens...)
  231. // Generate fake batches
  232. const nBatches = 10
  233. batches := test.GenBatches(nBatches, blocks)
  234. err = historyDB.AddBatches(batches)
  235. assert.NoError(t, err)
  236. // Generate fake accounts
  237. const nAccounts = 3
  238. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  239. err = historyDB.AddAccounts(accs)
  240. assert.NoError(t, err)
  241. /*
  242. Uncomment once the transaction generation is fixed
  243. !! test that batches that forge user L1s !!
  244. !! Missing tests to check that historic USD is not set if USDUpdate is too old (24h) !!
  245. // Generate fake L1 txs
  246. const nL1s = 64
  247. _, l1txs := test.GenL1Txs(256, nL1s, 0, nil, accs, tokens, blocks, batches)
  248. err = historyDB.AddL1Txs(l1txs)
  249. assert.NoError(t, err)
  250. // Generate fake L2 txs
  251. const nL2s = 2048 - nL1s
  252. _, l2txs := test.GenL2Txs(256, nL2s, 0, nil, accs, tokens, blocks, batches)
  253. err = historyDB.AddL2Txs(l2txs)
  254. assert.NoError(t, err)
  255. // Compare fetched txs vs generated txs.
  256. fetchAndAssertTxs(t, l1txs, l2txs)
  257. // Test trigger: L1 integrity
  258. // from_eth_addr can't be null
  259. l1txs[0].FromEthAddr = ethCommon.Address{}
  260. err = historyDB.AddL1Txs(l1txs)
  261. assert.Error(t, err)
  262. l1txs[0].FromEthAddr = ethCommon.BigToAddress(big.NewInt(int64(5)))
  263. // from_bjj can't be null
  264. l1txs[0].FromBJJ = nil
  265. err = historyDB.AddL1Txs(l1txs)
  266. assert.Error(t, err)
  267. privK := babyjub.NewRandPrivKey()
  268. l1txs[0].FromBJJ = privK.Public()
  269. // load_amount can't be null
  270. l1txs[0].LoadAmount = nil
  271. err = historyDB.AddL1Txs(l1txs)
  272. assert.Error(t, err)
  273. // Test trigger: L2 integrity
  274. // batch_num can't be null
  275. l2txs[0].BatchNum = 0
  276. err = historyDB.AddL2Txs(l2txs)
  277. assert.Error(t, err)
  278. l2txs[0].BatchNum = 1
  279. // nonce can't be null
  280. l2txs[0].Nonce = 0
  281. err = historyDB.AddL2Txs(l2txs)
  282. assert.Error(t, err)
  283. // Test trigger: forge L1 txs
  284. // add next batch to DB
  285. batchNum, toForgeL1TxsNum := test.GetNextToForgeNumAndBatch(batches)
  286. batch := batches[0]
  287. batch.BatchNum = batchNum
  288. batch.ForgeL1TxsNum = toForgeL1TxsNum
  289. assert.NoError(t, historyDB.AddBatch(&batch)) // This should update nL1s / 2 rows
  290. // Set batch num in txs that should have been marked as forged in the DB
  291. for i := 0; i < len(l1txs); i++ {
  292. fetchedTx, err := historyDB.GetTx(l1txs[i].TxID)
  293. assert.NoError(t, err)
  294. if l1txs[i].ToForgeL1TxsNum == toForgeL1TxsNum {
  295. assert.Equal(t, batchNum, *fetchedTx.BatchNum)
  296. } else {
  297. if fetchedTx.BatchNum != nil {
  298. assert.NotEqual(t, batchNum, *fetchedTx.BatchNum)
  299. }
  300. }
  301. }
  302. // Test helper functions for Synchronizer
  303. // GetLastTxsPosition
  304. expectedPosition := -1
  305. var choosenToForgeL1TxsNum int64 = -1
  306. for _, tx := range l1txs {
  307. if choosenToForgeL1TxsNum == -1 && tx.ToForgeL1TxsNum > 0 {
  308. choosenToForgeL1TxsNum = tx.ToForgeL1TxsNum
  309. expectedPosition = tx.Position
  310. } else if choosenToForgeL1TxsNum == tx.ToForgeL1TxsNum && expectedPosition < tx.Position {
  311. expectedPosition = tx.Position
  312. }
  313. }
  314. position, err := historyDB.GetLastTxsPosition(choosenToForgeL1TxsNum)
  315. assert.NoError(t, err)
  316. assert.Equal(t, expectedPosition, position)
  317. // GetL1UserTxs: not needed? tests were broken
  318. // txs, err := historyDB.GetL1UserTxs(2)
  319. // assert.NoError(t, err)
  320. // assert.NotZero(t, len(txs))
  321. // assert.NoError(t, err)
  322. // assert.Equal(t, 22, position)
  323. // // Test Update L1 TX Batch_num
  324. // assert.Equal(t, common.BatchNum(0), txs[0].BatchNum)
  325. // txs[0].BatchNum = common.BatchNum(1)
  326. // txs, err = historyDB.GetL1UserTxs(2)
  327. // assert.NoError(t, err)
  328. // assert.NotZero(t, len(txs))
  329. // assert.Equal(t, common.BatchNum(1), txs[0].BatchNum)
  330. */
  331. }
  332. /*
  333. func fetchAndAssertTxs(t *testing.T, l1txs []common.L1Tx, l2txs []common.L2Tx) {
  334. for i := 0; i < len(l1txs); i++ {
  335. tx := l1txs[i].Tx()
  336. fmt.Println("ASDF", i, tx.TxID)
  337. fetchedTx, err := historyDB.GetTx(tx.TxID)
  338. require.NoError(t, err)
  339. test.AssertUSD(t, tx.USD, fetchedTx.USD)
  340. test.AssertUSD(t, tx.LoadAmountUSD, fetchedTx.LoadAmountUSD)
  341. assert.Equal(t, tx, fetchedTx)
  342. }
  343. for i := 0; i < len(l2txs); i++ {
  344. tx := l2txs[i].Tx()
  345. fetchedTx, err := historyDB.GetTx(tx.TxID)
  346. tx.TokenID = fetchedTx.TokenID
  347. assert.NoError(t, err)
  348. test.AssertUSD(t, fetchedTx.USD, tx.USD)
  349. test.AssertUSD(t, fetchedTx.FeeUSD, tx.FeeUSD)
  350. assert.Equal(t, tx, fetchedTx)
  351. }
  352. }
  353. */
  354. func TestExitTree(t *testing.T) {
  355. nBatches := 17
  356. blocks := setTestBlocks(1, 10)
  357. batches := test.GenBatches(nBatches, blocks)
  358. err := historyDB.AddBatches(batches)
  359. assert.NoError(t, err)
  360. const nTokens = 50
  361. tokens, ethToken := test.GenTokens(nTokens, blocks)
  362. err = historyDB.AddTokens(tokens)
  363. assert.NoError(t, err)
  364. tokens = append([]common.Token{ethToken}, tokens...)
  365. const nAccounts = 3
  366. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  367. assert.NoError(t, historyDB.AddAccounts(accs))
  368. exitTree := test.GenExitTree(nBatches, batches, accs)
  369. err = historyDB.AddExitTree(exitTree)
  370. assert.NoError(t, err)
  371. }
  372. func TestGetL1UserTxs(t *testing.T) {
  373. test.WipeDB(historyDB.DB())
  374. set := `
  375. Type: Blockchain
  376. AddToken(1)
  377. AddToken(2)
  378. AddToken(3)
  379. CreateAccountDeposit(1) A: 20
  380. CreateAccountDeposit(2) A: 20
  381. CreateAccountDeposit(1) B: 5
  382. CreateAccountDeposit(1) C: 5
  383. CreateAccountDeposit(1) D: 5
  384. > block
  385. `
  386. tc := til.NewContext(128)
  387. blocks, err := tc.GenerateBlocks(set)
  388. require.Nil(t, err)
  389. // Sanity check
  390. require.Equal(t, 1, len(blocks))
  391. require.Equal(t, 5, len(blocks[0].Rollup.L1UserTxs))
  392. // fmt.Printf("DBG Blocks: %+v\n", blocks)
  393. toForgeL1TxsNum := int64(1)
  394. for i := range blocks {
  395. err = historyDB.AddBlockSCData(&blocks[i])
  396. require.Nil(t, err)
  397. }
  398. l1UserTxs, err := historyDB.GetL1UserTxs(toForgeL1TxsNum)
  399. require.Nil(t, err)
  400. assert.Equal(t, 5, len(l1UserTxs))
  401. assert.Equal(t, blocks[0].Rollup.L1UserTxs, l1UserTxs)
  402. // No l1UserTxs for this toForgeL1TxsNum
  403. l1UserTxs, err = historyDB.GetL1UserTxs(2)
  404. require.Nil(t, err)
  405. assert.Equal(t, 0, len(l1UserTxs))
  406. }
  407. func TestSetInitialSCVars(t *testing.T) {
  408. test.WipeDB(historyDB.DB())
  409. _, _, _, err := historyDB.GetSCVars()
  410. assert.Equal(t, sql.ErrNoRows, err)
  411. //nolint:govet
  412. rollup := &common.RollupVariables{
  413. 0,
  414. big.NewInt(10),
  415. 12,
  416. 13,
  417. }
  418. //nolint:govet
  419. auction := &common.AuctionVariables{
  420. 0,
  421. ethCommon.BigToAddress(big.NewInt(2)),
  422. ethCommon.BigToAddress(big.NewInt(3)),
  423. [6]*big.Int{
  424. big.NewInt(1), big.NewInt(2), big.NewInt(3),
  425. big.NewInt(4), big.NewInt(5), big.NewInt(6),
  426. },
  427. 2,
  428. 4320,
  429. [3]uint16{10, 11, 12},
  430. 1000,
  431. 20,
  432. }
  433. //nolint:govet
  434. wDelayer := &common.WDelayerVariables{
  435. 0,
  436. ethCommon.BigToAddress(big.NewInt(2)),
  437. ethCommon.BigToAddress(big.NewInt(3)),
  438. ethCommon.BigToAddress(big.NewInt(4)),
  439. 13,
  440. 14,
  441. false,
  442. }
  443. err = historyDB.SetInitialSCVars(rollup, auction, wDelayer)
  444. require.Nil(t, err)
  445. dbRollup, dbAuction, dbWDelayer, err := historyDB.GetSCVars()
  446. assert.Nil(t, err)
  447. require.Equal(t, rollup, dbRollup)
  448. require.Equal(t, auction, dbAuction)
  449. require.Equal(t, wDelayer, dbWDelayer)
  450. }
  451. // setTestBlocks WARNING: this will delete the blocks and recreate them
  452. func setTestBlocks(from, to int64) []common.Block {
  453. test.WipeDB(historyDB.DB())
  454. blocks := test.GenBlocks(from, to)
  455. if err := historyDB.AddBlocks(blocks); err != nil {
  456. panic(err)
  457. }
  458. return blocks
  459. }