hermez-node/db/statedb/txprocessors_test.go
db/statedb/txprocessors_test.goRaw
1package statedb
2
3import (
4 "encoding/json"
5 "fmt"
6 "io/ioutil"
7 "os"
8 "testing"
9
10 "github.com/hermeznetwork/hermez-node/common"
11 "github.com/hermeznetwork/hermez-node/eth"
12 "github.com/hermeznetwork/hermez-node/log"
13 "github.com/hermeznetwork/hermez-node/test/til"
14 "github.com/stretchr/testify/assert"
15 "github.com/stretchr/testify/require"
16)
17
18func checkBalance(t *testing.T, tc *til.Context, sdb *StateDB, username string, tokenid int, expected string) {
19 idx := tc.Users[username].Accounts[common.TokenID(tokenid)].Idx
20 acc, err := sdb.GetAccount(idx)
21 require.Nil(t, err)
22 assert.Equal(t, expected, acc.Balance.String())
23}
24
25func TestProcessTxsBalances(t *testing.T) {
26 dir, err := ioutil.TempDir("", "tmpdb")
27 require.Nil(t, err)
28 defer assert.Nil(t, os.RemoveAll(dir))
29
30 sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
31 assert.Nil(t, err)
32
33 // generate test transactions from test.SetBlockchain0 code
34 tc := til.NewContext(eth.RollupConstMaxL1UserTx)
35 blocks, err := tc.GenerateBlocks(til.SetBlockchainMinimumFlow0)
36 require.Nil(t, err)
37
38 // Coordinator Idx where to send the fees
39 coordIdxs := []common.Idx{256, 257}
40
41 log.Debug("block:0 batch:0, only L1CoordinatorTxs")
42 _, err = sdb.ProcessTxs(nil, nil, blocks[0].Batches[0].L1CoordinatorTxs, nil)
43 require.Nil(t, err)
44
45 log.Debug("block:0 batch:1")
46 l1UserTxs := []common.L1Tx{}
47 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs)
48 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
49 require.Nil(t, err)
50
51 log.Debug("block:0 batch:2")
52 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[2].Batch.ForgeL1TxsNum])
53 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[2].L2Txs)
54 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[2].L1CoordinatorTxs, l2Txs)
55 require.Nil(t, err)
56 checkBalance(t, tc, sdb, "A", 0, "500")
57
58 log.Debug("block:0 batch:3")
59 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[3].Batch.ForgeL1TxsNum])
60 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[3].L2Txs)
61 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[3].L1CoordinatorTxs, l2Txs)
62 require.Nil(t, err)
63 checkBalance(t, tc, sdb, "A", 0, "500")
64 checkBalance(t, tc, sdb, "A", 1, "500")
65
66 log.Debug("block:0 batch:4")
67 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[4].Batch.ForgeL1TxsNum])
68 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[4].L2Txs)
69 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[4].L1CoordinatorTxs, l2Txs)
70 require.Nil(t, err)
71 checkBalance(t, tc, sdb, "A", 0, "500")
72 checkBalance(t, tc, sdb, "A", 1, "500")
73
74 log.Debug("block:0 batch:5")
75 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[5].Batch.ForgeL1TxsNum])
76 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[5].L2Txs)
77 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[5].L1CoordinatorTxs, l2Txs)
78 require.Nil(t, err)
79 checkBalance(t, tc, sdb, "A", 0, "600")
80 checkBalance(t, tc, sdb, "A", 1, "500")
81 checkBalance(t, tc, sdb, "B", 0, "400")
82
83 log.Debug("block:0 batch:6")
84 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[6].Batch.ForgeL1TxsNum])
85 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[6].L2Txs)
86 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[6].L1CoordinatorTxs, l2Txs)
87 require.Nil(t, err)
88 checkBalance(t, tc, sdb, "Coord", 0, "10")
89 checkBalance(t, tc, sdb, "Coord", 1, "20")
90 checkBalance(t, tc, sdb, "A", 0, "600")
91 checkBalance(t, tc, sdb, "A", 1, "280")
92 checkBalance(t, tc, sdb, "B", 0, "290")
93 checkBalance(t, tc, sdb, "B", 1, "200")
94 checkBalance(t, tc, sdb, "C", 0, "100")
95 checkBalance(t, tc, sdb, "D", 0, "800")
96
97 log.Debug("block:0 batch:7")
98 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[7].Batch.ForgeL1TxsNum])
99 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[7].L2Txs)
100 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[7].L1CoordinatorTxs, l2Txs)
101 require.Nil(t, err)
102 checkBalance(t, tc, sdb, "Coord", 0, "35")
103 checkBalance(t, tc, sdb, "Coord", 1, "30")
104 checkBalance(t, tc, sdb, "A", 0, "430")
105 checkBalance(t, tc, sdb, "A", 1, "280")
106 checkBalance(t, tc, sdb, "B", 0, "390")
107 checkBalance(t, tc, sdb, "B", 1, "90")
108 checkBalance(t, tc, sdb, "C", 0, "45")
109 checkBalance(t, tc, sdb, "C", 1, "100")
110 checkBalance(t, tc, sdb, "D", 0, "800")
111
112 log.Debug("block:1 batch:0")
113 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Batches[0].Batch.ForgeL1TxsNum])
114 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[0].L2Txs)
115 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Batches[0].L1CoordinatorTxs, l2Txs)
116 require.Nil(t, err)
117 checkBalance(t, tc, sdb, "Coord", 0, "75")
118 checkBalance(t, tc, sdb, "Coord", 1, "30")
119 checkBalance(t, tc, sdb, "A", 0, "730")
120 checkBalance(t, tc, sdb, "A", 1, "280")
121 checkBalance(t, tc, sdb, "B", 0, "380")
122 checkBalance(t, tc, sdb, "B", 1, "90")
123 checkBalance(t, tc, sdb, "C", 0, "845")
124 checkBalance(t, tc, sdb, "C", 1, "100")
125 checkBalance(t, tc, sdb, "D", 0, "470")
126
127 log.Debug("block:1 batch:1")
128 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Batches[1].Batch.ForgeL1TxsNum])
129 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[1].L2Txs)
130 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Batches[1].L1CoordinatorTxs, l2Txs)
131 require.Nil(t, err)
132
133 // use Set of PoolL2 txs
134 poolL2Txs, err := tc.GeneratePoolL2Txs(til.SetPoolL2MinimumFlow0)
135 assert.Nil(t, err)
136
137 _, err = sdb.ProcessTxs(coordIdxs, []common.L1Tx{}, []common.L1Tx{}, poolL2Txs)
138 require.Nil(t, err)
139 checkBalance(t, tc, sdb, "Coord", 0, "105")
140 checkBalance(t, tc, sdb, "Coord", 1, "40")
141 checkBalance(t, tc, sdb, "A", 0, "510")
142 checkBalance(t, tc, sdb, "A", 1, "170")
143 checkBalance(t, tc, sdb, "B", 0, "480")
144 checkBalance(t, tc, sdb, "B", 1, "190")
145 checkBalance(t, tc, sdb, "C", 0, "845")
146 checkBalance(t, tc, sdb, "C", 1, "100")
147 checkBalance(t, tc, sdb, "D", 0, "360")
148 checkBalance(t, tc, sdb, "F", 0, "100")
149}
150
151func TestProcessTxsSynchronizer(t *testing.T) {
152 dir, err := ioutil.TempDir("", "tmpdb")
153 require.Nil(t, err)
154 defer assert.Nil(t, os.RemoveAll(dir))
155
156 sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
157 assert.Nil(t, err)
158
159 // generate test transactions from test.SetBlockchain0 code
160 tc := til.NewContext(eth.RollupConstMaxL1UserTx)
161 blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
162 require.Nil(t, err)
163
164 assert.Equal(t, 31, len(blocks[0].L1UserTxs))
165 assert.Equal(t, 4, len(blocks[0].Batches[0].L1CoordinatorTxs))
166 assert.Equal(t, 0, len(blocks[0].Batches[1].L1CoordinatorTxs))
167 assert.Equal(t, 22, len(blocks[0].Batches[2].L2Txs))
168 assert.Equal(t, 1, len(blocks[1].Batches[0].L1CoordinatorTxs))
169 assert.Equal(t, 62, len(blocks[1].Batches[0].L2Txs))
170 assert.Equal(t, 1, len(blocks[1].Batches[1].L1CoordinatorTxs))
171 assert.Equal(t, 8, len(blocks[1].Batches[1].L2Txs))
172
173 // Coordinator Idx where to send the fees
174 coordIdxs := []common.Idx{256, 257, 258, 259}
175
176 // Idx of user 'A'
177 idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
178
179 // Process the 1st batch, which contains the L1CoordinatorTxs necessary
180 // to create the Coordinator accounts to receive the fees
181 log.Debug("block:0 batch:0, only L1CoordinatorTxs")
182 ptOut, err := sdb.ProcessTxs(nil, nil, blocks[0].Batches[0].L1CoordinatorTxs, nil)
183 require.Nil(t, err)
184 assert.Equal(t, 4, len(ptOut.CreatedAccounts))
185 assert.Equal(t, 0, len(ptOut.CollectedFees))
186
187 log.Debug("block:0 batch:1")
188 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs)
189 ptOut, err = sdb.ProcessTxs(coordIdxs, blocks[0].L1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
190 require.Nil(t, err)
191 assert.Equal(t, 0, len(ptOut.ExitInfos))
192 assert.Equal(t, 31, len(ptOut.CreatedAccounts))
193 assert.Equal(t, 4, len(ptOut.CollectedFees))
194 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
195 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
196 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
197 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
198 acc, err := sdb.GetAccount(idxA1)
199 require.Nil(t, err)
200 assert.Equal(t, "50", acc.Balance.String())
201
202 log.Debug("block:0 batch:2")
203 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[2].L2Txs)
204 ptOut, err = sdb.ProcessTxs(coordIdxs, nil, blocks[0].Batches[2].L1CoordinatorTxs, l2Txs)
205 require.Nil(t, err)
206 assert.Equal(t, 0, len(ptOut.ExitInfos))
207 assert.Equal(t, 0, len(ptOut.CreatedAccounts))
208 assert.Equal(t, 4, len(ptOut.CollectedFees))
209 assert.Equal(t, "2", ptOut.CollectedFees[common.TokenID(0)].String())
210 assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
211 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
212 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
213 acc, err = sdb.GetAccount(idxA1)
214 require.Nil(t, err)
215 assert.Equal(t, "35", acc.Balance.String())
216
217 log.Debug("block:1 batch:0")
218 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[0].L2Txs)
219 // before processing expect l2Txs[0:2].Nonce==0
220 assert.Equal(t, common.Nonce(0), l2Txs[0].Nonce)
221 assert.Equal(t, common.Nonce(0), l2Txs[1].Nonce)
222 assert.Equal(t, common.Nonce(0), l2Txs[2].Nonce)
223
224 ptOut, err = sdb.ProcessTxs(coordIdxs, nil, blocks[1].Batches[0].L1CoordinatorTxs, l2Txs)
225 require.Nil(t, err)
226
227 // after processing expect l2Txs[0:2].Nonce!=0 and has expected value
228 assert.Equal(t, common.Nonce(6), l2Txs[0].Nonce)
229 assert.Equal(t, common.Nonce(7), l2Txs[1].Nonce)
230 assert.Equal(t, common.Nonce(8), l2Txs[2].Nonce)
231
232 assert.Equal(t, 4, len(ptOut.ExitInfos)) // the 'ForceExit(1)' is not computed yet, as the batch is without L1UserTxs
233 assert.Equal(t, 1, len(ptOut.CreatedAccounts))
234 assert.Equal(t, 4, len(ptOut.CollectedFees))
235 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
236 assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
237 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
238 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
239 acc, err = sdb.GetAccount(idxA1)
240 require.Nil(t, err)
241 assert.Equal(t, "57", acc.Balance.String())
242
243 log.Debug("block:1 batch:1")
244 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[1].L2Txs)
245 ptOut, err = sdb.ProcessTxs(coordIdxs, blocks[1].L1UserTxs, blocks[1].Batches[1].L1CoordinatorTxs, l2Txs)
246 require.Nil(t, err)
247
248 assert.Equal(t, 2, len(ptOut.ExitInfos)) // 2, as previous batch was without L1UserTxs, and has pending the 'ForceExit(1) A: 5'
249 assert.Equal(t, 1, len(ptOut.CreatedAccounts))
250 assert.Equal(t, 4, len(ptOut.CollectedFees))
251 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
252 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
253 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
254 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
255 acc, err = sdb.GetAccount(idxA1)
256 assert.Nil(t, err)
257 assert.Equal(t, "77", acc.Balance.String())
258
259 idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
260 acc, err = sdb.GetAccount(idxB0)
261 require.Nil(t, err)
262 assert.Equal(t, "51", acc.Balance.String())
263
264 // get balance of Coordinator account for TokenID==0
265 acc, err = sdb.GetAccount(common.Idx(256))
266 require.Nil(t, err)
267 assert.Equal(t, "2", acc.Balance.String())
268}
269
270func TestProcessTxsBatchBuilder(t *testing.T) {
271 dir, err := ioutil.TempDir("", "tmpdb")
272 require.Nil(t, err)
273 defer assert.Nil(t, os.RemoveAll(dir))
274
275 sdb, err := NewStateDB(dir, TypeBatchBuilder, 32)
276 assert.Nil(t, err)
277
278 // generate test transactions from test.SetBlockchain0 code
279 tc := til.NewContext(eth.RollupConstMaxL1UserTx)
280 blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
281 require.Nil(t, err)
282
283 // Coordinator Idx where to send the fees
284 coordIdxs := []common.Idx{256, 257, 258, 259}
285
286 // Idx of user 'A'
287 idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
288
289 // Process the 1st batch, which contains the L1CoordinatorTxs necessary
290 // to create the Coordinator accounts to receive the fees
291 log.Debug("block:0 batch:0, only L1CoordinatorTxs")
292 ptOut, err := sdb.ProcessTxs(nil, nil, blocks[0].Batches[0].L1CoordinatorTxs, nil)
293 require.Nil(t, err)
294 // expect 0 at CreatedAccount, as is only computed when StateDB.Type==TypeSynchronizer
295 assert.Equal(t, 0, len(ptOut.CreatedAccounts))
296
297 log.Debug("block:0 batch:1")
298 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs)
299 ptOut, err = sdb.ProcessTxs(coordIdxs, blocks[0].L1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
300 require.Nil(t, err)
301 assert.Equal(t, 0, len(ptOut.ExitInfos))
302 assert.Equal(t, 0, len(ptOut.CreatedAccounts))
303 acc, err := sdb.GetAccount(idxA1)
304 require.Nil(t, err)
305 assert.Equal(t, "50", acc.Balance.String())
306
307 log.Debug("block:0 batch:2")
308 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[2].L2Txs)
309 ptOut, err = sdb.ProcessTxs(coordIdxs, nil, blocks[0].Batches[2].L1CoordinatorTxs, l2Txs)
310 require.Nil(t, err)
311 assert.Equal(t, 0, len(ptOut.ExitInfos))
312 assert.Equal(t, 0, len(ptOut.CreatedAccounts))
313 acc, err = sdb.GetAccount(idxA1)
314 require.Nil(t, err)
315 assert.Equal(t, "35", acc.Balance.String())
316
317 log.Debug("block:1 batch:0")
318 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[0].L2Txs)
319 _, err = sdb.ProcessTxs(coordIdxs, nil, blocks[1].Batches[0].L1CoordinatorTxs, l2Txs)
320 require.Nil(t, err)
321 acc, err = sdb.GetAccount(idxA1)
322 require.Nil(t, err)
323 assert.Equal(t, "57", acc.Balance.String())
324
325 log.Debug("block:1 batch:1")
326 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[1].L2Txs)
327 _, err = sdb.ProcessTxs(coordIdxs, blocks[1].L1UserTxs, blocks[1].Batches[1].L1CoordinatorTxs, l2Txs)
328 require.Nil(t, err)
329 acc, err = sdb.GetAccount(idxA1)
330 assert.Nil(t, err)
331 assert.Equal(t, "77", acc.Balance.String())
332
333 idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
334 acc, err = sdb.GetAccount(idxB0)
335 require.Nil(t, err)
336 assert.Equal(t, "51", acc.Balance.String())
337
338 // get balance of Coordinator account for TokenID==0
339 acc, err = sdb.GetAccount(common.Idx(256))
340 require.Nil(t, err)
341 assert.Equal(t, common.TokenID(0), acc.TokenID)
342 assert.Equal(t, "2", acc.Balance.String())
343 acc, err = sdb.GetAccount(common.Idx(257))
344 require.Nil(t, err)
345 assert.Equal(t, common.TokenID(1), acc.TokenID)
346 assert.Equal(t, "2", acc.Balance.String())
347}
348
349func TestZKInputsGeneration(t *testing.T) {
350 dir, err := ioutil.TempDir("", "tmpdb")
351 require.Nil(t, err)
352 defer assert.Nil(t, os.RemoveAll(dir))
353
354 sdb, err := NewStateDB(dir, TypeBatchBuilder, 32)
355 assert.Nil(t, err)
356
357 // generate test transactions from test.SetBlockchain0 code
358 tc := til.NewContext(eth.RollupConstMaxL1UserTx)
359 blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
360 require.Nil(t, err)
361
362 // Coordinator Idx where to send the fees
363 coordIdxs := []common.Idx{256, 257, 258, 259}
364
365 log.Debug("block:0 batch:0, only L1CoordinatorTxs")
366 _, err = sdb.ProcessTxs(nil, nil, blocks[0].Batches[0].L1CoordinatorTxs, nil)
367 require.Nil(t, err)
368
369 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs)
370 ptOut, err := sdb.ProcessTxs(coordIdxs, blocks[0].L1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
371 require.Nil(t, err)
372
373 s, err := json.Marshal(ptOut.ZKInputs)
374 require.Nil(t, err)
375 debug := false
376 if debug {
377 fmt.Println(string(s))
378 }
379}