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