arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/synchronizer/synchronizer_test.go
synchronizer/synchronizer_test.goRaw
  1package synchronizer
  2
  3import (
  4	"context"
  5	"crypto/ecdsa"
  6	"encoding/binary"
  7	"fmt"
  8	"io/ioutil"
  9	"math/big"
 10	"os"
 11	"testing"
 12
 13	ethCommon "github.com/ethereum/go-ethereum/common"
 14	ethCrypto "github.com/ethereum/go-ethereum/crypto"
 15	"github.com/hermeznetwork/hermez-node/common"
 16	dbUtils "github.com/hermeznetwork/hermez-node/db"
 17	"github.com/hermeznetwork/hermez-node/db/historydb"
 18	"github.com/hermeznetwork/hermez-node/db/statedb"
 19	"github.com/hermeznetwork/hermez-node/eth"
 20	"github.com/hermeznetwork/hermez-node/test"
 21	"github.com/iden3/go-iden3-crypto/babyjub"
 22	"github.com/jinzhu/copier"
 23	"github.com/stretchr/testify/assert"
 24	"github.com/stretchr/testify/require"
 25)
 26
 27type timer struct {
 28	time int64
 29}
 30
 31func (t *timer) Time() int64 {
 32	currentTime := t.time
 33	t.time++
 34	return currentTime
 35}
 36
 37type tokenData struct {
 38	TokenID common.TokenID
 39	Addr    ethCommon.Address
 40	Consts  eth.ERC20Consts
 41}
 42
 43func TestSync(t *testing.T) {
 44	ctx := context.Background()
 45	// Int State DB
 46	dir, err := ioutil.TempDir("", "tmpdb")
 47	require.Nil(t, err)
 48	defer assert.Nil(t, os.RemoveAll(dir))
 49
 50	stateDB, err := statedb.NewStateDB(dir, statedb.TypeSynchronizer, 32)
 51	assert.Nil(t, err)
 52
 53	// Init History DB
 54	pass := os.Getenv("POSTGRES_PASS")
 55	db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
 56	require.Nil(t, err)
 57	historyDB := historydb.NewHistoryDB(db)
 58	// Clear DB
 59	err = historyDB.Reorg(-1)
 60	assert.Nil(t, err)
 61
 62	// Init eth client
 63	var timer timer
 64	clientSetup := test.NewClientSetupExample()
 65	client := test.NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
 66
 67	// Create Synchronizer
 68	s, err := NewSynchronizer(client, historyDB, stateDB)
 69	require.Nil(t, err)
 70
 71	// Test Sync for rollup genesis block
 72	blockData, _, err := s.Sync2(ctx, nil)
 73	require.Nil(t, err)
 74	require.NotNil(t, blockData)
 75	assert.Equal(t, int64(1), blockData.Block.EthBlockNum)
 76	blocks, err := s.historyDB.GetBlocks(0, 9999)
 77	require.Nil(t, err)
 78	assert.Equal(t, 1, len(blocks))
 79	assert.Equal(t, int64(1), blocks[0].EthBlockNum)
 80
 81	/*
 82		// Test Sync for a block with new Tokens and L1UserTxs
 83		// accounts := test.GenerateKeys(t, []string{"A", "B", "C", "D"})
 84		l1UserTxs, _, _, _ := test.GenerateTestTxsFromSet(t, `
 85		A (1): 10
 86		A (2): 20
 87		B (1): 5
 88		C (1): 8
 89		D (3): 15
 90		> advance batch
 91			`)
 92		require.Greater(t, len(l1UserTxs[0]), 0)
 93			// require.Greater(t, len(tokens), 0)
 94
 95			for i := 1; i <= 3; i++ {
 96				_, err := client.RollupAddToken(ethCommon.BigToAddress(big.NewInt(int64(i*10000))),
 97					clientSetup.RollupVariables.FeeAddToken)
 98				require.Nil(t, err)
 99			}
100
101			for i := range l1UserTxs[0] {
102				client.CtlAddL1TxUser(&l1UserTxs[0][i])
103			}
104			client.CtlMineBlock()
105
106			err = s.Sync(context.Background())
107			require.Nil(t, err)
108
109			getTokens, err := s.historyDB.GetTokens()
110			require.Nil(t, err)
111			assert.Equal(t, 3, len(getTokens))
112	*/
113
114	// Generate tokens vector
115	numTokens := 3
116	tokens := make([]tokenData, numTokens)
117	for i := 1; i <= numTokens; i++ {
118		addr := ethCommon.BigToAddress(big.NewInt(int64(i * 10000)))
119		consts := eth.ERC20Consts{
120			Name:     fmt.Sprintf("Token %d", i),
121			Symbol:   fmt.Sprintf("TK%d", i),
122			Decimals: uint64(i * 2),
123		}
124		tokens[i-1] = tokenData{common.TokenID(i), addr, consts}
125	}
126
127	numUsers := 4
128	keys := make([]*userKeys, numUsers)
129	for i := range keys {
130		keys[i] = genKeys(i)
131	}
132
133	// Generate some L1UserTxs of type deposit
134	l1UserTxs := make([]*common.L1Tx, 5)
135	for i := range l1UserTxs {
136		l1UserTxs[i] = &common.L1Tx{
137			FromIdx:     common.Idx(0),
138			FromEthAddr: keys[i%numUsers].Addr,
139			FromBJJ:     keys[i%numUsers].BJJPK,
140			Amount:      big.NewInt(0),
141			LoadAmount:  big.NewInt((int64(i) + 1) * 1000),
142			TokenID:     common.TokenID(i%numTokens + 1),
143		}
144	}
145
146	// Add tokens to ethereum, and to rollup
147	for _, token := range tokens {
148		client.CtlAddERC20(token.Addr, token.Consts)
149		_, err := client.RollupAddToken(token.Addr, clientSetup.RollupVariables.FeeAddToken)
150		require.Nil(t, err)
151	}
152
153	// Add L1Txs to rollup
154	for i := range l1UserTxs {
155		tx := l1UserTxs[i]
156		_, err := client.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.LoadAmount, tx.Amount,
157			uint32(tx.TokenID), int64(tx.ToIdx))
158		require.Nil(t, err)
159	}
160
161	// Mine block and sync
162	client.CtlMineBlock()
163
164	blockData, _, err = s.Sync2(ctx, nil)
165	require.Nil(t, err)
166	require.NotNil(t, blockData)
167	assert.Equal(t, int64(2), blockData.Block.EthBlockNum)
168
169	// Check tokens in DB
170	dbTokens, err := s.historyDB.GetAllTokens()
171	require.Nil(t, err)
172	assert.Equal(t, len(tokens), len(dbTokens))
173	assert.Equal(t, len(tokens), len(blockData.AddedTokens))
174	for i := range tokens {
175		token := tokens[i]
176		addToken := blockData.AddedTokens[i]
177		dbToken := dbTokens[i]
178
179		assert.Equal(t, int64(2), addToken.EthBlockNum)
180		assert.Equal(t, token.TokenID, addToken.TokenID)
181		assert.Equal(t, token.Addr, addToken.EthAddr)
182		assert.Equal(t, token.Consts.Name, addToken.Name)
183		assert.Equal(t, token.Consts.Symbol, addToken.Symbol)
184		assert.Equal(t, token.Consts.Decimals, addToken.Decimals)
185
186		var addTokenCpy historydb.TokenRead
187		require.Nil(t, copier.Copy(&addTokenCpy, &addToken)) // copy common.Token to historydb.TokenRead
188		addTokenCpy.ItemID = dbToken.ItemID                  // we don't care about ItemID
189		assert.Equal(t, addTokenCpy, dbToken)
190	}
191
192	// Check L1UserTxs in DB
193
194	// TODO: Reorg will be properly tested once we have the mock ethClient implemented
195	/*
196		// Force a Reorg
197		lastSavedBlock, err := historyDB.GetLastBlock()
198		require.Nil(t, err)
199
200		lastSavedBlock.EthBlockNum++
201		err = historyDB.AddBlock(lastSavedBlock)
202		require.Nil(t, err)
203
204		lastSavedBlock.EthBlockNum++
205		err = historyDB.AddBlock(lastSavedBlock)
206		require.Nil(t, err)
207
208		log.Debugf("Wait for the blockchain to generate some blocks...")
209		time.Sleep(40 * time.Second)
210
211
212		err = s.Sync()
213		require.Nil(t, err)
214	*/
215}
216
217type userKeys struct {
218	BJJSK *babyjub.PrivateKey
219	BJJPK *babyjub.PublicKey
220	Addr  ethCommon.Address
221}
222
223func genKeys(i int) *userKeys {
224	i++ // i = 0 doesn't work for the ecdsa key generation
225	var sk babyjub.PrivateKey
226	binary.LittleEndian.PutUint64(sk[:], uint64(i))
227
228	// eth address
229	var key ecdsa.PrivateKey
230	key.D = big.NewInt(int64(i)) // only for testing
231	key.PublicKey.X, key.PublicKey.Y = ethCrypto.S256().ScalarBaseMult(key.D.Bytes())
232	key.Curve = ethCrypto.S256()
233	addr := ethCrypto.PubkeyToAddress(key.PublicKey)
234
235	return &userKeys{
236		BJJSK: &sk,
237		BJJPK: sk.Public(),
238		Addr:  addr,
239	}
240}