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}