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