Skip to content

Commit 5c18b24

Browse files
committed
multi: allow valid single backups to be skipped
In case we have a channel.backup file which as partly valid channels we skip over them.
1 parent bc5a1d7 commit 5c18b24

File tree

2 files changed

+76
-2
lines changed

2 files changed

+76
-2
lines changed

cmd/chantools/fixoldbackup.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/lightninglabs/chantools/lnd"
1010
"github.com/lightningnetwork/lnd/chanbackup"
11+
"github.com/lightningnetwork/lnd/input"
1112
"github.com/lightningnetwork/lnd/keychain"
1213
"github.com/spf13/cobra"
1314
)
@@ -77,10 +78,61 @@ func fixOldChannelBackup(multiFile *chanbackup.MultiFile,
7778
for idx, single := range multi.StaticBackups {
7879
err := ring.CheckDescriptor(single.ShaChainRootDesc)
7980
switch {
80-
case err == nil:
81+
// If the descriptor is correct or the error is because no
82+
// public key is provided, skip the channel. This can happen
83+
// if the backup file has partially valid and invalid channels.
84+
case err == nil || errors.Is(err, lnd.ErrNoPublicKeyProvided):
85+
log.Infof("The shachain root for channel %s is "+
86+
"correct, skipping...",
87+
single.FundingOutpoint.String())
88+
8189
continue
8290

8391
case errors.Is(err, keychain.ErrCannotDerivePrivKey):
92+
// Before fixing the descriptor, print the funding multisig
93+
// P2WSH witness program hash. Derive the local multisig pubkey
94+
// via its locator if needed (and possible), similar to
95+
// CheckDescriptor.
96+
localPub, err := ring.PubKeyForDescriptor(
97+
single.LocalChanCfg.MultiSigKey,
98+
)
99+
if err != nil {
100+
return fmt.Errorf("could not derive local "+
101+
"multisig pubkey for channel %s: %w",
102+
single.FundingOutpoint.String(), err)
103+
}
104+
105+
remotePub, err := ring.PubKeyForDescriptor(
106+
single.RemoteChanCfg.MultiSigKey,
107+
)
108+
if err != nil {
109+
return fmt.Errorf("could not derive remote "+
110+
"multisig pubkey for channel %s: %w",
111+
single.FundingOutpoint.String(), err)
112+
}
113+
114+
a := localPub.SerializeCompressed()
115+
b := remotePub.SerializeCompressed()
116+
msScript, err := input.GenMultiSigScript(a, b)
117+
if err != nil {
118+
return fmt.Errorf("could not generate "+
119+
"multisig script for channel "+
120+
"%s: %w",
121+
single.FundingOutpoint.String(),
122+
err)
123+
}
124+
125+
msHash, err := input.WitnessScriptHash(msScript)
126+
if err != nil {
127+
return fmt.Errorf("could not compute"+
128+
"multisig script hash: %w", err)
129+
}
130+
131+
log.Infof("Channel %s funding multisig P2WSH "+
132+
"(pubkey): %x",
133+
single.FundingOutpoint.String(),
134+
msHash[:])
135+
84136
// Fix the incorrect descriptor by deriving a default
85137
// one and overwriting it in the backup.
86138
log.Infof("The shachain root for channel %s could "+

lnd/hdkeychain.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import (
2121
"github.com/lightningnetwork/lnd/shachain"
2222
)
2323

24+
// ErrNoPublicKeyProvided is returned when a key descriptor check is attempted
25+
// without a public key present in the descriptor.
26+
var ErrNoPublicKeyProvided = errors.New("no public key provided to check")
27+
2428
const (
2529
HardenedKeyStart = uint32(hdkeychain.HardenedKeyStart)
2630
WalletDefaultDerivationPath = "m/84'/0'/0'"
@@ -609,7 +613,7 @@ func (r *HDKeyRing) CheckDescriptor(
609613

610614
// A check doesn't make sense if there is no public key set.
611615
if keyDesc.PubKey == nil {
612-
return errors.New("no public key provided to check")
616+
return ErrNoPublicKeyProvided
613617
}
614618

615619
// Performance fix, derive static path only once.
@@ -658,3 +662,21 @@ func (r *HDKeyRing) NodePubKey() (*btcec.PublicKey, error) {
658662

659663
return keyDesc.PubKey, nil
660664
}
665+
666+
// PubKeyForDescriptor returns the public key for a given key descriptor. If the
667+
// descriptor already contains a public key, it is returned as-is. Otherwise,
668+
// the public key is derived using the descriptor's key locator.
669+
func (r *HDKeyRing) PubKeyForDescriptor(desc keychain.KeyDescriptor) (
670+
*btcec.PublicKey, error) {
671+
672+
if desc.PubKey != nil {
673+
return desc.PubKey, nil
674+
}
675+
676+
// Attempt to derive using the provided key locator.
677+
kd, err := r.DeriveKey(desc.KeyLocator)
678+
if err != nil {
679+
return nil, err
680+
}
681+
return kd.PubKey, nil
682+
}

0 commit comments

Comments
 (0)