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.

923 lines
33 KiB

Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
  1. package txselector
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "strconv"
  7. "testing"
  8. "time"
  9. ethCommon "github.com/ethereum/go-ethereum/common"
  10. ethCrypto "github.com/ethereum/go-ethereum/crypto"
  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/txprocessor"
  21. "github.com/jmoiron/sqlx"
  22. "github.com/stretchr/testify/assert"
  23. "github.com/stretchr/testify/require"
  24. )
  25. func initTest(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address,
  26. coordUser *til.User) *TxSelector {
  27. pass := os.Getenv("POSTGRES_PASS")
  28. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  29. require.NoError(t, err)
  30. l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 24*time.Hour, nil)
  31. dir, err := ioutil.TempDir("", "tmpdb")
  32. require.NoError(t, err)
  33. defer assert.NoError(t, os.RemoveAll(dir))
  34. syncStateDB, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
  35. Type: statedb.TypeTxSelector, NLevels: 0})
  36. require.NoError(t, err)
  37. txselDir, err := ioutil.TempDir("", "tmpTxSelDB")
  38. require.NoError(t, err)
  39. defer assert.NoError(t, os.RemoveAll(dir))
  40. // use Til Coord keys for tests compatibility
  41. coordAccount := &CoordAccount{
  42. Addr: coordUser.Addr,
  43. BJJ: coordUser.BJJ.Public().Compress(),
  44. AccountCreationAuth: nil,
  45. }
  46. // fmt.Printf("%v\n", coordAccount)
  47. auth := common.AccountCreationAuth{
  48. EthAddr: coordUser.Addr,
  49. BJJ: coordUser.BJJ.Public().Compress(),
  50. }
  51. err = auth.Sign(func(hash []byte) ([]byte, error) {
  52. return ethCrypto.Sign(hash, coordUser.EthSk)
  53. }, chainID, hermezContractAddr)
  54. assert.NoError(t, err)
  55. coordAccount.AccountCreationAuth = auth.Signature
  56. txsel, err := NewTxSelector(coordAccount, txselDir, syncStateDB, l2DB)
  57. require.NoError(t, err)
  58. test.WipeDB(txsel.l2db.DB())
  59. return txsel
  60. }
  61. func addAccCreationAuth(t *testing.T, tc *til.Context, txsel *TxSelector, chainID uint16,
  62. hermezContractAddr ethCommon.Address, username string) []byte {
  63. user := tc.Users[username]
  64. auth := &common.AccountCreationAuth{
  65. EthAddr: user.Addr,
  66. BJJ: user.BJJ.Public().Compress(),
  67. }
  68. err := auth.Sign(func(hash []byte) ([]byte, error) {
  69. return ethCrypto.Sign(hash, user.EthSk)
  70. }, chainID, hermezContractAddr)
  71. assert.NoError(t, err)
  72. err = txsel.l2db.AddAccountCreationAuth(auth)
  73. assert.NoError(t, err)
  74. return auth.Signature
  75. }
  76. func addL2Txs(t *testing.T, txsel *TxSelector, poolL2Txs []common.PoolL2Tx) {
  77. for i := 0; i < len(poolL2Txs); i++ {
  78. err := txsel.l2db.AddTxTest(&poolL2Txs[i])
  79. if err != nil {
  80. log.Error(err)
  81. }
  82. require.NoError(t, err)
  83. }
  84. }
  85. func addTokens(t *testing.T, tc *til.Context, db *sqlx.DB) {
  86. var tokens []common.Token
  87. for i := 0; i < int(tc.LastRegisteredTokenID); i++ {
  88. tokens = append(tokens, common.Token{
  89. TokenID: common.TokenID(i + 1),
  90. EthBlockNum: 1,
  91. EthAddr: ethCommon.BytesToAddress([]byte{byte(i + 1)}),
  92. Name: strconv.Itoa(i),
  93. Symbol: strconv.Itoa(i),
  94. Decimals: 18,
  95. })
  96. }
  97. hdb := historydb.NewHistoryDB(db, db, nil)
  98. assert.NoError(t, hdb.AddBlock(&common.Block{
  99. Num: 1,
  100. }))
  101. assert.NoError(t, hdb.AddTokens(tokens))
  102. }
  103. func checkBalance(t *testing.T, tc *til.Context, txsel *TxSelector, username string,
  104. tokenid int, expected string) {
  105. // Accounts.Idx does not match with the TxSelector tests as we are not
  106. // using the Til L1CoordinatorTxs (as are generated by the TxSelector
  107. // itself when processing the txs, so the Idxs does not match the Til
  108. // idxs). But the Idx is obtained through StateDB.GetIdxByEthAddrBJJ
  109. user := tc.Users[username]
  110. idx, err := txsel.localAccountsDB.GetIdxByEthAddrBJJ(user.Addr, user.BJJ.Public().Compress(),
  111. common.TokenID(tokenid))
  112. require.NoError(t, err)
  113. checkBalanceByIdx(t, txsel, idx, expected)
  114. }
  115. func checkBalanceByIdx(t *testing.T, txsel *TxSelector, idx common.Idx, expected string) {
  116. acc, err := txsel.localAccountsDB.GetAccount(idx)
  117. require.NoError(t, err)
  118. assert.Equal(t, expected, acc.Balance.String())
  119. }
  120. // checkSortedByNonce takes as input testAccNonces map, and the array of
  121. // common.PoolL2Txs, and checks if the nonces correspond to the accumulated
  122. // values of the map. Also increases the Nonces computed on the map.
  123. func checkSortedByNonce(t *testing.T, testAccNonces map[common.Idx]common.Nonce,
  124. txs []common.PoolL2Tx) {
  125. for _, tx := range txs {
  126. assert.True(t, testAccNonces[tx.FromIdx] == tx.Nonce,
  127. fmt.Sprintf("Idx: %d, expected: %d, tx.Nonce: %d",
  128. tx.FromIdx, testAccNonces[tx.FromIdx], tx.Nonce))
  129. testAccNonces[tx.FromIdx] = testAccNonces[tx.FromIdx] + 1
  130. }
  131. }
  132. func TestGetL2TxSelectionMinimumFlow0(t *testing.T) {
  133. chainID := uint16(0)
  134. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  135. // generate test transactions, the L1CoordinatorTxs generated by Til
  136. // will be ignored at this test, as will be the TxSelector who
  137. // generates them when needed
  138. blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
  139. assert.NoError(t, err)
  140. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  141. txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
  142. // restart nonces of TilContext, as will be set by generating directly
  143. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  144. tc.RestartNonces()
  145. testAccNonces := make(map[common.Idx]common.Nonce)
  146. // add tokens to HistoryDB to avoid breaking FK constrains
  147. addTokens(t, tc, txsel.l2db.DB())
  148. tpc := txprocessor.Config{
  149. NLevels: 16,
  150. MaxFeeTx: 10,
  151. MaxTx: 20,
  152. MaxL1Tx: 10,
  153. ChainID: chainID,
  154. }
  155. // coordIdxs, accAuths, l1UserTxs, l1CoordTxs, l2Txs, err
  156. log.Debug("block:0 batch:1")
  157. l1UserTxs := []common.L1Tx{}
  158. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err :=
  159. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  160. require.NoError(t, err)
  161. assert.Equal(t, 0, len(oL1UserTxs))
  162. assert.Equal(t, 0, len(oL1CoordTxs))
  163. assert.Equal(t, 0, len(oL2Txs))
  164. assert.Equal(t, common.BatchNum(1), txsel.localAccountsDB.CurrentBatch())
  165. assert.Equal(t, common.Idx(255), txsel.localAccountsDB.CurrentIdx())
  166. log.Debug("block:0 batch:2")
  167. l1UserTxs = []common.L1Tx{}
  168. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err =
  169. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  170. require.NoError(t, err)
  171. assert.Equal(t, 0, len(oL1UserTxs))
  172. assert.Equal(t, 0, len(oL1CoordTxs))
  173. assert.Equal(t, 0, len(oL2Txs))
  174. assert.Equal(t, common.BatchNum(2), txsel.localAccountsDB.CurrentBatch())
  175. assert.Equal(t, common.Idx(255), txsel.localAccountsDB.CurrentIdx())
  176. log.Debug("block:0 batch:3")
  177. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
  178. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err =
  179. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  180. require.NoError(t, err)
  181. assert.Equal(t, 2, len(oL1UserTxs))
  182. assert.Equal(t, 0, len(oL1CoordTxs))
  183. assert.Equal(t, 0, len(oL2Txs))
  184. assert.Equal(t, common.BatchNum(3), txsel.localAccountsDB.CurrentBatch())
  185. assert.Equal(t, common.Idx(257), txsel.localAccountsDB.CurrentIdx())
  186. checkBalance(t, tc, txsel, "A", 0, "500")
  187. checkBalance(t, tc, txsel, "C", 1, "0")
  188. log.Debug("block:0 batch:4")
  189. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
  190. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err =
  191. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  192. require.NoError(t, err)
  193. assert.Equal(t, 1, len(oL1UserTxs))
  194. assert.Equal(t, 0, len(oL1CoordTxs))
  195. assert.Equal(t, 0, len(oL2Txs))
  196. assert.Equal(t, common.BatchNum(4), txsel.localAccountsDB.CurrentBatch())
  197. assert.Equal(t, common.Idx(258), txsel.localAccountsDB.CurrentIdx())
  198. checkBalance(t, tc, txsel, "A", 0, "500")
  199. checkBalance(t, tc, txsel, "A", 1, "500")
  200. checkBalance(t, tc, txsel, "C", 1, "0")
  201. log.Debug("block:0 batch:5")
  202. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
  203. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err =
  204. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  205. require.NoError(t, err)
  206. assert.Equal(t, 0, len(oL1UserTxs))
  207. assert.Equal(t, 0, len(oL1CoordTxs))
  208. assert.Equal(t, 0, len(oL2Txs))
  209. assert.Equal(t, common.BatchNum(5), txsel.localAccountsDB.CurrentBatch())
  210. assert.Equal(t, common.Idx(258), txsel.localAccountsDB.CurrentIdx())
  211. checkBalance(t, tc, txsel, "A", 0, "500")
  212. checkBalance(t, tc, txsel, "A", 1, "500")
  213. checkBalance(t, tc, txsel, "C", 1, "0")
  214. log.Debug("block:0 batch:6")
  215. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
  216. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err =
  217. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  218. require.NoError(t, err)
  219. assert.Equal(t, 1, len(oL1UserTxs))
  220. assert.Equal(t, 0, len(oL1CoordTxs))
  221. assert.Equal(t, 0, len(oL2Txs))
  222. assert.Equal(t, common.BatchNum(6), txsel.localAccountsDB.CurrentBatch())
  223. assert.Equal(t, common.Idx(259), txsel.localAccountsDB.CurrentIdx())
  224. checkBalance(t, tc, txsel, "A", 0, "600")
  225. checkBalance(t, tc, txsel, "A", 1, "500")
  226. checkBalance(t, tc, txsel, "B", 0, "400")
  227. checkBalance(t, tc, txsel, "C", 1, "0")
  228. log.Debug("block:0 batch:7")
  229. // simulate the PoolL2Txs of the batch7
  230. batchPoolL2 := `
  231. Type: PoolL2
  232. PoolTransferToEthAddr(1) A-B: 200 (126)
  233. PoolTransferToEthAddr(0) B-C: 100 (126)`
  234. poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  235. require.NoError(t, err)
  236. // add AccountCreationAuths that will be used at the next batch
  237. accAuthSig0 := addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "B")
  238. accAuthSig1 := addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "C")
  239. // add the PoolL2Txs to the l2DB
  240. addL2Txs(t, txsel, poolL2Txs)
  241. // check signatures of L2Txs from the L2DB (to check that the
  242. // parameters of the PoolL2Tx match the original parameters signed
  243. // before inserting it to the L2DB)
  244. l2TxsFromDB, err := txsel.l2db.GetPendingTxs()
  245. require.NoError(t, err)
  246. assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress()))
  247. assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress()))
  248. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
  249. coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
  250. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  251. require.NoError(t, err)
  252. assert.Equal(t, []common.Idx{261, 263}, coordIdxs)
  253. assert.Equal(t, txsel.coordAccount.AccountCreationAuth, accAuths[0])
  254. assert.Equal(t, txsel.coordAccount.AccountCreationAuth, accAuths[2])
  255. assert.Equal(t, accAuthSig0, accAuths[1])
  256. assert.Equal(t, accAuthSig1, accAuths[3])
  257. assert.Equal(t, 1, len(oL1UserTxs))
  258. assert.Equal(t, 4, len(oL1CoordTxs))
  259. assert.Equal(t, 2, len(oL2Txs))
  260. assert.Equal(t, 0, len(discardedL2Txs))
  261. assert.Equal(t, len(oL1CoordTxs), len(accAuths))
  262. assert.Equal(t, common.BatchNum(7), txsel.localAccountsDB.CurrentBatch())
  263. assert.Equal(t, common.Idx(264), txsel.localAccountsDB.CurrentIdx())
  264. checkBalance(t, tc, txsel, "Coord", 1, "20") // CoordIdx for TokenID=1
  265. checkBalance(t, tc, txsel, "Coord", 0, "10") // CoordIdx for TokenID=1
  266. checkBalance(t, tc, txsel, "A", 0, "600")
  267. checkBalance(t, tc, txsel, "A", 1, "280")
  268. checkBalance(t, tc, txsel, "B", 0, "290")
  269. checkBalance(t, tc, txsel, "B", 1, "200")
  270. checkBalance(t, tc, txsel, "C", 0, "100")
  271. checkBalance(t, tc, txsel, "D", 0, "800")
  272. checkSortedByNonce(t, testAccNonces, oL2Txs)
  273. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(poolL2Txs),
  274. txsel.localAccountsDB.CurrentBatch())
  275. require.NoError(t, err)
  276. log.Debug("block:0 batch:8")
  277. // simulate the PoolL2Txs of the batch8
  278. batchPoolL2 = `
  279. Type: PoolL2
  280. PoolTransfer(0) A-B: 100 (126)
  281. PoolTransfer(0) C-A: 50 (126)
  282. PoolTransfer(1) B-C: 100 (126)
  283. PoolExit(0) A: 100 (126)`
  284. poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  285. require.NoError(t, err)
  286. addL2Txs(t, txsel, poolL2Txs)
  287. // check signatures of L2Txs from the L2DB (to check that the
  288. // parameters of the PoolL2Tx match the original parameters signed
  289. // before inserting it to the L2DB)
  290. l2TxsFromDB, err = txsel.l2db.GetPendingTxs()
  291. require.NoError(t, err)
  292. assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress()))
  293. assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["C"].BJJ.Public().Compress()))
  294. assert.True(t, l2TxsFromDB[2].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress()))
  295. assert.True(t, l2TxsFromDB[3].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress()))
  296. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
  297. coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  298. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  299. require.NoError(t, err)
  300. assert.Equal(t, []common.Idx{261, 263}, coordIdxs)
  301. assert.Equal(t, 0, len(accAuths))
  302. assert.Equal(t, 0, len(oL1UserTxs))
  303. assert.Equal(t, 0, len(oL1CoordTxs))
  304. assert.Equal(t, 4, len(oL2Txs))
  305. assert.Equal(t, 0, len(discardedL2Txs))
  306. assert.Equal(t, len(oL1CoordTxs), len(accAuths))
  307. assert.Equal(t, common.BatchNum(8), txsel.localAccountsDB.CurrentBatch())
  308. assert.Equal(t, common.Idx(264), txsel.localAccountsDB.CurrentIdx())
  309. checkBalance(t, tc, txsel, "Coord", 1, "30") // CoordIdx for TokenID=1
  310. checkBalance(t, tc, txsel, "Coord", 0, "35") // CoordIdx for TokenID=1
  311. checkBalance(t, tc, txsel, "A", 0, "430")
  312. checkBalance(t, tc, txsel, "A", 1, "280")
  313. checkBalance(t, tc, txsel, "B", 0, "390")
  314. checkBalance(t, tc, txsel, "B", 1, "90")
  315. checkBalance(t, tc, txsel, "C", 0, "45")
  316. checkBalance(t, tc, txsel, "C", 1, "100")
  317. checkBalance(t, tc, txsel, "D", 0, "800")
  318. checkSortedByNonce(t, testAccNonces, oL2Txs)
  319. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(poolL2Txs),
  320. txsel.localAccountsDB.CurrentBatch())
  321. require.NoError(t, err)
  322. log.Debug("(batch9)block:1 batch:1")
  323. // simulate the PoolL2Txs of the batch9
  324. batchPoolL2 = `
  325. Type: PoolL2
  326. PoolTransfer(0) D-A: 300 (126)
  327. PoolTransfer(0) B-D: 100 (126)
  328. `
  329. poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  330. require.NoError(t, err)
  331. addL2Txs(t, txsel, poolL2Txs)
  332. // check signatures of L2Txs from the L2DB (to check that the
  333. // parameters of the PoolL2Tx match the original parameters signed
  334. // before inserting it to the L2DB)
  335. l2TxsFromDB, err = txsel.l2db.GetPendingTxs()
  336. require.NoError(t, err)
  337. assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["D"].BJJ.Public().Compress()))
  338. assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress()))
  339. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
  340. coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, _, err =
  341. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  342. require.NoError(t, err)
  343. assert.Equal(t, []common.Idx{263}, coordIdxs)
  344. assert.Equal(t, 0, len(accAuths))
  345. assert.Equal(t, 4, len(oL1UserTxs))
  346. assert.Equal(t, 0, len(oL1CoordTxs))
  347. assert.Equal(t, 2, len(oL2Txs))
  348. assert.Equal(t, len(oL1CoordTxs), len(accAuths))
  349. assert.Equal(t, common.BatchNum(9), txsel.localAccountsDB.CurrentBatch())
  350. assert.Equal(t, common.Idx(264), txsel.localAccountsDB.CurrentIdx())
  351. checkBalanceByIdx(t, txsel, 261, "30")
  352. checkBalanceByIdx(t, txsel, 263, "75")
  353. checkBalance(t, tc, txsel, "A", 0, "730")
  354. checkBalance(t, tc, txsel, "A", 1, "280")
  355. checkBalance(t, tc, txsel, "B", 0, "380")
  356. checkBalance(t, tc, txsel, "B", 1, "90")
  357. checkBalance(t, tc, txsel, "C", 0, "845")
  358. checkBalance(t, tc, txsel, "C", 1, "100")
  359. checkBalance(t, tc, txsel, "D", 0, "470")
  360. checkSortedByNonce(t, testAccNonces, oL2Txs)
  361. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(poolL2Txs),
  362. txsel.localAccountsDB.CurrentBatch())
  363. require.NoError(t, err)
  364. }
  365. func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) {
  366. set := `
  367. Type: Blockchain
  368. CreateAccountDeposit(0) Coord: 0
  369. CreateAccountDeposit(0) A: 100
  370. CreateAccountDeposit(0) B: 100
  371. > batchL1 // freeze L1User{3}
  372. > batchL1 // forge L1User{3}
  373. > block
  374. `
  375. chainID := uint16(0)
  376. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  377. // generate test transactions, the L1CoordinatorTxs generated by Til
  378. // will be ignored at this test, as will be the TxSelector who
  379. // generates them when needed
  380. blocks, err := tc.GenerateBlocks(set)
  381. assert.NoError(t, err)
  382. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  383. txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
  384. // restart nonces of TilContext, as will be set by generating directly
  385. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  386. tc.RestartNonces()
  387. tpc := txprocessor.Config{
  388. NLevels: 16,
  389. MaxFeeTx: 10,
  390. MaxTx: 20,
  391. MaxL1Tx: 10,
  392. ChainID: chainID,
  393. }
  394. // batch1
  395. l1UserTxs := []common.L1Tx{}
  396. _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  397. require.NoError(t, err)
  398. // 1st TransferToEthAddr
  399. expectedTxID0 := "0x028847b86613c0b70be18c8622119ed045b42e4e47d7938fa90bb3d1dc14928965"
  400. // 1st Exit
  401. expectedTxID1 := "0x0200b18773dcf56f770d65870fb02041cb59a088fd35b7c3f3df69f8a250b99a42"
  402. // 2nd TransferToEthAddr
  403. expectedTxID2 := "0x029720ff506153f970f120ac638cd7ee759eeff2c2012e7634a78e4fdc05c04a90"
  404. // batch2
  405. // prepare the PoolL2Txs
  406. batchPoolL2 := `
  407. Type: PoolL2
  408. PoolTransferToEthAddr(0) A-B: 100 (126)
  409. PoolExit(0) B: 100 (126)`
  410. poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  411. require.NoError(t, err)
  412. // add the PoolL2Txs to the l2DB
  413. addL2Txs(t, txsel, poolL2Txs)
  414. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
  415. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
  416. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  417. require.NoError(t, err)
  418. assert.Equal(t, 3, len(oL1UserTxs))
  419. assert.Equal(t, 0, len(oL1CoordTxs))
  420. assert.Equal(t, 0, len(oL2Txs)) // should be 0 as the 2 PoolL2Txs does not have enough funds
  421. assert.Equal(t, 2, len(discardedL2Txs))
  422. assert.Equal(t, expectedTxID0, discardedL2Txs[0].TxID.String())
  423. assert.Equal(t, expectedTxID1, discardedL2Txs[1].TxID.String())
  424. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  425. txsel.localAccountsDB.CurrentBatch())
  426. require.NoError(t, err)
  427. // as the PoolL2Txs have not been really processed, restart nonces
  428. tc.RestartNonces()
  429. // batch3
  430. // NOTE: this batch will result with 1 L2Tx, as the PoolExit tx is not
  431. // possible, as the PoolTransferToEthAddr is not processed yet when
  432. // checking availability of PoolExit. This, in a near-future iteration
  433. // of the TxSelector will return the 2 transactions as valid and
  434. // selected, as the TxSelector will handle this kind of combinations.
  435. batchPoolL2 = `
  436. Type: PoolL2
  437. PoolTransferToEthAddr(0) A-B: 50 (126)`
  438. poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  439. require.NoError(t, err)
  440. addL2Txs(t, txsel, poolL2Txs)
  441. l1UserTxs = []common.L1Tx{}
  442. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  443. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  444. require.NoError(t, err)
  445. assert.Equal(t, 0, len(oL1UserTxs))
  446. assert.Equal(t, 0, len(oL1CoordTxs))
  447. assert.Equal(t, 1, len(oL2Txs)) // see 'NOTE' at the beginning of 'batch3' of this test
  448. assert.Equal(t, 2, len(discardedL2Txs))
  449. assert.Equal(t, expectedTxID2, oL2Txs[0].TxID.String())
  450. assert.Equal(t, expectedTxID0, discardedL2Txs[0].TxID.String())
  451. assert.Equal(t, expectedTxID1, discardedL2Txs[1].TxID.String())
  452. assert.Equal(t, common.TxTypeTransferToEthAddr, oL2Txs[0].Type)
  453. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  454. txsel.localAccountsDB.CurrentBatch())
  455. require.NoError(t, err)
  456. // batch4
  457. // make the selection of another batch, which should include the
  458. // initial PoolExit, which now is valid as B has enough Balance
  459. l1UserTxs = []common.L1Tx{}
  460. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  461. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  462. require.NoError(t, err)
  463. assert.Equal(t, 0, len(oL1UserTxs))
  464. assert.Equal(t, 0, len(oL1CoordTxs))
  465. assert.Equal(t, 1, len(oL2Txs))
  466. assert.Equal(t, 1, len(discardedL2Txs))
  467. // the Exit that was not accepted at the batch2
  468. assert.Equal(t, expectedTxID1, oL2Txs[0].TxID.String())
  469. assert.Equal(t, expectedTxID0, discardedL2Txs[0].TxID.String())
  470. assert.Equal(t, common.TxTypeExit, oL2Txs[0].Type)
  471. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  472. txsel.localAccountsDB.CurrentBatch())
  473. require.NoError(t, err)
  474. }
  475. func TestTransferToBjj(t *testing.T) {
  476. set := `
  477. Type: Blockchain
  478. AddToken(1)
  479. CreateAccountDeposit(0) Coord: 0
  480. CreateAccountDeposit(0) A: 1000
  481. CreateAccountDeposit(0) B: 1000
  482. CreateAccountDeposit(1) B: 1000
  483. > batchL1 // freeze L1User{4}
  484. > batchL1 // forge L1User{4}
  485. > block
  486. `
  487. chainID := uint16(0)
  488. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  489. blocks, err := tc.GenerateBlocks(set)
  490. assert.NoError(t, err)
  491. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  492. txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
  493. // restart nonces of TilContext, as will be set by generating directly
  494. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  495. tc.RestartNonces()
  496. addTokens(t, tc, txsel.l2db.DB())
  497. tpc := txprocessor.Config{
  498. NLevels: 16,
  499. MaxFeeTx: 10,
  500. MaxTx: 20,
  501. MaxL1Tx: 10,
  502. ChainID: chainID,
  503. }
  504. // batch1 to freeze L1UserTxs that will create some accounts with
  505. // positive balance
  506. l1UserTxs := []common.L1Tx{}
  507. _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  508. require.NoError(t, err)
  509. // Transfer is ToBJJ to a BJJ-only account that doesn't exist
  510. // and the coordinator will create it via L1CoordTx.
  511. batchPoolL2 := `
  512. Type: PoolL2
  513. PoolTransferToBJJ(0) A-B: 50 (126)
  514. `
  515. poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  516. require.NoError(t, err)
  517. // add the PoolL2Txs to the l2DB
  518. addL2Txs(t, txsel, poolL2Txs)
  519. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
  520. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
  521. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  522. require.NoError(t, err)
  523. assert.Equal(t, 4, len(oL1UserTxs))
  524. // We expect the coordinator to add an L1CoordTx to create an account for the recipient of the l2tx
  525. require.Equal(t, 1, len(oL1CoordTxs))
  526. assert.Equal(t, poolL2Txs[0].ToEthAddr, oL1CoordTxs[0].FromEthAddr)
  527. assert.Equal(t, poolL2Txs[0].ToBJJ, oL1CoordTxs[0].FromBJJ)
  528. assert.Equal(t, 1, len(oL2Txs))
  529. assert.Equal(t, 0, len(discardedL2Txs))
  530. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  531. txsel.localAccountsDB.CurrentBatch())
  532. require.NoError(t, err)
  533. // Now the BJJ-only account for B is already created, so the transfer
  534. // happens without an L1CoordTx that creates the user account.
  535. batchPoolL2 = `
  536. Type: PoolL2
  537. PoolTransferToBJJ(0) A-B: 50 (126)
  538. `
  539. poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  540. require.NoError(t, err)
  541. addL2Txs(t, txsel, poolL2Txs)
  542. l1UserTxs = []common.L1Tx{}
  543. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  544. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  545. require.NoError(t, err)
  546. assert.Equal(t, 0, len(oL1UserTxs))
  547. // Since the BJJ-only account B already exists, the coordinator doesn't add any L1CoordTxs
  548. assert.Equal(t, 0, len(oL1CoordTxs))
  549. assert.Equal(t, 1, len(oL2Txs))
  550. assert.Equal(t, 0, len(discardedL2Txs))
  551. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  552. txsel.localAccountsDB.CurrentBatch())
  553. require.NoError(t, err)
  554. // The transfer now is ToBJJ to a BJJ-only account that doesn't exist
  555. // and the coordinator will create it via L1CoordTx. Since it's a
  556. // transfer of a token for which the coordinator doesn't have a fee
  557. // account, another L1CoordTx will be created for the coordinator to
  558. // receive the fees.
  559. batchPoolL2 = `
  560. Type: PoolL2
  561. PoolTransferToBJJ(1) B-A: 50 (126)
  562. `
  563. poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
  564. require.NoError(t, err)
  565. addL2Txs(t, txsel, poolL2Txs)
  566. l1UserTxs = []common.L1Tx{}
  567. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  568. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  569. require.NoError(t, err)
  570. assert.Equal(t, 0, len(oL1UserTxs))
  571. // We expect the coordinator to add an L1CoordTx to create an account
  572. // to receive the fees by the coordinator and another one for the
  573. // recipient of the l2tx
  574. assert.Equal(t, 2, len(oL1CoordTxs))
  575. // [0] Coordinator account cration for token 1
  576. assert.Equal(t, tc.Users["Coord"].Addr, oL1CoordTxs[0].FromEthAddr)
  577. // [1] User A BJJ-only account creation for token 1
  578. assert.Equal(t, poolL2Txs[0].ToEthAddr, oL1CoordTxs[1].FromEthAddr)
  579. assert.Equal(t, poolL2Txs[0].ToBJJ, oL1CoordTxs[1].FromBJJ)
  580. assert.Equal(t, common.TokenID(1), oL1CoordTxs[1].TokenID)
  581. assert.Equal(t, 1, len(oL2Txs))
  582. assert.Equal(t, 0, len(discardedL2Txs))
  583. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  584. txsel.localAccountsDB.CurrentBatch())
  585. require.NoError(t, err)
  586. }
  587. func TestTransferManyFromSameAccount(t *testing.T) {
  588. set := `
  589. Type: Blockchain
  590. CreateAccountDeposit(0) Coord: 0
  591. CreateAccountDeposit(0) A: 1000
  592. CreateAccountDeposit(0) B: 1000
  593. > batchL1 // freeze L1User{3}
  594. > batchL1 // forge L1User{3}
  595. > block
  596. `
  597. chainID := uint16(0)
  598. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  599. blocks, err := tc.GenerateBlocks(set)
  600. assert.NoError(t, err)
  601. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  602. txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
  603. // restart nonces of TilContext, as will be set by generating directly
  604. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  605. tc.RestartNonces()
  606. tpc := txprocessor.Config{
  607. NLevels: 16,
  608. MaxFeeTx: 10,
  609. MaxTx: 10,
  610. MaxL1Tx: 10,
  611. ChainID: chainID,
  612. }
  613. // batch1 to freeze L1UserTxs
  614. l1UserTxs := []common.L1Tx{}
  615. _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  616. require.NoError(t, err)
  617. // 8 transfers from the same account
  618. batchPoolL2 := `
  619. Type: PoolL2
  620. PoolTransfer(0) A-B: 10 (126) // 1
  621. PoolTransfer(0) A-B: 10 (126) // 2
  622. PoolTransfer(0) A-B: 10 (126) // 3
  623. PoolTransfer(0) A-B: 10 (126) // 4
  624. PoolTransfer(0) A-B: 10 (126) // 5
  625. PoolTransfer(0) A-B: 10 (126) // 6
  626. PoolTransfer(0) A-B: 10 (126) // 7
  627. PoolTransfer(0) A-B: 10 (126) // 8
  628. PoolTransfer(0) A-B: 10 (126) // 9
  629. PoolTransfer(0) A-B: 10 (126) // 10
  630. PoolTransfer(0) A-B: 10 (126) // 11
  631. `
  632. poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  633. require.NoError(t, err)
  634. require.Equal(t, 11, len(poolL2Txs))
  635. // reorder poolL2Txs so that nonces are not sorted
  636. poolL2Txs[0], poolL2Txs[7] = poolL2Txs[7], poolL2Txs[0]
  637. poolL2Txs[1], poolL2Txs[10] = poolL2Txs[10], poolL2Txs[1]
  638. // add the PoolL2Txs to the l2DB
  639. addL2Txs(t, txsel, poolL2Txs)
  640. // batch 2 to crate some accounts with positive balance, and do 8 L2Tx
  641. // transfers from account A
  642. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
  643. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
  644. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  645. require.NoError(t, err)
  646. assert.Equal(t, 3, len(oL1UserTxs))
  647. require.Equal(t, 0, len(oL1CoordTxs))
  648. assert.Equal(t, 7, len(oL2Txs))
  649. assert.Equal(t, 4, len(discardedL2Txs))
  650. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  651. txsel.localAccountsDB.CurrentBatch())
  652. require.NoError(t, err)
  653. }
  654. func TestPoolL2TxInvalidNonces(t *testing.T) {
  655. // This test recreates the case where L2Txs of type TransferToEthAddr
  656. // for non existing accounts are not selected due not enough space for
  657. // the needed L1CoordinatorTxs (of account creation).
  658. set := `
  659. Type: Blockchain
  660. CreateAccountDeposit(0) Coord: 0
  661. CreateAccountDeposit(0) A: 100000
  662. CreateAccountDeposit(0) B: 10000
  663. > batchL1 // Batch1: freeze L1User{3}
  664. > batchL1 // Batch2: forge L1User{3}
  665. > block
  666. `
  667. chainID := uint16(0)
  668. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  669. blocks, err := tc.GenerateBlocks(set)
  670. assert.NoError(t, err)
  671. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  672. txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
  673. // restart nonces of TilContext, as will be set by generating directly
  674. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  675. tc.RestartNonces()
  676. tpc := txprocessor.Config{
  677. NLevels: 16,
  678. MaxFeeTx: 10,
  679. MaxTx: 20,
  680. MaxL1Tx: 3,
  681. ChainID: chainID,
  682. }
  683. // batch1 to freeze L1UserTxs
  684. l1UserTxs := []common.L1Tx{}
  685. _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  686. require.NoError(t, err)
  687. batchPoolL2 := `
  688. Type: PoolL2
  689. PoolTransferToEthAddr(0) B-C: 10 (126)
  690. PoolTransfer(0) B-A: 10 (126)
  691. PoolTransferToEthAddr(0) B-D: 10 (126)
  692. PoolTransfer(0) B-A: 10 (126)
  693. PoolTransferToEthAddr(0) B-E: 10 (126)
  694. PoolTransfer(0) B-A: 10 (126)
  695. PoolTransferToEthAddr(0) B-F: 10 (126)
  696. PoolTransfer(0) B-A: 10 (126)
  697. PoolTransferToEthAddr(0) B-G: 10 (126)
  698. PoolTransfer(0) B-A: 10 (126)
  699. `
  700. poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  701. require.NoError(t, err)
  702. require.Equal(t, 10, len(poolL2Txs))
  703. // add AccountCreationAuths that will be used at the next batch
  704. _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "C")
  705. _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "D")
  706. _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "E")
  707. _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "F")
  708. _ = addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "G")
  709. // add the PoolL2Txs to the l2DB
  710. addL2Txs(t, txsel, poolL2Txs)
  711. // batch 2 to crate the accounts (from L1UserTxs)
  712. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
  713. // select L1 & L2 txs
  714. _, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
  715. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  716. require.NoError(t, err)
  717. require.Equal(t, 3, len(oL1UserTxs))
  718. require.Equal(t, 0, len(oL1CoordTxs))
  719. require.Equal(t, 0, len(oL2Txs))
  720. require.Equal(t, 10, len(discardedL2Txs))
  721. require.Equal(t, 0, len(accAuths))
  722. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  723. txsel.localAccountsDB.CurrentBatch())
  724. require.NoError(t, err)
  725. // batch 3
  726. l1UserTxs = []common.L1Tx{}
  727. _, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  728. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  729. require.NoError(t, err)
  730. require.Equal(t, 0, len(oL1UserTxs))
  731. require.Equal(t, 3, len(oL1CoordTxs))
  732. require.Equal(t, 8, len(oL2Txs))
  733. require.Equal(t, 2, len(discardedL2Txs))
  734. require.Equal(t, 3, len(accAuths))
  735. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  736. txsel.localAccountsDB.CurrentBatch())
  737. require.NoError(t, err)
  738. // batch 4
  739. l1UserTxs = []common.L1Tx{}
  740. _, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
  741. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  742. require.NoError(t, err)
  743. require.Equal(t, 0, len(oL1UserTxs))
  744. require.Equal(t, 1, len(oL1CoordTxs))
  745. require.Equal(t, 2, len(oL2Txs))
  746. require.Equal(t, 0, len(discardedL2Txs))
  747. require.Equal(t, 1, len(accAuths))
  748. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  749. txsel.localAccountsDB.CurrentBatch())
  750. require.NoError(t, err)
  751. }
  752. func TestProcessL2Selection(t *testing.T) {
  753. set := `
  754. Type: Blockchain
  755. CreateAccountDeposit(0) Coord: 0
  756. CreateAccountDeposit(0) A: 18
  757. CreateAccountDeposit(0) B: 0
  758. > batchL1 // freeze L1User{3}
  759. > batchL1 // forge L1User{3}
  760. > block
  761. `
  762. chainID := uint16(0)
  763. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  764. blocks, err := tc.GenerateBlocks(set)
  765. assert.NoError(t, err)
  766. hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  767. txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
  768. // restart nonces of TilContext, as will be set by generating directly
  769. // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
  770. tc.RestartNonces()
  771. tpc := txprocessor.Config{
  772. NLevels: 16,
  773. MaxFeeTx: 10,
  774. MaxTx: 10,
  775. MaxL1Tx: 10,
  776. ChainID: chainID,
  777. }
  778. // batch1 to freeze L1UserTxs
  779. l1UserTxs := []common.L1Tx{}
  780. _, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  781. require.NoError(t, err)
  782. // 8 transfers from the same account
  783. batchPoolL2 := `
  784. Type: PoolL2
  785. PoolTransfer(0) A-B: 10 (126)
  786. PoolTransfer(0) A-B: 10 (126) // not enough funds
  787. PoolTransfer(0) A-B: 5 (126) // enough funds
  788. `
  789. poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
  790. require.NoError(t, err)
  791. require.Equal(t, 3, len(poolL2Txs))
  792. // add the PoolL2Txs to the l2DB
  793. addL2Txs(t, txsel, poolL2Txs)
  794. // batch 2 to crate some accounts with positive balance, and do 8 L2Tx transfers from account A
  795. l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
  796. _, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
  797. txsel.GetL1L2TxSelection(tpc, l1UserTxs)
  798. require.NoError(t, err)
  799. assert.Equal(t, 3, len(oL1UserTxs))
  800. require.Equal(t, 0, len(oL1CoordTxs))
  801. // only 1st L2Tx should be accepted, as:
  802. // - 2nd will not be selected as has not enough funds
  803. // - 3rd will not be selected as has Nonce=2, and the account Nonce==1
  804. // (due the 2nd txs not being accepted)
  805. assert.Equal(t, 1, len(oL2Txs))
  806. assert.Equal(t, 2, len(discardedL2Txs))
  807. assert.Equal(t, common.Nonce(0), oL2Txs[0].Nonce)
  808. assert.Equal(t, common.Nonce(1), discardedL2Txs[0].Nonce)
  809. assert.Equal(t, common.Nonce(2), discardedL2Txs[1].Nonce)
  810. assert.Equal(t, "Tx not selected due to not enough Balance at the sender. "+
  811. "Current sender account Balance: 7, Amount+Fee: 11", discardedL2Txs[0].Info)
  812. assert.Equal(t, "Tx not selected due to not current Nonce. Tx.Nonce: 2, "+
  813. "Account.Nonce: 1", discardedL2Txs[1].Info)
  814. err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
  815. txsel.localAccountsDB.CurrentBatch())
  816. require.NoError(t, err)
  817. }