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.

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