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(dir, 128, TypeTxSelector, 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(dir, 128, TypeTxSelector, 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.db.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(dir, 128, TypeTxSelector, 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(dir, 128, TypeTxSelector, 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(dir, 128, TypeSynchronizer, 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(dir, 128, TypeSynchronizer, 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.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(dirLocal, 128, sdb, TypeBatchBuilder, 32)
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(dirLocal2, 128, sdb, TypeBatchBuilder, 32)
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, err = ldb2.db.GetCurrentBatch()
403	require.NoError(t, err)
404	assert.Equal(t, common.BatchNum(4), cb)
405	// advance one checkpoint in ldb2
406	err = ldb2.db.MakeCheckpoint()
407	require.NoError(t, err)
408	cb, err = ldb2.db.GetCurrentBatch()
409	require.NoError(t, err)
410	assert.Equal(t, common.BatchNum(5), cb)
411
412	debug := false
413	if debug {
414		printCheckpoints(t, sdb.path)
415		printCheckpoints(t, ldb.path)
416		printCheckpoints(t, ldb2.path)
417	}
418}
419
420func TestStateDBGetAccounts(t *testing.T) {
421	dir, err := ioutil.TempDir("", "tmpdb")
422	require.NoError(t, err)
423
424	sdb, err := NewStateDB(dir, 128, TypeTxSelector, 0)
425	require.NoError(t, err)
426
427	// create test accounts
428	var accounts []common.Account
429	for i := 0; i < 16; i++ {
430		account := newAccount(t, i)
431		accounts = append(accounts, *account)
432	}
433
434	// add test accounts
435	for i := range accounts {
436		_, err = sdb.CreateAccount(accounts[i].Idx, &accounts[i])
437		require.NoError(t, err)
438	}
439
440	dbAccounts, err := sdb.TestGetAccounts()
441	require.NoError(t, err)
442	assert.Equal(t, accounts, dbAccounts)
443}
444
445func printCheckpoints(t *testing.T, path string) {
446	files, err := ioutil.ReadDir(path)
447	require.NoError(t, err)
448
449	fmt.Println(path)
450	for _, f := range files {
451		fmt.Println("	" + f.Name())
452	}
453}
454
455func bigFromStr(h string, u int) *big.Int {
456	if u == 16 {
457		h = strings.TrimPrefix(h, "0x")
458	}
459	b, ok := new(big.Int).SetString(h, u)
460	if !ok {
461		panic("bigFromStr err")
462	}
463	return b
464}
465
466func TestCheckAccountsTreeTestVectors(t *testing.T) {
467	dir, err := ioutil.TempDir("", "tmpdb")
468	require.NoError(t, err)
469	defer require.NoError(t, os.RemoveAll(dir))
470
471	sdb, err := NewStateDB(dir, 128, TypeSynchronizer, 32)
472	require.NoError(t, err)
473
474	ay0 := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(253), nil), big.NewInt(1))
475	// test value from js version (compatibility-canary)
476	assert.Equal(t, "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", (hex.EncodeToString(ay0.Bytes())))
477	bjjPoint0Comp := babyjub.PackSignY(true, ay0)
478	bjj0 := babyjub.PublicKeyComp(bjjPoint0Comp)
479
480	ay1 := bigFromStr("00", 16)
481	bjjPoint1Comp := babyjub.PackSignY(false, ay1)
482	bjj1 := babyjub.PublicKeyComp(bjjPoint1Comp)
483	ay2 := bigFromStr("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7", 16)
484	bjjPoint2Comp := babyjub.PackSignY(false, ay2)
485	bjj2 := babyjub.PublicKeyComp(bjjPoint2Comp)
486
487	ay3 := bigFromStr("0x10", 16) // 0x10=16
488	bjjPoint3Comp := babyjub.PackSignY(false, ay3)
489	require.NoError(t, err)
490	bjj3 := babyjub.PublicKeyComp(bjjPoint3Comp)
491	accounts := []*common.Account{
492		{
493			Idx:     1,
494			TokenID: 0xFFFFFFFF,
495			BJJ:     bjj0,
496			EthAddr: ethCommon.HexToAddress("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
497			Nonce:   common.Nonce(0xFFFFFFFFFF),
498			Balance: bigFromStr("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16),
499		},
500		{
501			Idx:     100,
502			TokenID: 0,
503			BJJ:     bjj1,
504			EthAddr: ethCommon.HexToAddress("0x00"),
505			Nonce:   common.Nonce(0),
506			Balance: bigFromStr("0", 10),
507		},
508		{
509			Idx:     0xFFFFFFFFFFFF,
510			TokenID: 3,
511			BJJ:     bjj2,
512			EthAddr: ethCommon.HexToAddress("0xA3C88ac39A76789437AED31B9608da72e1bbfBF9"),
513			Nonce:   common.Nonce(129),
514			Balance: bigFromStr("42000000000000000000", 10),
515		},
516		{
517			Idx:     10000,
518			TokenID: 1000,
519			BJJ:     bjj3,
520			EthAddr: ethCommon.HexToAddress("0x64"),
521			Nonce:   common.Nonce(1900),
522			Balance: bigFromStr("14000000000000000000", 10),
523		},
524	}
525	for i := 0; i < len(accounts); i++ {
526		_, err = accounts[i].HashValue()
527		require.NoError(t, err)
528		_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
529		if err != nil {
530			log.Error(err)
531		}
532		require.NoError(t, err)
533	}
534	// root value generated by js version:
535	assert.Equal(t, "17298264051379321456969039521810887093935433569451713402227686942080129181291", sdb.MT.Root().BigInt().String())
536}
537
538// TestListCheckpoints performs almost the same test than kvdb/kvdb_test.go
539// TestListCheckpoints, but over the StateDB
540func TestListCheckpoints(t *testing.T) {
541	dir, err := ioutil.TempDir("", "tmpdb")
542	require.NoError(t, err)
543	defer require.NoError(t, os.RemoveAll(dir))
544
545	sdb, err := NewStateDB(dir, 128, TypeSynchronizer, 32)
546	require.NoError(t, err)
547
548	numCheckpoints := 16
549	// do checkpoints
550	for i := 0; i < numCheckpoints; i++ {
551		err = sdb.MakeCheckpoint()
552		require.NoError(t, err)
553	}
554	list, err := sdb.db.ListCheckpoints()
555	require.NoError(t, err)
556	assert.Equal(t, numCheckpoints, len(list))
557	assert.Equal(t, 1, list[0])
558	assert.Equal(t, numCheckpoints, list[len(list)-1])
559
560	numReset := 10
561	err = sdb.Reset(common.BatchNum(numReset))
562	require.NoError(t, err)
563	list, err = sdb.db.ListCheckpoints()
564	require.NoError(t, err)
565	assert.Equal(t, numReset, len(list))
566	assert.Equal(t, 1, list[0])
567	assert.Equal(t, numReset, list[len(list)-1])
568}
569
570// TestDeleteOldCheckpoints performs almost the same test than
571// kvdb/kvdb_test.go TestDeleteOldCheckpoints, but over the StateDB
572func TestDeleteOldCheckpoints(t *testing.T) {
573	dir, err := ioutil.TempDir("", "tmpdb")
574	require.NoError(t, err)
575	defer require.NoError(t, os.RemoveAll(dir))
576
577	keep := 16
578	sdb, err := NewStateDB(dir, keep, TypeSynchronizer, 32)
579	require.NoError(t, err)
580
581	numCheckpoints := 32
582	// do checkpoints and check that we never have more than `keep`
583	// checkpoints
584	for i := 0; i < numCheckpoints; i++ {
585		err = sdb.MakeCheckpoint()
586		require.NoError(t, err)
587		checkpoints, err := sdb.db.ListCheckpoints()
588		require.NoError(t, err)
589		assert.LessOrEqual(t, len(checkpoints), keep)
590	}
591}
592
593func TestCurrentIdx(t *testing.T) {
594	dir, err := ioutil.TempDir("", "tmpdb")
595	require.NoError(t, err)
596	defer require.NoError(t, os.RemoveAll(dir))
597
598	keep := 16
599	sdb, err := NewStateDB(dir, keep, TypeSynchronizer, 32)
600	require.NoError(t, err)
601
602	idx := sdb.CurrentIdx()
603	assert.Equal(t, common.Idx(255), idx)
604
605	sdb.Close()
606
607	sdb, err = NewStateDB(dir, keep, TypeSynchronizer, 32)
608	require.NoError(t, err)
609
610	idx = sdb.CurrentIdx()
611	assert.Equal(t, common.Idx(255), idx)
612
613	err = sdb.MakeCheckpoint()
614	require.NoError(t, err)
615
616	idx = sdb.CurrentIdx()
617	assert.Equal(t, common.Idx(255), idx)
618
619	sdb.Close()
620
621	sdb, err = NewStateDB(dir, keep, TypeSynchronizer, 32)
622	require.NoError(t, err)
623
624	idx = sdb.CurrentIdx()
625	assert.Equal(t, common.Idx(255), idx)
626}