Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forceclose: allow to specify specific height #150

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 60 additions & 8 deletions cmd/chantools/forceclose.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ import (
)

type forceCloseCommand struct {
APIURL string
ChannelDB string
Publish bool
APIURL string
SingleChannel string
UpdateNum int64
ChannelDB string
Publish bool

rootKey *rootKey
inputs *inputFlags
Expand Down Expand Up @@ -50,17 +52,35 @@ blocks) transaction *or* they have a watch tower looking out for them.
Example: `chantools forceclose \
--fromsummary results/summary-xxxx-yyyy.json
--channeldb ~/.lnd/data/graph/mainnet/channel.db \
--publish

chantools forceclose \
--singlechannel aabb00...:0 \
--channeldb ~/.lnd/data/graph/mainnet/channel.db \
--publish`,
RunE: cc.Execute,
}
cc.cmd.Flags().StringVar(
&cc.APIURL, "apiurl", defaultAPIURL, "API URL to use (must "+
"be esplora compatible)",
)
cc.cmd.Flags().StringVar(
&cc.SingleChannel, "singlechannel", "", "force-close a "+
"single channel by providing the channel point "+
"instead of specifying any of the --fromchanneldb, "+
"--fromsummary --listchannels or --pendingchannels "+
"flags",
)
cc.cmd.Flags().StringVar(
&cc.ChannelDB, "channeldb", "", "lnd channel.db file to use "+
"for force-closing channels",
)
cc.cmd.Flags().Int64Var(
&cc.UpdateNum, "updatenum", -1, "attempt to publish a "+
"specific commitment transaction at the given height, "+
"leave at -1 to publish the latest state available in "+
"the channel DB",
)
cc.cmd.Flags().BoolVar(
&cc.Publish, "publish", false, "publish force-closing TX to "+
"the chain API instead of just printing the TX",
Expand All @@ -87,19 +107,28 @@ func (c *forceCloseCommand) Execute(_ *cobra.Command, _ []string) error {
return fmt.Errorf("error opening rescue DB: %w", err)
}

// Parse channel entries from any of the possible input files.
entries, err := c.inputs.parseInputType()
if err != nil {
return err
// Parse channel entries from any of the possible input files, unless
// a single channel is specified.
var entries []*dataformat.SummaryEntry
if c.SingleChannel != "" {
entries = []*dataformat.SummaryEntry{{
ChannelPoint: c.SingleChannel,
}}
} else {
entries, err = c.inputs.parseInputType()
if err != nil {
return err
}
}
return forceCloseChannels(
c.APIURL, extendedKey, entries, db.ChannelStateDB(), c.Publish,
c.UpdateNum,
)
}

func forceCloseChannels(apiURL string, extendedKey *hdkeychain.ExtendedKey,
entries []*dataformat.SummaryEntry, chanDb *channeldb.ChannelStateDB,
publish bool) error {
publish bool, updateNum int64) error {

channels, err := chanDb.FetchAllChannels()
if err != nil {
Expand Down Expand Up @@ -136,6 +165,29 @@ func forceCloseChannels(apiURL string, extendedKey *hdkeychain.ExtendedKey,
continue
}

// Attempt to publish a specific height?
if updateNum != -1 {
_, commit, err := channel.FindPreviousState(
uint64(updateNum),
)
if err != nil {
return fmt.Errorf("unable to find commit at "+
"height %d: %w", updateNum, err)
}

if commit == nil {
return fmt.Errorf("commit at height %d not "+
"available in channel DB", updateNum)
}

if commit.CommitTx == nil {
return fmt.Errorf("commit at height %d has no "+
"commit TX", updateNum)
}

channel.LocalCommitment = *commit
}

// Create signed transaction.
lc := &lnd.LightningChannel{
LocalChanCfg: channel.LocalChanCfg,
Expand Down
Loading