From c19d89149fc92d5b9df34c478893dba600011b72 Mon Sep 17 00:00:00 2001 From: ziggie Date: Thu, 12 Jun 2025 22:56:46 +0200 Subject: [PATCH] channeldb: add migration34 Migration34 garbage collects the decayed log database. This commit only adds the migration code and does not use it. --- channeldb/migration34/log.go | 14 ++++++ channeldb/migration34/migration.go | 76 ++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 channeldb/migration34/log.go create mode 100644 channeldb/migration34/migration.go diff --git a/channeldb/migration34/log.go b/channeldb/migration34/log.go new file mode 100644 index 000000000..891ed2b19 --- /dev/null +++ b/channeldb/migration34/log.go @@ -0,0 +1,14 @@ +package migration34 + +import ( + "github.com/btcsuite/btclog/v2" +) + +// log is a logger that is initialized as disabled. This means the package will +// not perform any logging by default until a logger is set. +var log = btclog.Disabled + +// UseLogger uses a specified Logger to output package logging info. +func UseLogger(logger btclog.Logger) { + log = logger +} diff --git a/channeldb/migration34/migration.go b/channeldb/migration34/migration.go new file mode 100644 index 000000000..da5df488c --- /dev/null +++ b/channeldb/migration34/migration.go @@ -0,0 +1,76 @@ +package migration34 + +import ( + "errors" + "fmt" + + "github.com/lightningnetwork/lnd/kvdb" +) + +// Migration34 is an optional migration that garbage collects the decayed log +// in particular the `batch-replay` bucket. However we did choose to use an +// optional migration which defaults to true because the decayed log db is +// separate from the channeldb and if we would have implemented it as a +// required migration, then it would have required a bigger change to the +// codebase. +// +// Most of the decayed log db will shrink significantly after this migration +// because the other bucket called `shared-secrets` is garbage collected +// continuously and the `batch-replay` bucket will be deleted. + +var ( + // batchReplayBucket is a bucket that maps batch identifiers to + // serialized ReplaySets. This is used to give idempotency in the event + // that a batch is processed more than once. + batchReplayBucket = []byte("batch-replay") +) + +// MigrationConfig is the interface for the migration configuration. +type MigrationConfig interface { + GetDecayedLog() kvdb.Backend +} + +// MigrationConfigImpl is the implementation of the migration configuration. +type MigrationConfigImpl struct { + DecayedLog kvdb.Backend +} + +// GetDecayedLog returns the decayed log backend. +func (c *MigrationConfigImpl) GetDecayedLog() kvdb.Backend { + return c.DecayedLog +} + +// MigrateDecayedLog migrates the decayed log. The migration deletes the +// `batch-replay` bucket, which is no longer used. +// +// NOTE: This migration is idempotent. If the bucket does not exist, then this +// migration is a no-op. +func MigrateDecayedLog(db kvdb.Backend, cfg MigrationConfig) error { + decayedLog := cfg.GetDecayedLog() + + // Make sure we have a reference to the decayed log. + if decayedLog == nil { + return fmt.Errorf("decayed log backend is not available") + } + + log.Info("Migrating decayed log...") + err := decayedLog.Update(func(tx kvdb.RwTx) error { + err := tx.DeleteTopLevelBucket(batchReplayBucket) + if err != nil && !errors.Is(err, kvdb.ErrBucketNotFound) { + return fmt.Errorf("deleting top level bucket %s: %w", + batchReplayBucket, err) + } + + log.Debugf("top level bucket %s deleted", batchReplayBucket) + + return nil + }, func() {}) + + if err != nil { + return fmt.Errorf("failed to migrate decayed log: %w", err) + } + + log.Info("Decayed log migrated successfully") + + return nil +}