mirror of
https://github.com/guggero/chantools
synced 2024-11-07 03:20:43 +00:00
triggerforceclose: make cmd compatible with all nodes
This commit is contained in:
parent
0fd58ee7eb
commit
179773fdb9
@ -107,7 +107,8 @@ Scenarios:
|
||||
Another reason might be that the peer is a CLN node with a specific version
|
||||
that doesn't react to force close requests normally. You can use the
|
||||
[`chantools triggerforceclose` command](doc/chantools_triggerforceclose.md) in
|
||||
that case (ONLY works with CLN peers of a certain version).
|
||||
that case (should work with CLN peers of a certain version that don't respond
|
||||
to normal force close requests).
|
||||
|
||||
## What should I NEVER do?
|
||||
|
||||
@ -437,7 +438,7 @@ Available Commands:
|
||||
sweeptimelock Sweep the force-closed state after the time lock has expired
|
||||
sweeptimelockmanual Sweep the force-closed state of a single channel manually if only a channel backup file is available
|
||||
sweepremoteclosed Go through all the addresses that could have funds of channels that were force-closed by the remote party. A public block explorer is queried for each address and if any balance is found, all funds are swept to a given address
|
||||
triggerforceclose Connect to a peer and send a custom message to trigger a force close of the specified channel
|
||||
triggerforceclose Connect to a peer and send request to trigger a force close of the specified channel
|
||||
vanitygen Generate a seed with a custom lnd node identity public key that starts with the given prefix
|
||||
walletinfo Shows info about an lnd wallet.db file and optionally extracts the BIP32 HD root key
|
||||
zombierecovery Try rescuing funds stuck in channels with zombie nodes
|
||||
@ -499,7 +500,7 @@ Legend:
|
||||
| [sweepremoteclosed](doc/chantools_sweepremoteclosed.md) | :pencil: Find channel funds from remotely force closed channels and sweep them |
|
||||
| [sweeptimelock](doc/chantools_sweeptimelock.md) | :pencil: Sweep funds in locally force closed channels once time lock has expired (requires `channel.db`) |
|
||||
| [sweeptimelockmanual](doc/chantools_sweeptimelockmanual.md) | :pencil: Manually sweep funds in a locally force closed channel where no `channel.db` file is available |
|
||||
| [triggerforceclose](doc/chantools_triggerforceclose.md) | :pencil: (:pushpin:) Request certain CLN peers to force close a channel that don't react to normal SCB recovery requests |
|
||||
| [triggerforceclose](doc/chantools_triggerforceclose.md) | :pencil: (:pushpin:) Request a peer to force close a channel |
|
||||
| [vanitygen](doc/chantools_vanitygen.md) | Generate an `lnd` seed for a node public key that starts with a certain sequence of hex digits |
|
||||
| [walletinfo](doc/chantools_walletinfo.md) | Show information from a `wallet.db` file, requires access to the wallet password |
|
||||
| [zombierecovery](doc/chantools_zombierecovery.md) | :pencil: Cooperatively rescue funds from channels where normal recovery is not possible (see [full guide here][zombie-recovery]) |
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/connmgr"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -37,13 +38,13 @@ func newTriggerForceCloseCommand() *cobra.Command {
|
||||
cc := &triggerForceCloseCommand{}
|
||||
cc.cmd = &cobra.Command{
|
||||
Use: "triggerforceclose",
|
||||
Short: "Connect to a CLN peer and send a custom message to " +
|
||||
"trigger a force close of the specified channel",
|
||||
Long: `Certain versions of CLN didn't properly react to error
|
||||
messages sent by peers and therefore didn't follow the DLP protocol to recover
|
||||
channel funds using SCB. This command can be used to trigger a force close with
|
||||
those earlier versions of CLN (this command will not work for lnd peers or CLN
|
||||
peers of a different version).`,
|
||||
Short: "Connect to a Lightning Network peer and send " +
|
||||
"specific messages to trigger a force close of the " +
|
||||
"specified channel",
|
||||
Long: `Asks the specified remote peer to force close a specific
|
||||
channel by first sending a channel re-establish message, and if that doesn't
|
||||
work, a custom error message (in case the peer is a specific version of CLN that
|
||||
does not properly respond to a Data Loss Protection re-establish message).'`,
|
||||
Example: `chantools triggerforceclose \
|
||||
--peer 03abce...@xx.yy.zz.aa:9735 \
|
||||
--channel_point abcdef01234...:x`,
|
||||
@ -88,64 +89,14 @@ func (c *triggerForceCloseCommand) Execute(_ *cobra.Command, _ []string) error {
|
||||
PrivKey: identityPriv,
|
||||
}
|
||||
|
||||
peerAddr, err := lncfg.ParseLNAddressString(
|
||||
c.Peer, "9735", net.ResolveTCPAddr,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing peer address: %w", err)
|
||||
}
|
||||
|
||||
outPoint, err := parseOutPoint(c.ChannelPoint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing channel point: %w", err)
|
||||
}
|
||||
channelID := lnwire.NewChanIDFromOutPoint(outPoint)
|
||||
|
||||
conn, err := noiseDial(
|
||||
identityECDH, peerAddr, &tor.ClearNet{}, dialTimeout,
|
||||
)
|
||||
err = requestForceClose(c.Peer, pubKey, outPoint, identityECDH)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error dialing peer: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Attempting to connect to peer %x, dial timeout is %v",
|
||||
pubKey.SerializeCompressed(), dialTimeout)
|
||||
req := &connmgr.ConnReq{
|
||||
Addr: peerAddr,
|
||||
Permanent: false,
|
||||
}
|
||||
p, err := lnd.ConnectPeer(conn, req, chainParams, identityECDH)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error connecting to peer: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Connection established to peer %x",
|
||||
pubKey.SerializeCompressed())
|
||||
|
||||
// We'll wait until the peer is active.
|
||||
select {
|
||||
case <-p.ActiveSignal():
|
||||
case <-p.QuitSignal():
|
||||
return fmt.Errorf("peer %x disconnected",
|
||||
pubKey.SerializeCompressed())
|
||||
}
|
||||
|
||||
// Channel ID (32 byte) + u16 for the data length (which will be 0).
|
||||
data := make([]byte, 34)
|
||||
copy(data[:32], channelID[:])
|
||||
|
||||
log.Infof("Sending channel error message to peer to trigger force "+
|
||||
"close of channel %v", c.ChannelPoint)
|
||||
|
||||
_ = lnwire.SetCustomOverrides([]uint16{lnwire.MsgError})
|
||||
msg, err := lnwire.NewCustom(lnwire.MsgError, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = p.SendMessageLazy(true, msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error sending message: %w", err)
|
||||
return fmt.Errorf("error requesting force close: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Message sent, waiting for force close transaction to " +
|
||||
@ -183,6 +134,80 @@ func noiseDial(idKey keychain.SingleKeyECDH, lnAddr *lnwire.NetAddress,
|
||||
return brontide.Dial(idKey, lnAddr, timeout, netCfg.Dial)
|
||||
}
|
||||
|
||||
func requestForceClose(peerHost string, peerPubKey *btcec.PublicKey,
|
||||
channelPoint *wire.OutPoint, identity keychain.SingleKeyECDH) error {
|
||||
|
||||
peerAddr, err := lncfg.ParseLNAddressString(
|
||||
peerHost, "9735", net.ResolveTCPAddr,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing peer address: %w", err)
|
||||
}
|
||||
|
||||
channelID := lnwire.NewChanIDFromOutPoint(channelPoint)
|
||||
|
||||
conn, err := noiseDial(
|
||||
identity, peerAddr, &tor.ClearNet{}, dialTimeout,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error dialing peer: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Attempting to connect to peer %x, dial timeout is %v",
|
||||
peerPubKey.SerializeCompressed(), dialTimeout)
|
||||
req := &connmgr.ConnReq{
|
||||
Addr: peerAddr,
|
||||
Permanent: false,
|
||||
}
|
||||
p, err := lnd.ConnectPeer(conn, req, chainParams, identity)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error connecting to peer: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Connection established to peer %x",
|
||||
peerPubKey.SerializeCompressed())
|
||||
|
||||
// We'll wait until the peer is active.
|
||||
select {
|
||||
case <-p.ActiveSignal():
|
||||
case <-p.QuitSignal():
|
||||
return fmt.Errorf("peer %x disconnected",
|
||||
peerPubKey.SerializeCompressed())
|
||||
}
|
||||
|
||||
// Channel ID (32 byte) + u16 for the data length (which will be 0).
|
||||
data := make([]byte, 34)
|
||||
copy(data[:32], channelID[:])
|
||||
|
||||
log.Infof("Sending channel re-establish to peer to trigger force "+
|
||||
"close of channel %v", channelPoint)
|
||||
|
||||
err = p.SendMessageLazy(true, &lnwire.ChannelReestablish{
|
||||
ChanID: channelID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Sending channel error message to peer to trigger force "+
|
||||
"close of channel %v", channelPoint)
|
||||
|
||||
_ = lnwire.SetCustomOverrides([]uint16{
|
||||
lnwire.MsgError, lnwire.MsgChannelReestablish,
|
||||
})
|
||||
msg, err := lnwire.NewCustom(lnwire.MsgError, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = p.SendMessageLazy(true, msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error sending message: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseOutPoint(s string) (*wire.OutPoint, error) {
|
||||
split := strings.Split(s, ":")
|
||||
if len(split) != 2 || len(split[0]) == 0 || len(split[1]) == 0 {
|
||||
|
@ -51,7 +51,7 @@ https://github.com/lightninglabs/chantools/.
|
||||
* [chantools sweepremoteclosed](chantools_sweepremoteclosed.md) - Go through all the addresses that could have funds of channels that were force-closed by the remote party. A public block explorer is queried for each address and if any balance is found, all funds are swept to a given address
|
||||
* [chantools sweeptimelock](chantools_sweeptimelock.md) - Sweep the force-closed state after the time lock has expired
|
||||
* [chantools sweeptimelockmanual](chantools_sweeptimelockmanual.md) - Sweep the force-closed state of a single channel manually if only a channel backup file is available
|
||||
* [chantools triggerforceclose](chantools_triggerforceclose.md) - Connect to a CLN peer and send a custom message to trigger a force close of the specified channel
|
||||
* [chantools triggerforceclose](chantools_triggerforceclose.md) - Connect to a Lightning Network peer and send specific messages to trigger a force close of the specified channel
|
||||
* [chantools vanitygen](chantools_vanitygen.md) - Generate a seed with a custom lnd node identity public key that starts with the given prefix
|
||||
* [chantools walletinfo](chantools_walletinfo.md) - Shows info about an lnd wallet.db file and optionally extracts the BIP32 HD root key
|
||||
* [chantools zombierecovery](chantools_zombierecovery.md) - Try rescuing funds stuck in channels with zombie nodes
|
||||
|
@ -10,7 +10,7 @@ If only the failed payments should be deleted (and not the successful ones), the
|
||||
|
||||
CAUTION: Running this command will make it impossible to use the channel DB
|
||||
with an older version of lnd. Downgrading is not possible and you'll need to
|
||||
run lnd v0.17.0-beta or later after using this command!'
|
||||
run lnd v0.17.4-beta or later after using this command!'
|
||||
|
||||
```
|
||||
chantools deletepayments [flags]
|
||||
|
@ -12,7 +12,7 @@ without removing any other data.
|
||||
|
||||
CAUTION: Running this command will make it impossible to use the channel DB
|
||||
with an older version of lnd. Downgrading is not possible and you'll need to
|
||||
run lnd v0.17.0-beta or later after using this command!'
|
||||
run lnd v0.17.4-beta or later after using this command!'
|
||||
|
||||
```
|
||||
chantools dropchannelgraph [flags]
|
||||
|
@ -12,7 +12,7 @@ be helpful to fix a graph that is out of sync with the network.
|
||||
|
||||
CAUTION: Running this command will make it impossible to use the channel DB
|
||||
with an older version of lnd. Downgrading is not possible and you'll need to
|
||||
run lnd v0.17.0-beta or later after using this command!'
|
||||
run lnd v0.17.4-beta or later after using this command!'
|
||||
|
||||
```
|
||||
chantools dropgraphzombies [flags]
|
||||
|
@ -11,7 +11,7 @@ needs to read the database content.
|
||||
|
||||
CAUTION: Running this command will make it impossible to use the channel DB
|
||||
with an older version of lnd. Downgrading is not possible and you'll need to
|
||||
run lnd v0.17.0-beta or later after using this command!'
|
||||
run lnd v0.17.4-beta or later after using this command!'
|
||||
|
||||
```
|
||||
chantools migratedb [flags]
|
||||
|
@ -30,6 +30,7 @@ chantools recoverloopin \
|
||||
--output_amt uint amount of the output to sweep
|
||||
--publish publish sweep TX to the chain API instead of just printing the TX
|
||||
--rootkey string BIP32 HD root key of the wallet to use for deriving starting key; leave empty to prompt for lnd 24 word aezeed
|
||||
--sqlite_file string optional path to the loop sqlite database file, if not specified, the default location will be loaded from --loop_db_dir
|
||||
--start_key_index int start key index to try to find the correct key index
|
||||
--swap_hash string swap hash of the loop in swap
|
||||
--sweepaddr string address to recover the funds to; specify 'fromseed' to derive a new address from the seed automatically
|
||||
|
@ -11,7 +11,7 @@ channel was never confirmed on chain!
|
||||
|
||||
CAUTION: Running this command will make it impossible to use the channel DB
|
||||
with an older version of lnd. Downgrading is not possible and you'll need to
|
||||
run lnd v0.17.0-beta or later after using this command!
|
||||
run lnd v0.17.4-beta or later after using this command!
|
||||
|
||||
```
|
||||
chantools removechannel [flags]
|
||||
|
@ -1,14 +1,13 @@
|
||||
## chantools triggerforceclose
|
||||
|
||||
Connect to a CLN peer and send a custom message to trigger a force close of the specified channel
|
||||
Connect to a Lightning Network peer and send specific messages to trigger a force close of the specified channel
|
||||
|
||||
### Synopsis
|
||||
|
||||
Certain versions of CLN didn't properly react to error
|
||||
messages sent by peers and therefore didn't follow the DLP protocol to recover
|
||||
channel funds using SCB. This command can be used to trigger a force close with
|
||||
those earlier versions of CLN (this command will not work for lnd peers or CLN
|
||||
peers of a different version).
|
||||
Asks the specified remote peer to force close a specific
|
||||
channel by first sending a channel re-establish message, and if that doesn't
|
||||
work, a custom error message (in case the peer is a specific version of CLN that
|
||||
does not properly respond to a Data Loss Protection re-establish message).'
|
||||
|
||||
```
|
||||
chantools triggerforceclose [flags]
|
||||
|
Loading…
Reference in New Issue
Block a user