arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
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}