Skip to content

Commit 1923257

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 1923257

File tree

2 files changed

+77
-4
lines changed

2 files changed

+77
-4
lines changed

cmd/chantools/fixoldbackup.go

Lines changed: 53 additions & 3 deletions
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,15 +78,64 @@ 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 %v is "+
86+
"correct, skipping...", single.FundingOutpoint)
87+
8188
continue
8289

8390
case errors.Is(err, keychain.ErrCannotDerivePrivKey):
91+
// Before fixing the descriptor, print the funding
92+
// multisig P2WSH witness program hash. Derive the
93+
// local multisig pubkey via its locator if needed
94+
// (and possible).
95+
localPub, err := ring.PubKeyForDescriptor(
96+
single.LocalChanCfg.MultiSigKey,
97+
)
98+
if err != nil {
99+
return fmt.Errorf("could not derive local "+
100+
"multisig pubkey for channel %v: %w",
101+
single.FundingOutpoint, err)
102+
}
103+
104+
remotePub, err := ring.PubKeyForDescriptor(
105+
single.RemoteChanCfg.MultiSigKey,
106+
)
107+
if err != nil {
108+
return fmt.Errorf("could not derive remote "+
109+
"multisig pubkey for channel %v: %w",
110+
single.FundingOutpoint, err)
111+
}
112+
113+
a := localPub.SerializeCompressed()
114+
b := remotePub.SerializeCompressed()
115+
msScript, err := input.GenMultiSigScript(a, b)
116+
if err != nil {
117+
return fmt.Errorf("could not generate "+
118+
"multisig script for channel "+
119+
"%v: %w",
120+
single.FundingOutpoint, err)
121+
}
122+
123+
msHash, err := input.WitnessScriptHash(msScript)
124+
if err != nil {
125+
return fmt.Errorf("could not compute "+
126+
"multisig script hash: %w", err)
127+
}
128+
129+
log.Infof("Channel %v funding multisig P2WSH "+
130+
"(pubkey): %x",
131+
single.FundingOutpoint, msHash)
132+
84133
// Fix the incorrect descriptor by deriving a default
85134
// one and overwriting it in the backup.
86-
log.Infof("The shachain root for channel %s could "+
135+
log.Infof("The shachain root for channel %v could "+
87136
"not be derived, must be in old format. "+
88-
"Fixing...", single.FundingOutpoint.String())
137+
"Fixing...", single.FundingOutpoint)
138+
89139
baseKeyDesc, err := ring.DeriveKey(keychain.KeyLocator{
90140
Family: keychain.KeyFamilyRevocationRoot,
91141
Index: 0,

lnd/hdkeychain.go

Lines changed: 24 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,22 @@ 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+
682+
return kd.PubKey, nil
683+
}

0 commit comments

Comments
 (0)