arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/txprocessor/txprocessor_test.go
txprocessor/txprocessor_test.goRaw
   1package txprocessor
   2
   3import (
   4	"io/ioutil"
   5	"math/big"
   6	"os"
   7	"testing"
   8
   9	ethCommon "github.com/ethereum/go-ethereum/common"
  10	"github.com/hermeznetwork/hermez-node/common"
  11	"github.com/hermeznetwork/hermez-node/db/statedb"
  12	"github.com/hermeznetwork/hermez-node/log"
  13	"github.com/hermeznetwork/hermez-node/test/til"
  14	"github.com/hermeznetwork/hermez-node/test/txsets"
  15	"github.com/stretchr/testify/assert"
  16	"github.com/stretchr/testify/require"
  17)
  18
  19func checkBalance(t *testing.T, tc *til.Context, sdb *statedb.StateDB, username string, tokenid int, expected string) {
  20	idx := tc.Users[username].Accounts[common.TokenID(tokenid)].Idx
  21	acc, err := sdb.GetAccount(idx)
  22	require.NoError(t, err)
  23	assert.Equal(t, expected, acc.Balance.String())
  24}
  25
  26func checkBalanceByIdx(t *testing.T, sdb *statedb.StateDB, idx common.Idx, expected string) {
  27	acc, err := sdb.GetAccount(idx)
  28	require.NoError(t, err)
  29	assert.Equal(t, expected, acc.Balance.String())
  30}
  31
  32func TestComputeEffectiveAmounts(t *testing.T) {
  33	dir, err := ioutil.TempDir("", "tmpdb")
  34	require.NoError(t, err)
  35	defer assert.NoError(t, os.RemoveAll(dir))
  36
  37	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
  38		Type: statedb.TypeSynchronizer, NLevels: 32})
  39	assert.NoError(t, err)
  40
  41	set := `
  42		Type: Blockchain
  43		AddToken(1)
  44	
  45		CreateAccountDeposit(0) A: 10
  46		CreateAccountDeposit(0) B: 10
  47		CreateAccountDeposit(1) C: 10
  48		> batchL1
  49		> batchL1
  50		> block
  51	`
  52	chainID := uint16(0)
  53	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  54	blocks, err := tc.GenerateBlocks(set)
  55	require.NoError(t, err)
  56
  57	config := Config{
  58		NLevels:  32,
  59		MaxFeeTx: 64,
  60		MaxTx:    512,
  61		MaxL1Tx:  16,
  62		ChainID:  chainID,
  63	}
  64	tp := NewTxProcessor(sdb, config)
  65	_, err = tp.ProcessTxs(nil, blocks[0].Rollup.L1UserTxs, nil, nil)
  66	require.NoError(t, err)
  67
  68	tx := common.L1Tx{
  69		FromIdx:       256,
  70		ToIdx:         257,
  71		Amount:        big.NewInt(10),
  72		DepositAmount: big.NewInt(0),
  73		FromEthAddr:   tc.Users["A"].Addr,
  74		UserOrigin:    true,
  75	}
  76	tp.computeEffectiveAmounts(&tx)
  77	assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
  78	assert.Equal(t, big.NewInt(10), tx.EffectiveAmount)
  79
  80	// expect error due not enough funds
  81	tx = common.L1Tx{
  82		FromIdx:       256,
  83		ToIdx:         257,
  84		Amount:        big.NewInt(11),
  85		DepositAmount: big.NewInt(0),
  86		FromEthAddr:   tc.Users["A"].Addr,
  87		UserOrigin:    true,
  88	}
  89	tp.computeEffectiveAmounts(&tx)
  90	assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
  91	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
  92
  93	// expect no-error as there are enough funds in a
  94	// CreateAccountDepositTransfer transction
  95	tx = common.L1Tx{
  96		FromIdx:       0,
  97		ToIdx:         257,
  98		Amount:        big.NewInt(10),
  99		DepositAmount: big.NewInt(10),
 100		UserOrigin:    true,
 101	}
 102	tp.computeEffectiveAmounts(&tx)
 103	assert.Equal(t, big.NewInt(10), tx.EffectiveDepositAmount)
 104	assert.Equal(t, big.NewInt(10), tx.EffectiveAmount)
 105
 106	// expect error due not enough funds in a CreateAccountDepositTransfer
 107	// transction
 108	tx = common.L1Tx{
 109		FromIdx:       0,
 110		ToIdx:         257,
 111		Amount:        big.NewInt(11),
 112		DepositAmount: big.NewInt(10),
 113		UserOrigin:    true,
 114	}
 115	tp.computeEffectiveAmounts(&tx)
 116	assert.Equal(t, big.NewInt(10), tx.EffectiveDepositAmount)
 117	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 118
 119	// expect error due not same TokenID
 120	tx = common.L1Tx{
 121		FromIdx:       256,
 122		ToIdx:         258,
 123		Amount:        big.NewInt(5),
 124		DepositAmount: big.NewInt(0),
 125		FromEthAddr:   tc.Users["A"].Addr,
 126		UserOrigin:    true,
 127	}
 128	tp.computeEffectiveAmounts(&tx)
 129	assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
 130	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 131
 132	// expect error due not same EthAddr
 133	tx = common.L1Tx{
 134		FromIdx:       256,
 135		ToIdx:         257,
 136		Amount:        big.NewInt(8),
 137		DepositAmount: big.NewInt(0),
 138		FromEthAddr:   tc.Users["B"].Addr,
 139		UserOrigin:    true,
 140	}
 141	tp.computeEffectiveAmounts(&tx)
 142	assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
 143	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 144
 145	// expect on TxTypeDepositTransfer EffectiveAmount=0, but
 146	// EffectiveDepositAmount!=0, due not enough funds to make the transfer
 147	tx = common.L1Tx{
 148		FromIdx:       256,
 149		ToIdx:         257,
 150		Amount:        big.NewInt(20),
 151		DepositAmount: big.NewInt(8),
 152		FromEthAddr:   tc.Users["A"].Addr,
 153		UserOrigin:    true,
 154	}
 155	tp.computeEffectiveAmounts(&tx)
 156	assert.Equal(t, big.NewInt(8), tx.EffectiveDepositAmount)
 157	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 158
 159	// expect on TxTypeDepositTransfer EffectiveAmount=0, but
 160	// EffectiveDepositAmount!=0, due different EthAddr from FromIdx
 161	// address
 162	tx = common.L1Tx{
 163		FromIdx:       256,
 164		ToIdx:         257,
 165		Amount:        big.NewInt(8),
 166		DepositAmount: big.NewInt(8),
 167		FromEthAddr:   tc.Users["B"].Addr,
 168		UserOrigin:    true,
 169	}
 170	tp.computeEffectiveAmounts(&tx)
 171	assert.Equal(t, big.NewInt(8), tx.EffectiveDepositAmount)
 172	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 173
 174	// CreateAccountDepositTransfer for TokenID=1 when receiver does not
 175	// have an account for that TokenID, expect that the
 176	// EffectiveDepositAmount=DepositAmount, but EffectiveAmount==0
 177	tx = common.L1Tx{
 178		FromIdx:       0,
 179		ToIdx:         257,
 180		Amount:        big.NewInt(8),
 181		DepositAmount: big.NewInt(8),
 182		FromEthAddr:   tc.Users["A"].Addr,
 183		TokenID:       2,
 184		UserOrigin:    true,
 185		Type:          common.TxTypeCreateAccountDepositTransfer,
 186	}
 187	tp.computeEffectiveAmounts(&tx)
 188	assert.Equal(t, big.NewInt(8), tx.EffectiveDepositAmount)
 189	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 190
 191	// DepositTransfer for TokenID=1 when receiver does not have an account
 192	// for that TokenID, expect that the
 193	// EffectiveDepositAmount=DepositAmount, but EffectiveAmount=0
 194	tx = common.L1Tx{
 195		FromIdx:       258,
 196		ToIdx:         256,
 197		Amount:        big.NewInt(8),
 198		DepositAmount: big.NewInt(8),
 199		FromEthAddr:   tc.Users["C"].Addr,
 200		TokenID:       1,
 201		UserOrigin:    true,
 202		Type:          common.TxTypeDepositTransfer,
 203	}
 204	tp.computeEffectiveAmounts(&tx)
 205	assert.Equal(t, big.NewInt(8), tx.EffectiveDepositAmount)
 206	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 207}
 208
 209func TestProcessTxsBalances(t *testing.T) {
 210	dir, err := ioutil.TempDir("", "tmpdb")
 211	require.NoError(t, err)
 212	defer assert.NoError(t, os.RemoveAll(dir))
 213
 214	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 215		Type: statedb.TypeSynchronizer, NLevels: 32})
 216	assert.NoError(t, err)
 217
 218	chainID := uint16(0)
 219	// generate test transactions from test.SetBlockchain0 code
 220	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
 221	blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
 222	require.NoError(t, err)
 223
 224	config := Config{
 225		NLevels:  32,
 226		MaxFeeTx: 64,
 227		MaxTx:    512,
 228		MaxL1Tx:  16,
 229		ChainID:  chainID,
 230	}
 231	tp := NewTxProcessor(sdb, config)
 232
 233	log.Debug("block:0 batch:1, only L1CoordinatorTxs")
 234	_, err = tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
 235	require.NoError(t, err)
 236	assert.Equal(t, "0", tp.s.MT.Root().BigInt().String())
 237
 238	log.Debug("block:0 batch:2")
 239	l1UserTxs := []common.L1Tx{}
 240	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
 241	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
 242	require.NoError(t, err)
 243	assert.Equal(t, "0", tp.s.MT.Root().BigInt().String())
 244
 245	log.Debug("block:0 batch:3")
 246	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
 247	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
 248	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
 249	require.NoError(t, err)
 250	checkBalance(t, tc, sdb, "A", 0, "500")
 251	assert.Equal(t, "13644148972047617726265275926674266298636745191961029124811988256139761111521", tp.s.MT.Root().BigInt().String())
 252
 253	log.Debug("block:0 batch:4")
 254	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
 255	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[3].L2Txs)
 256	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, l2Txs)
 257	require.NoError(t, err)
 258	checkBalance(t, tc, sdb, "A", 0, "500")
 259	checkBalance(t, tc, sdb, "A", 1, "500")
 260	assert.Equal(t, "12433441613247342495680642890662773367605896324555599297255745922589338651261", tp.s.MT.Root().BigInt().String())
 261
 262	log.Debug("block:0 batch:5")
 263	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
 264	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[4].L2Txs)
 265	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[4].L1CoordinatorTxs, l2Txs)
 266	require.NoError(t, err)
 267	checkBalance(t, tc, sdb, "A", 0, "500")
 268	checkBalance(t, tc, sdb, "A", 1, "500")
 269	assert.Equal(t, "12433441613247342495680642890662773367605896324555599297255745922589338651261", tp.s.MT.Root().BigInt().String())
 270
 271	log.Debug("block:0 batch:6")
 272	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
 273	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[5].L2Txs)
 274	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[5].L1CoordinatorTxs, l2Txs)
 275	require.NoError(t, err)
 276	checkBalance(t, tc, sdb, "A", 0, "600")
 277	checkBalance(t, tc, sdb, "A", 1, "500")
 278	checkBalance(t, tc, sdb, "B", 0, "400")
 279	assert.Equal(t, "4191361650490017591061467288209836928064232431729236465872209988325272262963", tp.s.MT.Root().BigInt().String())
 280
 281	coordIdxs := []common.Idx{261, 262}
 282	log.Debug("block:0 batch:7")
 283	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
 284	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[6].L2Txs)
 285	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[6].L1CoordinatorTxs, l2Txs)
 286	require.NoError(t, err)
 287	checkBalance(t, tc, sdb, "Coord", 0, "10")
 288	checkBalance(t, tc, sdb, "Coord", 1, "20")
 289	checkBalance(t, tc, sdb, "A", 0, "600")
 290	checkBalance(t, tc, sdb, "A", 1, "280")
 291	checkBalance(t, tc, sdb, "B", 0, "290")
 292	checkBalance(t, tc, sdb, "B", 1, "200")
 293	checkBalance(t, tc, sdb, "C", 0, "100")
 294	checkBalance(t, tc, sdb, "D", 0, "800")
 295	assert.Equal(t, "7614010373759339299470010949167613050707822522530721724565424494781010548240", tp.s.MT.Root().BigInt().String())
 296
 297	log.Debug("block:0 batch:8")
 298	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
 299	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[7].L2Txs)
 300	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[7].L1CoordinatorTxs, l2Txs)
 301	require.NoError(t, err)
 302	checkBalance(t, tc, sdb, "Coord", 0, "35")
 303	checkBalance(t, tc, sdb, "Coord", 1, "30")
 304	checkBalance(t, tc, sdb, "A", 0, "430")
 305	checkBalance(t, tc, sdb, "A", 1, "280")
 306	checkBalance(t, tc, sdb, "B", 0, "390")
 307	checkBalance(t, tc, sdb, "B", 1, "90")
 308	checkBalance(t, tc, sdb, "C", 0, "45")
 309	checkBalance(t, tc, sdb, "C", 1, "100")
 310	checkBalance(t, tc, sdb, "D", 0, "800")
 311	assert.Equal(t, "21231789250434471575486264439945776732824482207853465397552873521865656677689", tp.s.MT.Root().BigInt().String())
 312
 313	coordIdxs = []common.Idx{262}
 314	log.Debug("block:1 batch:1")
 315	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
 316	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
 317	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
 318	require.NoError(t, err)
 319	checkBalance(t, tc, sdb, "Coord", 0, "75")
 320	checkBalance(t, tc, sdb, "Coord", 1, "30")
 321	checkBalance(t, tc, sdb, "A", 0, "730")
 322	checkBalance(t, tc, sdb, "A", 1, "280")
 323	checkBalance(t, tc, sdb, "B", 0, "380")
 324	checkBalance(t, tc, sdb, "B", 1, "90")
 325	checkBalance(t, tc, sdb, "C", 0, "845")
 326	checkBalance(t, tc, sdb, "C", 1, "100")
 327	checkBalance(t, tc, sdb, "D", 0, "470")
 328	assert.Equal(t, "11289313644810782435120113035387729451095637380468777086895109386127538554246", tp.s.MT.Root().BigInt().String())
 329
 330	coordIdxs = []common.Idx{}
 331	log.Debug("block:1 batch:2")
 332	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
 333	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
 334	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
 335	require.NoError(t, err)
 336	assert.Equal(t, "10342681351319338354912862547249967104198317571995055517008223832276478908482", tp.s.MT.Root().BigInt().String())
 337
 338	// use Set of PoolL2 txs
 339	poolL2Txs, err := tc.GeneratePoolL2Txs(txsets.SetPoolL2MinimumFlow1)
 340	assert.NoError(t, err)
 341
 342	_, err = tp.ProcessTxs(coordIdxs, []common.L1Tx{}, []common.L1Tx{}, poolL2Txs)
 343	require.NoError(t, err)
 344	checkBalance(t, tc, sdb, "Coord", 0, "75")
 345	checkBalance(t, tc, sdb, "Coord", 1, "30")
 346	checkBalance(t, tc, sdb, "A", 0, "510")
 347	checkBalance(t, tc, sdb, "A", 1, "170")
 348	checkBalance(t, tc, sdb, "B", 0, "480")
 349	checkBalance(t, tc, sdb, "B", 1, "190")
 350	checkBalance(t, tc, sdb, "C", 0, "845")
 351	checkBalance(t, tc, sdb, "C", 1, "100")
 352	checkBalance(t, tc, sdb, "D", 0, "360")
 353	checkBalance(t, tc, sdb, "F", 0, "100")
 354}
 355
 356func TestProcessTxsSynchronizer(t *testing.T) {
 357	dir, err := ioutil.TempDir("", "tmpdb")
 358	require.NoError(t, err)
 359	defer assert.NoError(t, os.RemoveAll(dir))
 360
 361	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 362		Type: statedb.TypeSynchronizer, NLevels: 32})
 363	assert.NoError(t, err)
 364
 365	chainID := uint16(0)
 366	// generate test transactions from test.SetBlockchain0 code
 367	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
 368	blocks, err := tc.GenerateBlocks(txsets.SetBlockchain0)
 369	require.NoError(t, err)
 370
 371	assert.Equal(t, 31, len(blocks[0].Rollup.L1UserTxs))
 372	assert.Equal(t, 4, len(blocks[0].Rollup.Batches[0].L1CoordinatorTxs))
 373	assert.Equal(t, 0, len(blocks[0].Rollup.Batches[1].L1CoordinatorTxs))
 374	assert.Equal(t, 22, len(blocks[0].Rollup.Batches[2].L2Txs))
 375	assert.Equal(t, 1, len(blocks[1].Rollup.Batches[0].L1CoordinatorTxs))
 376	assert.Equal(t, 62, len(blocks[1].Rollup.Batches[0].L2Txs))
 377	assert.Equal(t, 1, len(blocks[1].Rollup.Batches[1].L1CoordinatorTxs))
 378	assert.Equal(t, 8, len(blocks[1].Rollup.Batches[1].L2Txs))
 379
 380	// Coordinator Idx where to send the fees
 381	coordIdxs := []common.Idx{256, 257, 258, 259}
 382
 383	// Idx of user 'A'
 384	idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
 385
 386	config := Config{
 387		NLevels:  32,
 388		MaxFeeTx: 64,
 389		MaxTx:    512,
 390		MaxL1Tx:  32,
 391		ChainID:  chainID,
 392	}
 393	tp := NewTxProcessor(sdb, config)
 394
 395	// Process the 1st batch, which contains the L1CoordinatorTxs necessary
 396	// to create the Coordinator accounts to receive the fees
 397	log.Debug("block:0 batch:1, only L1CoordinatorTxs")
 398	ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
 399	require.NoError(t, err)
 400	assert.Equal(t, 4, len(ptOut.CreatedAccounts))
 401	assert.Equal(t, 0, len(ptOut.CollectedFees))
 402
 403	log.Debug("block:0 batch:2")
 404	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
 405	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[0].Rollup.L1UserTxs,
 406		blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
 407	require.NoError(t, err)
 408	assert.Equal(t, 0, len(ptOut.ExitInfos))
 409	assert.Equal(t, 31, len(ptOut.CreatedAccounts))
 410	assert.Equal(t, 4, len(ptOut.CollectedFees))
 411	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
 412	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
 413	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
 414	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
 415	acc, err := sdb.GetAccount(idxA1)
 416	require.NoError(t, err)
 417	assert.Equal(t, "50", acc.Balance.String())
 418
 419	log.Debug("block:0 batch:3")
 420	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
 421	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
 422	require.NoError(t, err)
 423	assert.Equal(t, 0, len(ptOut.ExitInfos))
 424	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
 425	assert.Equal(t, 4, len(ptOut.CollectedFees))
 426	assert.Equal(t, "2", ptOut.CollectedFees[common.TokenID(0)].String())
 427	assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
 428	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
 429	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
 430	acc, err = sdb.GetAccount(idxA1)
 431	require.NoError(t, err)
 432	assert.Equal(t, "35", acc.Balance.String())
 433
 434	log.Debug("block:1 batch:1")
 435	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
 436	// before processing expect l2Txs[0:2].Nonce==0
 437	assert.Equal(t, common.Nonce(0), l2Txs[0].Nonce)
 438	assert.Equal(t, common.Nonce(0), l2Txs[1].Nonce)
 439	assert.Equal(t, common.Nonce(0), l2Txs[2].Nonce)
 440
 441	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
 442	require.NoError(t, err)
 443
 444	// after processing expect l2Txs[0:2].Nonce!=0 and has expected value
 445	assert.Equal(t, common.Nonce(5), l2Txs[0].Nonce)
 446	assert.Equal(t, common.Nonce(6), l2Txs[1].Nonce)
 447	assert.Equal(t, common.Nonce(7), l2Txs[2].Nonce)
 448
 449	assert.Equal(t, 4, len(ptOut.ExitInfos)) // the 'ForceExit(1)' is not computed yet, as the batch is without L1UserTxs
 450	assert.Equal(t, 1, len(ptOut.CreatedAccounts))
 451	assert.Equal(t, 4, len(ptOut.CollectedFees))
 452	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
 453	assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
 454	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
 455	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
 456	acc, err = sdb.GetAccount(idxA1)
 457	require.NoError(t, err)
 458	assert.Equal(t, "57", acc.Balance.String())
 459
 460	log.Debug("block:1 batch:2")
 461	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
 462	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[1].Rollup.L1UserTxs,
 463		blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
 464	require.NoError(t, err)
 465
 466	assert.Equal(t, 1, len(ptOut.ExitInfos)) // 1, as previous batch was without L1UserTxs, and has pending the 'ForceExit(1) A: 5', and the 2 exit transactions get grouped under 1 ExitInfo
 467	assert.Equal(t, 1, len(ptOut.CreatedAccounts))
 468	assert.Equal(t, 4, len(ptOut.CollectedFees))
 469	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
 470	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
 471	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
 472	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
 473	acc, err = sdb.GetAccount(idxA1)
 474	assert.NoError(t, err)
 475	assert.Equal(t, "77", acc.Balance.String())
 476
 477	idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
 478	acc, err = sdb.GetAccount(idxB0)
 479	require.NoError(t, err)
 480	assert.Equal(t, "51", acc.Balance.String())
 481
 482	// get balance of Coordinator account for TokenID==0
 483	acc, err = sdb.GetAccount(common.Idx(256))
 484	require.NoError(t, err)
 485	assert.Equal(t, "2", acc.Balance.String())
 486}
 487
 488func TestProcessTxsBatchBuilder(t *testing.T) {
 489	dir, err := ioutil.TempDir("", "tmpdb")
 490	require.NoError(t, err)
 491	defer assert.NoError(t, os.RemoveAll(dir))
 492
 493	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 494		Type: statedb.TypeBatchBuilder, NLevels: 32})
 495	assert.NoError(t, err)
 496
 497	chainID := uint16(0)
 498	// generate test transactions from test.SetBlockchain0 code
 499	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
 500	blocks, err := tc.GenerateBlocks(txsets.SetBlockchain0)
 501	require.NoError(t, err)
 502
 503	// Coordinator Idx where to send the fees
 504	coordIdxs := []common.Idx{256, 257, 258, 259}
 505
 506	// Idx of user 'A'
 507	idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
 508
 509	config := Config{
 510		NLevels:  32,
 511		MaxFeeTx: 64,
 512		MaxTx:    512,
 513		MaxL1Tx:  32,
 514		ChainID:  chainID,
 515	}
 516	tp := NewTxProcessor(sdb, config)
 517
 518	// Process the 1st batch, which contains the L1CoordinatorTxs necessary
 519	// to create the Coordinator accounts to receive the fees
 520	log.Debug("block:0 batch:1, only L1CoordinatorTxs")
 521	ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
 522	require.NoError(t, err)
 523	// expect 0 at CreatedAccount, as is only computed when StateDB.Type==TypeSynchronizer
 524	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
 525
 526	log.Debug("block:0 batch:2")
 527	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
 528	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[0].Rollup.L1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
 529	require.NoError(t, err)
 530	assert.Equal(t, 0, len(ptOut.ExitInfos))
 531	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
 532	acc, err := sdb.GetAccount(idxA1)
 533	require.NoError(t, err)
 534	assert.Equal(t, "50", acc.Balance.String())
 535
 536	log.Debug("block:0 batch:3")
 537	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
 538	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
 539	require.NoError(t, err)
 540	assert.Equal(t, 0, len(ptOut.ExitInfos))
 541	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
 542	acc, err = sdb.GetAccount(idxA1)
 543	require.NoError(t, err)
 544	assert.Equal(t, "35", acc.Balance.String())
 545
 546	log.Debug("block:1 batch:1")
 547	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
 548	_, err = tp.ProcessTxs(coordIdxs, nil, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
 549	require.NoError(t, err)
 550	acc, err = sdb.GetAccount(idxA1)
 551	require.NoError(t, err)
 552	assert.Equal(t, "57", acc.Balance.String())
 553
 554	log.Debug("block:1 batch:2")
 555	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
 556	_, err = tp.ProcessTxs(coordIdxs, blocks[1].Rollup.L1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
 557	require.NoError(t, err)
 558	acc, err = sdb.GetAccount(idxA1)
 559	assert.NoError(t, err)
 560	assert.Equal(t, "77", acc.Balance.String())
 561
 562	idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
 563	acc, err = sdb.GetAccount(idxB0)
 564	require.NoError(t, err)
 565	assert.Equal(t, "51", acc.Balance.String())
 566
 567	// get balance of Coordinator account for TokenID==0
 568	acc, err = sdb.GetAccount(common.Idx(256))
 569	require.NoError(t, err)
 570	assert.Equal(t, common.TokenID(0), acc.TokenID)
 571	assert.Equal(t, "2", acc.Balance.String())
 572	acc, err = sdb.GetAccount(common.Idx(257))
 573	require.NoError(t, err)
 574	assert.Equal(t, common.TokenID(1), acc.TokenID)
 575	assert.Equal(t, "2", acc.Balance.String())
 576
 577	assert.Equal(t, "18894163991492573893706613133132363559300580460789469708968288074813925659539", sdb.MT.Root().BigInt().String())
 578}
 579
 580func TestProcessTxsRootTestVectors(t *testing.T) {
 581	dir, err := ioutil.TempDir("", "tmpdb")
 582	require.NoError(t, err)
 583	defer assert.NoError(t, os.RemoveAll(dir))
 584
 585	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 586		Type: statedb.TypeBatchBuilder, NLevels: 32})
 587	assert.NoError(t, err)
 588
 589	// same values than in the js test
 590	bjj0, err := common.BJJFromStringWithChecksum("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7")
 591	assert.NoError(t, err)
 592	l1Txs := []common.L1Tx{
 593		{
 594			FromIdx:       0,
 595			DepositAmount: big.NewInt(16000000),
 596			Amount:        big.NewInt(0),
 597			TokenID:       1,
 598			FromBJJ:       bjj0,
 599			FromEthAddr:   ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"),
 600			ToIdx:         0,
 601			Type:          common.TxTypeCreateAccountDeposit,
 602			UserOrigin:    true,
 603		},
 604	}
 605	l2Txs := []common.PoolL2Tx{
 606		{
 607			FromIdx: 256,
 608			ToIdx:   256,
 609			TokenID: 1,
 610			Amount:  big.NewInt(1000),
 611			Nonce:   0,
 612			Fee:     126,
 613			Type:    common.TxTypeTransfer,
 614		},
 615	}
 616
 617	chainID := uint16(0)
 618	config := Config{
 619		NLevels:  32,
 620		MaxFeeTx: 8,
 621		MaxTx:    32,
 622		MaxL1Tx:  16,
 623		ChainID:  chainID,
 624	}
 625	tp := NewTxProcessor(sdb, config)
 626	_, err = tp.ProcessTxs(nil, l1Txs, nil, l2Txs)
 627	require.NoError(t, err)
 628	assert.Equal(t, "9827704113668630072730115158977131501210702363656902211840117643154933433410", sdb.MT.Root().BigInt().String())
 629}
 630
 631func TestCreateAccountDepositMaxValue(t *testing.T) {
 632	dir, err := ioutil.TempDir("", "tmpdb")
 633	require.NoError(t, err)
 634	defer assert.NoError(t, os.RemoveAll(dir))
 635
 636	nLevels := 16
 637	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 638		Type: statedb.TypeBatchBuilder, NLevels: nLevels})
 639	assert.NoError(t, err)
 640
 641	users := txsets.GenerateJsUsers(t)
 642
 643	daMaxF40 := common.Float40(0xFFFFFFFFFF)
 644	daMaxBI, err := daMaxF40.BigInt()
 645	require.NoError(t, err)
 646	assert.Equal(t, "343597383670000000000000000000000000000000", daMaxBI.String())
 647
 648	daMax1F40 := common.Float40(0xFFFFFFFFFE)
 649	require.NoError(t, err)
 650	daMax1BI, err := daMax1F40.BigInt()
 651	require.NoError(t, err)
 652	assert.Equal(t, "343597383660000000000000000000000000000000", daMax1BI.String())
 653
 654	l1Txs := []common.L1Tx{
 655		{
 656			FromIdx:       0,
 657			DepositAmount: daMaxBI,
 658			Amount:        big.NewInt(0),
 659			TokenID:       1,
 660			FromBJJ:       users[0].BJJ.Public().Compress(),
 661			FromEthAddr:   users[0].Addr,
 662			ToIdx:         0,
 663			Type:          common.TxTypeCreateAccountDeposit,
 664			UserOrigin:    true,
 665		},
 666		{
 667			FromIdx:       0,
 668			DepositAmount: daMax1BI,
 669			Amount:        big.NewInt(0),
 670			TokenID:       1,
 671			FromBJJ:       users[1].BJJ.Public().Compress(),
 672			FromEthAddr:   users[1].Addr,
 673			ToIdx:         0,
 674			Type:          common.TxTypeCreateAccountDeposit,
 675			UserOrigin:    true,
 676		},
 677	}
 678
 679	chainID := uint16(0)
 680	config := Config{
 681		NLevels:  uint32(nLevels),
 682		MaxTx:    3,
 683		MaxL1Tx:  2,
 684		MaxFeeTx: 2,
 685		ChainID:  chainID,
 686	}
 687	tp := NewTxProcessor(sdb, config)
 688
 689	_, err = tp.ProcessTxs(nil, l1Txs, nil, nil)
 690	require.NoError(t, err)
 691
 692	// check balances
 693	acc, err := sdb.GetAccount(common.Idx(256))
 694	require.NoError(t, err)
 695	assert.Equal(t, daMaxBI, acc.Balance)
 696	acc, err = sdb.GetAccount(common.Idx(257))
 697	require.NoError(t, err)
 698	assert.Equal(t, daMax1BI, acc.Balance)
 699}
 700
 701func initTestMultipleCoordIdxForTokenID(t *testing.T) (*TxProcessor, *til.Context, []common.BlockData) {
 702	dir, err := ioutil.TempDir("", "tmpdb")
 703	require.NoError(t, err)
 704	defer assert.NoError(t, os.RemoveAll(dir))
 705
 706	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 707		Type: statedb.TypeBatchBuilder, NLevels: 32})
 708	assert.NoError(t, err)
 709
 710	chainID := uint16(1)
 711
 712	// generate test transactions from test.SetBlockchain0 code
 713	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
 714
 715	set := `
 716		Type: Blockchain
 717
 718		CreateAccountDeposit(0) A: 200
 719
 720		> batchL1 // freeze L1User{1}
 721
 722		CreateAccountCoordinator(0) Coord
 723		CreateAccountCoordinator(0) B
 724
 725		Transfer(0) A-B: 100 (126)
 726
 727		> batchL1 // forge L1User{1}, forge L1Coord{4}, forge L2{2}
 728		> block
 729	`
 730	blocks, err := tc.GenerateBlocks(set)
 731	require.NoError(t, err)
 732
 733	config := Config{
 734		NLevels:  32,
 735		MaxFeeTx: 64,
 736		MaxTx:    512,
 737		MaxL1Tx:  16,
 738		ChainID:  chainID,
 739	}
 740	tp := NewTxProcessor(sdb, config)
 741	// batch1
 742	_, err = tp.ProcessTxs(nil, nil, nil, nil) // to simulate the first batch from the Til set
 743	require.NoError(t, err)
 744
 745	return tp, tc, blocks
 746}
 747
 748func TestMultipleCoordIdxForTokenID(t *testing.T) {
 749	// Check that ProcessTxs always uses the first occurrence of the
 750	// CoordIdx for each TokenID
 751
 752	coordIdxs := []common.Idx{257, 257, 257}
 753	tp, tc, blocks := initTestMultipleCoordIdxForTokenID(t)
 754	l1UserTxs := til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
 755	l1CoordTxs := blocks[0].Rollup.Batches[1].L1CoordinatorTxs
 756	l1CoordTxs = append(l1CoordTxs, l1CoordTxs[0]) // duplicate the CoordAccount for TokenID=0
 757	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
 758	_, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
 759	require.NoError(t, err)
 760
 761	checkBalanceByIdx(t, tp.s, 256, "90")  // A
 762	checkBalanceByIdx(t, tp.s, 257, "10")  // Coord0
 763	checkBalanceByIdx(t, tp.s, 258, "100") // B
 764	checkBalanceByIdx(t, tp.s, 259, "0")   // Coord0
 765
 766	// reset StateDB values
 767	coordIdxs = []common.Idx{259, 257}
 768	tp, tc, blocks = initTestMultipleCoordIdxForTokenID(t)
 769	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
 770	l1CoordTxs = blocks[0].Rollup.Batches[1].L1CoordinatorTxs
 771	l1CoordTxs = append(l1CoordTxs, l1CoordTxs[0]) // duplicate the CoordAccount for TokenID=0
 772	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
 773	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
 774	require.NoError(t, err)
 775
 776	checkBalanceByIdx(t, tp.s, 256, "90")  // A
 777	checkBalanceByIdx(t, tp.s, 257, "0")   // Coord0
 778	checkBalanceByIdx(t, tp.s, 258, "100") // B
 779	checkBalanceByIdx(t, tp.s, 259, "10")  // Coord0
 780
 781	// reset StateDB values
 782	coordIdxs = []common.Idx{257, 259}
 783	tp, tc, blocks = initTestMultipleCoordIdxForTokenID(t)
 784	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
 785	l1CoordTxs = blocks[0].Rollup.Batches[1].L1CoordinatorTxs
 786	l1CoordTxs = append(l1CoordTxs, l1CoordTxs[0]) // duplicate the CoordAccount for TokenID=0
 787	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
 788	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
 789	require.NoError(t, err)
 790
 791	checkBalanceByIdx(t, tp.s, 256, "90")  // A
 792	checkBalanceByIdx(t, tp.s, 257, "10")  // Coord0
 793	checkBalanceByIdx(t, tp.s, 258, "100") // B
 794	checkBalanceByIdx(t, tp.s, 259, "0")   // Coord0
 795}
 796
 797func TestTwoExits(t *testing.T) {
 798	// In the first part we generate a batch with two force exits for the
 799	// same account of 20 each.  The txprocessor output should be a single
 800	// exitInfo with balance of 40.
 801	dir, err := ioutil.TempDir("", "tmpdb")
 802	require.NoError(t, err)
 803	defer assert.NoError(t, os.RemoveAll(dir))
 804
 805	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 806		Type: statedb.TypeSynchronizer, NLevels: 32})
 807	assert.NoError(t, err)
 808
 809	chainID := uint16(1)
 810
 811	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
 812
 813	// Two exits for the same account.  The tx processor should output a
 814	// single exit with the accumulated exit balance
 815	set := `
 816		Type: Blockchain
 817
 818		CreateAccountDeposit(0) A: 100
 819
 820		> batchL1 // freeze L1User{1}
 821		> batchL1 // forge L1User{1}
 822
 823		ForceExit(0) A: 20
 824		ForceExit(0) A: 20
 825
 826		> batchL1 // freeze L1User{2}
 827		> batchL1 // forge L1User{2}
 828		> block
 829	`
 830	blocks, err := tc.GenerateBlocks(set)
 831	require.NoError(t, err)
 832	err = tc.FillBlocksExtra(blocks, &til.ConfigExtra{})
 833	require.NoError(t, err)
 834	err = tc.FillBlocksForgedL1UserTxs(blocks)
 835	require.NoError(t, err)
 836
 837	// Sanity check
 838	require.Equal(t, 1, len(blocks[0].Rollup.Batches[1].L1UserTxs))
 839	require.Equal(t, 2, len(blocks[0].Rollup.Batches[3].L1UserTxs))
 840
 841	config := Config{
 842		NLevels:  32,
 843		MaxFeeTx: 64,
 844		MaxTx:    512,
 845		MaxL1Tx:  16,
 846		ChainID:  chainID,
 847	}
 848	tp := NewTxProcessor(sdb, config)
 849	ptOuts := []*ProcessTxOutput{}
 850	for _, block := range blocks {
 851		for _, batch := range block.Rollup.Batches {
 852			ptOut, err := tp.ProcessTxs(nil, batch.L1UserTxs, nil, nil)
 853			require.NoError(t, err)
 854			ptOuts = append(ptOuts, ptOut)
 855		}
 856	}
 857
 858	assert.Equal(t, 1, len(ptOuts[3].ExitInfos))
 859	assert.Equal(t, big.NewInt(40), ptOuts[3].ExitInfos[0].Balance)
 860	acc, err := sdb.GetAccount(256)
 861	require.NoError(t, err)
 862	assert.Equal(t, big.NewInt(60), acc.Balance)
 863
 864	// In the second part we start a fresh statedb and generate a batch
 865	// with one force exit for the same account as before.  The txprocessor
 866	// output should be a single exitInfo with balance of 40, and the exit
 867	// merkle tree proof should be equal to the previous one.
 868
 869	dir2, err := ioutil.TempDir("", "tmpdb")
 870	require.NoError(t, err)
 871	defer assert.NoError(t, os.RemoveAll(dir2))
 872
 873	sdb2, err := statedb.NewStateDB(statedb.Config{Path: dir2, Keep: 128,
 874		Type: statedb.TypeSynchronizer, NLevels: 32})
 875	assert.NoError(t, err)
 876
 877	tc = til.NewContext(chainID, common.RollupConstMaxL1UserTx)
 878
 879	// Single exit with balance of both exits in previous set.  The exit
 880	// root should match.
 881	set2 := `
 882		Type: Blockchain
 883
 884		CreateAccountDeposit(0) A: 100
 885
 886		> batchL1 // freeze L1User{1}
 887		> batchL1 // forge L1User{1}
 888
 889		ForceExit(0) A: 40
 890
 891		> batchL1 // freeze L1User{2}
 892		> batchL1 // forge L1User{2}
 893		> block
 894	`
 895	blocks, err = tc.GenerateBlocks(set2)
 896	require.NoError(t, err)
 897	err = tc.FillBlocksExtra(blocks, &til.ConfigExtra{})
 898	require.NoError(t, err)
 899	err = tc.FillBlocksForgedL1UserTxs(blocks)
 900	require.NoError(t, err)
 901
 902	tp = NewTxProcessor(sdb2, config)
 903	ptOuts2 := []*ProcessTxOutput{}
 904	for _, block := range blocks {
 905		for _, batch := range block.Rollup.Batches {
 906			ptOut, err := tp.ProcessTxs(nil, batch.L1UserTxs, nil, nil)
 907			require.NoError(t, err)
 908			ptOuts2 = append(ptOuts2, ptOut)
 909		}
 910	}
 911
 912	assert.Equal(t, ptOuts[3].ExitInfos[0].MerkleProof, ptOuts2[3].ExitInfos[0].MerkleProof)
 913}
 914
 915func TestExitOf0Amount(t *testing.T) {
 916	// Test to check that when doing an Exit with amount 0 the Exit Root
 917	// does not change (as there is no new Exit Leaf created)
 918
 919	dir, err := ioutil.TempDir("", "tmpdb")
 920	require.NoError(t, err)
 921	defer assert.NoError(t, os.RemoveAll(dir))
 922
 923	sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
 924		Type: statedb.TypeBatchBuilder, NLevels: 32})
 925	assert.NoError(t, err)
 926
 927	chainID := uint16(1)
 928
 929	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
 930
 931	set := `
 932		Type: Blockchain
 933
 934		CreateAccountDeposit(0) A: 100
 935		CreateAccountDeposit(0) B: 100
 936
 937		> batchL1 // batch1: freeze L1User{2}
 938		> batchL1 // batch2: forge L1User{2}
 939
 940		ForceExit(0) A: 10
 941		ForceExit(0) B: 0
 942
 943		> batchL1 // batch3: freeze L1User{2}
 944		> batchL1 // batch4: forge L1User{2}
 945
 946		ForceExit(0) A: 10
 947
 948		> batchL1 // batch5: freeze L1User{1}
 949		> batchL1 // batch6: forge L1User{1}
 950
 951		ForceExit(0) A: 0
 952		> batchL1 // batch7: freeze L1User{1}
 953		> batchL1 // batch8: forge L1User{1}
 954		> block
 955	`
 956	blocks, err := tc.GenerateBlocks(set)
 957	require.NoError(t, err)
 958	err = tc.FillBlocksExtra(blocks, &til.ConfigExtra{})
 959	require.NoError(t, err)
 960	err = tc.FillBlocksForgedL1UserTxs(blocks)
 961	require.NoError(t, err)
 962
 963	// Sanity check
 964	require.Equal(t, 2, len(blocks[0].Rollup.Batches[1].L1UserTxs))
 965	require.Equal(t, 2, len(blocks[0].Rollup.Batches[3].L1UserTxs))
 966	require.Equal(t, big.NewInt(10), blocks[0].Rollup.Batches[3].L1UserTxs[0].Amount)
 967	require.Equal(t, big.NewInt(0), blocks[0].Rollup.Batches[3].L1UserTxs[1].Amount)
 968
 969	config := Config{
 970		NLevels:  32,
 971		MaxFeeTx: 64,
 972		MaxTx:    512,
 973		MaxL1Tx:  16,
 974		ChainID:  chainID,
 975	}
 976	tp := NewTxProcessor(sdb, config)
 977
 978	// For this test are only processed the batches with transactions:
 979	// - Batch2, equivalent to Batches[1]
 980	// - Batch4, equivalent to Batches[3]
 981	// - Batch6, equivalent to Batches[5]
 982	// - Batch8, equivalent to Batches[7]
 983
 984	// process Batch2:
 985	_, err = tp.ProcessTxs(nil, blocks[0].Rollup.Batches[1].L1UserTxs, nil, nil)
 986	require.NoError(t, err)
 987	// process Batch4:
 988	ptOut, err := tp.ProcessTxs(nil, blocks[0].Rollup.Batches[3].L1UserTxs, nil, nil)
 989	require.NoError(t, err)
 990	assert.Equal(t, "14329759303391468223438874789317921522067594445474390443816827472846339238908", ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
 991	exitRootBatch4 := ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String()
 992
 993	// process Batch6:
 994	ptOut, err = tp.ProcessTxs(nil, blocks[0].Rollup.Batches[5].L1UserTxs, nil, nil)
 995	require.NoError(t, err)
 996	assert.Equal(t, "14329759303391468223438874789317921522067594445474390443816827472846339238908", ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
 997	// Expect that the ExitRoot for the Batch6 will be equal than for the
 998	// Batch4, as the Batch4 & Batch6 have the same tx with Exit Amount=10,
 999	// and Batch4 has a 2nd tx with Exit Amount=0.
1000	assert.Equal(t, exitRootBatch4, ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
1001
1002	// For the Batch8, as there is only 1 exit with Amount=0, the ExitRoot
1003	// should be 0.
1004	// process Batch8:
1005	ptOut, err = tp.ProcessTxs(nil, blocks[0].Rollup.Batches[7].L1UserTxs, nil, nil)
1006	require.NoError(t, err)
1007	assert.Equal(t, "0", ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
1008}