You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

473 lines
13 KiB

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