arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/txprocessor/txprocessor_test.go
txprocessor/txprocessor_test.goRaw
  1package txprocessor
  2
  3import (
  4	"encoding/binary"
  5	"encoding/hex"
  6	"io/ioutil"
  7	"math/big"
  8	"os"
  9	"testing"
 10
 11	ethCommon "github.com/ethereum/go-ethereum/common"
 12	"github.com/hermeznetwork/hermez-node/common"
 13	"github.com/hermeznetwork/hermez-node/db/statedb"
 14	"github.com/hermeznetwork/hermez-node/log"
 15	"github.com/hermeznetwork/hermez-node/test/til"
 16	"github.com/stretchr/testify/assert"
 17	"github.com/stretchr/testify/require"
 18)
 19
 20func checkBalance(t *testing.T, tc *til.Context, sdb *statedb.StateDB, username string, tokenid int, expected string) {
 21	idx := tc.Users[username].Accounts[common.TokenID(tokenid)].Idx
 22	acc, err := sdb.GetAccount(idx)
 23	require.NoError(t, err)
 24	assert.Equal(t, expected, acc.Balance.String())
 25}
 26
 27func TestComputeEffectiveAmounts(t *testing.T) {
 28	dir, err := ioutil.TempDir("", "tmpdb")
 29	require.NoError(t, err)
 30	defer assert.NoError(t, os.RemoveAll(dir))
 31
 32	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeSynchronizer, 32)
 33	assert.NoError(t, err)
 34
 35	set := `
 36		Type: Blockchain
 37		AddToken(1)
 38	
 39		CreateAccountDeposit(0) A: 10
 40		CreateAccountDeposit(0) B: 10
 41		CreateAccountDeposit(1) C: 10
 42		> batchL1
 43		> batchL1
 44		> block
 45	`
 46	chainID := uint16(0)
 47	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
 48	blocks, err := tc.GenerateBlocks(set)
 49	require.NoError(t, err)
 50
 51	config := Config{
 52		NLevels:  32,
 53		MaxFeeTx: 64,
 54		MaxTx:    512,
 55		MaxL1Tx:  16,
 56		ChainID:  chainID,
 57	}
 58	tp := NewTxProcessor(sdb, config)
 59	_, err = tp.ProcessTxs(nil, blocks[0].Rollup.L1UserTxs, nil, nil)
 60	require.NoError(t, err)
 61
 62	tx := common.L1Tx{
 63		FromIdx:       256,
 64		ToIdx:         257,
 65		Amount:        big.NewInt(10),
 66		DepositAmount: big.NewInt(0),
 67		FromEthAddr:   tc.Users["A"].Addr,
 68		UserOrigin:    true,
 69	}
 70	tp.computeEffectiveAmounts(&tx)
 71	assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
 72	assert.Equal(t, big.NewInt(10), tx.EffectiveAmount)
 73
 74	// expect error due not enough funds
 75	tx = common.L1Tx{
 76		FromIdx:       256,
 77		ToIdx:         257,
 78		Amount:        big.NewInt(11),
 79		DepositAmount: big.NewInt(0),
 80		FromEthAddr:   tc.Users["A"].Addr,
 81		UserOrigin:    true,
 82	}
 83	tp.computeEffectiveAmounts(&tx)
 84	assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
 85	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
 86
 87	// expect no-error as there are enough funds in a
 88	// CreateAccountDepositTransfer transction
 89	tx = common.L1Tx{
 90		FromIdx:       0,
 91		ToIdx:         257,
 92		Amount:        big.NewInt(10),
 93		DepositAmount: big.NewInt(10),
 94		UserOrigin:    true,
 95	}
 96	tp.computeEffectiveAmounts(&tx)
 97	assert.Equal(t, big.NewInt(10), tx.EffectiveDepositAmount)
 98	assert.Equal(t, big.NewInt(10), tx.EffectiveAmount)
 99
100	// expect error due not enough funds in a CreateAccountDepositTransfer
101	// transction
102	tx = common.L1Tx{
103		FromIdx:       0,
104		ToIdx:         257,
105		Amount:        big.NewInt(11),
106		DepositAmount: big.NewInt(10),
107		UserOrigin:    true,
108	}
109	tp.computeEffectiveAmounts(&tx)
110	assert.Equal(t, big.NewInt(10), tx.EffectiveDepositAmount)
111	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
112
113	// expect error due not same TokenID
114	tx = common.L1Tx{
115		FromIdx:       256,
116		ToIdx:         258,
117		Amount:        big.NewInt(5),
118		DepositAmount: big.NewInt(0),
119		FromEthAddr:   tc.Users["A"].Addr,
120		UserOrigin:    true,
121	}
122	tp.computeEffectiveAmounts(&tx)
123	assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
124	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
125
126	// expect error due not same EthAddr
127	tx = common.L1Tx{
128		FromIdx:       256,
129		ToIdx:         257,
130		Amount:        big.NewInt(8),
131		DepositAmount: big.NewInt(0),
132		FromEthAddr:   tc.Users["B"].Addr,
133		UserOrigin:    true,
134	}
135	tp.computeEffectiveAmounts(&tx)
136	assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
137	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
138
139	// expect on TxTypeDepositTransfer EffectiveAmount=0, but
140	// EffectiveDepositAmount!=0, due not enough funds to make the transfer
141	tx = common.L1Tx{
142		FromIdx:       256,
143		ToIdx:         257,
144		Amount:        big.NewInt(20),
145		DepositAmount: big.NewInt(8),
146		FromEthAddr:   tc.Users["A"].Addr,
147		UserOrigin:    true,
148	}
149	tp.computeEffectiveAmounts(&tx)
150	assert.Equal(t, big.NewInt(8), tx.EffectiveDepositAmount)
151	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
152
153	// expect on TxTypeDepositTransfer EffectiveAmount=0, but
154	// EffectiveDepositAmount!=0, due different EthAddr from FromIdx
155	// address
156	tx = common.L1Tx{
157		FromIdx:       256,
158		ToIdx:         257,
159		Amount:        big.NewInt(8),
160		DepositAmount: big.NewInt(8),
161		FromEthAddr:   tc.Users["B"].Addr,
162		UserOrigin:    true,
163	}
164	tp.computeEffectiveAmounts(&tx)
165	assert.Equal(t, big.NewInt(8), tx.EffectiveDepositAmount)
166	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
167
168	// CreateAccountDepositTransfer for TokenID=1 when receiver does not
169	// have an account for that TokenID, expect that the
170	// EffectiveDepositAmount=DepositAmount, but EffectiveAmount==0
171	tx = common.L1Tx{
172		FromIdx:       0,
173		ToIdx:         257,
174		Amount:        big.NewInt(8),
175		DepositAmount: big.NewInt(8),
176		FromEthAddr:   tc.Users["A"].Addr,
177		TokenID:       2,
178		UserOrigin:    true,
179		Type:          common.TxTypeCreateAccountDepositTransfer,
180	}
181	tp.computeEffectiveAmounts(&tx)
182	assert.Equal(t, big.NewInt(8), tx.EffectiveDepositAmount)
183	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
184
185	// DepositTransfer for TokenID=1 when receiver does not have an account
186	// for that TokenID, expect that the
187	// EffectiveDepositAmount=DepositAmount, but EffectiveAmount=0
188	tx = common.L1Tx{
189		FromIdx:       258,
190		ToIdx:         256,
191		Amount:        big.NewInt(8),
192		DepositAmount: big.NewInt(8),
193		FromEthAddr:   tc.Users["C"].Addr,
194		TokenID:       1,
195		UserOrigin:    true,
196		Type:          common.TxTypeDepositTransfer,
197	}
198	tp.computeEffectiveAmounts(&tx)
199	assert.Equal(t, big.NewInt(8), tx.EffectiveDepositAmount)
200	assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
201}
202
203func TestProcessTxsBalances(t *testing.T) {
204	dir, err := ioutil.TempDir("", "tmpdb")
205	require.NoError(t, err)
206	defer assert.NoError(t, os.RemoveAll(dir))
207
208	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeSynchronizer, 32)
209	assert.NoError(t, err)
210
211	chainID := uint16(0)
212	// generate test transactions from test.SetBlockchain0 code
213	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
214	blocks, err := tc.GenerateBlocks(til.SetBlockchainMinimumFlow0)
215	require.NoError(t, err)
216
217	config := Config{
218		NLevels:  32,
219		MaxFeeTx: 64,
220		MaxTx:    512,
221		MaxL1Tx:  16,
222		ChainID:  chainID,
223	}
224	tp := NewTxProcessor(sdb, config)
225
226	log.Debug("block:0 batch:0, only L1CoordinatorTxs")
227	_, err = tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
228	require.NoError(t, err)
229
230	log.Debug("block:0 batch:1")
231	l1UserTxs := []common.L1Tx{}
232	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
233	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
234	require.NoError(t, err)
235
236	log.Debug("block:0 batch:2")
237	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
238	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
239	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
240	require.NoError(t, err)
241	checkBalance(t, tc, sdb, "A", 0, "500")
242
243	log.Debug("block:0 batch:3")
244	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
245	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[3].L2Txs)
246	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, l2Txs)
247	require.NoError(t, err)
248	checkBalance(t, tc, sdb, "A", 0, "500")
249	checkBalance(t, tc, sdb, "A", 1, "500")
250
251	log.Debug("block:0 batch:4")
252	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
253	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[4].L2Txs)
254	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[4].L1CoordinatorTxs, l2Txs)
255	require.NoError(t, err)
256	checkBalance(t, tc, sdb, "A", 0, "500")
257	checkBalance(t, tc, sdb, "A", 1, "500")
258
259	log.Debug("block:0 batch:5")
260	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
261	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[5].L2Txs)
262	_, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[5].L1CoordinatorTxs, l2Txs)
263	require.NoError(t, err)
264	checkBalance(t, tc, sdb, "A", 0, "600")
265	checkBalance(t, tc, sdb, "A", 1, "500")
266	checkBalance(t, tc, sdb, "B", 0, "400")
267
268	coordIdxs := []common.Idx{261, 262}
269	log.Debug("block:0 batch:6")
270	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
271	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[6].L2Txs)
272	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[6].L1CoordinatorTxs, l2Txs)
273	require.NoError(t, err)
274	checkBalance(t, tc, sdb, "Coord", 0, "10")
275	checkBalance(t, tc, sdb, "Coord", 1, "20")
276	checkBalance(t, tc, sdb, "A", 0, "600")
277	checkBalance(t, tc, sdb, "A", 1, "280")
278	checkBalance(t, tc, sdb, "B", 0, "290")
279	checkBalance(t, tc, sdb, "B", 1, "200")
280	checkBalance(t, tc, sdb, "C", 0, "100")
281	checkBalance(t, tc, sdb, "D", 0, "800")
282
283	log.Debug("block:0 batch:7")
284	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
285	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[7].L2Txs)
286	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[7].L1CoordinatorTxs, l2Txs)
287	require.NoError(t, err)
288	checkBalance(t, tc, sdb, "Coord", 0, "35")
289	checkBalance(t, tc, sdb, "Coord", 1, "30")
290	checkBalance(t, tc, sdb, "A", 0, "430")
291	checkBalance(t, tc, sdb, "A", 1, "280")
292	checkBalance(t, tc, sdb, "B", 0, "390")
293	checkBalance(t, tc, sdb, "B", 1, "90")
294	checkBalance(t, tc, sdb, "C", 0, "45")
295	checkBalance(t, tc, sdb, "C", 1, "100")
296	checkBalance(t, tc, sdb, "D", 0, "800")
297
298	log.Debug("block:1 batch:0")
299	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
300	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
301	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
302	require.NoError(t, err)
303	checkBalance(t, tc, sdb, "Coord", 0, "75")
304	checkBalance(t, tc, sdb, "Coord", 1, "30")
305	checkBalance(t, tc, sdb, "A", 0, "730")
306	checkBalance(t, tc, sdb, "A", 1, "280")
307	checkBalance(t, tc, sdb, "B", 0, "380")
308	checkBalance(t, tc, sdb, "B", 1, "90")
309	checkBalance(t, tc, sdb, "C", 0, "845")
310	checkBalance(t, tc, sdb, "C", 1, "100")
311	checkBalance(t, tc, sdb, "D", 0, "470")
312
313	log.Debug("block:1 batch:1")
314	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
315	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
316	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
317	require.NoError(t, err)
318
319	// use Set of PoolL2 txs
320	poolL2Txs, err := tc.GeneratePoolL2Txs(til.SetPoolL2MinimumFlow1)
321	assert.NoError(t, err)
322
323	_, err = tp.ProcessTxs(coordIdxs, []common.L1Tx{}, []common.L1Tx{}, poolL2Txs)
324	require.NoError(t, err)
325	checkBalance(t, tc, sdb, "Coord", 0, "105")
326	checkBalance(t, tc, sdb, "Coord", 1, "40")
327	checkBalance(t, tc, sdb, "A", 0, "510")
328	checkBalance(t, tc, sdb, "A", 1, "170")
329	checkBalance(t, tc, sdb, "B", 0, "480")
330	checkBalance(t, tc, sdb, "B", 1, "190")
331	checkBalance(t, tc, sdb, "C", 0, "845")
332	checkBalance(t, tc, sdb, "C", 1, "100")
333	checkBalance(t, tc, sdb, "D", 0, "360")
334	checkBalance(t, tc, sdb, "F", 0, "100")
335}
336
337func TestProcessTxsSynchronizer(t *testing.T) {
338	dir, err := ioutil.TempDir("", "tmpdb")
339	require.NoError(t, err)
340	defer assert.NoError(t, os.RemoveAll(dir))
341
342	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeSynchronizer, 32)
343	assert.NoError(t, err)
344
345	chainID := uint16(0)
346	// generate test transactions from test.SetBlockchain0 code
347	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
348	blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
349	require.NoError(t, err)
350
351	assert.Equal(t, 31, len(blocks[0].Rollup.L1UserTxs))
352	assert.Equal(t, 4, len(blocks[0].Rollup.Batches[0].L1CoordinatorTxs))
353	assert.Equal(t, 0, len(blocks[0].Rollup.Batches[1].L1CoordinatorTxs))
354	assert.Equal(t, 22, len(blocks[0].Rollup.Batches[2].L2Txs))
355	assert.Equal(t, 1, len(blocks[1].Rollup.Batches[0].L1CoordinatorTxs))
356	assert.Equal(t, 62, len(blocks[1].Rollup.Batches[0].L2Txs))
357	assert.Equal(t, 1, len(blocks[1].Rollup.Batches[1].L1CoordinatorTxs))
358	assert.Equal(t, 8, len(blocks[1].Rollup.Batches[1].L2Txs))
359
360	// Coordinator Idx where to send the fees
361	coordIdxs := []common.Idx{256, 257, 258, 259}
362
363	// Idx of user 'A'
364	idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
365
366	config := Config{
367		NLevels:  32,
368		MaxFeeTx: 64,
369		MaxTx:    512,
370		MaxL1Tx:  32,
371		ChainID:  chainID,
372	}
373	tp := NewTxProcessor(sdb, config)
374
375	// Process the 1st batch, which contains the L1CoordinatorTxs necessary
376	// to create the Coordinator accounts to receive the fees
377	log.Debug("block:0 batch:0, only L1CoordinatorTxs")
378	ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
379	require.NoError(t, err)
380	assert.Equal(t, 4, len(ptOut.CreatedAccounts))
381	assert.Equal(t, 0, len(ptOut.CollectedFees))
382
383	log.Debug("block:0 batch:1")
384	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
385	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[0].Rollup.L1UserTxs,
386		blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
387	require.NoError(t, err)
388	assert.Equal(t, 0, len(ptOut.ExitInfos))
389	assert.Equal(t, 31, len(ptOut.CreatedAccounts))
390	assert.Equal(t, 4, len(ptOut.CollectedFees))
391	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
392	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
393	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
394	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
395	acc, err := sdb.GetAccount(idxA1)
396	require.NoError(t, err)
397	assert.Equal(t, "50", acc.Balance.String())
398
399	log.Debug("block:0 batch:2")
400	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
401	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
402	require.NoError(t, err)
403	assert.Equal(t, 0, len(ptOut.ExitInfos))
404	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
405	assert.Equal(t, 4, len(ptOut.CollectedFees))
406	assert.Equal(t, "2", ptOut.CollectedFees[common.TokenID(0)].String())
407	assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
408	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
409	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
410	acc, err = sdb.GetAccount(idxA1)
411	require.NoError(t, err)
412	assert.Equal(t, "35", acc.Balance.String())
413
414	log.Debug("block:1 batch:0")
415	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
416	// before processing expect l2Txs[0:2].Nonce==0
417	assert.Equal(t, common.Nonce(0), l2Txs[0].Nonce)
418	assert.Equal(t, common.Nonce(0), l2Txs[1].Nonce)
419	assert.Equal(t, common.Nonce(0), l2Txs[2].Nonce)
420
421	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
422	require.NoError(t, err)
423
424	// after processing expect l2Txs[0:2].Nonce!=0 and has expected value
425	assert.Equal(t, common.Nonce(5), l2Txs[0].Nonce)
426	assert.Equal(t, common.Nonce(6), l2Txs[1].Nonce)
427	assert.Equal(t, common.Nonce(7), l2Txs[2].Nonce)
428
429	assert.Equal(t, 4, len(ptOut.ExitInfos)) // the 'ForceExit(1)' is not computed yet, as the batch is without L1UserTxs
430	assert.Equal(t, 1, len(ptOut.CreatedAccounts))
431	assert.Equal(t, 4, len(ptOut.CollectedFees))
432	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
433	assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
434	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
435	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
436	acc, err = sdb.GetAccount(idxA1)
437	require.NoError(t, err)
438	assert.Equal(t, "57", acc.Balance.String())
439
440	log.Debug("block:1 batch:1")
441	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
442	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[1].Rollup.L1UserTxs,
443		blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
444	require.NoError(t, err)
445
446	assert.Equal(t, 2, len(ptOut.ExitInfos)) // 2, as previous batch was without L1UserTxs, and has pending the 'ForceExit(1) A: 5'
447	assert.Equal(t, 1, len(ptOut.CreatedAccounts))
448	assert.Equal(t, 4, len(ptOut.CollectedFees))
449	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
450	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
451	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
452	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
453	acc, err = sdb.GetAccount(idxA1)
454	assert.NoError(t, err)
455	assert.Equal(t, "77", acc.Balance.String())
456
457	idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
458	acc, err = sdb.GetAccount(idxB0)
459	require.NoError(t, err)
460	assert.Equal(t, "51", acc.Balance.String())
461
462	// get balance of Coordinator account for TokenID==0
463	acc, err = sdb.GetAccount(common.Idx(256))
464	require.NoError(t, err)
465	assert.Equal(t, "2", acc.Balance.String())
466}
467
468func TestProcessTxsBatchBuilder(t *testing.T) {
469	dir, err := ioutil.TempDir("", "tmpdb")
470	require.NoError(t, err)
471	defer assert.NoError(t, os.RemoveAll(dir))
472
473	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeBatchBuilder, 32)
474	assert.NoError(t, err)
475
476	chainID := uint16(0)
477	// generate test transactions from test.SetBlockchain0 code
478	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
479	blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
480	require.NoError(t, err)
481
482	// Coordinator Idx where to send the fees
483	coordIdxs := []common.Idx{256, 257, 258, 259}
484
485	// Idx of user 'A'
486	idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
487
488	config := Config{
489		NLevels:  32,
490		MaxFeeTx: 64,
491		MaxTx:    512,
492		MaxL1Tx:  32,
493		ChainID:  chainID,
494	}
495	tp := NewTxProcessor(sdb, config)
496
497	// Process the 1st batch, which contains the L1CoordinatorTxs necessary
498	// to create the Coordinator accounts to receive the fees
499	log.Debug("block:0 batch:0, only L1CoordinatorTxs")
500	ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
501	require.NoError(t, err)
502	// expect 0 at CreatedAccount, as is only computed when StateDB.Type==TypeSynchronizer
503	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
504
505	log.Debug("block:0 batch:1")
506	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
507	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[0].Rollup.L1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
508	require.NoError(t, err)
509	assert.Equal(t, 0, len(ptOut.ExitInfos))
510	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
511	acc, err := sdb.GetAccount(idxA1)
512	require.NoError(t, err)
513	assert.Equal(t, "50", acc.Balance.String())
514
515	log.Debug("block:0 batch:2")
516	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
517	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
518	require.NoError(t, err)
519	assert.Equal(t, 0, len(ptOut.ExitInfos))
520	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
521	acc, err = sdb.GetAccount(idxA1)
522	require.NoError(t, err)
523	assert.Equal(t, "35", acc.Balance.String())
524
525	log.Debug("block:1 batch:0")
526	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
527	_, err = tp.ProcessTxs(coordIdxs, nil, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
528	require.NoError(t, err)
529	acc, err = sdb.GetAccount(idxA1)
530	require.NoError(t, err)
531	assert.Equal(t, "57", acc.Balance.String())
532
533	log.Debug("block:1 batch:1")
534	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
535	_, err = tp.ProcessTxs(coordIdxs, blocks[1].Rollup.L1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
536	require.NoError(t, err)
537	acc, err = sdb.GetAccount(idxA1)
538	assert.NoError(t, err)
539	assert.Equal(t, "77", acc.Balance.String())
540
541	idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
542	acc, err = sdb.GetAccount(idxB0)
543	require.NoError(t, err)
544	assert.Equal(t, "51", acc.Balance.String())
545
546	// get balance of Coordinator account for TokenID==0
547	acc, err = sdb.GetAccount(common.Idx(256))
548	require.NoError(t, err)
549	assert.Equal(t, common.TokenID(0), acc.TokenID)
550	assert.Equal(t, "2", acc.Balance.String())
551	acc, err = sdb.GetAccount(common.Idx(257))
552	require.NoError(t, err)
553	assert.Equal(t, common.TokenID(1), acc.TokenID)
554	assert.Equal(t, "2", acc.Balance.String())
555
556	assert.Equal(t, "2720257526434001367979405991743527513807903085728407823609738212616896104498", sdb.MT.Root().BigInt().String())
557}
558
559func TestProcessTxsRootTestVectors(t *testing.T) {
560	dir, err := ioutil.TempDir("", "tmpdb")
561	require.NoError(t, err)
562	defer assert.NoError(t, os.RemoveAll(dir))
563
564	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeBatchBuilder, 32)
565	assert.NoError(t, err)
566
567	// same values than in the js test
568	bjj0, err := common.BJJFromStringWithChecksum("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7")
569	assert.NoError(t, err)
570	l1Txs := []common.L1Tx{
571		{
572			FromIdx:       0,
573			DepositAmount: big.NewInt(16000000),
574			Amount:        big.NewInt(0),
575			TokenID:       1,
576			FromBJJ:       bjj0,
577			FromEthAddr:   ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"),
578			ToIdx:         0,
579			Type:          common.TxTypeCreateAccountDeposit,
580			UserOrigin:    true,
581		},
582	}
583	l2Txs := []common.PoolL2Tx{
584		{
585			FromIdx: 256,
586			ToIdx:   256,
587			TokenID: 1,
588			Amount:  big.NewInt(1000),
589			Nonce:   0,
590			Fee:     126,
591			Type:    common.TxTypeTransfer,
592		},
593	}
594
595	chainID := uint16(0)
596	config := Config{
597		NLevels:  32,
598		MaxFeeTx: 8,
599		MaxTx:    32,
600		MaxL1Tx:  16,
601		ChainID:  chainID,
602	}
603	tp := NewTxProcessor(sdb, config)
604	_, err = tp.ProcessTxs(nil, l1Txs, nil, l2Txs)
605	require.NoError(t, err)
606	assert.Equal(t, "9827704113668630072730115158977131501210702363656902211840117643154933433410", sdb.MT.Root().BigInt().String())
607}
608
609func TestCreateAccountDepositMaxValue(t *testing.T) {
610	dir, err := ioutil.TempDir("", "tmpdb")
611	require.NoError(t, err)
612	defer assert.NoError(t, os.RemoveAll(dir))
613
614	nLevels := 16
615	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeBatchBuilder, nLevels)
616	assert.NoError(t, err)
617
618	users := generateJsUsers(t)
619
620	daMaxHex, err := hex.DecodeString("FFFF")
621	require.NoError(t, err)
622	daMaxF16 := common.Float16(binary.BigEndian.Uint16(daMaxHex))
623	daMaxBI := daMaxF16.BigInt()
624	assert.Equal(t, "10235000000000000000000000000000000", daMaxBI.String())
625
626	daMax1Hex, err := hex.DecodeString("FFFE")
627	require.NoError(t, err)
628	daMax1F16 := common.Float16(binary.BigEndian.Uint16(daMax1Hex))
629	daMax1BI := daMax1F16.BigInt()
630	assert.Equal(t, "10225000000000000000000000000000000", daMax1BI.String())
631
632	l1Txs := []common.L1Tx{
633		{
634			FromIdx:       0,
635			DepositAmount: daMaxBI,
636			Amount:        big.NewInt(0),
637			TokenID:       1,
638			FromBJJ:       users[0].BJJ.Public().Compress(),
639			FromEthAddr:   users[0].Addr,
640			ToIdx:         0,
641			Type:          common.TxTypeCreateAccountDeposit,
642			UserOrigin:    true,
643		},
644		{
645			FromIdx:       0,
646			DepositAmount: daMax1BI,
647			Amount:        big.NewInt(0),
648			TokenID:       1,
649			FromBJJ:       users[1].BJJ.Public().Compress(),
650			FromEthAddr:   users[1].Addr,
651			ToIdx:         0,
652			Type:          common.TxTypeCreateAccountDeposit,
653			UserOrigin:    true,
654		},
655	}
656
657	chainID := uint16(0)
658	config := Config{
659		NLevels:  uint32(nLevels),
660		MaxTx:    3,
661		MaxL1Tx:  2,
662		MaxFeeTx: 2,
663		ChainID:  chainID,
664	}
665	tp := NewTxProcessor(sdb, config)
666
667	_, err = tp.ProcessTxs(nil, l1Txs, nil, nil)
668	require.NoError(t, err)
669
670	// check balances
671	acc, err := sdb.GetAccount(common.Idx(256))
672	require.NoError(t, err)
673	assert.Equal(t, daMaxBI, acc.Balance)
674	acc, err = sdb.GetAccount(common.Idx(257))
675	require.NoError(t, err)
676	assert.Equal(t, daMax1BI, acc.Balance)
677}