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