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}