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.

255 lines
10 KiB

  1. package zkproof
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "strconv"
  6. "testing"
  7. "time"
  8. ethCommon "github.com/ethereum/go-ethereum/common"
  9. ethCrypto "github.com/ethereum/go-ethereum/crypto"
  10. "github.com/hermeznetwork/hermez-node/batchbuilder"
  11. "github.com/hermeznetwork/hermez-node/common"
  12. dbUtils "github.com/hermeznetwork/hermez-node/db"
  13. "github.com/hermeznetwork/hermez-node/db/historydb"
  14. "github.com/hermeznetwork/hermez-node/db/l2db"
  15. "github.com/hermeznetwork/hermez-node/db/statedb"
  16. "github.com/hermeznetwork/hermez-node/log"
  17. "github.com/hermeznetwork/hermez-node/test"
  18. "github.com/hermeznetwork/hermez-node/test/til"
  19. "github.com/hermeznetwork/hermez-node/test/txsets"
  20. "github.com/hermeznetwork/hermez-node/txselector"
  21. "github.com/jmoiron/sqlx"
  22. "github.com/stretchr/testify/assert"
  23. "github.com/stretchr/testify/require"
  24. )
  25. func addTokens(t *testing.T, tc *til.Context, db *sqlx.DB) {
  26. var tokens []common.Token
  27. for i := 0; i < int(tc.LastRegisteredTokenID); i++ {
  28. tokens = append(tokens, common.Token{
  29. TokenID: common.TokenID(i + 1),
  30. EthBlockNum: 1,
  31. EthAddr: ethCommon.BytesToAddress([]byte{byte(i + 1)}),
  32. Name: strconv.Itoa(i),
  33. Symbol: strconv.Itoa(i),
  34. Decimals: 18,
  35. })
  36. }
  37. hdb := historydb.NewHistoryDB(db)
  38. assert.NoError(t, hdb.AddBlock(&common.Block{
  39. Num: 1,
  40. }))
  41. assert.NoError(t, hdb.AddTokens(tokens))
  42. }
  43. func addL2Txs(t *testing.T, l2DB *l2db.L2DB, poolL2Txs []common.PoolL2Tx) {
  44. for i := 0; i < len(poolL2Txs); i++ {
  45. err := l2DB.AddTxTest(&poolL2Txs[i])
  46. if err != nil {
  47. log.Error(err)
  48. }
  49. require.NoError(t, err)
  50. }
  51. }
  52. func addAccCreationAuth(t *testing.T, tc *til.Context, l2DB *l2db.L2DB, chainID uint16, hermezContractAddr ethCommon.Address, username string) []byte {
  53. user := tc.Users[username]
  54. auth := &common.AccountCreationAuth{
  55. EthAddr: user.Addr,
  56. BJJ: user.BJJ.Public().Compress(),
  57. }
  58. err := auth.Sign(func(hash []byte) ([]byte, error) {
  59. return ethCrypto.Sign(hash, user.EthSk)
  60. }, chainID, hermezContractAddr)
  61. assert.NoError(t, err)
  62. err = l2DB.AddAccountCreationAuth(auth)
  63. assert.NoError(t, err)
  64. return auth.Signature
  65. }
  66. func initTxSelector(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address, coordUser *til.User) (*txselector.TxSelector, *l2db.L2DB, *statedb.StateDB) {
  67. pass := os.Getenv("POSTGRES_PASS")
  68. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  69. require.NoError(t, err)
  70. l2DB := l2db.NewL2DB(db, 10, 100, 24*time.Hour)
  71. dir, err := ioutil.TempDir("", "tmpSyncDB")
  72. require.NoError(t, err)
  73. defer assert.NoError(t, os.RemoveAll(dir))
  74. syncStateDB, err := statedb.NewStateDB(dir, 128, statedb.TypeSynchronizer, 0)
  75. require.NoError(t, err)
  76. txselDir, err := ioutil.TempDir("", "tmpTxSelDB")
  77. require.NoError(t, err)
  78. defer assert.NoError(t, os.RemoveAll(dir))
  79. // use Til Coord keys for tests compatibility
  80. coordAccount := &txselector.CoordAccount{
  81. Addr: coordUser.Addr,
  82. BJJ: coordUser.BJJ.Public().Compress(),
  83. AccountCreationAuth: nil,
  84. }
  85. auth := common.AccountCreationAuth{
  86. EthAddr: coordUser.Addr,
  87. BJJ: coordUser.BJJ.Public().Compress(),
  88. }
  89. err = auth.Sign(func(hash []byte) ([]byte, error) {
  90. return ethCrypto.Sign(hash, coordUser.EthSk)
  91. }, chainID, hermezContractAddr)
  92. assert.NoError(t, err)
  93. coordAccount.AccountCreationAuth = auth.Signature
  94. txsel, err := txselector.NewTxSelector(coordAccount, txselDir, syncStateDB, l2DB)
  95. require.NoError(t, err)
  96. test.WipeDB(l2DB.DB())
  97. return txsel, l2DB, syncStateDB
  98. }
  99. func TestTxSelectorBatchBuilderZKInputs(t *testing.T) {
  100. tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
  101. // generate test transactions, the L1CoordinatorTxs generated by Til
  102. // will be ignored at this test, as will be the TxSelector who
  103. // generates them when needed
  104. blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
  105. require.NoError(t, err)
  106. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  107. txsel, l2DBTxSel, syncStateDB := initTxSelector(t, ChainID, hermezContractAddr, tc.Users["Coord"])
  108. bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB")
  109. require.NoError(t, err)
  110. bb, err := batchbuilder.NewBatchBuilder(bbDir, syncStateDB, 0, NLevels)
  111. require.NoError(t, err)
  112. // restart nonces of TilContext, as will be set by generating directly
  113. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  114. tc.RestartNonces()
  115. // add tokens to HistoryDB to avoid breaking FK constrains
  116. addTokens(t, tc, l2DBTxSel.DB())
  117. selectionConfig := &txselector.SelectionConfig{
  118. MaxL1UserTxs: 100, // TODO
  119. TxProcessorConfig: txprocConfig,
  120. }
  121. configBatch := &batchbuilder.ConfigBatch{
  122. // ForgerAddress:
  123. TxProcessorConfig: txprocConfig,
  124. }
  125. // loop over the first 6 batches
  126. expectedRoots := []string{"0", "0", "13644148972047617726265275926674266298636745191961029124811988256139761111521", "12433441613247342495680642890662773367605896324555599297255745922589338651261", "12433441613247342495680642890662773367605896324555599297255745922589338651261", "4191361650490017591061467288209836928064232431729236465872209988325272262963"}
  127. for i := 0; i < 6; i++ {
  128. log.Debugf("block:0 batch:%d", i+1)
  129. var l1UserTxs []common.L1Tx
  130. if blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum != nil {
  131. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum])
  132. }
  133. // TxSelector select the transactions for the next Batch
  134. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
  135. require.NoError(t, err)
  136. // BatchBuilder build Batch
  137. zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  138. require.NoError(t, err)
  139. assert.Equal(t, expectedRoots[i], bb.LocalStateDB().MT.Root().BigInt().String())
  140. sendProofAndCheckResp(t, zki)
  141. }
  142. log.Debug("block:0 batch:7")
  143. // simulate the PoolL2Txs of the batch6
  144. batchPoolL2 := `
  145. Type: PoolL2
  146. PoolTransferToEthAddr(1) A-B: 200 (126)
  147. PoolTransferToEthAddr(0) B-C: 100 (126)`
  148. l2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  149. require.NoError(t, err)
  150. // add AccountCreationAuths that will be used at the next batch
  151. _ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "B")
  152. _ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "C")
  153. addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
  154. l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
  155. // TxSelector select the transactions for the next Batch
  156. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
  157. require.NoError(t, err)
  158. // BatchBuilder build Batch
  159. zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  160. require.NoError(t, err)
  161. assert.Equal(t, "7614010373759339299470010949167613050707822522530721724565424494781010548240", bb.LocalStateDB().MT.Root().BigInt().String())
  162. sendProofAndCheckResp(t, zki)
  163. err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.LocalAccountsDB().CurrentBatch())
  164. require.NoError(t, err)
  165. err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
  166. require.NoError(t, err)
  167. log.Debug("block:0 batch:8")
  168. // simulate the PoolL2Txs of the batch8
  169. batchPoolL2 = `
  170. Type: PoolL2
  171. PoolTransfer(0) A-B: 100 (126)
  172. PoolTransfer(0) C-A: 50 (126)
  173. PoolTransfer(1) B-C: 100 (126)
  174. PoolExit(0) A: 100 (126)`
  175. l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  176. require.NoError(t, err)
  177. addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
  178. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
  179. // TxSelector select the transactions for the next Batch
  180. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
  181. require.NoError(t, err)
  182. // BatchBuilder build Batch
  183. zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  184. require.NoError(t, err)
  185. assert.Equal(t, "21231789250434471575486264439945776732824482207853465397552873521865656677689", bb.LocalStateDB().MT.Root().BigInt().String())
  186. sendProofAndCheckResp(t, zki)
  187. err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch())
  188. require.NoError(t, err)
  189. err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
  190. require.NoError(t, err)
  191. log.Debug("(batch9) block:1 batch:1")
  192. // simulate the PoolL2Txs of the batch9
  193. batchPoolL2 = `
  194. Type: PoolL2
  195. PoolTransfer(0) D-A: 300 (126)
  196. PoolTransfer(0) B-D: 100 (126)`
  197. l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  198. require.NoError(t, err)
  199. addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
  200. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
  201. // TxSelector select the transactions for the next Batch
  202. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
  203. require.NoError(t, err)
  204. // BatchBuilder build Batch
  205. zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  206. require.NoError(t, err)
  207. assert.Equal(t, "11289313644810782435120113035387729451095637380468777086895109386127538554246", bb.LocalStateDB().MT.Root().BigInt().String())
  208. sendProofAndCheckResp(t, zki)
  209. err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch())
  210. require.NoError(t, err)
  211. err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
  212. require.NoError(t, err)
  213. log.Debug("(batch10) block:1 batch:2")
  214. l2Txs = []common.PoolL2Tx{}
  215. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
  216. // TxSelector select the transactions for the next Batch
  217. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
  218. require.NoError(t, err)
  219. // BatchBuilder build Batch
  220. zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  221. require.NoError(t, err)
  222. // same root as previous batch, as the L1CoordinatorTxs created by the
  223. // Til set is not created by the TxSelector in this test
  224. assert.Equal(t, "11289313644810782435120113035387729451095637380468777086895109386127538554246", bb.LocalStateDB().MT.Root().BigInt().String())
  225. sendProofAndCheckResp(t, zki)
  226. err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs), txsel.LocalAccountsDB().CurrentBatch())
  227. require.NoError(t, err)
  228. err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
  229. require.NoError(t, err)
  230. }