arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/db/statedb/statedb_test.go
db/statedb/statedb_test.goRaw
  1package statedb
  2
  3import (
  4	"encoding/hex"
  5	"fmt"
  6	"io/ioutil"
  7	"math/big"
  8	"os"
  9	"strings"
 10	"testing"
 11
 12	ethCommon "github.com/ethereum/go-ethereum/common"
 13	ethCrypto "github.com/ethereum/go-ethereum/crypto"
 14	"github.com/hermeznetwork/hermez-node/common"
 15	"github.com/hermeznetwork/hermez-node/log"
 16	"github.com/hermeznetwork/tracerr"
 17	"github.com/iden3/go-iden3-crypto/babyjub"
 18	"github.com/iden3/go-merkletree/db"
 19	"github.com/stretchr/testify/assert"
 20	"github.com/stretchr/testify/require"
 21)
 22
 23func newAccount(t *testing.T, i int) *common.Account {
 24	var sk babyjub.PrivateKey
 25	_, err := hex.Decode(sk[:],
 26		[]byte("0001020304050607080900010203040506070809000102030405060708090001"))
 27	require.NoError(t, err)
 28	pk := sk.Public()
 29
 30	key, err := ethCrypto.GenerateKey()
 31	require.NoError(t, err)
 32	address := ethCrypto.PubkeyToAddress(key.PublicKey)
 33
 34	return &common.Account{
 35		Idx:     common.Idx(256 + i),
 36		TokenID: common.TokenID(i),
 37		Nonce:   common.Nonce(i),
 38		Balance: big.NewInt(1000),
 39		BJJ:     pk.Compress(),
 40		EthAddr: address,
 41	}
 42}
 43
 44func TestNewStateDBIntermediateState(t *testing.T) {
 45	dir, err := ioutil.TempDir("", "tmpdb")
 46	require.NoError(t, err)
 47	defer require.NoError(t, os.RemoveAll(dir))
 48
 49	sdb, err := NewStateDB(Config{Path: dir, Keep: 128, Type: TypeTxSelector, NLevels: 0})
 50	require.NoError(t, err)
 51
 52	// test values
 53	k0 := []byte("testkey0")
 54	k1 := []byte("testkey1")
 55	v0 := []byte("testvalue0")
 56	v1 := []byte("testvalue1")
 57
 58	// store some data
 59	tx, err := sdb.db.DB().NewTx()
 60	require.NoError(t, err)
 61	err = tx.Put(k0, v0)
 62	require.NoError(t, err)
 63	err = tx.Commit()
 64	require.NoError(t, err)
 65	v, err := sdb.db.DB().Get(k0)
 66	require.NoError(t, err)
 67	assert.Equal(t, v0, v)
 68
 69	// k0 not yet in last
 70	err = sdb.LastRead(func(sdb *Last) error {
 71		_, err := sdb.DB().Get(k0)
 72		assert.Equal(t, db.ErrNotFound, tracerr.Unwrap(err))
 73		return nil
 74	})
 75	require.NoError(t, err)
 76
 77	// Close PebbleDB before creating a new StateDB
 78	sdb.Close()
 79
 80	// call NewStateDB which should get the db at the last checkpoint state
 81	// executing a Reset (discarding the last 'testkey0'&'testvalue0' data)
 82	sdb, err = NewStateDB(Config{Path: dir, Keep: 128, Type: TypeTxSelector, NLevels: 0})
 83	require.NoError(t, err)
 84	v, err = sdb.db.DB().Get(k0)
 85	assert.NotNil(t, err)
 86	assert.Equal(t, db.ErrNotFound, tracerr.Unwrap(err))
 87	assert.Nil(t, v)
 88
 89	// k0 not in last
 90	err = sdb.LastRead(func(sdb *Last) error {
 91		_, err := sdb.DB().Get(k0)
 92		assert.Equal(t, db.ErrNotFound, tracerr.Unwrap(err))
 93		return nil
 94	})
 95	require.NoError(t, err)
 96
 97	// store the same data from the beginning that has ben lost since last NewStateDB
 98	tx, err = sdb.db.DB().NewTx()
 99	require.NoError(t, err)
100	err = tx.Put(k0, v0)
101	require.NoError(t, err)
102	err = tx.Commit()
103	require.NoError(t, err)
104	v, err = sdb.db.DB().Get(k0)
105	require.NoError(t, err)
106	assert.Equal(t, v0, v)
107
108	// k0 yet not in last
109	err = sdb.LastRead(func(sdb *Last) error {
110		_, err := sdb.DB().Get(k0)
111		assert.Equal(t, db.ErrNotFound, tracerr.Unwrap(err))
112		return nil
113	})
114	require.NoError(t, err)
115
116	// make checkpoints with the current state
117	bn, err := sdb.getCurrentBatch()
118	require.NoError(t, err)
119	assert.Equal(t, common.BatchNum(0), bn)
120	err = sdb.MakeCheckpoint()
121	require.NoError(t, err)
122	bn, err = sdb.getCurrentBatch()
123	require.NoError(t, err)
124	assert.Equal(t, common.BatchNum(1), bn)
125
126	// k0 in last
127	err = sdb.LastRead(func(sdb *Last) error {
128		v, err := sdb.DB().Get(k0)
129		require.NoError(t, err)
130		assert.Equal(t, v0, v)
131		return nil
132	})
133	require.NoError(t, err)
134
135	// write more data
136	tx, err = sdb.db.DB().NewTx()
137	require.NoError(t, err)
138	err = tx.Put(k1, v1)
139	require.NoError(t, err)
140	err = tx.Put(k0, v1) // overwrite k0 with v1
141	require.NoError(t, err)
142	err = tx.Commit()
143	require.NoError(t, err)
144
145	v, err = sdb.db.DB().Get(k1)
146	require.NoError(t, err)
147	assert.Equal(t, v1, v)
148
149	err = sdb.LastRead(func(sdb *Last) error {
150		v, err := sdb.DB().Get(k0)
151		require.NoError(t, err)
152		assert.Equal(t, v0, v)
153		return nil
154	})
155	require.NoError(t, err)
156
157	// Close PebbleDB before creating a new StateDB
158	sdb.Close()
159
160	// call NewStateDB which should get the db at the last checkpoint state
161	// executing a Reset (discarding the last 'testkey1'&'testvalue1' data)
162	sdb, err = NewStateDB(Config{Path: dir, Keep: 128, Type: TypeTxSelector, NLevels: 0})
163	require.NoError(t, err)
164
165	bn, err = sdb.getCurrentBatch()
166	require.NoError(t, err)
167	assert.Equal(t, common.BatchNum(1), bn)
168
169	// we closed the db without doing a checkpoint after overwriting k0, so
170	// it's back to v0
171	v, err = sdb.db.DB().Get(k0)
172	require.NoError(t, err)
173	assert.Equal(t, v0, v)
174
175	v, err = sdb.db.DB().Get(k1)
176	assert.NotNil(t, err)
177	assert.Equal(t, db.ErrNotFound, tracerr.Unwrap(err))
178	assert.Nil(t, v)
179}
180
181func TestStateDBWithoutMT(t *testing.T) {
182	dir, err := ioutil.TempDir("", "tmpdb")
183	require.NoError(t, err)
184	defer require.NoError(t, os.RemoveAll(dir))
185
186	sdb, err := NewStateDB(Config{Path: dir, Keep: 128, Type: TypeTxSelector, NLevels: 0})
187	require.NoError(t, err)
188
189	// create test accounts
190	var accounts []*common.Account
191	for i := 0; i < 4; i++ {
192		accounts = append(accounts, newAccount(t, i))
193	}
194
195	// get non-existing account, expecting an error
196	unexistingAccount := common.Idx(1)
197	_, err = sdb.GetAccount(unexistingAccount)
198	assert.NotNil(t, err)
199	assert.Equal(t, db.ErrNotFound, tracerr.Unwrap(err))
200
201	// add test accounts
202	for i := 0; i < len(accounts); i++ {
203		_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
204		require.NoError(t, err)
205	}
206
207	for i := 0; i < len(accounts); i++ {
208		existingAccount := accounts[i].Idx
209		accGetted, err := sdb.GetAccount(existingAccount)
210		require.NoError(t, err)
211		assert.Equal(t, accounts[i], accGetted)
212	}
213
214	// try already existing idx and get error
215	existingAccount := common.Idx(256)
216	_, err = sdb.GetAccount(existingAccount) // check that exist
217	require.NoError(t, err)
218	_, err = sdb.CreateAccount(common.Idx(256), accounts[1]) // check that can not be created twice
219	assert.NotNil(t, err)
220	assert.Equal(t, ErrAccountAlreadyExists, tracerr.Unwrap(err))
221
222	// update accounts
223	for i := 0; i < len(accounts); i++ {
224		accounts[i].Nonce = accounts[i].Nonce + 1
225		existingAccount = common.Idx(i)
226		_, err = sdb.UpdateAccount(existingAccount, accounts[i])
227		require.NoError(t, err)
228	}
229
230	_, err = sdb.MTGetProof(common.Idx(1))
231	assert.NotNil(t, err)
232	assert.Equal(t, ErrStateDBWithoutMT, tracerr.Unwrap(err))
233}
234
235func TestStateDBWithMT(t *testing.T) {
236	dir, err := ioutil.TempDir("", "tmpdb")
237	require.NoError(t, err)
238	defer require.NoError(t, os.RemoveAll(dir))
239
240	sdb, err := NewStateDB(Config{Path: dir, Keep: 128, Type: TypeSynchronizer, NLevels: 32})
241	require.NoError(t, err)
242
243	// create test accounts
244	var accounts []*common.Account
245	for i := 0; i < 20; i++ {
246		accounts = append(accounts, newAccount(t, i))
247	}
248
249	// get non-existing account, expecting an error
250	_, err = sdb.GetAccount(common.Idx(1))
251	assert.NotNil(t, err)
252	assert.Equal(t, db.ErrNotFound, tracerr.Unwrap(err))
253
254	// add test accounts
255	for i := 0; i < len(accounts); i++ {
256		_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
257		require.NoError(t, err)
258	}
259
260	for i := 0; i < len(accounts); i++ {
261		accGetted, err := sdb.GetAccount(accounts[i].Idx)
262		require.NoError(t, err)
263		assert.Equal(t, accounts[i], accGetted)
264	}
265
266	// try already existing idx and get error
267	_, err = sdb.GetAccount(common.Idx(256)) // check that exist
268	require.NoError(t, err)
269	_, err = sdb.CreateAccount(common.Idx(256), accounts[1]) // check that can not be created twice
270	assert.NotNil(t, err)
271	assert.Equal(t, ErrAccountAlreadyExists, tracerr.Unwrap(err))
272
273	_, err = sdb.MTGetProof(common.Idx(256))
274	require.NoError(t, err)
275
276	// update accounts
277	for i := 0; i < len(accounts); i++ {
278		accounts[i].Nonce = accounts[i].Nonce + 1
279		_, err = sdb.UpdateAccount(accounts[i].Idx, accounts[i])
280		require.NoError(t, err)
281	}
282	a, err := sdb.GetAccount(common.Idx(256)) // check that account value has been updated
283	require.NoError(t, err)
284	assert.Equal(t, accounts[0].Nonce, a.Nonce)
285}
286
287// TestCheckpoints performs almost the same test than kvdb/kvdb_test.go
288// TestCheckpoints, but over the StateDB
289func TestCheckpoints(t *testing.T) {
290	dir, err := ioutil.TempDir("", "sdb")
291	require.NoError(t, err)
292	defer require.NoError(t, os.RemoveAll(dir))
293
294	sdb, err := NewStateDB(Config{Path: dir, Keep: 128, Type: TypeSynchronizer, NLevels: 32})
295	require.NoError(t, err)
296
297	err = sdb.Reset(0)
298	require.NoError(t, err)
299
300	// create test accounts
301	var accounts []*common.Account
302	for i := 0; i < 10; i++ {
303		accounts = append(accounts, newAccount(t, i))
304	}
305
306	// add test accounts
307	for i := 0; i < len(accounts); i++ {
308		_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
309		require.NoError(t, err)
310	}
311	// account doesn't exist in Last checkpoint
312	_, err = sdb.LastGetAccount(accounts[0].Idx)
313	assert.Equal(t, db.ErrNotFound, tracerr.Unwrap(err))
314
315	// do checkpoints and check that currentBatch is correct
316	err = sdb.MakeCheckpoint()
317	require.NoError(t, err)
318	cb, err := sdb.getCurrentBatch()
319	require.NoError(t, err)
320	assert.Equal(t, common.BatchNum(1), cb)
321
322	// account exists in Last checkpoint
323	accCur, err := sdb.GetAccount(accounts[0].Idx)
324	require.NoError(t, err)
325	accLast, err := sdb.LastGetAccount(accounts[0].Idx)
326	require.NoError(t, err)
327	assert.Equal(t, accounts[0], accLast)
328	assert.Equal(t, accCur, accLast)
329
330	for i := 1; i < 10; i++ {
331		err = sdb.MakeCheckpoint()
332		require.NoError(t, err)
333
334		cb, err = sdb.getCurrentBatch()
335		require.NoError(t, err)
336		assert.Equal(t, common.BatchNum(i+1), cb)
337	}
338
339	// printCheckpoints(t, sdb.cfg.Path)
340
341	// reset checkpoint
342	err = sdb.Reset(3)
343	require.NoError(t, err)
344
345	// check that reset can be repeated (as there exist the 'current' and
346	// 'BatchNum3', from where the 'current' is a copy)
347	err = sdb.Reset(3)
348	require.NoError(t, err)
349
350	// check that currentBatch is as expected after Reset
351	cb, err = sdb.getCurrentBatch()
352	require.NoError(t, err)
353	assert.Equal(t, common.BatchNum(3), cb)
354
355	// advance one checkpoint and check that currentBatch is fine
356	err = sdb.MakeCheckpoint()
357	require.NoError(t, err)
358	cb, err = sdb.getCurrentBatch()
359	require.NoError(t, err)
360	assert.Equal(t, common.BatchNum(4), cb)
361
362	err = sdb.db.DeleteCheckpoint(common.BatchNum(1))
363	require.NoError(t, err)
364	err = sdb.db.DeleteCheckpoint(common.BatchNum(2))
365	require.NoError(t, err)
366	err = sdb.db.DeleteCheckpoint(common.BatchNum(1)) // does not exist, should return err
367	assert.NotNil(t, err)
368	err = sdb.db.DeleteCheckpoint(common.BatchNum(2)) // does not exist, should return err
369	assert.NotNil(t, err)
370
371	// Create a LocalStateDB from the initial StateDB
372	dirLocal, err := ioutil.TempDir("", "ldb")
373	require.NoError(t, err)
374	defer require.NoError(t, os.RemoveAll(dirLocal))
375	ldb, err := NewLocalStateDB(Config{Path: dirLocal, Keep: 128, Type: TypeBatchBuilder,
376		NLevels: 32}, sdb)
377	require.NoError(t, err)
378
379	// get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
380	err = ldb.Reset(4, true)
381	require.NoError(t, err)
382	// check that currentBatch is 4 after the Reset
383	cb, err = ldb.getCurrentBatch()
384	require.NoError(t, err)
385	assert.Equal(t, common.BatchNum(4), cb)
386	// advance one checkpoint in ldb
387	err = ldb.MakeCheckpoint()
388	require.NoError(t, err)
389	cb, err = ldb.getCurrentBatch()
390	require.NoError(t, err)
391	assert.Equal(t, common.BatchNum(5), cb)
392
393	// Create a 2nd LocalStateDB from the initial StateDB
394	dirLocal2, err := ioutil.TempDir("", "ldb2")
395	require.NoError(t, err)
396	defer require.NoError(t, os.RemoveAll(dirLocal2))
397	ldb2, err := NewLocalStateDB(Config{Path: dirLocal2, Keep: 128, Type: TypeBatchBuilder,
398		NLevels: 32}, sdb)
399	require.NoError(t, err)
400
401	// get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
402	err = ldb2.Reset(4, true)
403	require.NoError(t, err)
404	// check that currentBatch is 4 after the Reset
405	cb = ldb2.CurrentBatch()
406	assert.Equal(t, common.BatchNum(4), cb)
407	// advance one checkpoint in ldb2
408	err = ldb2.MakeCheckpoint()
409	require.NoError(t, err)
410	cb = ldb2.CurrentBatch()
411	assert.Equal(t, common.BatchNum(5), cb)
412
413	debug := false
414	if debug {
415		printCheckpoints(t, sdb.cfg.Path)
416		printCheckpoints(t, ldb.cfg.Path)
417		printCheckpoints(t, ldb2.cfg.Path)
418	}
419}
420
421func TestStateDBGetAccounts(t *testing.T) {
422	dir, err := ioutil.TempDir("", "tmpdb")
423	require.NoError(t, err)
424
425	sdb, err := NewStateDB(Config{Path: dir, Keep: 128, Type: TypeTxSelector, NLevels: 0})
426	require.NoError(t, err)
427
428	// create test accounts
429	var accounts []common.Account
430	for i := 0; i < 16; i++ {
431		account := newAccount(t, i)
432		accounts = append(accounts, *account)
433	}
434
435	// add test accounts
436	for i := range accounts {
437		_, err = sdb.CreateAccount(accounts[i].Idx, &accounts[i])
438		require.NoError(t, err)
439	}
440
441	dbAccounts, err := sdb.TestGetAccounts()
442	require.NoError(t, err)
443	assert.Equal(t, accounts, dbAccounts)
444}
445
446func printCheckpoints(t *testing.T, path string) {
447	files, err := ioutil.ReadDir(path)
448	require.NoError(t, err)
449
450	fmt.Println(path)
451	for _, f := range files {
452		fmt.Println("	" + f.Name())
453	}
454}
455
456func bigFromStr(h string, u int) *big.Int {
457	if u == 16 {
458		h = strings.TrimPrefix(h, "0x")
459	}
460	b, ok := new(big.Int).SetString(h, u)
461	if !ok {
462		panic("bigFromStr err")
463	}
464	return b
465}
466
467func TestCheckAccountsTreeTestVectors(t *testing.T) {
468	dir, err := ioutil.TempDir("", "tmpdb")
469	require.NoError(t, err)
470	defer require.NoError(t, os.RemoveAll(dir))
471
472	sdb, err := NewStateDB(Config{Path: dir, Keep: 128, Type: TypeSynchronizer, NLevels: 32})
473	require.NoError(t, err)
474
475	ay0 := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(253), nil), big.NewInt(1))
476	// test value from js version (compatibility-canary)
477	assert.Equal(t, "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
478		(hex.EncodeToString(ay0.Bytes())))
479	bjjPoint0Comp := babyjub.PackSignY(true, ay0)
480	bjj0 := babyjub.PublicKeyComp(bjjPoint0Comp)
481
482	ay1 := bigFromStr("00", 16)
483	bjjPoint1Comp := babyjub.PackSignY(false, ay1)
484	bjj1 := babyjub.PublicKeyComp(bjjPoint1Comp)
485	ay2 := bigFromStr("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7", 16)
486	bjjPoint2Comp := babyjub.PackSignY(false, ay2)
487	bjj2 := babyjub.PublicKeyComp(bjjPoint2Comp)
488
489	ay3 := bigFromStr("0x10", 16) // 0x10=16
490	bjjPoint3Comp := babyjub.PackSignY(false, ay3)
491	require.NoError(t, err)
492	bjj3 := babyjub.PublicKeyComp(bjjPoint3Comp)
493	accounts := []*common.Account{
494		{
495			Idx:     1,
496			TokenID: 0xFFFFFFFF,
497			BJJ:     bjj0,
498			EthAddr: ethCommon.HexToAddress("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
499			Nonce:   common.Nonce(0xFFFFFFFFFF),
500			Balance: bigFromStr("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16),
501		},
502		{
503			Idx:     100,
504			TokenID: 0,
505			BJJ:     bjj1,
506			EthAddr: ethCommon.HexToAddress("0x00"),
507			Nonce:   common.Nonce(0),
508			Balance: bigFromStr("0", 10),
509		},
510		{
511			Idx:     0xFFFFFFFFFFFF,
512			TokenID: 3,
513			BJJ:     bjj2,
514			EthAddr: ethCommon.HexToAddress("0xA3C88ac39A76789437AED31B9608da72e1bbfBF9"),
515			Nonce:   common.Nonce(129),
516			Balance: bigFromStr("42000000000000000000", 10),
517		},
518		{
519			Idx:     10000,
520			TokenID: 1000,
521			BJJ:     bjj3,
522			EthAddr: ethCommon.HexToAddress("0x64"),
523			Nonce:   common.Nonce(1900),
524			Balance: bigFromStr("14000000000000000000", 10),
525		},
526	}
527	for i := 0; i < len(accounts); i++ {
528		_, err = accounts[i].HashValue()
529		require.NoError(t, err)
530		_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
531		if err != nil {
532			log.Error(err)
533		}
534		require.NoError(t, err)
535	}
536	// root value generated by js version:
537	assert.Equal(t,
538		"13174362770971232417413036794215823584762073355951212910715422236001731746065",
539		sdb.MT.Root().BigInt().String())
540}
541
542// TestListCheckpoints performs almost the same test than kvdb/kvdb_test.go
543// TestListCheckpoints, but over the StateDB
544func TestListCheckpoints(t *testing.T) {
545	dir, err := ioutil.TempDir("", "tmpdb")
546	require.NoError(t, err)
547	defer require.NoError(t, os.RemoveAll(dir))
548
549	sdb, err := NewStateDB(Config{Path: dir, Keep: 128, Type: TypeSynchronizer, NLevels: 32})
550	require.NoError(t, err)
551
552	numCheckpoints := 16
553	// do checkpoints
554	for i := 0; i < numCheckpoints; i++ {
555		err = sdb.MakeCheckpoint()
556		require.NoError(t, err)
557	}
558	list, err := sdb.db.ListCheckpoints()
559	require.NoError(t, err)
560	assert.Equal(t, numCheckpoints, len(list))
561	assert.Equal(t, 1, list[0])
562	assert.Equal(t, numCheckpoints, list[len(list)-1])
563
564	numReset := 10
565	err = sdb.Reset(common.BatchNum(numReset))
566	require.NoError(t, err)
567	list, err = sdb.db.ListCheckpoints()
568	require.NoError(t, err)
569	assert.Equal(t, numReset, len(list))
570	assert.Equal(t, 1, list[0])
571	assert.Equal(t, numReset, list[len(list)-1])
572}
573
574// TestDeleteOldCheckpoints performs almost the same test than
575// kvdb/kvdb_test.go TestDeleteOldCheckpoints, but over the StateDB
576func TestDeleteOldCheckpoints(t *testing.T) {
577	dir, err := ioutil.TempDir("", "tmpdb")
578	require.NoError(t, err)
579	defer require.NoError(t, os.RemoveAll(dir))
580
581	keep := 16
582	sdb, err := NewStateDB(Config{Path: dir, Keep: keep, Type: TypeSynchronizer, NLevels: 32})
583	require.NoError(t, err)
584
585	numCheckpoints := 32
586	// do checkpoints and check that we never have more than `keep`
587	// checkpoints
588	for i := 0; i < numCheckpoints; i++ {
589		err = sdb.MakeCheckpoint()
590		require.NoError(t, err)
591		checkpoints, err := sdb.db.ListCheckpoints()
592		require.NoError(t, err)
593		assert.LessOrEqual(t, len(checkpoints), keep)
594	}
595}
596
597func TestCurrentIdx(t *testing.T) {
598	dir, err := ioutil.TempDir("", "tmpdb")
599	require.NoError(t, err)
600	defer require.NoError(t, os.RemoveAll(dir))
601
602	keep := 16
603	sdb, err := NewStateDB(Config{Path: dir, Keep: keep, Type: TypeSynchronizer, NLevels: 32})
604	require.NoError(t, err)
605
606	idx := sdb.CurrentIdx()
607	assert.Equal(t, common.Idx(255), idx)
608
609	sdb.Close()
610
611	sdb, err = NewStateDB(Config{Path: dir, Keep: keep, Type: TypeSynchronizer, NLevels: 32})
612	require.NoError(t, err)
613
614	idx = sdb.CurrentIdx()
615	assert.Equal(t, common.Idx(255), idx)
616
617	err = sdb.MakeCheckpoint()
618	require.NoError(t, err)
619
620	idx = sdb.CurrentIdx()
621	assert.Equal(t, common.Idx(255), idx)
622
623	sdb.Close()
624
625	sdb, err = NewStateDB(Config{Path: dir, Keep: keep, Type: TypeSynchronizer, NLevels: 32})
626	require.NoError(t, err)
627
628	idx = sdb.CurrentIdx()
629	assert.Equal(t, common.Idx(255), idx)
630}
631
632func TestResetFromBadCheckpoint(t *testing.T) {
633	dir, err := ioutil.TempDir("", "tmpdb")
634	require.NoError(t, err)
635	defer require.NoError(t, os.RemoveAll(dir))
636
637	keep := 16
638	sdb, err := NewStateDB(Config{Path: dir, Keep: keep, Type: TypeSynchronizer, NLevels: 32})
639	require.NoError(t, err)
640
641	err = sdb.MakeCheckpoint()
642	require.NoError(t, err)
643	err = sdb.MakeCheckpoint()
644	require.NoError(t, err)
645	err = sdb.MakeCheckpoint()
646	require.NoError(t, err)
647
648	// reset from a checkpoint that doesn't exist
649	err = sdb.Reset(10)
650	require.Error(t, err)
651}