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.

441 lines
12 KiB

Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
  1. package test
  2. import (
  3. "errors"
  4. "fmt"
  5. "math/big"
  6. "time"
  7. ethCommon "github.com/ethereum/go-ethereum/common"
  8. "github.com/hermeznetwork/hermez-node/common"
  9. "github.com/iden3/go-iden3-crypto/babyjub"
  10. "github.com/iden3/go-merkletree"
  11. )
  12. // WARNING: the generators in this file doesn't necessary follow the protocol
  13. // they are intended to check that the parsers between struct <==> DB are correct
  14. // GenBlocks generates block from, to block numbers. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  15. func GenBlocks(from, to int64) []common.Block {
  16. var blocks []common.Block
  17. for i := from; i < to; i++ {
  18. blocks = append(blocks, common.Block{
  19. EthBlockNum: i,
  20. //nolint:gomnd
  21. Timestamp: time.Now().Add(time.Second * 13).UTC(),
  22. Hash: ethCommon.BigToHash(big.NewInt(int64(i))),
  23. })
  24. }
  25. return blocks
  26. }
  27. // GenTokens generates tokens. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  28. func GenTokens(nTokens int, blocks []common.Block) (tokensToAddInDB []common.Token, ethToken common.Token) {
  29. tokensToAddInDB = []common.Token{}
  30. for i := 1; i < nTokens; i++ {
  31. token := common.Token{
  32. TokenID: common.TokenID(i),
  33. Name: "NAME" + fmt.Sprint(i),
  34. Symbol: fmt.Sprint(i),
  35. Decimals: uint64(i + 1),
  36. EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
  37. EthAddr: ethCommon.BigToAddress(big.NewInt(int64(i))),
  38. }
  39. tokensToAddInDB = append(tokensToAddInDB, token)
  40. }
  41. return tokensToAddInDB, common.Token{
  42. TokenID: 0,
  43. Name: "Ether",
  44. Symbol: "ETH",
  45. Decimals: 18, //nolint:gomnd
  46. EthBlockNum: 0,
  47. EthAddr: ethCommon.BigToAddress(big.NewInt(0)),
  48. }
  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: big.NewInt(int64(i+1) * 5), //nolint:gomnd
  65. //nolint:gomnd
  66. NumAccounts: 30,
  67. ExitRoot: big.NewInt(int64(i+1) * 16), //nolint:gomnd
  68. SlotNum: int64(i),
  69. }
  70. if i%2 == 0 {
  71. toForge := new(int64)
  72. *toForge = int64(i + 1)
  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. Balance: big.NewInt(int64(i * 10000000)), //nolint:gomnd
  103. })
  104. }
  105. return accs
  106. }
  107. // GenL1Txs generates L1 txs. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  108. func GenL1Txs(
  109. fromIdx int,
  110. totalTxs, nUserTxs int,
  111. userAddr *ethCommon.Address,
  112. accounts []common.Account,
  113. tokens []common.Token,
  114. blocks []common.Block,
  115. batches []common.Batch,
  116. ) ([]common.L1Tx, []common.L1Tx) {
  117. if totalTxs < nUserTxs {
  118. panic("totalTxs must be greater than userTxs")
  119. }
  120. userTxs := []common.L1Tx{}
  121. othersTxs := []common.L1Tx{}
  122. _, nextTxsNum := GetNextToForgeNumAndBatch(batches)
  123. for i := fromIdx; i < fromIdx+totalTxs; i++ {
  124. token := tokens[i%len(tokens)]
  125. amount := big.NewInt(int64(i + 1))
  126. tx := common.L1Tx{
  127. Position: i - fromIdx,
  128. UserOrigin: i%2 == 0,
  129. TokenID: token.TokenID,
  130. Amount: amount,
  131. LoadAmount: amount,
  132. EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
  133. }
  134. if tx.UserOrigin {
  135. n := nextTxsNum
  136. tx.ToForgeL1TxsNum = &n
  137. } else {
  138. tx.BatchNum = &batches[i%len(batches)].BatchNum
  139. }
  140. nTx, err := common.NewL1Tx(&tx)
  141. if err != nil {
  142. panic(err)
  143. }
  144. tx = *nTx
  145. if !tx.UserOrigin {
  146. tx.BatchNum = &batches[i%len(batches)].BatchNum
  147. } else if batches[i%len(batches)].ForgeL1TxsNum != nil {
  148. // Add already forged txs
  149. tx.BatchNum = &batches[i%len(batches)].BatchNum
  150. setFromToAndAppend(fromIdx, tx, i, nUserTxs, userAddr, accounts, &userTxs, &othersTxs)
  151. } else {
  152. // Add unforged txs
  153. n := nextTxsNum
  154. tx.ToForgeL1TxsNum = &n
  155. tx.UserOrigin = true
  156. setFromToAndAppend(fromIdx, tx, i, nUserTxs, userAddr, accounts, &userTxs, &othersTxs)
  157. }
  158. }
  159. return userTxs, othersTxs
  160. }
  161. // GetNextToForgeNumAndBatch returns the next BatchNum and ForgeL1TxsNum to be added
  162. func GetNextToForgeNumAndBatch(batches []common.Batch) (common.BatchNum, int64) {
  163. batchNum := batches[len(batches)-1].BatchNum + 1
  164. var toForgeL1TxsNum int64
  165. found := false
  166. for i := len(batches) - 1; i >= 0; i-- {
  167. if batches[i].ForgeL1TxsNum != nil {
  168. toForgeL1TxsNum = *batches[i].ForgeL1TxsNum + 1
  169. found = true
  170. break
  171. }
  172. }
  173. if !found {
  174. panic("toForgeL1TxsNum not found")
  175. }
  176. return batchNum, toForgeL1TxsNum
  177. }
  178. func setFromToAndAppend(
  179. fromIdx int,
  180. tx common.L1Tx,
  181. i, nUserTxs int,
  182. userAddr *ethCommon.Address,
  183. accounts []common.Account,
  184. userTxs *[]common.L1Tx,
  185. othersTxs *[]common.L1Tx,
  186. ) {
  187. if i < fromIdx+nUserTxs {
  188. var from, to *common.Account
  189. var err error
  190. if i%2 == 0 {
  191. from, err = randomAccount(i, true, userAddr, accounts)
  192. if err != nil {
  193. panic(err)
  194. }
  195. to, err = randomAccount(i, false, userAddr, accounts)
  196. if err != nil {
  197. panic(err)
  198. }
  199. } else {
  200. from, err = randomAccount(i, false, userAddr, accounts)
  201. if err != nil {
  202. panic(err)
  203. }
  204. to, err = randomAccount(i, true, userAddr, accounts)
  205. if err != nil {
  206. panic(err)
  207. }
  208. }
  209. tx.FromIdx = from.Idx
  210. tx.FromEthAddr = from.EthAddr
  211. tx.FromBJJ = from.PublicKey
  212. tx.ToIdx = to.Idx
  213. *userTxs = append(*userTxs, tx)
  214. } else {
  215. from, err := randomAccount(i, false, userAddr, accounts)
  216. if err != nil {
  217. panic(err)
  218. }
  219. to, err := randomAccount(i, false, userAddr, accounts)
  220. if err != nil {
  221. panic(err)
  222. }
  223. tx.FromIdx = from.Idx
  224. tx.FromEthAddr = from.EthAddr
  225. tx.FromBJJ = from.PublicKey
  226. tx.ToIdx = to.Idx
  227. *othersTxs = append(*othersTxs, tx)
  228. }
  229. }
  230. // GenL2Txs generates L2 txs. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  231. func GenL2Txs(
  232. fromIdx int,
  233. totalTxs, nUserTxs int,
  234. userAddr *ethCommon.Address,
  235. accounts []common.Account,
  236. tokens []common.Token,
  237. blocks []common.Block,
  238. batches []common.Batch,
  239. ) ([]common.L2Tx, []common.L2Tx) {
  240. if totalTxs < nUserTxs {
  241. panic("totalTxs must be greater than userTxs")
  242. }
  243. userTxs := []common.L2Tx{}
  244. othersTxs := []common.L2Tx{}
  245. for i := fromIdx; i < fromIdx+totalTxs; i++ {
  246. amount := big.NewInt(int64(i + 1))
  247. fee := common.FeeSelector(i % 256) //nolint:gomnd
  248. tx := common.L2Tx{
  249. TxID: common.TxID([12]byte{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, byte(i)}), // only for testing purposes
  250. BatchNum: batches[i%len(batches)].BatchNum,
  251. Position: i - fromIdx,
  252. Amount: amount,
  253. Fee: fee,
  254. Nonce: common.Nonce(i + 1),
  255. EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
  256. Type: randomTxType(i),
  257. }
  258. if i < nUserTxs {
  259. var from, to *common.Account
  260. var err error
  261. if i%2 == 0 {
  262. from, err = randomAccount(i, true, userAddr, accounts)
  263. if err != nil {
  264. panic(err)
  265. }
  266. to, err = randomAccount(i, false, userAddr, accounts)
  267. if err != nil {
  268. panic(err)
  269. }
  270. } else {
  271. from, err = randomAccount(i, false, userAddr, accounts)
  272. if err != nil {
  273. panic(err)
  274. }
  275. to, err = randomAccount(i, true, userAddr, accounts)
  276. if err != nil {
  277. panic(err)
  278. }
  279. }
  280. tx.FromIdx = from.Idx
  281. tx.ToIdx = to.Idx
  282. } else {
  283. from, err := randomAccount(i, false, userAddr, accounts)
  284. if err != nil {
  285. panic(err)
  286. }
  287. to, err := randomAccount(i, false, userAddr, accounts)
  288. if err != nil {
  289. panic(err)
  290. }
  291. tx.FromIdx = from.Idx
  292. tx.ToIdx = to.Idx
  293. }
  294. if i < nUserTxs {
  295. userTxs = append(userTxs, tx)
  296. } else {
  297. othersTxs = append(othersTxs, tx)
  298. }
  299. }
  300. return userTxs, othersTxs
  301. }
  302. // GenCoordinators generates coordinators. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  303. func GenCoordinators(nCoords int, blocks []common.Block) []common.Coordinator {
  304. coords := []common.Coordinator{}
  305. for i := 0; i < nCoords; i++ {
  306. coords = append(coords, common.Coordinator{
  307. EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
  308. Forger: ethCommon.BigToAddress(big.NewInt(int64(i))),
  309. Bidder: ethCommon.BigToAddress(big.NewInt(int64(i))),
  310. URL: "https://foo.bar",
  311. })
  312. }
  313. return coords
  314. }
  315. // GenBids generates bids. WARNING: This is meant for DB/API testing, and may not be fully consistent with the protocol.
  316. func GenBids(nBids int, blocks []common.Block, coords []common.Coordinator) []common.Bid {
  317. bids := []common.Bid{}
  318. for i := 0; i < nBids; i++ {
  319. bids = append(bids, common.Bid{
  320. SlotNum: int64(i),
  321. BidValue: big.NewInt(int64(i)),
  322. EthBlockNum: blocks[i%len(blocks)].EthBlockNum,
  323. Bidder: coords[i%len(blocks)].Bidder,
  324. })
  325. }
  326. return bids
  327. }
  328. // GenExitTree generates an exitTree (as an array of Exits)
  329. //nolint:gomnd
  330. func GenExitTree(n int, batches []common.Batch, accounts []common.Account) []common.ExitInfo {
  331. exitTree := make([]common.ExitInfo, n)
  332. for i := 0; i < n; i++ {
  333. exitTree[i] = common.ExitInfo{
  334. BatchNum: batches[i%len(batches)].BatchNum,
  335. InstantWithdrawn: nil,
  336. DelayedWithdrawRequest: nil,
  337. DelayedWithdrawn: nil,
  338. AccountIdx: accounts[i%len(accounts)].Idx,
  339. MerkleProof: &merkletree.CircomVerifierProof{
  340. Root: &merkletree.Hash{byte(i), byte(i + 1)},
  341. Siblings: []*big.Int{
  342. big.NewInt(int64(i) * 10),
  343. big.NewInt(int64(i)*100 + 1),
  344. big.NewInt(int64(i)*1000 + 2)},
  345. OldKey: &merkletree.Hash{byte(i * 1), byte(i*1 + 1)},
  346. OldValue: &merkletree.Hash{byte(i * 2), byte(i*2 + 1)},
  347. IsOld0: i%2 == 0,
  348. Key: &merkletree.Hash{byte(i * 3), byte(i*3 + 1)},
  349. Value: &merkletree.Hash{byte(i * 4), byte(i*4 + 1)},
  350. Fnc: i % 2,
  351. },
  352. Balance: big.NewInt(int64(i) * 1000),
  353. }
  354. if i%2 == 0 {
  355. instant := new(int64)
  356. *instant = int64(batches[(i+1)%len(batches)].BatchNum)
  357. exitTree[i].InstantWithdrawn = instant
  358. } else if i%3 == 0 {
  359. delayedReq := new(int64)
  360. *delayedReq = int64(batches[(i+1)%len(batches)].BatchNum)
  361. exitTree[i].DelayedWithdrawRequest = delayedReq
  362. if i%9 == 0 {
  363. delayed := new(int64)
  364. *delayed = int64(batches[(i+2)%len(batches)].BatchNum)
  365. exitTree[i].DelayedWithdrawn = delayed
  366. }
  367. }
  368. }
  369. return exitTree
  370. }
  371. func randomAccount(seed int, userAccount bool, userAddr *ethCommon.Address, accs []common.Account) (*common.Account, error) {
  372. i := seed % len(accs)
  373. firstI := i
  374. for {
  375. acc := accs[i]
  376. if userAccount && *userAddr == acc.EthAddr {
  377. return &acc, nil
  378. }
  379. if !userAccount && (userAddr == nil || *userAddr != acc.EthAddr) {
  380. return &acc, nil
  381. }
  382. i++
  383. i = i % len(accs)
  384. if i == firstI {
  385. return &acc, errors.New("Didnt found any account matchinng the criteria")
  386. }
  387. }
  388. }
  389. func randomTxType(seed int) common.TxType {
  390. //nolint:gomnd
  391. switch seed % 11 {
  392. case 0:
  393. return common.TxTypeExit
  394. //nolint:gomnd
  395. case 2:
  396. return common.TxTypeTransfer
  397. //nolint:gomnd
  398. case 3:
  399. return common.TxTypeDeposit
  400. //nolint:gomnd
  401. case 4:
  402. return common.TxTypeCreateAccountDeposit
  403. //nolint:gomnd
  404. case 5:
  405. return common.TxTypeCreateAccountDepositTransfer
  406. //nolint:gomnd
  407. case 6:
  408. return common.TxTypeDepositTransfer
  409. //nolint:gomnd
  410. case 7:
  411. return common.TxTypeForceTransfer
  412. //nolint:gomnd
  413. case 8:
  414. return common.TxTypeForceExit
  415. //nolint:gomnd
  416. case 9:
  417. return common.TxTypeTransferToEthAddr
  418. //nolint:gomnd
  419. case 10:
  420. return common.TxTypeTransferToBJJ
  421. default:
  422. return common.TxTypeTransfer
  423. }
  424. }