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.

266 lines
7.4 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
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/iden3/go-iden3-crypto/babyjub"
  14. "github.com/stretchr/testify/assert"
  15. "github.com/stretchr/testify/require"
  16. )
  17. type timer struct {
  18. time int64
  19. }
  20. func (t *timer) Time() int64 {
  21. currentTime := t.time
  22. t.time++
  23. return currentTime
  24. }
  25. func TestClientInterface(t *testing.T) {
  26. var c eth.ClientInterface
  27. var timer timer
  28. clientSetup := NewClientSetupExample()
  29. client := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
  30. c = client
  31. require.NotNil(t, c)
  32. }
  33. func TestClientEth(t *testing.T) {
  34. var timer timer
  35. clientSetup := NewClientSetupExample()
  36. c := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
  37. blockNum, err := c.EthLastBlock()
  38. require.Nil(t, err)
  39. assert.Equal(t, int64(1), blockNum)
  40. block, err := c.EthBlockByNumber(context.TODO(), 0)
  41. require.Nil(t, err)
  42. assert.Equal(t, int64(0), block.EthBlockNum)
  43. assert.Equal(t, time.Unix(0, 0), block.Timestamp)
  44. assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000000", block.Hash.Hex())
  45. // Mine some empty blocks
  46. assert.Equal(t, int64(1), c.blockNum)
  47. c.CtlMineBlock()
  48. assert.Equal(t, int64(2), c.blockNum)
  49. c.CtlMineBlock()
  50. assert.Equal(t, int64(3), c.blockNum)
  51. block, err = c.EthBlockByNumber(context.TODO(), 2)
  52. require.Nil(t, err)
  53. assert.Equal(t, int64(2), block.EthBlockNum)
  54. assert.Equal(t, time.Unix(2, 0), block.Timestamp)
  55. // Add a token
  56. tokenAddr := ethCommon.HexToAddress("0x44021007485550008e0f9f1f7b506c7d970ad8ce")
  57. constants := eth.ERC20Consts{
  58. Name: "FooBar",
  59. Symbol: "FOO",
  60. Decimals: 4,
  61. }
  62. c.CtlAddERC20(tokenAddr, constants)
  63. c.CtlMineBlock()
  64. tokenConstants, err := c.EthERC20Consts(tokenAddr)
  65. require.Nil(t, err)
  66. assert.Equal(t, constants, *tokenConstants)
  67. }
  68. func TestClientAuction(t *testing.T) {
  69. addrBidder1 := ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f")
  70. addrBidder2 := ethCommon.HexToAddress("0xc27cadc437d067a6ec869502cc9f7F834cFc087a")
  71. addrForge := ethCommon.HexToAddress("0xCfAA413eEb796f328620a3630Ae39124cabcEa92")
  72. addrForge2 := ethCommon.HexToAddress("0x1fCb4ac309428feCc61B1C8cA5823C15A5e1a800")
  73. var timer timer
  74. clientSetup := NewClientSetupExample()
  75. clientSetup.AuctionVariables.ClosedAuctionSlots = 2
  76. clientSetup.AuctionVariables.OpenAuctionSlots = 4320
  77. clientSetup.AuctionVariables.DefaultSlotSetBid = [6]*big.Int{
  78. big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
  79. big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)}
  80. c := NewClient(true, &timer, &addrBidder1, clientSetup)
  81. // Check several cases in which bid doesn't succed, and also do 2 successful bids.
  82. _, err := c.AuctionBidSimple(0, big.NewInt(1))
  83. assert.Equal(t, errBidClosed, err)
  84. _, err = c.AuctionBidSimple(4322, big.NewInt(1))
  85. assert.Equal(t, errBidNotOpen, err)
  86. // 101 % 6 = 5; defaultSlotSetBid[5] = 1500; 1500 + 10% = 1650
  87. _, err = c.AuctionBidSimple(101, big.NewInt(1650))
  88. assert.Equal(t, errCoordNotReg, err)
  89. _, err = c.AuctionSetCoordinator(addrForge, "https://foo.bar")
  90. assert.Nil(t, err)
  91. _, err = c.AuctionBidSimple(3, big.NewInt(1))
  92. assert.Equal(t, errBidBelowMin, err)
  93. _, err = c.AuctionBidSimple(3, big.NewInt(1650))
  94. assert.Nil(t, err)
  95. c.CtlSetAddr(addrBidder2)
  96. _, err = c.AuctionSetCoordinator(addrForge2, "https://foo2.bar")
  97. assert.Nil(t, err)
  98. _, err = c.AuctionBidSimple(3, big.NewInt(16))
  99. assert.Equal(t, errBidBelowMin, err)
  100. // 1650 + 10% = 1815
  101. _, err = c.AuctionBidSimple(3, big.NewInt(1815))
  102. assert.Nil(t, err)
  103. c.CtlMineBlock()
  104. blockNum, err := c.EthLastBlock()
  105. require.Nil(t, err)
  106. auctionEvents, _, err := c.AuctionEventsByBlock(blockNum)
  107. require.Nil(t, err)
  108. assert.Equal(t, 2, len(auctionEvents.NewBid))
  109. }
  110. func TestClientRollup(t *testing.T) {
  111. token1Addr := ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f")
  112. var timer timer
  113. clientSetup := NewClientSetupExample()
  114. c := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
  115. // Add a token
  116. tx, err := c.RollupAddTokenSimple(token1Addr, clientSetup.RollupVariables.FeeAddToken)
  117. require.Nil(t, err)
  118. assert.NotNil(t, tx)
  119. // Add some L1UserTxs
  120. // Create Accounts
  121. const N = 16
  122. var keys [N]*keys
  123. for i := 0; i < N; i++ {
  124. keys[i] = genKeys(int64(i))
  125. tx := common.L1Tx{
  126. FromIdx: 0,
  127. FromEthAddr: keys[i].Addr,
  128. FromBJJ: keys[i].BJJPublicKey,
  129. TokenID: common.TokenID(0),
  130. Amount: big.NewInt(0),
  131. LoadAmount: big.NewInt(10 + int64(i)),
  132. }
  133. _, err := c.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.LoadAmount,
  134. tx.Amount, uint32(tx.TokenID), int64(tx.ToIdx))
  135. require.Nil(t, err)
  136. }
  137. c.CtlMineBlock()
  138. blockNum, err := c.EthLastBlock()
  139. require.Nil(t, err)
  140. rollupEvents, _, err := c.RollupEventsByBlock(blockNum)
  141. require.Nil(t, err)
  142. assert.Equal(t, N, len(rollupEvents.L1UserTx))
  143. assert.Equal(t, 1, len(rollupEvents.AddToken))
  144. // Forge a batch
  145. c.CtlAddBatch(&eth.RollupForgeBatchArgs{
  146. NewLastIdx: 0,
  147. NewStRoot: big.NewInt(1),
  148. NewExitRoot: big.NewInt(100),
  149. L1CoordinatorTxs: []common.L1Tx{},
  150. L2TxsData: []common.L2Tx{},
  151. FeeIdxCoordinator: []common.Idx{},
  152. VerifierIdx: 0,
  153. L1Batch: true,
  154. })
  155. c.CtlMineBlock()
  156. blockNumA, err := c.EthLastBlock()
  157. require.Nil(t, err)
  158. rollupEvents, hashA, err := c.RollupEventsByBlock(blockNumA)
  159. require.Nil(t, err)
  160. assert.Equal(t, 0, len(rollupEvents.L1UserTx))
  161. assert.Equal(t, 0, len(rollupEvents.AddToken))
  162. assert.Equal(t, 1, len(rollupEvents.ForgeBatch))
  163. // Simulate reorg discarding last mined block
  164. c.CtlRollback()
  165. c.CtlMineBlock()
  166. blockNumB, err := c.EthLastBlock()
  167. require.Nil(t, err)
  168. rollupEvents, hashB, err := c.RollupEventsByBlock(blockNumA)
  169. require.Nil(t, err)
  170. assert.Equal(t, 0, len(rollupEvents.L1UserTx))
  171. assert.Equal(t, 0, len(rollupEvents.AddToken))
  172. assert.Equal(t, 0, len(rollupEvents.ForgeBatch))
  173. assert.Equal(t, blockNumA, blockNumB)
  174. assert.NotEqual(t, hashA, hashB)
  175. // Forge again
  176. rollupForgeBatchArgs0 := &eth.RollupForgeBatchArgs{
  177. NewLastIdx: 0,
  178. NewStRoot: big.NewInt(1),
  179. NewExitRoot: big.NewInt(100),
  180. L1CoordinatorTxs: []common.L1Tx{},
  181. L2TxsData: []common.L2Tx{},
  182. FeeIdxCoordinator: []common.Idx{},
  183. VerifierIdx: 0,
  184. L1Batch: true,
  185. }
  186. c.CtlAddBatch(rollupForgeBatchArgs0)
  187. c.CtlMineBlock()
  188. // Retrieve ForgeBatchArguments starting from the events
  189. blockNum, err = c.EthLastBlock()
  190. require.Nil(t, err)
  191. rollupEvents, _, err = c.RollupEventsByBlock(blockNum)
  192. require.Nil(t, err)
  193. rollupForgeBatchArgs1, sender, err := c.RollupForgeBatchArgs(rollupEvents.ForgeBatch[0].EthTxHash)
  194. require.Nil(t, err)
  195. assert.Equal(t, *c.addr, *sender)
  196. assert.Equal(t, rollupForgeBatchArgs0, rollupForgeBatchArgs1)
  197. }
  198. type keys struct {
  199. BJJSecretKey *babyjub.PrivateKey
  200. BJJPublicKey *babyjub.PublicKey
  201. Addr ethCommon.Address
  202. }
  203. func genKeys(i int64) *keys {
  204. i++ // i = 0 doesn't work for the ecdsa key generation
  205. var sk babyjub.PrivateKey
  206. binary.LittleEndian.PutUint64(sk[:], uint64(i))
  207. // eth address
  208. var key ecdsa.PrivateKey
  209. key.D = big.NewInt(i) // only for testing
  210. key.PublicKey.X, key.PublicKey.Y = ethCrypto.S256().ScalarBaseMult(key.D.Bytes())
  211. key.Curve = ethCrypto.S256()
  212. addr := ethCrypto.PubkeyToAddress(key.PublicKey)
  213. return &keys{
  214. BJJSecretKey: &sk,
  215. BJJPublicKey: sk.Public(),
  216. Addr: addr,
  217. }
  218. }