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