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}