hermez-node/test/historydb.go
test/historydb.goRaw
1package test
2
3import (
4 "errors"
5 "fmt"
6 "math/big"
7 "strconv"
8 "time"
9
10 ethCommon "github.com/ethereum/go-ethereum/common"
11 "github.com/hermeznetwork/hermez-node/common"
12 "github.com/iden3/go-iden3-crypto/babyjub"
13 "github.com/iden3/go-merkletree"
14)
15
16// WARNING: the generators in this file doesn't necessary follow the protocol
17// they are intended to check that the parsers between struct <==> DB are correct
18
19// GenBlocks generates block from, to block numbers. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
20func GenBlocks(from, to int64) []common.Block {
21 var blocks []common.Block
22 for i := from; i < to; i++ {
23 blocks = append(blocks, common.Block{
24 EthBlockNum: i,
25 //nolint:gomnd
26 Timestamp: time.Now().Add(time.Second * 13).UTC(),
27 Hash: ethCommon.BigToHash(big.NewInt(int64(i))),
28 })
29 }
30 return blocks
31}
32
33// GenTokens generates tokens. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
34func GenTokens(nTokens int, blocks []common.Block) []common.Token {
35 tokens := []common.Token{}
36 for i := 0; i < nTokens; i++ {
37 token := common.Token{
38 TokenID: common.TokenID(i),
39 Name: fmt.Sprint(i),
40 Symbol: fmt.Sprint(i),
41 Decimals: uint64(i),
42 EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
43 EthAddr: ethCommon.BigToAddress(big.NewInt(int64(i))),
44 }
45 if i%2 == 0 {
46 token.USD = 3
47 token.USDUpdate = time.Now()
48 }
49 tokens = append(tokens, token)
50 }
51 return tokens
52}
53
54// GenBatches generates batches. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
55func GenBatches(nBatches int, blocks []common.Block) []common.Batch {
56 batches := []common.Batch{}
57 collectedFees := make(map[common.TokenID]*big.Int)
58 for i := 0; i < 64; i++ {
59 collectedFees[common.TokenID(i)] = big.NewInt(int64(i))
60 }
61 for i := 0; i < nBatches; i++ {
62 batch := common.Batch{
63 BatchNum: common.BatchNum(i + 1),
64 EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
65 //nolint:gomnd
66 ForgerAddr: ethCommon.BigToAddress(big.NewInt(6886723)),
67 CollectedFees: collectedFees,
68 StateRoot: common.Hash([]byte("duhdqlwiucgwqeiu")),
69 //nolint:gomnd
70 NumAccounts: 30,
71 ExitRoot: common.Hash([]byte("tykertheuhtgenuer3iuw3b")),
72 SlotNum: common.SlotNum(i),
73 }
74 if i%2 == 0 {
75 batch.ForgeL1TxsNum = int64(i)
76 }
77 batches = append(batches, batch)
78 }
79 return batches
80}
81
82// GenAccounts generates accounts. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
83func GenAccounts(totalAccounts, userAccounts int, tokens []common.Token, userAddr *ethCommon.Address, userBjj *babyjub.PublicKey, batches []common.Batch) []common.Account {
84 if totalAccounts < userAccounts {
85 panic("totalAccounts must be greater than userAccounts")
86 }
87 accs := []common.Account{}
88 for i := 0; i < totalAccounts; i++ {
89 var addr ethCommon.Address
90 var pubK *babyjub.PublicKey
91 if i < userAccounts {
92 addr = *userAddr
93 pubK = userBjj
94 } else {
95 addr = ethCommon.BigToAddress(big.NewInt(int64(i)))
96 privK := babyjub.NewRandPrivKey()
97 pubK = privK.Public()
98 }
99 accs = append(accs, common.Account{
100 Idx: common.Idx(i),
101 TokenID: tokens[i%len(tokens)].TokenID,
102 EthAddr: addr,
103 BatchNum: batches[i%len(batches)].BatchNum,
104 PublicKey: pubK,
105 })
106 }
107 return accs
108}
109
110// GenL1Txs generates L1 txs. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
111func GenL1Txs(
112 fromIdx int,
113 totalTxs, nUserTxs int,
114 userAddr *ethCommon.Address,
115 accounts []common.Account,
116 tokens []common.Token,
117 blocks []common.Block,
118 batches []common.Batch,
119) ([]common.L1Tx, []common.L1Tx) {
120 if totalTxs < nUserTxs {
121 panic("totalTxs must be greater than userTxs")
122 }
123 userTxs := []common.L1Tx{}
124 othersTxs := []common.L1Tx{}
125 for i := 0; i < totalTxs; i++ {
126 var tx common.L1Tx
127 if batches[i%len(batches)].ForgeL1TxsNum != 0 {
128 tx = common.L1Tx{
129 TxID: common.TxID(common.Hash([]byte("L1_" + strconv.Itoa(fromIdx+i)))),
130 ToForgeL1TxsNum: batches[i%len(batches)].ForgeL1TxsNum,
131 Position: i,
132 UserOrigin: i%2 == 0,
133 TokenID: tokens[i%len(tokens)].TokenID,
134 Amount: big.NewInt(int64(i + 1)),
135 LoadAmount: big.NewInt(int64(i + 1)),
136 EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
137 Type: randomTxType(i),
138 }
139 if i%4 == 0 {
140 tx.BatchNum = batches[i%len(batches)].BatchNum
141 }
142 } else {
143 continue
144 }
145 if i < nUserTxs {
146 var from, to *common.Account
147 var err error
148 if i%2 == 0 {
149 from, err = randomAccount(i, true, userAddr, accounts)
150 if err != nil {
151 panic(err)
152 }
153 to, err = randomAccount(i, false, userAddr, accounts)
154 if err != nil {
155 panic(err)
156 }
157 } else {
158 from, err = randomAccount(i, false, userAddr, accounts)
159 if err != nil {
160 panic(err)
161 }
162 to, err = randomAccount(i, true, userAddr, accounts)
163 if err != nil {
164 panic(err)
165 }
166 }
167 tx.FromIdx = from.Idx
168 tx.FromEthAddr = from.EthAddr
169 tx.FromBJJ = from.PublicKey
170 tx.ToIdx = to.Idx
171 userTxs = append(userTxs, tx)
172 } else {
173 from, err := randomAccount(i, false, userAddr, accounts)
174 if err != nil {
175 panic(err)
176 }
177 to, err := randomAccount(i, false, userAddr, accounts)
178 if err != nil {
179 panic(err)
180 }
181 tx.FromIdx = from.Idx
182 tx.FromEthAddr = from.EthAddr
183 tx.FromBJJ = from.PublicKey
184 tx.ToIdx = to.Idx
185 othersTxs = append(othersTxs, tx)
186 }
187 }
188 return userTxs, othersTxs
189}
190
191// GenL2Txs generates L2 txs. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
192func GenL2Txs(
193 fromIdx int,
194 totalTxs, nUserTxs int,
195 userAddr *ethCommon.Address,
196 accounts []common.Account,
197 tokens []common.Token,
198 blocks []common.Block,
199 batches []common.Batch,
200) ([]common.L2Tx, []common.L2Tx) {
201 if totalTxs < nUserTxs {
202 panic("totalTxs must be greater than userTxs")
203 }
204 userTxs := []common.L2Tx{}
205 othersTxs := []common.L2Tx{}
206 for i := 0; i < totalTxs; i++ {
207 tx := common.L2Tx{
208 TxID: common.TxID(common.Hash([]byte("L2_" + strconv.Itoa(fromIdx+i)))),
209 BatchNum: batches[i%len(batches)].BatchNum,
210 Position: i,
211 //nolint:gomnd
212 Amount: big.NewInt(int64(i + 1)),
213 //nolint:gomnd
214 Fee: common.FeeSelector(i % 256),
215 Nonce: common.Nonce(i + 1),
216 EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
217 Type: randomTxType(i),
218 }
219 if i < nUserTxs {
220 var from, to *common.Account
221 var err error
222 if i%2 == 0 {
223 from, err = randomAccount(i, true, userAddr, accounts)
224 if err != nil {
225 panic(err)
226 }
227 to, err = randomAccount(i, false, userAddr, accounts)
228 if err != nil {
229 panic(err)
230 }
231 } else {
232 from, err = randomAccount(i, false, userAddr, accounts)
233 if err != nil {
234 panic(err)
235 }
236 to, err = randomAccount(i, true, userAddr, accounts)
237 if err != nil {
238 panic(err)
239 }
240 }
241 tx.FromIdx = from.Idx
242 tx.ToIdx = to.Idx
243 userTxs = append(userTxs, tx)
244 } else {
245 from, err := randomAccount(i, false, userAddr, accounts)
246 if err != nil {
247 panic(err)
248 }
249 to, err := randomAccount(i, false, userAddr, accounts)
250 if err != nil {
251 panic(err)
252 }
253 tx.FromIdx = from.Idx
254 tx.ToIdx = to.Idx
255 othersTxs = append(othersTxs, tx)
256 }
257 }
258 return userTxs, othersTxs
259}
260
261// GenCoordinators generates coordinators. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
262func GenCoordinators(nCoords int, blocks []common.Block) []common.Coordinator {
263 coords := []common.Coordinator{}
264 for i := 0; i < nCoords; i++ {
265 coords = append(coords, common.Coordinator{
266 EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
267 Forger: ethCommon.BigToAddress(big.NewInt(int64(i))),
268 WithdrawAddr: ethCommon.BigToAddress(big.NewInt(int64(i))),
269 URL: "https://foo.bar",
270 })
271 }
272 return coords
273}
274
275// GenBids generates bids. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
276func GenBids(nBids int, blocks []common.Block, coords []common.Coordinator) []common.Bid {
277 bids := []common.Bid{}
278 for i := 0; i < nBids; i++ {
279 bids = append(bids, common.Bid{
280 SlotNum: common.SlotNum(i),
281 BidValue: big.NewInt(int64(i)),
282 EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
283 ForgerAddr: coords[i%len(blocks)].Forger,
284 })
285 }
286 return bids
287}
288
289// GenExitTree generates an exitTree (as an array of Exits)
290//nolint:gomnd
291func GenExitTree(n int) []common.ExitInfo {
292 exitTree := make([]common.ExitInfo, n)
293 for i := 0; i < n; i++ {
294 exitTree[i] = common.ExitInfo{
295 BatchNum: common.BatchNum(i + 1),
296 InstantWithdrawn: nil,
297 DelayedWithdrawRequest: nil,
298 DelayedWithdrawn: nil,
299 AccountIdx: common.Idx(i * 10),
300 MerkleProof: &merkletree.CircomVerifierProof{
301 Root: &merkletree.Hash{byte(i), byte(i + 1)},
302 Siblings: []*big.Int{
303 big.NewInt(int64(i) * 10),
304 big.NewInt(int64(i)*100 + 1),
305 big.NewInt(int64(i)*1000 + 2)},
306 OldKey: &merkletree.Hash{byte(i * 1), byte(i*1 + 1)},
307 OldValue: &merkletree.Hash{byte(i * 2), byte(i*2 + 1)},
308 IsOld0: i%2 == 0,
309 Key: &merkletree.Hash{byte(i * 3), byte(i*3 + 1)},
310 Value: &merkletree.Hash{byte(i * 4), byte(i*4 + 1)},
311 Fnc: i % 2,
312 },
313 Balance: big.NewInt(int64(i) * 1000),
314 }
315 }
316 return exitTree
317}
318
319func randomAccount(seed int, userAccount bool, userAddr *ethCommon.Address, accs []common.Account) (*common.Account, error) {
320 i := seed % len(accs)
321 firstI := i
322 for {
323 acc := accs[i]
324 if userAccount && *userAddr == acc.EthAddr {
325 return &acc, nil
326 }
327 if !userAccount && (userAddr == nil || *userAddr != acc.EthAddr) {
328 return &acc, nil
329 }
330 i++
331 i = i % len(accs)
332 if i == firstI {
333 return &acc, errors.New("Didnt found any account matchinng the criteria")
334 }
335 }
336}
337
338func randomTxType(seed int) common.TxType {
339 //nolint:gomnd
340 switch seed % 11 {
341 case 0:
342 return common.TxTypeExit
343 //nolint:gomnd
344 case 1:
345 return common.TxTypeWithdrawn
346 //nolint:gomnd
347 case 2:
348 return common.TxTypeTransfer
349 //nolint:gomnd
350 case 3:
351 return common.TxTypeDeposit
352 //nolint:gomnd
353 case 4:
354 return common.TxTypeCreateAccountDeposit
355 //nolint:gomnd
356 case 5:
357 return common.TxTypeCreateAccountDepositTransfer
358 //nolint:gomnd
359 case 6:
360 return common.TxTypeDepositTransfer
361 //nolint:gomnd
362 case 7:
363 return common.TxTypeForceTransfer
364 //nolint:gomnd
365 case 8:
366 return common.TxTypeForceExit
367 //nolint:gomnd
368 case 9:
369 return common.TxTypeTransferToEthAddr
370 //nolint:gomnd
371 case 10:
372 return common.TxTypeTransferToBJJ
373 default:
374 return common.TxTypeTransfer
375 }
376}