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