Merge pull request #203 from RocketNodeLN/patch-2

Fix multisig path for sweeptimelockmanual
This commit is contained in:
Oliver Gugger 2025-07-29 13:28:47 -06:00 committed by GitHub
commit 2199e5893a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 28 additions and 13 deletions

View file

@ -167,6 +167,7 @@ func (c *sweepTimeLockManualCommand) Execute(_ *cobra.Command, _ []string) error
startNumChannelsTotal uint16
maxNumChannelsTotal = c.MaxNumChannelsTotal
remoteRevocationBasePoint = c.RemoteRevocationBasePoint
multiSigIdx uint32
)
// We either support specifying the remote revocation base point
@ -193,14 +194,13 @@ func (c *sweepTimeLockManualCommand) Execute(_ *cobra.Command, _ []string) error
}
remoteCfg := backupChan.RemoteChanCfg
localCfg := backupChan.LocalChanCfg
remoteRevocationBasePoint = remoteCfg.RevocationBasePoint.PubKey
startCsvLimit = remoteCfg.CsvDelay
maxCsvLimit = startCsvLimit + 1
delayPath, err := lnd.ParsePath(
backupChan.LocalChanCfg.DelayBasePoint.Path,
)
delayPath, err := lnd.ParsePath(localCfg.DelayBasePoint.Path)
if err != nil {
return fmt.Errorf("error parsing delay path: %w", err)
}
@ -210,6 +210,16 @@ func (c *sweepTimeLockManualCommand) Execute(_ *cobra.Command, _ []string) error
startNumChannelsTotal = uint16(delayPath[4])
maxNumChannelsTotal = startNumChannelsTotal + 1
multiSigKeyPath, err := lnd.ParsePath(localCfg.MultiSigKey.Path)
if err != nil {
return fmt.Errorf("error parsing multisigkey path: %w",
err)
}
if len(multiSigKeyPath) != 5 {
return fmt.Errorf("invalid multisig path '%v'",
multiSigKeyPath)
}
multiSigIdx = multiSigKeyPath[4]
case c.ChannelBackup != "" && c.RemoteRevocationBasePoint != "":
return errors.New("cannot use both --frombackup and " +
@ -230,7 +240,7 @@ func (c *sweepTimeLockManualCommand) Execute(_ *cobra.Command, _ []string) error
return sweepTimeLockManual(
extendedKey, c.APIURL, c.SweepAddr, c.TimeLockAddr,
remoteRevPoint, startCsvLimit, maxCsvLimit,
remoteRevPoint, multiSigIdx, startCsvLimit, maxCsvLimit,
startNumChannelsTotal, maxNumChannelsTotal,
c.MaxNumChanUpdates, c.Publish, c.FeeRate,
)
@ -238,8 +248,9 @@ func (c *sweepTimeLockManualCommand) Execute(_ *cobra.Command, _ []string) error
func sweepTimeLockManual(extendedKey *hdkeychain.ExtendedKey, apiURL string,
sweepAddr, timeLockAddr string, remoteRevPoint *btcec.PublicKey,
startCsvTimeout, maxCsvTimeout, startNumChannels, maxNumChannels uint16,
maxNumChanUpdates uint64, publish bool, feeRate uint32) error {
multiSigIdx uint32, startCsvTimeout, maxCsvTimeout, startNumChannels,
maxNumChannels uint16, maxNumChanUpdates uint64, publish bool,
feeRate uint32) error {
log.Debugf("Starting to brute force the time lock script, using: "+
"remote_rev_base_point=%x, start_csv_limit=%d, "+
@ -301,9 +312,13 @@ func sweepTimeLockManual(extendedKey *hdkeychain.ExtendedKey, apiURL string,
commitPoint *btcec.PublicKey
)
for i := startNumChannels; i < maxNumChannels; i++ {
if multiSigIdx == 0 {
multiSigIdx = uint32(i)
}
csvTimeout, script, scriptHash, commitPoint, delayDesc, err = tryKey(
baseKey, remoteRevPoint, startCsvTimeout, maxCsvTimeout,
lockScript, uint32(i), maxNumChanUpdates,
lockScript, uint32(i), multiSigIdx, maxNumChanUpdates,
)
if err == nil {
@ -413,9 +428,9 @@ func sweepTimeLockManual(extendedKey *hdkeychain.ExtendedKey, apiURL string,
}
func tryKey(baseKey *hdkeychain.ExtendedKey, remoteRevPoint *btcec.PublicKey,
startCsvTimeout, maxCsvTimeout uint16, lockScript []byte, idx uint32,
maxNumChanUpdates uint64) (int32, []byte, []byte, *btcec.PublicKey,
*keychain.KeyDescriptor, error) {
startCsvTimeout, maxCsvTimeout uint16, lockScript []byte, idx,
multiSigIdx uint32, maxNumChanUpdates uint64) (int32, []byte,
[]byte, *btcec.PublicKey, *keychain.KeyDescriptor, error) {
// The easy part first, let's derive the delay base point.
delayPath := []uint32{
@ -495,7 +510,7 @@ func tryKey(baseKey *hdkeychain.ExtendedKey, remoteRevPoint *btcec.PublicKey,
// Now we try the same with the new revocation producer format.
multiSigPath := []uint32{
lnd.HardenedKey(uint32(keychain.KeyFamilyMultiSig)),
0, idx,
0, multiSigIdx,
}
multiSigPrivKey, err := lnd.PrivKeyFromPath(baseKey, multiSigPath)
if err != nil {

View file

@ -91,7 +91,7 @@ var sweepTimeLockManualCases = []struct {
func TestSweepTimeLockManual(t *testing.T) {
for _, tc := range sweepTimeLockManualCases {
// First, we need to parse the lock addr and make sure we can
// brute force the script with the information we have. If not,
// brute-force the script with the information we have. If not,
// we can't continue anyway.
lockScript, err := lnd.GetP2WSHScript(
tc.timeLockAddr, tc.params,
@ -115,7 +115,7 @@ func TestSweepTimeLockManual(t *testing.T) {
_, _, _, _, _, err = tryKey(
baseKey, revPubKey, 0, defaultCsvLimit, lockScript,
tc.keyIndex, 1000,
tc.keyIndex, tc.keyIndex, 1000,
)
require.NoError(t, err)
}