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