From 0730337cc71e36c4dcfaa72037f4b20aef096403 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Fri, 10 Feb 2023 10:13:34 +0200 Subject: [PATCH] multi: add new NoRevLogAmtData config option In this commit, a new `--db.no-rev-log-amt-data` flag is added. The config option is passed though to everywhere that it will be used. Note that it is still a no-op in this commit. An upcoming commit will make use of the flag. --- channeldb/channel.go | 4 ++-- channeldb/db.go | 9 ++++++++- channeldb/migration30/revocation_log.go | 2 +- channeldb/migration30/test_utils.go | 6 +++--- channeldb/options.go | 12 ++++++++++++ channeldb/revocation_log.go | 2 +- channeldb/revocation_log_test.go | 4 +++- config.go | 7 +++++++ config_builder.go | 13 ++++++++++--- lncfg/db.go | 2 ++ sample-lnd.conf | 6 ++++++ 11 files changed, 55 insertions(+), 12 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 8fbeeea5c..d71f17047 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -2657,8 +2657,8 @@ func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg, // With the commitment pointer swapped, we can now add the // revoked (prior) state to the revocation log. err = putRevocationLog( - logBucket, &c.RemoteCommitment, - ourOutputIndex, theirOutputIndex, + logBucket, &c.RemoteCommitment, ourOutputIndex, + theirOutputIndex, c.Db.parent.noRevLogAmtData, ) if err != nil { return err diff --git a/channeldb/db.go b/channeldb/db.go index 37bee6ff1..38493d240 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -324,6 +324,10 @@ type DB struct { dryRun bool keepFailedPaymentAttempts bool storeFinalHtlcResolutions bool + + // noRevLogAmtData if true, means that commitment transaction amount + // data should not be stored in the revocation log. + noRevLogAmtData bool } // Open opens or creates channeldb. Any necessary schemas migrations due @@ -382,6 +386,7 @@ func CreateWithBackend(backend kvdb.Backend, dryRun: opts.dryRun, keepFailedPaymentAttempts: opts.keepFailedPaymentAttempts, storeFinalHtlcResolutions: opts.storeFinalHtlcResolutions, + noRevLogAmtData: opts.NoRevLogAmtData, } // Set the parent pointer (only used in tests). @@ -1562,7 +1567,9 @@ func (d *DB) applyOptionalVersions(cfg OptionalMiragtionConfig) error { log.Infof("Performing database optional migration: %s", version.name) migrationCfg := &MigrationConfigImpl{ - migration30.MigrateRevLogConfigImpl{}, + migration30.MigrateRevLogConfigImpl{ + NoAmountData: d.noRevLogAmtData, + }, } // Migrate the data. diff --git a/channeldb/migration30/revocation_log.go b/channeldb/migration30/revocation_log.go index 24382e707..99539736e 100644 --- a/channeldb/migration30/revocation_log.go +++ b/channeldb/migration30/revocation_log.go @@ -223,7 +223,7 @@ type RevocationLog struct { // disk. It also saves our output index and their output index, which are // useful when creating breach retribution. func putRevocationLog(bucket kvdb.RwBucket, commit *mig.ChannelCommitment, - ourOutputIndex, theirOutputIndex uint32) error { + ourOutputIndex, theirOutputIndex uint32, noAmtData bool) error { // Sanity check that the output indexes can be safely converted. if ourOutputIndex > math.MaxUint16 { diff --git a/channeldb/migration30/test_utils.go b/channeldb/migration30/test_utils.go index 2a3093fb1..97de53fb3 100644 --- a/channeldb/migration30/test_utils.go +++ b/channeldb/migration30/test_utils.go @@ -306,7 +306,7 @@ func setupTestLogs(db kvdb.Backend, c *mig26.OpenChannel, } // Create new logs. - return writeNewRevocationLogs(chanBucket, newLogs) + return writeNewRevocationLogs(chanBucket, newLogs, !withAmtData) }, func() {}) } @@ -460,7 +460,7 @@ func writeOldRevocationLogs(chanBucket kvdb.RwBucket, // writeNewRevocationLogs saves a new revocation log to db. func writeNewRevocationLogs(chanBucket kvdb.RwBucket, - oldLogs []mig.ChannelCommitment) error { + oldLogs []mig.ChannelCommitment, noAmtData bool) error { // Don't bother continue if the logs are empty. if len(oldLogs) == 0 { @@ -480,7 +480,7 @@ func writeNewRevocationLogs(chanBucket kvdb.RwBucket, // old commit tx. We do this intentionally so we can // distinguish a newly created log from an already saved one. err := putRevocationLog( - logBucket, &c, testOurIndex, testTheirIndex, + logBucket, &c, testOurIndex, testTheirIndex, noAmtData, ) if err != nil { return err diff --git a/channeldb/options.go b/channeldb/options.go index d3b26a739..3f5b472f6 100644 --- a/channeldb/options.go +++ b/channeldb/options.go @@ -64,6 +64,10 @@ type Options struct { // applications that use the channeldb package as a library. NoMigration bool + // NoRevLogAmtData when set to true, indicates that amount data should + // not be stored in the revocation log. + NoRevLogAmtData bool + // clock is the time source used by the database. clock clock.Clock @@ -130,6 +134,14 @@ func OptionSetUseGraphCache(use bool) OptionModifier { } } +// OptionNoRevLogAmtData sets the NoRevLogAmtData option to the given value. If +// it is set to true then amount data will not be stored in the revocation log. +func OptionNoRevLogAmtData(noAmtData bool) OptionModifier { + return func(o *Options) { + o.NoRevLogAmtData = noAmtData + } +} + // OptionSetSyncFreelist allows the database to sync its freelist. func OptionSetSyncFreelist(b bool) OptionModifier { return func(o *Options) { diff --git a/channeldb/revocation_log.go b/channeldb/revocation_log.go index 30405ba8a..2df93fd5b 100644 --- a/channeldb/revocation_log.go +++ b/channeldb/revocation_log.go @@ -211,7 +211,7 @@ type RevocationLog struct { // disk. It also saves our output index and their output index, which are // useful when creating breach retribution. func putRevocationLog(bucket kvdb.RwBucket, commit *ChannelCommitment, - ourOutputIndex, theirOutputIndex uint32) error { + ourOutputIndex, theirOutputIndex uint32, noAmtData bool) error { // Sanity check that the output indexes can be safely converted. if ourOutputIndex > math.MaxUint16 { diff --git a/channeldb/revocation_log_test.go b/channeldb/revocation_log_test.go index 6ca5b33b0..1f6d1f813 100644 --- a/channeldb/revocation_log_test.go +++ b/channeldb/revocation_log_test.go @@ -368,6 +368,7 @@ func TestPutRevocationLog(t *testing.T) { commit ChannelCommitment ourIndex uint32 theirIndex uint32 + noAmtData bool expectedErr error expectedLog RevocationLog }{ @@ -435,6 +436,7 @@ func TestPutRevocationLog(t *testing.T) { // Save the log. err = putRevocationLog( bucket, &tc.commit, tc.ourIndex, tc.theirIndex, + tc.noAmtData, ) if err != nil { return RevocationLog{}, err @@ -542,7 +544,7 @@ func TestFetchRevocationLogCompatible(t *testing.T) { require.NoError(t, err) err = putRevocationLog( - lb, &testChannelCommit, 0, 1, + lb, &testChannelCommit, 0, 1, false, ) require.NoError(t, err) } diff --git a/config.go b/config.go index dca79551f..41fe291ba 100644 --- a/config.go +++ b/config.go @@ -981,6 +981,13 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, ) } + // Ensure that the amount data for revoked commitment transactions is + // stored if the watchtower client is active. + if cfg.DB.NoRevLogAmtData && cfg.WtClient.Active { + return nil, mkErr("revocation log amount data must be stored " + + "if the watchtower client is active") + } + // Ensure a valid max channel fee allocation was set. if cfg.MaxChannelFeeAllocation <= 0 || cfg.MaxChannelFeeAllocation > 1 { return nil, mkErr("invalid max channel fee allocation: %v, "+ diff --git a/config_builder.go b/config_builder.go index 3b71a21b0..225c82b96 100644 --- a/config_builder.go +++ b/config_builder.go @@ -867,15 +867,22 @@ func (d *DefaultDatabaseBuilder) BuildDatabase( dbOptions := []channeldb.OptionModifier{ channeldb.OptionSetRejectCacheSize(cfg.Caches.RejectCacheSize), - channeldb.OptionSetChannelCacheSize(cfg.Caches.ChannelCacheSize), - channeldb.OptionSetBatchCommitInterval(cfg.DB.BatchCommitInterval), + channeldb.OptionSetChannelCacheSize( + cfg.Caches.ChannelCacheSize, + ), + channeldb.OptionSetBatchCommitInterval( + cfg.DB.BatchCommitInterval, + ), channeldb.OptionDryRunMigration(cfg.DryRunMigration), channeldb.OptionSetUseGraphCache(!cfg.DB.NoGraphCache), - channeldb.OptionKeepFailedPaymentAttempts(cfg.KeepFailedPaymentAttempts), + channeldb.OptionKeepFailedPaymentAttempts( + cfg.KeepFailedPaymentAttempts, + ), channeldb.OptionStoreFinalHtlcResolutions( cfg.StoreFinalHtlcResolutions, ), channeldb.OptionPruneRevocationLog(cfg.DB.PruneRevocation), + channeldb.OptionNoRevLogAmtData(cfg.DB.NoRevLogAmtData), } // We want to pre-allocate the channel graph cache according to what we diff --git a/lncfg/db.go b/lncfg/db.go index e446553ae..ed0bdf6b7 100644 --- a/lncfg/db.go +++ b/lncfg/db.go @@ -85,6 +85,8 @@ type DB struct { NoGraphCache bool `long:"no-graph-cache" description:"Don't use the in-memory graph cache for path finding. Much slower but uses less RAM. Can only be used with a bolt database backend."` PruneRevocation bool `long:"prune-revocation" description:"Run the optional migration that prunes the revocation logs to save disk space."` + + NoRevLogAmtData bool `long:"no-rev-log-amt-data" description:"If set, the to-local and to-remote output amounts of revoked commitment transactions will not be stored in the revocation log. Note that once this data is lost, a watchtower client will not be able to back up the revoked state."` } // DefaultDB creates and returns a new default DB config. diff --git a/sample-lnd.conf b/sample-lnd.conf index 96ac7e015..805db4202 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -1241,6 +1241,12 @@ litecoin.node=ltcd ; channels prior to lnd@v0.15.0. ; db.prune-revocation=false +; If set to true, then the to-local and to-remote output amount data of revoked +; commitment transactions will not be stored in the revocation log. Note that +; this flag can only be set if --wtclient.active is not set. It is not +; recommended to set this flag if you plan on ever setting wtclient.active in +; the future. +; db.no-rev-log-amt-data=false [etcd]