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