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.

268 lines
7.6 KiB

Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
  1. package test
  2. import (
  3. "context"
  4. "crypto/ecdsa"
  5. "encoding/binary"
  6. "math/big"
  7. "testing"
  8. "time"
  9. ethCommon "github.com/ethereum/go-ethereum/common"
  10. ethCrypto "github.com/ethereum/go-ethereum/crypto"
  11. "github.com/hermeznetwork/hermez-node/common"
  12. "github.com/hermeznetwork/hermez-node/eth"
  13. "github.com/hermeznetwork/tracerr"
  14. "github.com/iden3/go-iden3-crypto/babyjub"
  15. "github.com/stretchr/testify/assert"
  16. "github.com/stretchr/testify/require"
  17. )
  18. type timer struct {
  19. time int64
  20. }
  21. func (t *timer) Time() int64 {
  22. currentTime := t.time
  23. t.time++
  24. return currentTime
  25. }
  26. func TestClientInterface(t *testing.T) {
  27. var c eth.ClientInterface
  28. var timer timer
  29. clientSetup := NewClientSetupExample()
  30. client := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
  31. c = client
  32. require.NotNil(t, c)
  33. }
  34. func TestClientEth(t *testing.T) {
  35. var timer timer
  36. clientSetup := NewClientSetupExample()
  37. c := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
  38. blockNum, err := c.EthLastBlock()
  39. require.Nil(t, err)
  40. assert.Equal(t, int64(1), blockNum)
  41. block, err := c.EthBlockByNumber(context.TODO(), 0)
  42. require.Nil(t, err)
  43. assert.Equal(t, int64(0), block.Num)
  44. assert.Equal(t, time.Unix(0, 0), block.Timestamp)
  45. assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000000", block.Hash.Hex())
  46. // Mine some empty blocks
  47. assert.Equal(t, int64(1), c.blockNum)
  48. c.CtlMineBlock()
  49. assert.Equal(t, int64(2), c.blockNum)
  50. c.CtlMineBlock()
  51. assert.Equal(t, int64(3), c.blockNum)
  52. block, err = c.EthBlockByNumber(context.TODO(), 2)
  53. require.Nil(t, err)
  54. assert.Equal(t, int64(2), block.Num)
  55. assert.Equal(t, time.Unix(2, 0), block.Timestamp)
  56. // Add a token
  57. tokenAddr := ethCommon.HexToAddress("0x44021007485550008e0f9f1f7b506c7d970ad8ce")
  58. constants := eth.ERC20Consts{
  59. Name: "FooBar",
  60. Symbol: "FOO",
  61. Decimals: 4,
  62. }
  63. c.CtlAddERC20(tokenAddr, constants)
  64. c.CtlMineBlock()
  65. tokenConstants, err := c.EthERC20Consts(tokenAddr)
  66. require.Nil(t, err)
  67. assert.Equal(t, constants, *tokenConstants)
  68. }
  69. func TestClientAuction(t *testing.T) {
  70. addrBidder1 := ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f")
  71. addrBidder2 := ethCommon.HexToAddress("0xc27cadc437d067a6ec869502cc9f7F834cFc087a")
  72. addrForge := ethCommon.HexToAddress("0xCfAA413eEb796f328620a3630Ae39124cabcEa92")
  73. addrForge2 := ethCommon.HexToAddress("0x1fCb4ac309428feCc61B1C8cA5823C15A5e1a800")
  74. var timer timer
  75. clientSetup := NewClientSetupExample()
  76. clientSetup.AuctionVariables.ClosedAuctionSlots = 2
  77. clientSetup.AuctionVariables.OpenAuctionSlots = 4320
  78. clientSetup.AuctionVariables.DefaultSlotSetBid = [6]*big.Int{
  79. big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
  80. big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)}
  81. c := NewClient(true, &timer, &addrBidder1, clientSetup)
  82. // Check several cases in which bid doesn't succed, and also do 2 successful bids.
  83. _, err := c.AuctionBidSimple(0, big.NewInt(1))
  84. assert.Equal(t, errBidClosed, tracerr.Unwrap(err))
  85. _, err = c.AuctionBidSimple(4322, big.NewInt(1))
  86. assert.Equal(t, errBidNotOpen, tracerr.Unwrap(err))
  87. // 101 % 6 = 5; defaultSlotSetBid[5] = 1500; 1500 + 10% = 1650
  88. _, err = c.AuctionBidSimple(101, big.NewInt(1650))
  89. assert.Equal(t, errCoordNotReg, tracerr.Unwrap(err))
  90. _, err = c.AuctionSetCoordinator(addrForge, "https://foo.bar")
  91. assert.Nil(t, err)
  92. _, err = c.AuctionBidSimple(3, big.NewInt(1))
  93. assert.Equal(t, errBidBelowMin, tracerr.Unwrap(err))
  94. _, err = c.AuctionBidSimple(3, big.NewInt(1650))
  95. assert.Nil(t, err)
  96. c.CtlSetAddr(addrBidder2)
  97. _, err = c.AuctionSetCoordinator(addrForge2, "https://foo2.bar")
  98. assert.Nil(t, err)
  99. _, err = c.AuctionBidSimple(3, big.NewInt(16))
  100. assert.Equal(t, errBidBelowMin, tracerr.Unwrap(err))
  101. // 1650 + 10% = 1815
  102. _, err = c.AuctionBidSimple(3, big.NewInt(1815))
  103. assert.Nil(t, err)
  104. c.CtlMineBlock()
  105. blockNum, err := c.EthLastBlock()
  106. require.Nil(t, err)
  107. auctionEvents, _, err := c.AuctionEventsByBlock(blockNum)
  108. require.Nil(t, err)
  109. assert.Equal(t, 2, len(auctionEvents.NewBid))
  110. }
  111. func TestClientRollup(t *testing.T) {
  112. token1Addr := ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f")
  113. var timer timer
  114. clientSetup := NewClientSetupExample()
  115. c := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
  116. // Add a token
  117. tx, err := c.RollupAddTokenSimple(token1Addr, clientSetup.RollupVariables.FeeAddToken)
  118. require.Nil(t, err)
  119. assert.NotNil(t, tx)
  120. // Add some L1UserTxs
  121. // Create Accounts
  122. const N = 16
  123. var keys [N]*keys
  124. for i := 0; i < N; i++ {
  125. keys[i] = genKeys(int64(i))
  126. tx := common.L1Tx{
  127. FromIdx: 0,
  128. FromEthAddr: keys[i].Addr,
  129. FromBJJ: keys[i].BJJPublicKey.Compress(),
  130. TokenID: common.TokenID(0),
  131. Amount: big.NewInt(0),
  132. DepositAmount: big.NewInt(10 + int64(i)),
  133. }
  134. _, err := c.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.DepositAmount,
  135. tx.Amount, uint32(tx.TokenID), int64(tx.ToIdx))
  136. require.Nil(t, err)
  137. }
  138. c.CtlMineBlock()
  139. blockNum, err := c.EthLastBlock()
  140. require.Nil(t, err)
  141. rollupEvents, _, err := c.RollupEventsByBlock(blockNum)
  142. require.Nil(t, err)
  143. assert.Equal(t, N, len(rollupEvents.L1UserTx))
  144. assert.Equal(t, 1, len(rollupEvents.AddToken))
  145. // Forge a batch
  146. c.CtlAddBatch(&eth.RollupForgeBatchArgs{
  147. NewLastIdx: 0,
  148. NewStRoot: big.NewInt(1),
  149. NewExitRoot: big.NewInt(100),
  150. L1CoordinatorTxs: []common.L1Tx{},
  151. L2TxsData: []common.L2Tx{},
  152. FeeIdxCoordinator: []common.Idx{},
  153. VerifierIdx: 0,
  154. L1Batch: true,
  155. })
  156. c.CtlMineBlock()
  157. blockNumA, err := c.EthLastBlock()
  158. require.Nil(t, err)
  159. rollupEvents, hashA, err := c.RollupEventsByBlock(blockNumA)
  160. require.Nil(t, err)
  161. assert.Equal(t, 0, len(rollupEvents.L1UserTx))
  162. assert.Equal(t, 0, len(rollupEvents.AddToken))
  163. assert.Equal(t, 1, len(rollupEvents.ForgeBatch))
  164. // Simulate reorg discarding last mined block
  165. c.CtlRollback()
  166. c.CtlMineBlock()
  167. blockNumB, err := c.EthLastBlock()
  168. require.Nil(t, err)
  169. rollupEvents, hashB, err := c.RollupEventsByBlock(blockNumA)
  170. require.Nil(t, err)
  171. assert.Equal(t, 0, len(rollupEvents.L1UserTx))
  172. assert.Equal(t, 0, len(rollupEvents.AddToken))
  173. assert.Equal(t, 0, len(rollupEvents.ForgeBatch))
  174. assert.Equal(t, blockNumA, blockNumB)
  175. assert.NotEqual(t, hashA, hashB)
  176. // Forge again
  177. rollupForgeBatchArgs0 := &eth.RollupForgeBatchArgs{
  178. NewLastIdx: 0,
  179. NewStRoot: big.NewInt(1),
  180. NewExitRoot: big.NewInt(100),
  181. L1CoordinatorTxs: []common.L1Tx{},
  182. L2TxsData: []common.L2Tx{},
  183. FeeIdxCoordinator: []common.Idx{},
  184. VerifierIdx: 0,
  185. L1Batch: true,
  186. }
  187. c.CtlAddBatch(rollupForgeBatchArgs0)
  188. c.CtlMineBlock()
  189. // Retrieve ForgeBatchArguments starting from the events
  190. blockNum, err = c.EthLastBlock()
  191. require.Nil(t, err)
  192. rollupEvents, _, err = c.RollupEventsByBlock(blockNum)
  193. require.Nil(t, err)
  194. rollupForgeBatchArgs1, sender, err := c.RollupForgeBatchArgs(rollupEvents.ForgeBatch[0].EthTxHash,
  195. rollupEvents.ForgeBatch[0].L1UserTxsLen)
  196. require.Nil(t, err)
  197. assert.Equal(t, *c.addr, *sender)
  198. assert.Equal(t, rollupForgeBatchArgs0, rollupForgeBatchArgs1)
  199. }
  200. type keys struct {
  201. BJJSecretKey *babyjub.PrivateKey
  202. BJJPublicKey *babyjub.PublicKey
  203. Addr ethCommon.Address
  204. }
  205. func genKeys(i int64) *keys {
  206. i++ // i = 0 doesn't work for the ecdsa key generation
  207. var sk babyjub.PrivateKey
  208. binary.LittleEndian.PutUint64(sk[:], uint64(i))
  209. // eth address
  210. var key ecdsa.PrivateKey
  211. key.D = big.NewInt(i) // only for testing
  212. key.PublicKey.X, key.PublicKey.Y = ethCrypto.S256().ScalarBaseMult(key.D.Bytes())
  213. key.Curve = ethCrypto.S256()
  214. addr := ethCrypto.PubkeyToAddress(key.PublicKey)
  215. return &keys{
  216. BJJSecretKey: &sk,
  217. BJJPublicKey: sk.Public(),
  218. Addr: addr,
  219. }
  220. }