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	expectedTxID0 := "0x0248bae02b5c8c3847d312bfac3a33ae790616e888f2f711f22aeaff007cde92c2" // 1st TransferToEthAddr
427	expectedTxID1 := "0x0249af018311a393c337ab9174ca2466cba489e49942b4ca4e5c530903671c4aef" // 1st Exit
428	expectedTxID2 := "0x0228b93a261a0cdc62f35588c03bd179d31a0807c28afffdb6a7aaf0c4f017e4cf" // 2nd TransferToEthAddr
429
430	// batch2
431	// prepare the PoolL2Txs
432	batchPoolL2 := `
433	Type: PoolL2
434	PoolTransferToEthAddr(0) A-B: 100 (126)
435	PoolExit(0) B: 100 (126)`
436	poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
437	require.NoError(t, err)
438	// add the PoolL2Txs to the l2DB
439	addL2Txs(t, txsel, poolL2Txs)
440
441	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
442	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err := txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
443	require.NoError(t, err)
444	assert.Equal(t, 3, len(oL1UserTxs))
445	assert.Equal(t, 0, len(oL1CoordTxs))
446	assert.Equal(t, 0, len(oL2Txs)) // should be 0 as the 2 PoolL2Txs does not have enough funds
447	assert.Equal(t, 2, len(discardedL2Txs))
448	assert.Equal(t, expectedTxID0, discardedL2Txs[0].TxID.String())
449	assert.Equal(t, expectedTxID1, discardedL2Txs[1].TxID.String())
450	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.localAccountsDB.CurrentBatch())
451	require.NoError(t, err)
452
453	// as the PoolL2Txs have not been really processed, restart nonces
454	tc.RestartNonces()
455
456	// batch3
457	// NOTE: this batch will result with 1 L2Tx, as the PoolExit tx is not
458	// possible, as the PoolTransferToEthAddr is not processed yet when
459	// checking availability of PoolExit.  This, in a near-future iteration
460	// of the TxSelector will return the 2 transactions as valid and
461	// selected, as the TxSelector will handle this kind of combinations.
462	batchPoolL2 = `
463	Type: PoolL2
464	PoolTransferToEthAddr(0) A-B: 50 (126)`
465	poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
466	require.NoError(t, err)
467	addL2Txs(t, txsel, poolL2Txs)
468
469	l1UserTxs = []common.L1Tx{}
470	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
471	require.NoError(t, err)
472	assert.Equal(t, 0, len(oL1UserTxs))
473	assert.Equal(t, 0, len(oL1CoordTxs))
474	assert.Equal(t, 1, len(oL2Txs)) // see 'NOTE' at the beginning of 'batch3' of this test
475	assert.Equal(t, 2, len(discardedL2Txs))
476	assert.Equal(t, expectedTxID2, oL2Txs[0].TxID.String())
477	assert.Equal(t, expectedTxID0, discardedL2Txs[0].TxID.String())
478	assert.Equal(t, expectedTxID1, discardedL2Txs[1].TxID.String())
479	assert.Equal(t, common.TxTypeTransferToEthAddr, oL2Txs[0].Type)
480	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.localAccountsDB.CurrentBatch())
481	require.NoError(t, err)
482
483	// batch4
484	// make the selection of another batch, which should include the
485	// initial PoolExit, which now is valid as B has enough Balance
486	l1UserTxs = []common.L1Tx{}
487	_, _, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err = txsel.GetL1L2TxSelection(selectionConfig, l1UserTxs)
488	require.NoError(t, err)
489	assert.Equal(t, 0, len(oL1UserTxs))
490	assert.Equal(t, 0, len(oL1CoordTxs))
491	assert.Equal(t, 1, len(oL2Txs))
492	assert.Equal(t, 1, len(discardedL2Txs))
493	assert.Equal(t, expectedTxID1, oL2Txs[0].TxID.String()) // the Exit that was not accepted at the batch2
494	assert.Equal(t, expectedTxID0, discardedL2Txs[0].TxID.String())
495	assert.Equal(t, common.TxTypeExit, oL2Txs[0].Type)
496	err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs), txsel.localAccountsDB.CurrentBatch())
497	require.NoError(t, err)
498}