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