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