From 85bba2ca7a46893bb4e8b3a3610de0c7af72438f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 13 Apr 2026 12:14:23 -0700 Subject: [PATCH] multi: add SCB restore support for production taproot channels Add the missing SimpleTaprootFinalVersion case to chanrestore.openChannelShell() so that SCB backups created for production taproot channels can be properly restored. Without this, the channel type bits were not reconstructed during restore, causing DLP to fail. Also add integration tests for both confirmed and zero-conf variants of production taproot channel backup restoration. --- chanrestore.go | 7 +++++++ itest/lnd_channel_backup_test.go | 24 ++++++++++++++++++++++++ lnwallet/channel.go | 7 +++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/chanrestore.go b/chanrestore.go index a041f571a..1f506cc27 100644 --- a/chanrestore.go +++ b/chanrestore.go @@ -170,6 +170,13 @@ func (c *chanDBRestorer) openChannelShell(backup chanbackup.Single) ( chanType |= channeldb.SimpleTaprootFeatureBit chanType |= channeldb.TapscriptRootBit + case chanbackup.SimpleTaprootFinalVersion: + chanType = channeldb.ZeroHtlcTxFeeBit + chanType |= channeldb.AnchorOutputsBit + chanType |= channeldb.SingleFunderTweaklessBit + chanType |= channeldb.SimpleTaprootFeatureBit + chanType |= channeldb.TaprootFinalBit + default: return nil, fmt.Errorf("unknown Single version: %w", err) } diff --git a/itest/lnd_channel_backup_test.go b/itest/lnd_channel_backup_test.go index b100fe514..bdfb21a9d 100644 --- a/itest/lnd_channel_backup_test.go +++ b/itest/lnd_channel_backup_test.go @@ -85,6 +85,30 @@ var channelRestoreTestCases = []*lntest.TestCase{ ) }, }, + { + // Restore a channel back up of a confirmed production + // taproot channel. + Name: "restore simple taproot final", + TestFunc: func(ht *lntest.HarnessTest) { + runChanRestoreScenarioCommitTypes( + ht, + lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL, + false, + ) + }, + }, + { + // Restore a channel back up of an unconfirmed production + // taproot channel. + Name: "restore simple taproot final zero conf", + TestFunc: func(ht *lntest.HarnessTest) { + runChanRestoreScenarioCommitTypes( + ht, + lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL, + true, + ) + }, + }, { Name: "restore from rpc", TestFunc: testChannelBackupRestoreFromRPC, diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 694aaed8d..78ca89565 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -922,8 +922,11 @@ func WithAuxResolver(resolver AuxContractResolver) ChannelOpt { } // WithCustomSigningRand is used to provide a custom random source for -// generating deterministic JIT signing nonces in MuSig2 sessions. This should -// only be used in tests that need reproducible MuSig2 signatures. +// generating deterministic JIT signing nonces in MuSig2 sessions. +// +// WARNING: This MUST only be used for test vector generation. Setting this in +// production will produce deterministic nonces, enabling private key extraction +// via nonce reuse. func WithCustomSigningRand(rand io.Reader) ChannelOpt { return func(o *channelOpts) { o.customSigningRand = fn.Some[io.Reader](rand)