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.

480 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. if tx.UserOrigin {
  148. n := nextTxsNum
  149. tx.ToForgeL1TxsNum = &n
  150. } else {
  151. tx.BatchNum = &batches[i%len(batches)].BatchNum
  152. }
  153. nTx, err := common.NewL1Tx(&tx)
  154. if err != nil {
  155. panic(err)
  156. }
  157. tx = *nTx
  158. if batches[i%len(batches)].ForgeL1TxsNum != nil {
  159. // Add already forged txs
  160. tx.BatchNum = &batches[i%len(batches)].BatchNum
  161. setFromToAndAppend(fromIdx, tx, i, nUserTxs, userAddr, accounts, &userTxs, &othersTxs)
  162. } else {
  163. // Add unforged txs
  164. n := nextTxsNum
  165. tx.ToForgeL1TxsNum = &n
  166. tx.UserOrigin = true
  167. setFromToAndAppend(fromIdx, tx, i, nUserTxs, userAddr, accounts, &userTxs, &othersTxs)
  168. }
  169. }
  170. return userTxs, othersTxs
  171. }
  172. // GetNextToForgeNumAndBatch returns the next BatchNum and ForgeL1TxsNum to be added
  173. func GetNextToForgeNumAndBatch(batches []common.Batch) (common.BatchNum, int64) {
  174. batchNum := batches[len(batches)-1].BatchNum + 1
  175. var toForgeL1TxsNum int64
  176. found := false
  177. for i := len(batches) - 1; i >= 0; i-- {
  178. if batches[i].ForgeL1TxsNum != nil {
  179. toForgeL1TxsNum = *batches[i].ForgeL1TxsNum + 1
  180. found = true
  181. break
  182. }
  183. }
  184. if !found {
  185. panic("toForgeL1TxsNum not found")
  186. }
  187. return batchNum, toForgeL1TxsNum
  188. }
  189. func setFromToAndAppend(
  190. fromIdx int,
  191. tx common.L1Tx,
  192. i, nUserTxs int,
  193. userAddr *ethCommon.Address,
  194. accounts []common.Account,
  195. userTxs *[]common.L1Tx,
  196. othersTxs *[]common.L1Tx,
  197. ) {
  198. if i < fromIdx+nUserTxs {
  199. var from, to *common.Account
  200. var err error
  201. if i%2 == 0 {
  202. from, err = randomAccount(i, true, userAddr, accounts)
  203. if err != nil {
  204. panic(err)
  205. }
  206. to, err = randomAccount(i, false, userAddr, accounts)
  207. if err != nil {
  208. panic(err)
  209. }
  210. } else {
  211. from, err = randomAccount(i, false, userAddr, accounts)
  212. if err != nil {
  213. panic(err)
  214. }
  215. to, err = randomAccount(i, true, userAddr, accounts)
  216. if err != nil {
  217. panic(err)
  218. }
  219. }
  220. fromIdx := new(common.Idx)
  221. *fromIdx = from.Idx
  222. tx.FromIdx = fromIdx
  223. tx.FromEthAddr = from.EthAddr
  224. tx.FromBJJ = from.PublicKey
  225. tx.ToIdx = to.Idx
  226. *userTxs = append(*userTxs, tx)
  227. } else {
  228. from, err := randomAccount(i, false, userAddr, accounts)
  229. if err != nil {
  230. panic(err)
  231. }
  232. to, err := randomAccount(i, false, userAddr, accounts)
  233. if err != nil {
  234. panic(err)
  235. }
  236. fromIdx := new(common.Idx)
  237. *fromIdx = from.Idx
  238. tx.FromIdx = fromIdx
  239. tx.FromEthAddr = from.EthAddr
  240. tx.FromBJJ = from.PublicKey
  241. tx.ToIdx = to.Idx
  242. *othersTxs = append(*othersTxs, tx)
  243. }
  244. }
  245. // GenL2Txs generates L2 txs. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  246. func GenL2Txs(
  247. fromIdx int,
  248. totalTxs, nUserTxs int,
  249. userAddr *ethCommon.Address,
  250. accounts []common.Account,
  251. tokens []common.Token,
  252. blocks []common.Block,
  253. batches []common.Batch,
  254. ) ([]common.L2Tx, []common.L2Tx) {
  255. if totalTxs < nUserTxs {
  256. panic("totalTxs must be greater than userTxs")
  257. }
  258. userTxs := []common.L2Tx{}
  259. othersTxs := []common.L2Tx{}
  260. for i := fromIdx; i < fromIdx+totalTxs; i++ {
  261. amount := big.NewInt(int64(i + 1))
  262. fee := common.FeeSelector(i % 256) //nolint:gomnd
  263. tx := common.L2Tx{
  264. TxID: common.TxID([12]byte{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, byte(i)}), // only for testing purposes
  265. BatchNum: batches[i%len(batches)].BatchNum,
  266. Position: i - fromIdx,
  267. Amount: amount,
  268. Fee: fee,
  269. Nonce: common.Nonce(i + 1),
  270. EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
  271. Type: randomTxType(i),
  272. }
  273. if i < nUserTxs {
  274. var from, to *common.Account
  275. var err error
  276. if i%2 == 0 {
  277. from, err = randomAccount(i, true, userAddr, accounts)
  278. if err != nil {
  279. panic(err)
  280. }
  281. to, err = randomAccount(i, false, userAddr, accounts)
  282. if err != nil {
  283. panic(err)
  284. }
  285. } else {
  286. from, err = randomAccount(i, false, userAddr, accounts)
  287. if err != nil {
  288. panic(err)
  289. }
  290. to, err = randomAccount(i, true, userAddr, accounts)
  291. if err != nil {
  292. panic(err)
  293. }
  294. }
  295. tx.FromIdx = from.Idx
  296. tx.ToIdx = to.Idx
  297. } else {
  298. from, err := randomAccount(i, false, userAddr, accounts)
  299. if err != nil {
  300. panic(err)
  301. }
  302. to, err := randomAccount(i, false, userAddr, accounts)
  303. if err != nil {
  304. panic(err)
  305. }
  306. tx.FromIdx = from.Idx
  307. tx.ToIdx = to.Idx
  308. }
  309. var usd *float64
  310. var fUSD *float64
  311. token := GetToken(tx.FromIdx, accounts, tokens)
  312. if token.USD != nil {
  313. //nolint:gomnd
  314. noDecimalsUSD := *token.USD / math.Pow(10, float64(token.Decimals))
  315. f := new(big.Float).SetInt(amount)
  316. af, _ := f.Float64()
  317. usd = new(float64)
  318. fUSD = new(float64)
  319. *usd = noDecimalsUSD * af
  320. *fUSD = *usd * fee.Percentage()
  321. }
  322. tx.USD = usd
  323. tx.FeeUSD = fUSD
  324. if i < nUserTxs {
  325. userTxs = append(userTxs, tx)
  326. } else {
  327. othersTxs = append(othersTxs, tx)
  328. }
  329. }
  330. return userTxs, othersTxs
  331. }
  332. // GetToken returns the Token associated to an Idx given a list of tokens and accounts.
  333. // It panics when not found, intended for testing only.
  334. func GetToken(idx common.Idx, accs []common.Account, tokens []common.Token) common.Token {
  335. var id common.TokenID
  336. found := false
  337. for _, acc := range accs {
  338. if acc.Idx == idx {
  339. found = true
  340. id = acc.TokenID
  341. break
  342. }
  343. }
  344. if !found {
  345. panic("tokenID not found")
  346. }
  347. for i := 0; i < len(tokens); i++ {
  348. if tokens[i].TokenID == id {
  349. return tokens[i]
  350. }
  351. }
  352. panic("token not found")
  353. }
  354. // GenCoordinators generates coordinators. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  355. func GenCoordinators(nCoords int, blocks []common.Block) []common.Coordinator {
  356. coords := []common.Coordinator{}
  357. for i := 0; i < nCoords; i++ {
  358. coords = append(coords, common.Coordinator{
  359. EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
  360. Forger: ethCommon.BigToAddress(big.NewInt(int64(i))),
  361. Bidder: ethCommon.BigToAddress(big.NewInt(int64(i))),
  362. URL: "https://foo.bar",
  363. })
  364. }
  365. return coords
  366. }
  367. // GenBids generates bids. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  368. func GenBids(nBids int, blocks []common.Block, coords []common.Coordinator) []common.Bid {
  369. bids := []common.Bid{}
  370. for i := 0; i < nBids; i++ {
  371. bids = append(bids, common.Bid{
  372. SlotNum: common.SlotNum(i),
  373. BidValue: big.NewInt(int64(i)),
  374. EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
  375. Bidder: coords[i%len(blocks)].Bidder,
  376. })
  377. }
  378. return bids
  379. }
  380. // GenExitTree generates an exitTree (as an array of Exits)
  381. //nolint:gomnd
  382. func GenExitTree(n int) []common.ExitInfo {
  383. exitTree := make([]common.ExitInfo, n)
  384. for i := 0; i < n; i++ {
  385. exitTree[i] = common.ExitInfo{
  386. BatchNum: common.BatchNum(i + 1),
  387. InstantWithdrawn: nil,
  388. DelayedWithdrawRequest: nil,
  389. DelayedWithdrawn: nil,
  390. AccountIdx: common.Idx(i * 10),
  391. MerkleProof: &merkletree.CircomVerifierProof{
  392. Root: &merkletree.Hash{byte(i), byte(i + 1)},
  393. Siblings: []*big.Int{
  394. big.NewInt(int64(i) * 10),
  395. big.NewInt(int64(i)*100 + 1),
  396. big.NewInt(int64(i)*1000 + 2)},
  397. OldKey: &merkletree.Hash{byte(i * 1), byte(i*1 + 1)},
  398. OldValue: &merkletree.Hash{byte(i * 2), byte(i*2 + 1)},
  399. IsOld0: i%2 == 0,
  400. Key: &merkletree.Hash{byte(i * 3), byte(i*3 + 1)},
  401. Value: &merkletree.Hash{byte(i * 4), byte(i*4 + 1)},
  402. Fnc: i % 2,
  403. },
  404. Balance: big.NewInt(int64(i) * 1000),
  405. }
  406. }
  407. return exitTree
  408. }
  409. func randomAccount(seed int, userAccount bool, userAddr *ethCommon.Address, accs []common.Account) (*common.Account, error) {
  410. i := seed % len(accs)
  411. firstI := i
  412. for {
  413. acc := accs[i]
  414. if userAccount && *userAddr == acc.EthAddr {
  415. return &acc, nil
  416. }
  417. if !userAccount && (userAddr == nil || *userAddr != acc.EthAddr) {
  418. return &acc, nil
  419. }
  420. i++
  421. i = i % len(accs)
  422. if i == firstI {
  423. return &acc, errors.New("Didnt found any account matchinng the criteria")
  424. }
  425. }
  426. }
  427. func randomTxType(seed int) common.TxType {
  428. //nolint:gomnd
  429. switch seed % 11 {
  430. case 0:
  431. return common.TxTypeExit
  432. //nolint:gomnd
  433. case 2:
  434. return common.TxTypeTransfer
  435. //nolint:gomnd
  436. case 3:
  437. return common.TxTypeDeposit
  438. //nolint:gomnd
  439. case 4:
  440. return common.TxTypeCreateAccountDeposit
  441. //nolint:gomnd
  442. case 5:
  443. return common.TxTypeCreateAccountDepositTransfer
  444. //nolint:gomnd
  445. case 6:
  446. return common.TxTypeDepositTransfer
  447. //nolint:gomnd
  448. case 7:
  449. return common.TxTypeForceTransfer
  450. //nolint:gomnd
  451. case 8:
  452. return common.TxTypeForceExit
  453. //nolint:gomnd
  454. case 9:
  455. return common.TxTypeTransferToEthAddr
  456. //nolint:gomnd
  457. case 10:
  458. return common.TxTypeTransferToBJJ
  459. default:
  460. return common.TxTypeTransfer
  461. }
  462. }