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