multi: make decayed log DB remote compatible

Even though the sphinx router's persistent replay log is not crucial in
the operation of lnd as its state can be re-created by creating a new
brontide connection, we want to make lnd fully stateless and therefore
have the option of not storing any state on disk.
This commit is contained in:
Oliver Gugger committed 2021-08-04 14:55:53 +02:00
1 parent 6043113857
commit 1e27f491c7
6 files changed
+91 -56

No files matched your search

+31 -25
View File
@@ -41,6 +41,35 @@ var (
ErrDecayedLogCorrupted = errors.New("decayed log structure corrupted")
)
// NewBoltBackendCreator returns a function that creates a new bbolt backend for
// the decayed logs database.
func NewBoltBackendCreator(dbPath,
dbFileName string) func(boltCfg *kvdb.BoltConfig) (kvdb.Backend, error) {
return func(boltCfg *kvdb.BoltConfig) (kvdb.Backend, error) {
cfg := &kvdb.BoltBackendConfig{
DBPath: dbPath,
DBFileName: dbFileName,
NoFreelistSync: !boltCfg.SyncFreelist,
AutoCompact: boltCfg.AutoCompact,
AutoCompactMinAge: boltCfg.AutoCompactMinAge,
DBTimeout: boltCfg.DBTimeout,
}
// Use default path for log database.
if dbPath == "" {
cfg.DBPath = defaultDbDirectory
}
db, err := kvdb.GetBoltBackend(cfg)
if err != nil {
return nil, fmt.Errorf("could not open boltdb: %v", err)
}
return db, nil
}
}
// DecayedLog implements the PersistLog interface. It stores the first
// HashPrefixSize bytes of a sha256-hashed shared secret along with a node's
// CLTV value. It is a decaying log meaning there will be a garbage collector
@@ -51,8 +80,6 @@ type DecayedLog struct {
started int32 // To be used atomically.
stopped int32 // To be used atomically.
cfg *kvdb.BoltBackendConfig
db kvdb.Backend
notifier chainntnfs.ChainNotifier
@@ -64,25 +91,11 @@ type DecayedLog struct {
// NewDecayedLog creates a new DecayedLog, which caches recently seen hash
// shared secrets. Entries are evicted as their cltv expires using block epochs
// from the given notifier.
func NewDecayedLog(dbPath, dbFileName string, boltCfg *kvdb.BoltConfig,
func NewDecayedLog(db kvdb.Backend,
notifier chainntnfs.ChainNotifier) *DecayedLog {
cfg := &kvdb.BoltBackendConfig{
DBPath: dbPath,
DBFileName: dbFileName,
NoFreelistSync: true,
AutoCompact: boltCfg.AutoCompact,
AutoCompactMinAge: boltCfg.AutoCompactMinAge,
DBTimeout: boltCfg.DBTimeout,
}
// Use default path for log database
if dbPath == "" {
cfg.DBPath = defaultDbDirectory
}
return &DecayedLog{
cfg: cfg,
db: db,
notifier: notifier,
quit: make(chan struct{}),
}
@@ -96,13 +109,6 @@ func (d *DecayedLog) Start() error {
return nil
}
// Open the boltdb for use.
var err error
d.db, err = kvdb.GetBoltBackend(d.cfg)
if err != nil {
return fmt.Errorf("could not open boltdb: %v", err)
}
// Initialize the primary buckets used by the decayed log.
if err := d.initBuckets(); err != nil {
return err
+30 -22
View File
@@ -2,6 +2,7 @@ package htlcswitch
import (
"crypto/rand"
"fmt"
"io/ioutil"
"os"
"testing"
@@ -18,20 +19,29 @@ const (
)
// tempDecayedLogPath creates a new temporary database path to back a single
// deccayed log instance.
func tempDecayedLogPath(t *testing.T) (string, string) {
// decayed log instance.
func tempDecayedLogPath(t *testing.T) string {
dir, err := ioutil.TempDir("", "decayedlog")
if err != nil {
t.Fatalf("unable to create temporary decayed log dir: %v", err)
}
return dir, "sphinxreplay.db"
return dir
}
// startup sets up the DecayedLog and possibly the garbage collector.
func startup(dbPath, dbFileName string, notifier bool) (sphinx.ReplayLog,
func startup(dbPath string, notifier bool) (sphinx.ReplayLog,
*mock.ChainNotifier, *sphinx.HashPrefix, error) {
cfg := &kvdb.BoltConfig{
DBTimeout: time.Second,
}
backend, err := NewBoltBackendCreator(dbPath, "sphinxreplay.db")(cfg)
if err != nil {
return nil, nil, nil, fmt.Errorf("unable to create temporary "+
"decayed log db: %v", err)
}
var log sphinx.ReplayLog
var chainNotifier *mock.ChainNotifier
if notifier {
@@ -44,16 +54,14 @@ func startup(dbPath, dbFileName string, notifier bool) (sphinx.ReplayLog,
}
// Initialize the DecayedLog object
log = NewDecayedLog(
dbPath, dbFileName, &kvdb.BoltConfig{}, chainNotifier,
)
log = NewDecayedLog(backend, chainNotifier)
} else {
// Initialize the DecayedLog object
log = NewDecayedLog(dbPath, dbFileName, &kvdb.BoltConfig{}, nil)
log = NewDecayedLog(backend, nil)
}
// Open the channeldb (start the garbage collector)
err := log.Start()
err = log.Start()
if err != nil {
return nil, nil, nil, err
}
@@ -83,9 +91,9 @@ func shutdown(dir string, d sphinx.ReplayLog) {
func TestDecayedLogGarbageCollector(t *testing.T) {
t.Parallel()
dbPath, dbFileName := tempDecayedLogPath(t)
dbPath := tempDecayedLogPath(t)
d, notifier, hashedSecret, err := startup(dbPath, dbFileName, true)
d, notifier, hashedSecret, err := startup(dbPath, true)
if err != nil {
t.Fatalf("Unable to start up DecayedLog: %v", err)
}
@@ -144,9 +152,9 @@ func TestDecayedLogGarbageCollector(t *testing.T) {
func TestDecayedLogPersistentGarbageCollector(t *testing.T) {
t.Parallel()
dbPath, dbFileName := tempDecayedLogPath(t)
dbPath := tempDecayedLogPath(t)
d, _, hashedSecret, err := startup(dbPath, dbFileName, true)
d, _, hashedSecret, err := startup(dbPath, true)
if err != nil {
t.Fatalf("Unable to start up DecayedLog: %v", err)
}
@@ -166,7 +174,7 @@ func TestDecayedLogPersistentGarbageCollector(t *testing.T) {
// Shut down DecayedLog and the garbage collector along with it.
d.Stop()
d2, notifier2, _, err := startup(dbPath, dbFileName, true)
d2, notifier2, _, err := startup(dbPath, true)
if err != nil {
t.Fatalf("Unable to restart DecayedLog: %v", err)
}
@@ -200,9 +208,9 @@ func TestDecayedLogPersistentGarbageCollector(t *testing.T) {
func TestDecayedLogInsertionAndDeletion(t *testing.T) {
t.Parallel()
dbPath, dbFileName := tempDecayedLogPath(t)
dbPath := tempDecayedLogPath(t)
d, _, hashedSecret, err := startup(dbPath, dbFileName, false)
d, _, hashedSecret, err := startup(dbPath, false)
if err != nil {
t.Fatalf("Unable to start up DecayedLog: %v", err)
}
@@ -238,9 +246,9 @@ func TestDecayedLogInsertionAndDeletion(t *testing.T) {
func TestDecayedLogStartAndStop(t *testing.T) {
t.Parallel()
dbPath, dbFileName := tempDecayedLogPath(t)
dbPath := tempDecayedLogPath(t)
d, _, hashedSecret, err := startup(dbPath, dbFileName, false)
d, _, hashedSecret, err := startup(dbPath, false)
if err != nil {
t.Fatalf("Unable to start up DecayedLog: %v", err)
}
@@ -255,7 +263,7 @@ func TestDecayedLogStartAndStop(t *testing.T) {
// Shutdown the DecayedLog's channeldb
d.Stop()
d2, _, hashedSecret2, err := startup(dbPath, dbFileName, false)
d2, _, hashedSecret2, err := startup(dbPath, false)
if err != nil {
t.Fatalf("Unable to restart DecayedLog: %v", err)
}
@@ -282,7 +290,7 @@ func TestDecayedLogStartAndStop(t *testing.T) {
// Shutdown the DecayedLog's channeldb
d2.Stop()
d3, _, hashedSecret3, err := startup(dbPath, dbFileName, false)
d3, _, hashedSecret3, err := startup(dbPath, false)
if err != nil {
t.Fatalf("Unable to restart DecayedLog: %v", err)
}
@@ -304,9 +312,9 @@ func TestDecayedLogStartAndStop(t *testing.T) {
func TestDecayedLogStorageAndRetrieval(t *testing.T) {
t.Parallel()
dbPath, dbFileName := tempDecayedLogPath(t)
dbPath := tempDecayedLogPath(t)
d, _, hashedSecret, err := startup(dbPath, dbFileName, false)
d, _, hashedSecret, err := startup(dbPath, false)
if err != nil {
t.Fatalf("Unable to start up DecayedLog: %v", err)
}