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