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.

206 lines
5.5 KiB

  1. package coordinator
  2. import (
  3. "io/ioutil"
  4. "math/big"
  5. "os"
  6. "testing"
  7. "time"
  8. ethCommon "github.com/ethereum/go-ethereum/common"
  9. "github.com/hermeznetwork/hermez-node/batchbuilder"
  10. dbUtils "github.com/hermeznetwork/hermez-node/db"
  11. "github.com/hermeznetwork/hermez-node/db/historydb"
  12. "github.com/hermeznetwork/hermez-node/db/l2db"
  13. "github.com/hermeznetwork/hermez-node/db/statedb"
  14. "github.com/hermeznetwork/hermez-node/log"
  15. "github.com/hermeznetwork/hermez-node/test"
  16. "github.com/hermeznetwork/hermez-node/txselector"
  17. "github.com/stretchr/testify/assert"
  18. "github.com/stretchr/testify/require"
  19. )
  20. func newTestModules(t *testing.T) (*txselector.TxSelector, *batchbuilder.BatchBuilder) { // FUTURE once Synchronizer is ready, should return it also
  21. nLevels := 32
  22. synchDBPath, err := ioutil.TempDir("", "tmpSynchDB")
  23. require.Nil(t, err)
  24. synchSdb, err := statedb.NewStateDB(synchDBPath, statedb.TypeSynchronizer, nLevels)
  25. assert.Nil(t, err)
  26. // txselDBPath, err := ioutil.TempDir("", "tmpTxSelDB")
  27. // require.Nil(t, err)
  28. // bbDBPath, err := ioutil.TempDir("", "tmpBBDB")
  29. // require.Nil(t, err)
  30. // txselSdb, err := statedb.NewLocalStateDB(txselDBPath, synchSdb, statedb.TypeTxSelector, nLevels)
  31. // assert.Nil(t, err)
  32. // bbSdb, err := statedb.NewLocalStateDB(bbDBPath, synchSdb, statedb.TypeBatchBuilder, nLevels)
  33. // assert.Nil(t, err)
  34. pass := os.Getenv("POSTGRES_PASS")
  35. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  36. require.Nil(t, err)
  37. l2DB := l2db.NewL2DB(db, 10, 100, 24*time.Hour)
  38. txselDir, err := ioutil.TempDir("", "tmpTxSelDB")
  39. require.Nil(t, err)
  40. txsel, err := txselector.NewTxSelector(txselDir, synchSdb, l2DB, 10, 10, 10)
  41. assert.Nil(t, err)
  42. bbDir, err := ioutil.TempDir("", "tmpBatchBuilderDB")
  43. require.Nil(t, err)
  44. bb, err := batchbuilder.NewBatchBuilder(bbDir, synchSdb, nil, 0, uint64(nLevels))
  45. assert.Nil(t, err)
  46. // l1Txs, coordinatorL1Txs, poolL2Txs := test.GenerateTestTxsFromSet(t, test.SetTest0)
  47. return txsel, bb
  48. }
  49. // CoordNode is an example of a Node that handles the goroutines for the coordinator
  50. type CoordNode struct {
  51. c *Coordinator
  52. stopForge chan bool
  53. stopGetProofCallForge chan bool
  54. stopForgeCallConfirm chan bool
  55. }
  56. func NewCoordNode(c *Coordinator) *CoordNode {
  57. return &CoordNode{
  58. c: c,
  59. }
  60. }
  61. func (cn *CoordNode) Start() {
  62. log.Debugw("Starting CoordNode...")
  63. cn.stopForge = make(chan bool)
  64. cn.stopGetProofCallForge = make(chan bool)
  65. cn.stopForgeCallConfirm = make(chan bool)
  66. queueSize := 8
  67. batchCh0 := make(chan *BatchInfo, queueSize)
  68. batchCh1 := make(chan *BatchInfo, queueSize)
  69. go func() {
  70. for {
  71. select {
  72. case <-cn.stopForge:
  73. return
  74. default:
  75. if forge, err := cn.c.ForgeLoopFn(batchCh0, cn.stopForge); err == ErrStop {
  76. return
  77. } else if err != nil {
  78. log.Errorw("CoordNode ForgeLoopFn", "error", err)
  79. time.Sleep(200 * time.Millisecond) // Avoid overflowing log with errors
  80. } else if !forge {
  81. time.Sleep(200 * time.Millisecond)
  82. }
  83. }
  84. }
  85. }()
  86. go func() {
  87. for {
  88. select {
  89. case <-cn.stopGetProofCallForge:
  90. return
  91. default:
  92. if err := cn.c.GetProofCallForgeLoopFn(
  93. batchCh0, batchCh1, cn.stopGetProofCallForge); err == ErrStop {
  94. return
  95. } else if err != nil {
  96. log.Errorw("CoordNode GetProofCallForgeLoopFn", "error", err)
  97. }
  98. }
  99. }
  100. }()
  101. go func() {
  102. for {
  103. select {
  104. case <-cn.stopForgeCallConfirm:
  105. return
  106. default:
  107. if err := cn.c.ForgeCallConfirmLoopFn(
  108. batchCh1, cn.stopForgeCallConfirm); err == ErrStop {
  109. return
  110. } else if err != nil {
  111. log.Errorw("CoordNode ForgeCallConfirmLoopFn", "error", err)
  112. }
  113. }
  114. }
  115. }()
  116. }
  117. func (cn *CoordNode) Stop() {
  118. log.Debugw("Stopping CoordNode...")
  119. cn.stopForge <- true
  120. cn.stopGetProofCallForge <- true
  121. cn.stopForgeCallConfirm <- true
  122. }
  123. type timer struct {
  124. time int64
  125. }
  126. func (t *timer) Time() int64 {
  127. currentTime := t.time
  128. t.time++
  129. return currentTime
  130. }
  131. func waitForSlot(t *testing.T, c *test.Client, slot int64) {
  132. for {
  133. blockNum, err := c.EthCurrentBlock()
  134. require.Nil(t, err)
  135. nextBlockSlot, err := c.AuctionGetSlotNumber(blockNum + 1)
  136. require.Nil(t, err)
  137. if nextBlockSlot == slot {
  138. break
  139. }
  140. c.CtlMineBlock()
  141. }
  142. }
  143. func TestCoordinator(t *testing.T) {
  144. txsel, bb := newTestModules(t)
  145. conf := Config{}
  146. hdb := &historydb.HistoryDB{}
  147. serverProofs := []ServerProofInterface{&ServerProofMock{}, &ServerProofMock{}}
  148. var timer timer
  149. ethClientSetup := test.NewClientSetupExample()
  150. addr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
  151. ethClient := test.NewClient(true, &timer, &addr, ethClientSetup)
  152. // Bid for slot 2 and 4
  153. _, err := ethClient.AuctionRegisterCoordinator(addr, "https://foo.bar")
  154. require.Nil(t, err)
  155. _, err = ethClient.AuctionBid(2, big.NewInt(9999), addr)
  156. require.Nil(t, err)
  157. _, err = ethClient.AuctionBid(4, big.NewInt(9999), addr)
  158. require.Nil(t, err)
  159. c := NewCoordinator(conf, hdb, txsel, bb, serverProofs, ethClient)
  160. cn := NewCoordNode(c)
  161. cn.Start()
  162. time.Sleep(1 * time.Second)
  163. // simulate forgeSequence time
  164. waitForSlot(t, ethClient, 2)
  165. log.Info("simulate entering in forge time")
  166. time.Sleep(1 * time.Second)
  167. // simulate going out from forgeSequence
  168. waitForSlot(t, ethClient, 3)
  169. log.Info("simulate going out from forge time")
  170. time.Sleep(1 * time.Second)
  171. // simulate entering forgeSequence time again
  172. waitForSlot(t, ethClient, 4)
  173. log.Info("simulate entering in forge time again")
  174. time.Sleep(2 * time.Second)
  175. // simulate stopping forgerLoop by channel
  176. log.Info("simulate stopping forgerLoop by closing coordinator stopch")
  177. cn.Stop()
  178. time.Sleep(1 * time.Second)
  179. }