mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
- KVDB/StateDB
- Pass config parameters in a Config type instead of using many
arguments in constructor.
- Add new parameter `NoLast` which disables having an opened DB with a
checkpoint to the last batchNum for thread-safe reads. Last will be
disabled in the StateDB used by the TxSelector and BatchBuilder.
- Add new parameter `NoGapsCheck` which skips checking gaps in the list
of checkpoints and returning errors if there are gaps. Gaps check
will be disabled in the StateDB used by the TxSelector and
BatchBuilder, because we expect to have gaps when there are multiple
coordinators forging (slots not forged by our coordinator will leave
gaps).
237 lines
6.1 KiB
Go
237 lines
6.1 KiB
Go
package kvdb
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/hermeznetwork/hermez-node/common"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func addTestKV(t *testing.T, db *KVDB, k, v []byte) {
|
|
tx, err := db.db.NewTx()
|
|
require.NoError(t, err)
|
|
|
|
err = tx.Put(k, v)
|
|
require.NoError(t, err)
|
|
|
|
err = tx.Commit()
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func printCheckpoints(t *testing.T, path string) {
|
|
files, err := ioutil.ReadDir(path)
|
|
require.NoError(t, err)
|
|
|
|
fmt.Println(path)
|
|
for _, f := range files {
|
|
fmt.Println(" " + f.Name())
|
|
}
|
|
}
|
|
|
|
func TestCheckpoints(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "sdb")
|
|
require.NoError(t, err)
|
|
defer require.NoError(t, os.RemoveAll(dir))
|
|
|
|
db, err := NewKVDB(Config{Path: dir, Keep: 128})
|
|
require.NoError(t, err)
|
|
|
|
// add test key-values
|
|
for i := 0; i < 10; i++ {
|
|
addTestKV(t, db, []byte{byte(i), byte(i)}, []byte{byte(i * 2), byte(i * 2)})
|
|
}
|
|
|
|
// do checkpoints and check that currentBatch is correct
|
|
err = db.MakeCheckpoint()
|
|
require.NoError(t, err)
|
|
cb, err := db.GetCurrentBatch()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.BatchNum(1), cb)
|
|
|
|
for i := 1; i < 10; i++ {
|
|
err = db.MakeCheckpoint()
|
|
require.NoError(t, err)
|
|
|
|
cb, err = db.GetCurrentBatch()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.BatchNum(i+1), cb)
|
|
}
|
|
|
|
// printCheckpoints(t, db.path)
|
|
|
|
// reset checkpoint
|
|
err = db.Reset(3)
|
|
require.NoError(t, err)
|
|
|
|
// check that reset can be repeated (as there exist the 'current' and
|
|
// 'BatchNum3', from where the 'current' is a copy)
|
|
err = db.Reset(3)
|
|
require.NoError(t, err)
|
|
|
|
printCheckpoints(t, db.cfg.Path)
|
|
|
|
// check that currentBatch is as expected after Reset
|
|
cb, err = db.GetCurrentBatch()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.BatchNum(3), cb)
|
|
|
|
// advance one checkpoint and check that currentBatch is fine
|
|
err = db.MakeCheckpoint()
|
|
require.NoError(t, err)
|
|
cb, err = db.GetCurrentBatch()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.BatchNum(4), cb)
|
|
|
|
err = db.DeleteCheckpoint(common.BatchNum(1))
|
|
require.NoError(t, err)
|
|
err = db.DeleteCheckpoint(common.BatchNum(2))
|
|
require.NoError(t, err)
|
|
err = db.DeleteCheckpoint(common.BatchNum(1)) // does not exist, should return err
|
|
assert.NotNil(t, err)
|
|
err = db.DeleteCheckpoint(common.BatchNum(2)) // does not exist, should return err
|
|
assert.NotNil(t, err)
|
|
|
|
// Create a new KVDB which will get Reset from the initial KVDB
|
|
dirLocal, err := ioutil.TempDir("", "ldb")
|
|
require.NoError(t, err)
|
|
defer require.NoError(t, os.RemoveAll(dirLocal))
|
|
ldb, err := NewKVDB(Config{Path: dirLocal, Keep: 128})
|
|
require.NoError(t, err)
|
|
|
|
// get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
|
|
err = ldb.ResetFromSynchronizer(4, db)
|
|
require.NoError(t, err)
|
|
// check that currentBatch is 4 after the Reset
|
|
cb, err = ldb.GetCurrentBatch()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.BatchNum(4), cb)
|
|
// advance one checkpoint in ldb
|
|
err = ldb.MakeCheckpoint()
|
|
require.NoError(t, err)
|
|
cb, err = ldb.GetCurrentBatch()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.BatchNum(5), cb)
|
|
|
|
// Create a 3rd KVDB which will get Reset from the initial KVDB
|
|
dirLocal2, err := ioutil.TempDir("", "ldb2")
|
|
require.NoError(t, err)
|
|
defer require.NoError(t, os.RemoveAll(dirLocal2))
|
|
ldb2, err := NewKVDB(Config{Path: dirLocal2, Keep: 128})
|
|
require.NoError(t, err)
|
|
|
|
// get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
|
|
err = ldb2.ResetFromSynchronizer(4, db)
|
|
require.NoError(t, err)
|
|
// check that currentBatch is 4 after the Reset
|
|
cb, err = ldb2.GetCurrentBatch()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.BatchNum(4), cb)
|
|
// advance one checkpoint in ldb2
|
|
err = ldb2.MakeCheckpoint()
|
|
require.NoError(t, err)
|
|
cb, err = ldb2.GetCurrentBatch()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.BatchNum(5), cb)
|
|
|
|
debug := false
|
|
if debug {
|
|
printCheckpoints(t, db.cfg.Path)
|
|
printCheckpoints(t, ldb.cfg.Path)
|
|
printCheckpoints(t, ldb2.cfg.Path)
|
|
}
|
|
}
|
|
|
|
func TestListCheckpoints(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "tmpdb")
|
|
require.NoError(t, err)
|
|
defer require.NoError(t, os.RemoveAll(dir))
|
|
|
|
db, err := NewKVDB(Config{Path: dir, Keep: 128})
|
|
require.NoError(t, err)
|
|
|
|
numCheckpoints := 16
|
|
// do checkpoints
|
|
for i := 0; i < numCheckpoints; i++ {
|
|
err = db.MakeCheckpoint()
|
|
require.NoError(t, err)
|
|
}
|
|
list, err := db.ListCheckpoints()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, numCheckpoints, len(list))
|
|
assert.Equal(t, 1, list[0])
|
|
assert.Equal(t, numCheckpoints, list[len(list)-1])
|
|
|
|
numReset := 10
|
|
err = db.Reset(common.BatchNum(numReset))
|
|
require.NoError(t, err)
|
|
list, err = db.ListCheckpoints()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, numReset, len(list))
|
|
assert.Equal(t, 1, list[0])
|
|
assert.Equal(t, numReset, list[len(list)-1])
|
|
}
|
|
|
|
func TestDeleteOldCheckpoints(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "tmpdb")
|
|
require.NoError(t, err)
|
|
defer require.NoError(t, os.RemoveAll(dir))
|
|
|
|
keep := 16
|
|
db, err := NewKVDB(Config{Path: dir, Keep: keep})
|
|
require.NoError(t, err)
|
|
|
|
numCheckpoints := 32
|
|
// do checkpoints and check that we never have more than `keep`
|
|
// checkpoints
|
|
for i := 0; i < numCheckpoints; i++ {
|
|
err = db.MakeCheckpoint()
|
|
require.NoError(t, err)
|
|
checkpoints, err := db.ListCheckpoints()
|
|
require.NoError(t, err)
|
|
assert.LessOrEqual(t, len(checkpoints), keep)
|
|
}
|
|
}
|
|
|
|
func TestGetCurrentIdx(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "tmpdb")
|
|
require.NoError(t, err)
|
|
defer require.NoError(t, os.RemoveAll(dir))
|
|
|
|
keep := 16
|
|
db, err := NewKVDB(Config{Path: dir, Keep: keep})
|
|
require.NoError(t, err)
|
|
|
|
idx, err := db.GetCurrentIdx()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.Idx(255), idx)
|
|
|
|
db.Close()
|
|
|
|
db, err = NewKVDB(Config{Path: dir, Keep: keep})
|
|
require.NoError(t, err)
|
|
|
|
idx, err = db.GetCurrentIdx()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.Idx(255), idx)
|
|
|
|
err = db.MakeCheckpoint()
|
|
require.NoError(t, err)
|
|
|
|
idx, err = db.GetCurrentIdx()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.Idx(255), idx)
|
|
|
|
db.Close()
|
|
|
|
db, err = NewKVDB(Config{Path: dir, Keep: keep})
|
|
require.NoError(t, err)
|
|
|
|
idx, err = db.GetCurrentIdx()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, common.Idx(255), idx)
|
|
}
|