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	// Coordinator Idx where to send the fees
218	coordIdxs := []common.Idx{256, 257}
219	config := Config{
220		NLevels:  32,
221		MaxFeeTx: 64,
222		MaxTx:    512,
223		MaxL1Tx:  16,
224		ChainID:  chainID,
225	}
226	tp := NewTxProcessor(sdb, config)
227
228	log.Debug("block:0 batch:0, only L1CoordinatorTxs")
229	_, err = tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
230	require.NoError(t, err)
231
232	log.Debug("block:0 batch:1")
233	l1UserTxs := []common.L1Tx{}
234	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
235	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
236	require.NoError(t, err)
237
238	log.Debug("block:0 batch:2")
239	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
240	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
241	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
242	require.NoError(t, err)
243	checkBalance(t, tc, sdb, "A", 0, "500")
244
245	log.Debug("block:0 batch:3")
246	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
247	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[3].L2Txs)
248	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, l2Txs)
249	require.NoError(t, err)
250	checkBalance(t, tc, sdb, "A", 0, "500")
251	checkBalance(t, tc, sdb, "A", 1, "500")
252
253	log.Debug("block:0 batch:4")
254	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
255	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[4].L2Txs)
256	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[4].L1CoordinatorTxs, l2Txs)
257	require.NoError(t, err)
258	checkBalance(t, tc, sdb, "A", 0, "500")
259	checkBalance(t, tc, sdb, "A", 1, "500")
260
261	log.Debug("block:0 batch:5")
262	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
263	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[5].L2Txs)
264	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[5].L1CoordinatorTxs, l2Txs)
265	require.NoError(t, err)
266	checkBalance(t, tc, sdb, "A", 0, "600")
267	checkBalance(t, tc, sdb, "A", 1, "500")
268	checkBalance(t, tc, sdb, "B", 0, "400")
269
270	log.Debug("block:0 batch:6")
271	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
272	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[6].L2Txs)
273	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[6].L1CoordinatorTxs, l2Txs)
274	require.NoError(t, err)
275	checkBalance(t, tc, sdb, "Coord", 0, "10")
276	checkBalance(t, tc, sdb, "Coord", 1, "20")
277	checkBalance(t, tc, sdb, "A", 0, "600")
278	checkBalance(t, tc, sdb, "A", 1, "280")
279	checkBalance(t, tc, sdb, "B", 0, "290")
280	checkBalance(t, tc, sdb, "B", 1, "200")
281	checkBalance(t, tc, sdb, "C", 0, "100")
282	checkBalance(t, tc, sdb, "D", 0, "800")
283
284	log.Debug("block:0 batch:7")
285	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
286	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[7].L2Txs)
287	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[7].L1CoordinatorTxs, l2Txs)
288	require.NoError(t, err)
289	checkBalance(t, tc, sdb, "Coord", 0, "35")
290	checkBalance(t, tc, sdb, "Coord", 1, "30")
291	checkBalance(t, tc, sdb, "A", 0, "430")
292	checkBalance(t, tc, sdb, "A", 1, "280")
293	checkBalance(t, tc, sdb, "B", 0, "390")
294	checkBalance(t, tc, sdb, "B", 1, "90")
295	checkBalance(t, tc, sdb, "C", 0, "45")
296	checkBalance(t, tc, sdb, "C", 1, "100")
297	checkBalance(t, tc, sdb, "D", 0, "800")
298
299	log.Debug("block:1 batch:0")
300	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
301	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
302	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
303	require.NoError(t, err)
304	checkBalance(t, tc, sdb, "Coord", 0, "75")
305	checkBalance(t, tc, sdb, "Coord", 1, "30")
306	checkBalance(t, tc, sdb, "A", 0, "730")
307	checkBalance(t, tc, sdb, "A", 1, "280")
308	checkBalance(t, tc, sdb, "B", 0, "380")
309	checkBalance(t, tc, sdb, "B", 1, "90")
310	checkBalance(t, tc, sdb, "C", 0, "845")
311	checkBalance(t, tc, sdb, "C", 1, "100")
312	checkBalance(t, tc, sdb, "D", 0, "470")
313
314	log.Debug("block:1 batch:1")
315	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
316	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
317	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
318	require.NoError(t, err)
319
320	// use Set of PoolL2 txs
321	poolL2Txs, err := tc.GeneratePoolL2Txs(til.SetPoolL2MinimumFlow1)
322	assert.NoError(t, err)
323
324	_, err = tp.ProcessTxs(coordIdxs, []common.L1Tx{}, []common.L1Tx{}, poolL2Txs)
325	require.NoError(t, err)
326	checkBalance(t, tc, sdb, "Coord", 0, "105")
327	checkBalance(t, tc, sdb, "Coord", 1, "40")
328	checkBalance(t, tc, sdb, "A", 0, "510")
329	checkBalance(t, tc, sdb, "A", 1, "170")
330	checkBalance(t, tc, sdb, "B", 0, "480")
331	checkBalance(t, tc, sdb, "B", 1, "190")
332	checkBalance(t, tc, sdb, "C", 0, "845")
333	checkBalance(t, tc, sdb, "C", 1, "100")
334	checkBalance(t, tc, sdb, "D", 0, "360")
335	checkBalance(t, tc, sdb, "F", 0, "100")
336}
337
338func TestProcessTxsSynchronizer(t *testing.T) {
339	dir, err := ioutil.TempDir("", "tmpdb")
340	require.NoError(t, err)
341	defer assert.NoError(t, os.RemoveAll(dir))
342
343	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeSynchronizer, 32)
344	assert.NoError(t, err)
345
346	chainID := uint16(0)
347	// generate test transactions from test.SetBlockchain0 code
348	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
349	blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
350	require.NoError(t, err)
351
352	assert.Equal(t, 31, len(blocks[0].Rollup.L1UserTxs))
353	assert.Equal(t, 4, len(blocks[0].Rollup.Batches[0].L1CoordinatorTxs))
354	assert.Equal(t, 0, len(blocks[0].Rollup.Batches[1].L1CoordinatorTxs))
355	assert.Equal(t, 22, len(blocks[0].Rollup.Batches[2].L2Txs))
356	assert.Equal(t, 1, len(blocks[1].Rollup.Batches[0].L1CoordinatorTxs))
357	assert.Equal(t, 62, len(blocks[1].Rollup.Batches[0].L2Txs))
358	assert.Equal(t, 1, len(blocks[1].Rollup.Batches[1].L1CoordinatorTxs))
359	assert.Equal(t, 8, len(blocks[1].Rollup.Batches[1].L2Txs))
360
361	// Coordinator Idx where to send the fees
362	coordIdxs := []common.Idx{256, 257, 258, 259}
363
364	// Idx of user 'A'
365	idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
366
367	config := Config{
368		NLevels:  32,
369		MaxFeeTx: 64,
370		MaxTx:    512,
371		MaxL1Tx:  32,
372		ChainID:  chainID,
373	}
374	tp := NewTxProcessor(sdb, config)
375
376	// Process the 1st batch, which contains the L1CoordinatorTxs necessary
377	// to create the Coordinator accounts to receive the fees
378	log.Debug("block:0 batch:0, only L1CoordinatorTxs")
379	ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
380	require.NoError(t, err)
381	assert.Equal(t, 4, len(ptOut.CreatedAccounts))
382	assert.Equal(t, 0, len(ptOut.CollectedFees))
383
384	log.Debug("block:0 batch:1")
385	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
386	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[0].Rollup.L1UserTxs,
387		blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
388	require.NoError(t, err)
389	assert.Equal(t, 0, len(ptOut.ExitInfos))
390	assert.Equal(t, 31, len(ptOut.CreatedAccounts))
391	assert.Equal(t, 4, len(ptOut.CollectedFees))
392	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
393	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
394	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
395	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
396	acc, err := sdb.GetAccount(idxA1)
397	require.NoError(t, err)
398	assert.Equal(t, "50", acc.Balance.String())
399
400	log.Debug("block:0 batch:2")
401	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
402	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
403	require.NoError(t, err)
404	assert.Equal(t, 0, len(ptOut.ExitInfos))
405	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
406	assert.Equal(t, 4, len(ptOut.CollectedFees))
407	assert.Equal(t, "2", ptOut.CollectedFees[common.TokenID(0)].String())
408	assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
409	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
410	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
411	acc, err = sdb.GetAccount(idxA1)
412	require.NoError(t, err)
413	assert.Equal(t, "35", acc.Balance.String())
414
415	log.Debug("block:1 batch:0")
416	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
417	// before processing expect l2Txs[0:2].Nonce==0
418	assert.Equal(t, common.Nonce(0), l2Txs[0].Nonce)
419	assert.Equal(t, common.Nonce(0), l2Txs[1].Nonce)
420	assert.Equal(t, common.Nonce(0), l2Txs[2].Nonce)
421
422	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
423	require.NoError(t, err)
424
425	// after processing expect l2Txs[0:2].Nonce!=0 and has expected value
426	assert.Equal(t, common.Nonce(5), l2Txs[0].Nonce)
427	assert.Equal(t, common.Nonce(6), l2Txs[1].Nonce)
428	assert.Equal(t, common.Nonce(7), l2Txs[2].Nonce)
429
430	assert.Equal(t, 4, len(ptOut.ExitInfos)) // the 'ForceExit(1)' is not computed yet, as the batch is without L1UserTxs
431	assert.Equal(t, 1, len(ptOut.CreatedAccounts))
432	assert.Equal(t, 4, len(ptOut.CollectedFees))
433	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
434	assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
435	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
436	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
437	acc, err = sdb.GetAccount(idxA1)
438	require.NoError(t, err)
439	assert.Equal(t, "57", acc.Balance.String())
440
441	log.Debug("block:1 batch:1")
442	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
443	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[1].Rollup.L1UserTxs,
444		blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
445	require.NoError(t, err)
446
447	assert.Equal(t, 2, len(ptOut.ExitInfos)) // 2, as previous batch was without L1UserTxs, and has pending the 'ForceExit(1) A: 5'
448	assert.Equal(t, 1, len(ptOut.CreatedAccounts))
449	assert.Equal(t, 4, len(ptOut.CollectedFees))
450	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
451	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
452	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
453	assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
454	acc, err = sdb.GetAccount(idxA1)
455	assert.NoError(t, err)
456	assert.Equal(t, "77", acc.Balance.String())
457
458	idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
459	acc, err = sdb.GetAccount(idxB0)
460	require.NoError(t, err)
461	assert.Equal(t, "51", acc.Balance.String())
462
463	// get balance of Coordinator account for TokenID==0
464	acc, err = sdb.GetAccount(common.Idx(256))
465	require.NoError(t, err)
466	assert.Equal(t, "2", acc.Balance.String())
467}
468
469func TestProcessTxsBatchBuilder(t *testing.T) {
470	dir, err := ioutil.TempDir("", "tmpdb")
471	require.NoError(t, err)
472	defer assert.NoError(t, os.RemoveAll(dir))
473
474	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeBatchBuilder, 32)
475	assert.NoError(t, err)
476
477	chainID := uint16(0)
478	// generate test transactions from test.SetBlockchain0 code
479	tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
480	blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
481	require.NoError(t, err)
482
483	// Coordinator Idx where to send the fees
484	coordIdxs := []common.Idx{256, 257, 258, 259}
485
486	// Idx of user 'A'
487	idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
488
489	config := Config{
490		NLevels:  32,
491		MaxFeeTx: 64,
492		MaxTx:    512,
493		MaxL1Tx:  32,
494		ChainID:  chainID,
495	}
496	tp := NewTxProcessor(sdb, config)
497
498	// Process the 1st batch, which contains the L1CoordinatorTxs necessary
499	// to create the Coordinator accounts to receive the fees
500	log.Debug("block:0 batch:0, only L1CoordinatorTxs")
501	ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
502	require.NoError(t, err)
503	// expect 0 at CreatedAccount, as is only computed when StateDB.Type==TypeSynchronizer
504	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
505
506	log.Debug("block:0 batch:1")
507	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
508	ptOut, err = tp.ProcessTxs(coordIdxs, blocks[0].Rollup.L1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
509	require.NoError(t, err)
510	assert.Equal(t, 0, len(ptOut.ExitInfos))
511	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
512	acc, err := sdb.GetAccount(idxA1)
513	require.NoError(t, err)
514	assert.Equal(t, "50", acc.Balance.String())
515
516	log.Debug("block:0 batch:2")
517	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
518	ptOut, err = tp.ProcessTxs(coordIdxs, nil, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
519	require.NoError(t, err)
520	assert.Equal(t, 0, len(ptOut.ExitInfos))
521	assert.Equal(t, 0, len(ptOut.CreatedAccounts))
522	acc, err = sdb.GetAccount(idxA1)
523	require.NoError(t, err)
524	assert.Equal(t, "35", acc.Balance.String())
525
526	log.Debug("block:1 batch:0")
527	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
528	_, err = tp.ProcessTxs(coordIdxs, nil, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
529	require.NoError(t, err)
530	acc, err = sdb.GetAccount(idxA1)
531	require.NoError(t, err)
532	assert.Equal(t, "57", acc.Balance.String())
533
534	log.Debug("block:1 batch:1")
535	l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
536	_, err = tp.ProcessTxs(coordIdxs, blocks[1].Rollup.L1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
537	require.NoError(t, err)
538	acc, err = sdb.GetAccount(idxA1)
539	assert.NoError(t, err)
540	assert.Equal(t, "77", acc.Balance.String())
541
542	idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
543	acc, err = sdb.GetAccount(idxB0)
544	require.NoError(t, err)
545	assert.Equal(t, "51", acc.Balance.String())
546
547	// get balance of Coordinator account for TokenID==0
548	acc, err = sdb.GetAccount(common.Idx(256))
549	require.NoError(t, err)
550	assert.Equal(t, common.TokenID(0), acc.TokenID)
551	assert.Equal(t, "2", acc.Balance.String())
552	acc, err = sdb.GetAccount(common.Idx(257))
553	require.NoError(t, err)
554	assert.Equal(t, common.TokenID(1), acc.TokenID)
555	assert.Equal(t, "2", acc.Balance.String())
556
557	assert.Equal(t, "2720257526434001367979405991743527513807903085728407823609738212616896104498", sdb.MT.Root().BigInt().String())
558}
559
560func TestProcessTxsRootTestVectors(t *testing.T) {
561	dir, err := ioutil.TempDir("", "tmpdb")
562	require.NoError(t, err)
563	defer assert.NoError(t, os.RemoveAll(dir))
564
565	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeBatchBuilder, 32)
566	assert.NoError(t, err)
567
568	// same values than in the js test
569	bjj0, err := common.BJJFromStringWithChecksum("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7")
570	assert.NoError(t, err)
571	l1Txs := []common.L1Tx{
572		{
573			FromIdx:       0,
574			DepositAmount: big.NewInt(16000000),
575			Amount:        big.NewInt(0),
576			TokenID:       1,
577			FromBJJ:       bjj0,
578			FromEthAddr:   ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"),
579			ToIdx:         0,
580			Type:          common.TxTypeCreateAccountDeposit,
581			UserOrigin:    true,
582		},
583	}
584	l2Txs := []common.PoolL2Tx{
585		{
586			FromIdx: 256,
587			ToIdx:   256,
588			TokenID: 1,
589			Amount:  big.NewInt(1000),
590			Nonce:   0,
591			Fee:     126,
592			Type:    common.TxTypeTransfer,
593		},
594	}
595
596	chainID := uint16(0)
597	config := Config{
598		NLevels:  32,
599		MaxFeeTx: 8,
600		MaxTx:    32,
601		MaxL1Tx:  16,
602		ChainID:  chainID,
603	}
604	tp := NewTxProcessor(sdb, config)
605	_, err = tp.ProcessTxs(nil, l1Txs, nil, l2Txs)
606	require.NoError(t, err)
607	assert.Equal(t, "9827704113668630072730115158977131501210702363656902211840117643154933433410", sdb.MT.Root().BigInt().String())
608}
609
610func TestCreateAccountDepositMaxValue(t *testing.T) {
611	dir, err := ioutil.TempDir("", "tmpdb")
612	require.NoError(t, err)
613	defer assert.NoError(t, os.RemoveAll(dir))
614
615	nLevels := 16
616	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeBatchBuilder, nLevels)
617	assert.NoError(t, err)
618
619	users := generateJsUsers(t)
620
621	daMaxHex, err := hex.DecodeString("FFFF")
622	require.NoError(t, err)
623	daMaxF16 := common.Float16(binary.BigEndian.Uint16(daMaxHex))
624	daMaxBI := daMaxF16.BigInt()
625	assert.Equal(t, "10235000000000000000000000000000000", daMaxBI.String())
626
627	daMax1Hex, err := hex.DecodeString("FFFE")
628	require.NoError(t, err)
629	daMax1F16 := common.Float16(binary.BigEndian.Uint16(daMax1Hex))
630	daMax1BI := daMax1F16.BigInt()
631	assert.Equal(t, "10225000000000000000000000000000000", daMax1BI.String())
632
633	l1Txs := []common.L1Tx{
634		{
635			FromIdx:       0,
636			DepositAmount: daMaxBI,
637			Amount:        big.NewInt(0),
638			TokenID:       1,
639			FromBJJ:       users[0].BJJ.Public().Compress(),
640			FromEthAddr:   users[0].Addr,
641			ToIdx:         0,
642			Type:          common.TxTypeCreateAccountDeposit,
643			UserOrigin:    true,
644		},
645		{
646			FromIdx:       0,
647			DepositAmount: daMax1BI,
648			Amount:        big.NewInt(0),
649			TokenID:       1,
650			FromBJJ:       users[1].BJJ.Public().Compress(),
651			FromEthAddr:   users[1].Addr,
652			ToIdx:         0,
653			Type:          common.TxTypeCreateAccountDeposit,
654			UserOrigin:    true,
655		},
656	}
657
658	chainID := uint16(0)
659	config := Config{
660		NLevels:  uint32(nLevels),
661		MaxTx:    3,
662		MaxL1Tx:  2,
663		MaxFeeTx: 2,
664		ChainID:  chainID,
665	}
666	tp := NewTxProcessor(sdb, config)
667
668	_, err = tp.ProcessTxs(nil, l1Txs, nil, nil)
669	require.NoError(t, err)
670
671	// check balances
672	acc, err := sdb.GetAccount(common.Idx(256))
673	require.NoError(t, err)
674	assert.Equal(t, daMaxBI, acc.Balance)
675	acc, err = sdb.GetAccount(common.Idx(257))
676	require.NoError(t, err)
677	assert.Equal(t, daMax1BI, acc.Balance)
678}