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