arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/txselector/txselector_test.go
txselector/txselector_test.goRaw
  1package txselector
  2
  3import (
  4	"fmt"
  5	"io/ioutil"
  6	"os"
  7	"strconv"
  8	"testing"
  9	"time"
 10
 11	ethCommon "github.com/ethereum/go-ethereum/common"
 12	ethCrypto "github.com/ethereum/go-ethereum/crypto"
 13	"github.com/hermeznetwork/hermez-node/common"
 14	dbUtils "github.com/hermeznetwork/hermez-node/db"
 15	"github.com/hermeznetwork/hermez-node/db/historydb"
 16	"github.com/hermeznetwork/hermez-node/db/l2db"
 17	"github.com/hermeznetwork/hermez-node/db/statedb"
 18	"github.com/hermeznetwork/hermez-node/log"
 19	"github.com/hermeznetwork/hermez-node/test"
 20	"github.com/hermeznetwork/hermez-node/test/til"
 21	"github.com/hermeznetwork/hermez-node/test/txsets"
 22	"github.com/hermeznetwork/hermez-node/txprocessor"
 23	"github.com/jmoiron/sqlx"
 24	"github.com/stretchr/testify/assert"
 25	"github.com/stretchr/testify/require"
 26)
 27
 28func initTest(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address, coordUser *til.User) *TxSelector {
 29	pass := os.Getenv("POSTGRES_PASS")
 30	db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
 31	require.NoError(t, err)
 32	l2DB := l2db.NewL2DB(db, 10, 100, 24*time.Hour)
 33
 34	dir, err := ioutil.TempDir("", "tmpdb")
 35	require.NoError(t, err)
 36	defer assert.NoError(t, os.RemoveAll(dir))
 37	syncStateDB, err := statedb.NewStateDB(dir, 128, statedb.TypeTxSelector, 0)
 38	require.NoError(t, err)
 39
 40	txselDir, err := ioutil.TempDir("", "tmpTxSelDB")
 41	require.NoError(t, err)
 42	defer assert.NoError(t, os.RemoveAll(dir))
 43
 44	// use Til Coord keys for tests compatibility
 45	coordAccount := &CoordAccount{
 46		Addr:                coordUser.Addr,
 47		BJJ:                 coordUser.BJJ.Public().Compress(),
 48		AccountCreationAuth: nil,
 49	}
 50	fmt.Printf("%v", coordAccount)
 51	auth := common.AccountCreationAuth{
 52		EthAddr: coordUser.Addr,
 53		BJJ:     coordUser.BJJ.Public().Compress(),
 54	}
 55	err = auth.Sign(func(hash []byte) ([]byte, error) {
 56		return ethCrypto.Sign(hash, coordUser.EthSk)
 57	}, chainID, hermezContractAddr)
 58	assert.NoError(t, err)
 59	coordAccount.AccountCreationAuth = auth.Signature
 60
 61	txsel, err := NewTxSelector(coordAccount, txselDir, syncStateDB, l2DB)
 62	require.NoError(t, err)
 63
 64	test.WipeDB(txsel.l2db.DB())
 65
 66	return txsel
 67}
 68
 69func addAccCreationAuth(t *testing.T, tc *til.Context, txsel *TxSelector, chainID uint16, hermezContractAddr ethCommon.Address, username string) []byte {
 70	user := tc.Users[username]
 71	auth := &common.AccountCreationAuth{
 72		EthAddr: user.Addr,
 73		BJJ:     user.BJJ.Public().Compress(),
 74	}
 75	err := auth.Sign(func(hash []byte) ([]byte, error) {
 76		return ethCrypto.Sign(hash, user.EthSk)
 77	}, chainID, hermezContractAddr)
 78	assert.NoError(t, err)
 79
 80	err = txsel.l2db.AddAccountCreationAuth(auth)
 81	assert.NoError(t, err)
 82	return auth.Signature
 83}
 84
 85func addL2Txs(t *testing.T, txsel *TxSelector, poolL2Txs []common.PoolL2Tx) {
 86	for i := 0; i < len(poolL2Txs); i++ {
 87		err := txsel.l2db.AddTxTest(&poolL2Txs[i])
 88		if err != nil {
 89			log.Error(err)
 90		}
 91		require.NoError(t, err)
 92	}
 93}
 94
 95func addTokens(t *testing.T, tc *til.Context, db *sqlx.DB) {
 96	var tokens []common.Token
 97	for i := 0; i < int(tc.LastRegisteredTokenID); i++ {
 98		tokens = append(tokens, common.Token{
 99			TokenID:     common.TokenID(i + 1),
100			EthBlockNum: 1,
101			EthAddr:     ethCommon.BytesToAddress([]byte{byte(i + 1)}),
102			Name:        strconv.Itoa(i),
103			Symbol:      strconv.Itoa(i),
104			Decimals:    18,
105		})
106	}
107
108	hdb := historydb.NewHistoryDB(db)
109	assert.NoError(t, hdb.AddBlock(&common.Block{
110		Num: 1,
111	}))
112	assert.NoError(t, hdb.AddTokens(tokens))
113}
114
115func checkBalance(t *testing.T, tc *til.Context, txsel *TxSelector, username string, tokenid int, expected string) {
116	// Accounts.Idx does not match with the TxSelector tests as we are not
117	// using the Til L1CoordinatorTxs (as are generated by the TxSelector
118	// itself when processing the txs, so the Idxs does not match the Til
119	// idxs). But the Idx is obtained through StateDB.GetIdxByEthAddrBJJ
120	user := tc.Users[username]
121	idx, err := txsel.localAccountsDB.GetIdxByEthAddrBJJ(user.Addr, user.BJJ.Public().Compress(), common.TokenID(tokenid))
122	require.NoError(t, err)
123	checkBalanceByIdx(t, txsel, idx, expected)
124}
125
126func checkBalanceByIdx(t *testing.T, txsel *TxSelector, idx common.Idx, expected string) {
127	acc, err := txsel.localAccountsDB.GetAccount(idx)
128	require.NoError(t, err)
129	assert.Equal(t, expected, acc.Balance.String())
130}
131
132// checkSortedByNonce takes as input testAccNonces map, and the array of
133// common.PoolL2Txs, and checks if the nonces correspond to the accumulated
134// values of the map. Also increases the Nonces computed on the map.
135func checkSortedByNonce(t *testing.T, testAccNonces map[common.Idx]common.Nonce, txs []common.PoolL2Tx) {
136	for _, tx := range txs {
137		assert.True(t, testAccNonces[tx.FromIdx] == tx.Nonce,
138			fmt.Sprintf("Idx: %d, expected: %d, tx.Nonce: %d",
139				tx.FromIdx, testAccNonces[tx.FromIdx], tx.Nonce))
140		testAccNonces[tx.FromIdx] = testAccNonces[tx.FromIdx] + 1
141	}
142}
143
144func TestGetL2TxSelectionMinimumFlow0(t *testing.T) {
145	chainID := uint16(0)
146	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
147	// generate test transactions, the L1CoordinatorTxs generated by Til
148	// will be ignored at this test, as will be the TxSelector who
149	// generates them when needed
150	blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
151	assert.NoError(t, err)
152
153	hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
154	txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
155
156	// restart nonces of TilContext, as will be set by generating directly
157	// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
158	tc.RestartNonces()
159	testAccNonces := make(map[common.Idx]common.Nonce)
160
161	// add tokens to HistoryDB to avoid breaking FK constrains
162	addTokens(t, tc, txsel.l2db.DB())
163
164	tpc := txprocessor.Config{
165		NLevels:  16,
166		MaxFeeTx: 10,
167		MaxTx:    20,
168		MaxL1Tx:  10,
169		ChainID:  chainID,
170	}
171	selectionConfig := &SelectionConfig{
172		MaxL1UserTxs:      5,
173		TxProcessorConfig: tpc,
174	}
175
176	// coordIdxs, accAuths, l1UserTxs, l1CoordTxs, l2Txs, err
177
178	log.Debug("block:0 batch:1")
179	l1UserTxs := []common.L1Tx{}
180	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
181	require.NoError(t, err)
182	assert.Equal(t, 0, len(oL1UserTxs))
183	assert.Equal(t, 0, len(oL1CoordTxs))
184	assert.Equal(t, 0, len(oL2Txs))
185	assert.Equal(t, common.BatchNum(1), txsel.localAccountsDB.CurrentBatch())
186	assert.Equal(t, common.Idx(255), txsel.localAccountsDB.CurrentIdx())
187
188	log.Debug("block:0 batch:2")
189	l1UserTxs = []common.L1Tx{}
190	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
191	require.NoError(t, err)
192	assert.Equal(t, 0, len(oL1UserTxs))
193	assert.Equal(t, 0, len(oL1CoordTxs))
194	assert.Equal(t, 0, len(oL2Txs))
195	assert.Equal(t, common.BatchNum(2), txsel.localAccountsDB.CurrentBatch())
196	assert.Equal(t, common.Idx(255), txsel.localAccountsDB.CurrentIdx())
197
198	log.Debug("block:0 batch:3")
199	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
200	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
201	require.NoError(t, err)
202	assert.Equal(t, 2, len(oL1UserTxs))
203	assert.Equal(t, 0, len(oL1CoordTxs))
204	assert.Equal(t, 0, len(oL2Txs))
205	assert.Equal(t, common.BatchNum(3), txsel.localAccountsDB.CurrentBatch())
206	assert.Equal(t, common.Idx(257), txsel.localAccountsDB.CurrentIdx())
207	checkBalance(t, tc, txsel, "A", 0, "500")
208	checkBalance(t, tc, txsel, "C", 1, "0")
209
210	log.Debug("block:0 batch:4")
211	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
212	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
213	require.NoError(t, err)
214	assert.Equal(t, 1, len(oL1UserTxs))
215	assert.Equal(t, 0, len(oL1CoordTxs))
216	assert.Equal(t, 0, len(oL2Txs))
217	assert.Equal(t, common.BatchNum(4), txsel.localAccountsDB.CurrentBatch())
218	assert.Equal(t, common.Idx(258), txsel.localAccountsDB.CurrentIdx())
219	checkBalance(t, tc, txsel, "A", 0, "500")
220	checkBalance(t, tc, txsel, "A", 1, "500")
221	checkBalance(t, tc, txsel, "C", 1, "0")
222
223	log.Debug("block:0 batch:5")
224	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
225	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
226	require.NoError(t, err)
227	assert.Equal(t, 0, len(oL1UserTxs))
228	assert.Equal(t, 0, len(oL1CoordTxs))
229	assert.Equal(t, 0, len(oL2Txs))
230	assert.Equal(t, common.BatchNum(5), txsel.localAccountsDB.CurrentBatch())
231	assert.Equal(t, common.Idx(258), txsel.localAccountsDB.CurrentIdx())
232	checkBalance(t, tc, txsel, "A", 0, "500")
233	checkBalance(t, tc, txsel, "A", 1, "500")
234	checkBalance(t, tc, txsel, "C", 1, "0")
235
236	log.Debug("block:0 batch:6")
237	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
238	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
239	require.NoError(t, err)
240	assert.Equal(t, 1, len(oL1UserTxs))
241	assert.Equal(t, 0, len(oL1CoordTxs))
242	assert.Equal(t, 0, len(oL2Txs))
243	assert.Equal(t, common.BatchNum(6), txsel.localAccountsDB.CurrentBatch())
244	assert.Equal(t, common.Idx(259), txsel.localAccountsDB.CurrentIdx())
245	checkBalance(t, tc, txsel, "A", 0, "600")
246	checkBalance(t, tc, txsel, "A", 1, "500")
247	checkBalance(t, tc, txsel, "B", 0, "400")
248	checkBalance(t, tc, txsel, "C", 1, "0")
249
250	log.Debug("block:0 batch:7")
251	// simulate the PoolL2Txs of the batch7
252	batchPoolL2 := `
253	Type: PoolL2
254	PoolTransferToEthAddr(1) A-B: 200 (126)
255	PoolTransferToEthAddr(0) B-C: 100 (126)`
256	poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
257	require.NoError(t, err)
258	// add AccountCreationAuths that will be used at the next batch
259	accAuthSig0 := addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "B")
260	accAuthSig1 := addAccCreationAuth(t, tc, txsel, chainID, hermezContractAddr, "C")
261	// add the PoolL2Txs to the l2DB
262	addL2Txs(t, txsel, poolL2Txs)
263	// check signatures of L2Txs from the L2DB (to check that the
264	// parameters of the PoolL2Tx match the original parameters signed
265	// before inserting it to the L2DB)
266	l2TxsFromDB, err := txsel.l2db.GetPendingTxs()
267	require.NoError(t, err)
268	assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress()))
269	assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress()))
270	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
271	coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
272	require.NoError(t, err)
273	assert.Equal(t, []common.Idx{261, 262}, coordIdxs)
274	assert.Equal(t, txsel.coordAccount.AccountCreationAuth, accAuths[0])
275	assert.Equal(t, txsel.coordAccount.AccountCreationAuth, accAuths[1])
276	assert.Equal(t, accAuthSig0, accAuths[2])
277	assert.Equal(t, accAuthSig1, accAuths[3])
278	assert.Equal(t, 1, len(oL1UserTxs))
279	assert.Equal(t, 4, len(oL1CoordTxs))
280	assert.Equal(t, 2, len(oL2Txs))
281	assert.Equal(t, len(oL1CoordTxs), len(accAuths))
282	assert.Equal(t, common.BatchNum(7), txsel.localAccountsDB.CurrentBatch())
283	assert.Equal(t, common.Idx(264), txsel.localAccountsDB.CurrentIdx())
284	checkBalanceByIdx(t, txsel, 261, "20") // CoordIdx for TokenID=1
285	checkBalanceByIdx(t, txsel, 262, "10") // CoordIdx for TokenID=0
286	checkBalance(t, tc, txsel, "A", 0, "600")
287	checkBalance(t, tc, txsel, "A", 1, "280")
288	checkBalance(t, tc, txsel, "B", 0, "290")
289	checkBalance(t, tc, txsel, "B", 1, "200")
290	checkBalance(t, tc, txsel, "C", 0, "100")
291	checkBalance(t, tc, txsel, "D", 0, "800")
292	checkSortedByNonce(t, testAccNonces, oL2Txs)
293	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(poolL2Txs), txsel.localAccountsDB.CurrentBatch())
294	require.NoError(t, err)
295
296	log.Debug("block:0 batch:8")
297	// simulate the PoolL2Txs of the batch8
298	batchPoolL2 = `
299	Type: PoolL2
300	PoolTransfer(0) A-B: 100 (126)
301	PoolTransfer(0) C-A: 50 (126)
302	PoolTransfer(1) B-C: 100 (126)
303	PoolExit(0) A: 100 (126)`
304	poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
305	require.NoError(t, err)
306	addL2Txs(t, txsel, poolL2Txs)
307	// check signatures of L2Txs from the L2DB (to check that the
308	// parameters of the PoolL2Tx match the original parameters signed
309	// before inserting it to the L2DB)
310	l2TxsFromDB, err = txsel.l2db.GetPendingTxs()
311	require.NoError(t, err)
312	assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress()))
313	assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["C"].BJJ.Public().Compress()))
314	assert.True(t, l2TxsFromDB[2].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress()))
315	assert.True(t, l2TxsFromDB[3].VerifySignature(chainID, tc.Users["A"].BJJ.Public().Compress()))
316	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
317	coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
318	require.NoError(t, err)
319	assert.Equal(t, []common.Idx{261, 262}, coordIdxs)
320	assert.Equal(t, 0, len(accAuths))
321	assert.Equal(t, 0, len(oL1UserTxs))
322	assert.Equal(t, 0, len(oL1CoordTxs))
323	assert.Equal(t, 4, len(oL2Txs))
324	assert.Equal(t, len(oL1CoordTxs), len(accAuths))
325	assert.Equal(t, common.BatchNum(8), txsel.localAccountsDB.CurrentBatch())
326	assert.Equal(t, common.Idx(264), txsel.localAccountsDB.CurrentIdx())
327	checkBalanceByIdx(t, txsel, 261, "30")
328	checkBalanceByIdx(t, txsel, 262, "35")
329	checkBalance(t, tc, txsel, "A", 0, "430")
330	checkBalance(t, tc, txsel, "A", 1, "280")
331	checkBalance(t, tc, txsel, "B", 0, "390")
332	checkBalance(t, tc, txsel, "B", 1, "90")
333	checkBalance(t, tc, txsel, "C", 0, "45")
334	checkBalance(t, tc, txsel, "C", 1, "100")
335	checkBalance(t, tc, txsel, "D", 0, "800")
336	checkSortedByNonce(t, testAccNonces, oL2Txs)
337	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(poolL2Txs), txsel.localAccountsDB.CurrentBatch())
338	require.NoError(t, err)
339
340	log.Debug("(batch9)block:1 batch:1")
341	// simulate the PoolL2Txs of the batch9
342	batchPoolL2 = `
343	Type: PoolL2
344	PoolTransfer(0) D-A: 300 (126)
345	PoolTransfer(0) B-D: 100 (126)
346	`
347	poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
348	require.NoError(t, err)
349	addL2Txs(t, txsel, poolL2Txs)
350	// check signatures of L2Txs from the L2DB (to check that the
351	// parameters of the PoolL2Tx match the original parameters signed
352	// before inserting it to the L2DB)
353	l2TxsFromDB, err = txsel.l2db.GetPendingTxs()
354	require.NoError(t, err)
355	assert.True(t, l2TxsFromDB[0].VerifySignature(chainID, tc.Users["D"].BJJ.Public().Compress()))
356	assert.True(t, l2TxsFromDB[1].VerifySignature(chainID, tc.Users["B"].BJJ.Public().Compress()))
357	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
358	coordIdxs, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
359	require.NoError(t, err)
360	assert.Equal(t, []common.Idx{262}, coordIdxs)
361	assert.Equal(t, 0, len(accAuths))
362	assert.Equal(t, 4, len(oL1UserTxs))
363	assert.Equal(t, 0, len(oL1CoordTxs))
364	assert.Equal(t, 2, len(oL2Txs))
365	assert.Equal(t, len(oL1CoordTxs), len(accAuths))
366	assert.Equal(t, common.BatchNum(9), txsel.localAccountsDB.CurrentBatch())
367	assert.Equal(t, common.Idx(264), txsel.localAccountsDB.CurrentIdx())
368	checkBalanceByIdx(t, txsel, 261, "30")
369	checkBalanceByIdx(t, txsel, 262, "75")
370	checkBalance(t, tc, txsel, "A", 0, "730")
371	checkBalance(t, tc, txsel, "A", 1, "280")
372	checkBalance(t, tc, txsel, "B", 0, "380")
373	checkBalance(t, tc, txsel, "B", 1, "90")
374	checkBalance(t, tc, txsel, "C", 0, "845")
375	checkBalance(t, tc, txsel, "C", 1, "100")
376	checkBalance(t, tc, txsel, "D", 0, "470")
377	checkSortedByNonce(t, testAccNonces, oL2Txs)
378	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(poolL2Txs), txsel.localAccountsDB.CurrentBatch())
379	require.NoError(t, err)
380}
381
382func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) {
383	set := `
384		Type: Blockchain
385
386		CreateAccountDeposit(0) Coord: 0
387		CreateAccountDeposit(0) A: 100
388		CreateAccountDeposit(0) B: 100
389
390		> batchL1 // freeze L1User{1}
391		> batchL1 // forge L1User{1}
392		> block
393	`
394
395	chainID := uint16(0)
396	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
397	// generate test transactions, the L1CoordinatorTxs generated by Til
398	// will be ignored at this test, as will be the TxSelector who
399	// generates them when needed
400	blocks, err := tc.GenerateBlocks(set)
401	assert.NoError(t, err)
402
403	hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
404	txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
405
406	// restart nonces of TilContext, as will be set by generating directly
407	// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
408	tc.RestartNonces()
409
410	tpc := txprocessor.Config{
411		NLevels:  16,
412		MaxFeeTx: 10,
413		MaxTx:    20,
414		MaxL1Tx:  10,
415		ChainID:  chainID,
416	}
417	selectionConfig := &SelectionConfig{
418		MaxL1UserTxs:      5,
419		TxProcessorConfig: tpc,
420	}
421	// batch1
422	l1UserTxs := []common.L1Tx{}
423	_, _, _, _, _, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
424	require.NoError(t, err)
425
426	// batch2
427	// prepare the PoolL2Txs
428	batchPoolL2 := `
429	Type: PoolL2
430	PoolTransferToEthAddr(0) A-B: 100 (126)
431	PoolExit(0) B: 100 (126)`
432	poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
433	require.NoError(t, err)
434	// add the PoolL2Txs to the l2DB
435	addL2Txs(t, txsel, poolL2Txs)
436
437	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
438	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
439	require.NoError(t, err)
440	assert.Equal(t, 3, len(oL1UserTxs))
441	assert.Equal(t, 0, len(oL1CoordTxs))
442	assert.Equal(t, 0, len(oL2Txs)) // should be 0 as the 2 PoolL2Txs does not have enough funds
443	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.localAccountsDB.CurrentBatch())
444	require.NoError(t, err)
445
446	// as the PoolL2Txs have not been really processed, restart nonces
447	tc.RestartNonces()
448
449	// batch3
450	// NOTE: this batch will result with 1 L2Tx, as the PoolExit tx is not
451	// possible, as the PoolTransferToEthAddr is not processed yet when
452	// checking availability of PoolExit.  This, in a near-future iteration
453	// of the TxSelector will return the 2 transactions as valid and
454	// selected, as the TxSelector will handle this kind of combinations.
455	batchPoolL2 = `
456	Type: PoolL2
457	PoolTransferToEthAddr(0) A-B: 50 (126)`
458	poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
459	require.NoError(t, err)
460	addL2Txs(t, txsel, poolL2Txs)
461
462	l1UserTxs = []common.L1Tx{}
463	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
464	require.NoError(t, err)
465	assert.Equal(t, 0, len(oL1UserTxs))
466	assert.Equal(t, 0, len(oL1CoordTxs))
467	assert.Equal(t, 1, len(oL2Txs)) // see 'NOTE' at the beginning of 'batch3' of this test
468	assert.Equal(t, common.TxTypeTransferToEthAddr, oL2Txs[0].Type)
469	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.localAccountsDB.CurrentBatch())
470	require.NoError(t, err)
471
472	// batch4
473	// make the selection of another batch, which should include the
474	// initial PoolExit, which now is valid as B has enough Balance
475	l1UserTxs = []common.L1Tx{}
476	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
477	require.NoError(t, err)
478	assert.Equal(t, 0, len(oL1UserTxs))
479	assert.Equal(t, 0, len(oL1CoordTxs))
480	assert.Equal(t, 1, len(oL2Txs))
481	assert.Equal(t, common.TxTypeExit, oL2Txs[0].Type)
482	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.localAccountsDB.CurrentBatch())
483	require.NoError(t, err)
484}