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.

366 lines
13 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, db, nil)
  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,
  53. hermezContractAddr ethCommon.Address, username string) []byte {
  54. user := tc.Users[username]
  55. auth := &common.AccountCreationAuth{
  56. EthAddr: user.Addr,
  57. BJJ: user.BJJ.Public().Compress(),
  58. }
  59. err := auth.Sign(func(hash []byte) ([]byte, error) {
  60. return ethCrypto.Sign(hash, user.EthSk)
  61. }, chainID, hermezContractAddr)
  62. assert.NoError(t, err)
  63. err = l2DB.AddAccountCreationAuth(auth)
  64. assert.NoError(t, err)
  65. return auth.Signature
  66. }
  67. func initTxSelector(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address,
  68. coordUser *til.User) (*txselector.TxSelector, *l2db.L2DB, *statedb.StateDB) {
  69. pass := os.Getenv("POSTGRES_PASS")
  70. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  71. require.NoError(t, err)
  72. l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 24*time.Hour, nil)
  73. dir, err := ioutil.TempDir("", "tmpSyncDB")
  74. require.NoError(t, err)
  75. defer assert.NoError(t, os.RemoveAll(dir))
  76. syncStateDB, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
  77. Type: statedb.TypeSynchronizer, NLevels: 0})
  78. require.NoError(t, err)
  79. txselDir, err := ioutil.TempDir("", "tmpTxSelDB")
  80. require.NoError(t, err)
  81. defer assert.NoError(t, os.RemoveAll(dir))
  82. // use Til Coord keys for tests compatibility
  83. coordAccount := &txselector.CoordAccount{
  84. Addr: coordUser.Addr,
  85. BJJ: coordUser.BJJ.Public().Compress(),
  86. AccountCreationAuth: nil,
  87. }
  88. auth := common.AccountCreationAuth{
  89. EthAddr: coordUser.Addr,
  90. BJJ: coordUser.BJJ.Public().Compress(),
  91. }
  92. err = auth.Sign(func(hash []byte) ([]byte, error) {
  93. return ethCrypto.Sign(hash, coordUser.EthSk)
  94. }, chainID, hermezContractAddr)
  95. assert.NoError(t, err)
  96. coordAccount.AccountCreationAuth = auth.Signature
  97. txsel, err := txselector.NewTxSelector(coordAccount, txselDir, syncStateDB, l2DB)
  98. require.NoError(t, err)
  99. test.WipeDB(l2DB.DB())
  100. return txsel, l2DB, syncStateDB
  101. }
  102. func TestTxSelectorBatchBuilderZKInputsMinimumFlow0(t *testing.T) {
  103. tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
  104. // generate test transactions, the L1CoordinatorTxs generated by Til
  105. // will be ignored at this test, as will be the TxSelector who
  106. // generates them when needed
  107. blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
  108. require.NoError(t, err)
  109. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  110. txsel, l2DBTxSel, syncStateDB := initTxSelector(t, ChainID, hermezContractAddr, tc.Users["Coord"])
  111. bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB")
  112. require.NoError(t, err)
  113. bb, err := batchbuilder.NewBatchBuilder(bbDir, syncStateDB, 0, NLevels)
  114. require.NoError(t, err)
  115. // restart nonces of TilContext, as will be set by generating directly
  116. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  117. tc.RestartNonces()
  118. // add tokens to HistoryDB to avoid breaking FK constrains
  119. addTokens(t, tc, l2DBTxSel.DB())
  120. configBatch := &batchbuilder.ConfigBatch{
  121. // ForgerAddress:
  122. TxProcessorConfig: txprocConfig,
  123. }
  124. // loop over the first 6 batches
  125. expectedRoots := []string{"0", "0",
  126. "13644148972047617726265275926674266298636745191961029124811988256139761111521",
  127. "12433441613247342495680642890662773367605896324555599297255745922589338651261",
  128. "12433441613247342495680642890662773367605896324555599297255745922589338651261",
  129. "4191361650490017591061467288209836928064232431729236465872209988325272262963"}
  130. for i := 0; i < 6; i++ {
  131. log.Debugf("block:0 batch:%d", i+1)
  132. var l1UserTxs []common.L1Tx
  133. if blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum != nil {
  134. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[i].Batch.ForgeL1TxsNum])
  135. }
  136. // TxSelector select the transactions for the next Batch
  137. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err :=
  138. txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
  139. require.NoError(t, err)
  140. // BatchBuilder build Batch
  141. zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  142. require.NoError(t, err)
  143. assert.Equal(t, expectedRoots[i], bb.LocalStateDB().MT.Root().BigInt().String())
  144. sendProofAndCheckResp(t, zki)
  145. }
  146. log.Debug("block:0 batch:7")
  147. // simulate the PoolL2Txs of the batch6
  148. batchPoolL2 := `
  149. Type: PoolL2
  150. PoolTransferToEthAddr(1) A-B: 200 (126)
  151. PoolTransferToEthAddr(0) B-C: 100 (126)`
  152. l2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  153. require.NoError(t, err)
  154. // add AccountCreationAuths that will be used at the next batch
  155. _ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "B")
  156. _ = addAccCreationAuth(t, tc, l2DBTxSel, ChainID, hermezContractAddr, "C")
  157. addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
  158. l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
  159. // TxSelector select the transactions for the next Batch
  160. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
  161. txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
  162. require.NoError(t, err)
  163. // BatchBuilder build Batch
  164. zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  165. require.NoError(t, err)
  166. assert.Equal(t,
  167. "7614010373759339299470010949167613050707822522530721724565424494781010548240",
  168. bb.LocalStateDB().MT.Root().BigInt().String())
  169. sendProofAndCheckResp(t, zki)
  170. err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  171. txsel.LocalAccountsDB().CurrentBatch())
  172. require.NoError(t, err)
  173. err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
  174. require.NoError(t, err)
  175. log.Debug("block:0 batch:8")
  176. // simulate the PoolL2Txs of the batch8
  177. batchPoolL2 = `
  178. Type: PoolL2
  179. PoolTransfer(0) A-B: 100 (126)
  180. PoolTransfer(0) C-A: 50 (126)
  181. PoolTransfer(1) B-C: 100 (126)
  182. PoolExit(0) A: 100 (126)`
  183. l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  184. require.NoError(t, err)
  185. addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
  186. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
  187. // TxSelector select the transactions for the next Batch
  188. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  189. txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
  190. require.NoError(t, err)
  191. // BatchBuilder build Batch
  192. zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  193. require.NoError(t, err)
  194. assert.Equal(t,
  195. "21231789250434471575486264439945776732824482207853465397552873521865656677689",
  196. bb.LocalStateDB().MT.Root().BigInt().String())
  197. sendProofAndCheckResp(t, zki)
  198. err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs),
  199. txsel.LocalAccountsDB().CurrentBatch())
  200. require.NoError(t, err)
  201. err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
  202. require.NoError(t, err)
  203. log.Debug("(batch9) block:1 batch:1")
  204. // simulate the PoolL2Txs of the batch9
  205. batchPoolL2 = `
  206. Type: PoolL2
  207. PoolTransfer(0) D-A: 300 (126)
  208. PoolTransfer(0) B-D: 100 (126)`
  209. l2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  210. require.NoError(t, err)
  211. addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
  212. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
  213. // TxSelector select the transactions for the next Batch
  214. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  215. txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
  216. require.NoError(t, err)
  217. // BatchBuilder build Batch
  218. zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  219. require.NoError(t, err)
  220. assert.Equal(t,
  221. "11289313644810782435120113035387729451095637380468777086895109386127538554246",
  222. bb.LocalStateDB().MT.Root().BigInt().String())
  223. sendProofAndCheckResp(t, zki)
  224. err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs),
  225. txsel.LocalAccountsDB().CurrentBatch())
  226. require.NoError(t, err)
  227. err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
  228. require.NoError(t, err)
  229. log.Debug("(batch10) block:1 batch:2")
  230. l2Txs = []common.PoolL2Tx{}
  231. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
  232. // TxSelector select the transactions for the next Batch
  233. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  234. txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
  235. require.NoError(t, err)
  236. // BatchBuilder build Batch
  237. zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  238. require.NoError(t, err)
  239. // same root as previous batch, as the L1CoordinatorTxs created by the
  240. // Til set is not created by the TxSelector in this test
  241. assert.Equal(t,
  242. "11289313644810782435120113035387729451095637380468777086895109386127538554246",
  243. bb.LocalStateDB().MT.Root().BigInt().String())
  244. sendProofAndCheckResp(t, zki)
  245. err = l2DBTxSel.StartForging(common.TxIDsFromPoolL2Txs(l2Txs),
  246. txsel.LocalAccountsDB().CurrentBatch())
  247. require.NoError(t, err)
  248. err = l2DBTxSel.UpdateTxsInfo(discardedL2Txs)
  249. require.NoError(t, err)
  250. }
  251. // TestZKInputsExitWithFee0 checks the case where there is a PoolTxs of type
  252. // Exit with fee 0 for a TokenID that the Coordinator does not have it
  253. // registered yet
  254. func TestZKInputsExitWithFee0(t *testing.T) {
  255. tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
  256. var set = `
  257. Type: Blockchain
  258. AddToken(1)
  259. CreateAccountDeposit(1) A: 1000
  260. CreateAccountDeposit(1) B: 1000
  261. CreateAccountDeposit(1) C: 1000
  262. > batchL1
  263. > batchL1
  264. CreateAccountCoordinator(1) Coord
  265. > batch
  266. > block
  267. `
  268. blocks, err := tc.GenerateBlocks(set)
  269. require.NoError(t, err)
  270. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  271. txsel, l2DBTxSel, syncStateDB := initTxSelector(t, ChainID, hermezContractAddr, tc.Users["Coord"])
  272. bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB")
  273. require.NoError(t, err)
  274. bb, err := batchbuilder.NewBatchBuilder(bbDir, syncStateDB, 0, NLevels)
  275. require.NoError(t, err)
  276. // restart nonces of TilContext, as will be set by generating directly
  277. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  278. tc.RestartNonces()
  279. // add tokens to HistoryDB to avoid breaking FK constrains
  280. addTokens(t, tc, l2DBTxSel.DB())
  281. configBatch := &batchbuilder.ConfigBatch{
  282. TxProcessorConfig: txprocConfig,
  283. }
  284. // batch2
  285. // TxSelector select the transactions for the next Batch
  286. l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
  287. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err :=
  288. txsel.GetL1L2TxSelection(txprocConfig, l1UserTxs)
  289. require.NoError(t, err)
  290. // BatchBuilder build Batch
  291. zki, err := bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  292. require.NoError(t, err)
  293. assert.Equal(t,
  294. "8737171572459172806192626402462788826264011087579491137542380589998149683116",
  295. bb.LocalStateDB().MT.Root().BigInt().String())
  296. h, err := zki.HashGlobalData()
  297. require.NoError(t, err)
  298. assert.Equal(t,
  299. "18608843755023673022528019960628191162333429206359207449879743919826610006009",
  300. h.String())
  301. sendProofAndCheckResp(t, zki)
  302. // batch3
  303. batchPoolL2 := `
  304. Type: PoolL2
  305. PoolExit(1) A: 100 (0)`
  306. l2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  307. require.NoError(t, err)
  308. addL2Txs(t, l2DBTxSel, l2Txs) // Add L2s to TxSelector.L2DB
  309. coordIdxs, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
  310. txsel.GetL1L2TxSelection(txprocConfig, nil)
  311. require.NoError(t, err)
  312. assert.Equal(t, 1, len(coordIdxs))
  313. assert.Equal(t, 0, len(oL1UserTxs))
  314. assert.Equal(t, 1, len(oL1CoordTxs))
  315. assert.Equal(t, 1, len(oL2Txs))
  316. assert.Equal(t, 0, len(discardedL2Txs))
  317. // BatchBuilder build Batch
  318. zki, err = bb.BuildBatch(coordIdxs, configBatch, oL1UserTxs, oL1CoordTxs, oL2Txs)
  319. require.NoError(t, err)
  320. assert.Equal(t,
  321. "18306761925365215381387147754881756804475668085493847010988306480531520370130",
  322. bb.LocalStateDB().MT.Root().BigInt().String())
  323. h, err = zki.HashGlobalData()
  324. require.NoError(t, err)
  325. assert.Equal(t,
  326. "6651837443119278772088559395433504719862425648816904171510845286897104469889",
  327. h.String())
  328. assert.Equal(t, common.EthAddrToBigInt(tc.Users["Coord"].Addr), zki.EthAddr3[0])
  329. assert.Equal(t, "0", zki.EthAddr3[1].String())
  330. sendProofAndCheckResp(t, zki)
  331. }