mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-01-19 05:45:21 +01:00
rpcserver+lnrpc+lncli: add AbandonChannel rpc call
Using AbandonChannel, a channel can be abandoned. This means removing all state without any on-chain or off-chain action. A close summary is the only thing that is stored in the db after abandoning. A specific close type Abandoned is added. Abandoned channels can be retrieved via the ClosedChannels RPC.
This commit is contained in:
parent
3b6f7fdb83
commit
ab67b9a4de
@ -1792,6 +1792,11 @@ const (
|
||||
// we or the remote fail at some point during the opening workflow, or
|
||||
// we timeout waiting for the funding transaction to be confirmed.
|
||||
FundingCanceled ClosureType = 3
|
||||
|
||||
// Abandoned indicates that the channel state was removed without
|
||||
// any further actions. This is intended to clean up unusable
|
||||
// channels during development.
|
||||
Abandoned ClosureType = 5
|
||||
)
|
||||
|
||||
// ChannelCloseSummary contains the final state of a channel at the point it
|
||||
|
@ -709,43 +709,19 @@ func closeChannel(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
channelPoint, err := parseChannelPoint(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(roasbeef): implement time deadline within server
|
||||
req := &lnrpc.CloseChannelRequest{
|
||||
ChannelPoint: &lnrpc.ChannelPoint{},
|
||||
ChannelPoint: channelPoint,
|
||||
Force: ctx.Bool("force"),
|
||||
TargetConf: int32(ctx.Int64("conf_target")),
|
||||
SatPerByte: ctx.Int64("sat_per_byte"),
|
||||
}
|
||||
|
||||
args := ctx.Args()
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("funding_txid"):
|
||||
req.ChannelPoint.FundingTxid = &lnrpc.ChannelPoint_FundingTxidStr{
|
||||
FundingTxidStr: ctx.String("funding_txid"),
|
||||
}
|
||||
case args.Present():
|
||||
req.ChannelPoint.FundingTxid = &lnrpc.ChannelPoint_FundingTxidStr{
|
||||
FundingTxidStr: args.First(),
|
||||
}
|
||||
args = args.Tail()
|
||||
default:
|
||||
return fmt.Errorf("funding txid argument missing")
|
||||
}
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("output_index"):
|
||||
req.ChannelPoint.OutputIndex = uint32(ctx.Int("output_index"))
|
||||
case args.Present():
|
||||
index, err := strconv.ParseUint(args.First(), 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to decode output index: %v", err)
|
||||
}
|
||||
req.ChannelPoint.OutputIndex = uint32(index)
|
||||
default:
|
||||
req.ChannelPoint.OutputIndex = 0
|
||||
}
|
||||
|
||||
// After parsing the request, we'll spin up a goroutine that will
|
||||
// retrieve the closing transaction ID when attempting to close the
|
||||
// channel. We do this to because `executeChannelClose` can block, so we
|
||||
@ -765,7 +741,7 @@ func closeChannel(ctx *cli.Context) error {
|
||||
})
|
||||
}()
|
||||
|
||||
err := executeChannelClose(client, req, txidChan, ctx.Bool("block"))
|
||||
err = executeChannelClose(client, req, txidChan, ctx.Bool("block"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1029,6 +1005,102 @@ func promptForConfirmation(msg string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
var abandonChannelCommand = cli.Command{
|
||||
Name: "abandonchannel",
|
||||
Category: "Channels",
|
||||
Usage: "Abandons an existing channel.",
|
||||
Description: `
|
||||
Removes all channel state from the database except for a close
|
||||
summary. This method can be used to get rid of permanently unusable
|
||||
channels due to bugs fixed in newer versions of lnd.
|
||||
|
||||
Only available when lnd is built in debug mode.
|
||||
|
||||
To view which funding_txids/output_indexes can be used for this command,
|
||||
see the channel_point values within the listchannels command output.
|
||||
The format for a channel_point is 'funding_txid:output_index'.`,
|
||||
ArgsUsage: "funding_txid [output_index]",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "funding_txid",
|
||||
Usage: "the txid of the channel's funding transaction",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "output_index",
|
||||
Usage: "the output index for the funding output of the funding " +
|
||||
"transaction",
|
||||
},
|
||||
},
|
||||
Action: actionDecorator(abandonChannel),
|
||||
}
|
||||
|
||||
func abandonChannel(ctx *cli.Context) error {
|
||||
ctxb := context.Background()
|
||||
|
||||
client, cleanUp := getClient(ctx)
|
||||
defer cleanUp()
|
||||
|
||||
// Show command help if no arguments and flags were provided.
|
||||
if ctx.NArg() == 0 && ctx.NumFlags() == 0 {
|
||||
cli.ShowCommandHelp(ctx, "abandonchannel")
|
||||
return nil
|
||||
}
|
||||
|
||||
channelPoint, err := parseChannelPoint(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := &lnrpc.AbandonChannelRequest{
|
||||
ChannelPoint: channelPoint,
|
||||
}
|
||||
|
||||
resp, err := client.AbandonChannel(ctxb, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printRespJSON(resp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseChannelPoint parses a funding txid and output index from the command
|
||||
// line. Both named options as well as unnamed parameters are supported.
|
||||
func parseChannelPoint(ctx *cli.Context) (*lnrpc.ChannelPoint, error) {
|
||||
channelPoint := &lnrpc.ChannelPoint{}
|
||||
|
||||
args := ctx.Args()
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("funding_txid"):
|
||||
channelPoint.FundingTxid = &lnrpc.ChannelPoint_FundingTxidStr{
|
||||
FundingTxidStr: ctx.String("funding_txid"),
|
||||
}
|
||||
case args.Present():
|
||||
channelPoint.FundingTxid = &lnrpc.ChannelPoint_FundingTxidStr{
|
||||
FundingTxidStr: args.First(),
|
||||
}
|
||||
args = args.Tail()
|
||||
default:
|
||||
return nil, fmt.Errorf("funding txid argument missing")
|
||||
}
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("output_index"):
|
||||
channelPoint.OutputIndex = uint32(ctx.Int("output_index"))
|
||||
case args.Present():
|
||||
index, err := strconv.ParseUint(args.First(), 10, 32)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decode output index: %v", err)
|
||||
}
|
||||
channelPoint.OutputIndex = uint32(index)
|
||||
default:
|
||||
channelPoint.OutputIndex = 0
|
||||
}
|
||||
|
||||
return channelPoint, nil
|
||||
}
|
||||
|
||||
var listPeersCommand = cli.Command{
|
||||
Name: "listpeers",
|
||||
Category: "Peers",
|
||||
@ -1618,6 +1690,11 @@ var closedChannelsCommand = cli.Command{
|
||||
Name: "funding_canceled",
|
||||
Usage: "list channels that were never fully opened",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "abandoned",
|
||||
Usage: "list channels that were abandoned by " +
|
||||
"the local node",
|
||||
},
|
||||
},
|
||||
Action: actionDecorator(closedChannels),
|
||||
}
|
||||
@ -1633,6 +1710,7 @@ func closedChannels(ctx *cli.Context) error {
|
||||
RemoteForce: ctx.Bool("remote_force"),
|
||||
Breach: ctx.Bool("breach"),
|
||||
FundingCanceled: ctx.Bool("funding_cancelled"),
|
||||
Abandoned: ctx.Bool("abandoned"),
|
||||
}
|
||||
|
||||
resp, err := client.ClosedChannels(ctxb, req)
|
||||
|
@ -264,6 +264,7 @@ func main() {
|
||||
openChannelCommand,
|
||||
closeChannelCommand,
|
||||
closeAllChannelsCommand,
|
||||
abandonChannelCommand,
|
||||
listPeersCommand,
|
||||
walletBalanceCommand,
|
||||
channelBalanceCommand,
|
||||
|
6
config_debug.go
Normal file
6
config_debug.go
Normal file
@ -0,0 +1,6 @@
|
||||
// +build debug
|
||||
|
||||
package main
|
||||
|
||||
// DebugBuild signals that this is a debug build.
|
||||
const DebugBuild = true
|
6
config_production.go
Normal file
6
config_production.go
Normal file
@ -0,0 +1,6 @@
|
||||
// +build !debug
|
||||
|
||||
package main
|
||||
|
||||
// DebugBuild signals that this is a debug build.
|
||||
const DebugBuild = false
|
903
lnrpc/rpc.pb.go
903
lnrpc/rpc.pb.go
File diff suppressed because it is too large
Load Diff
@ -301,6 +301,52 @@ func request_Lightning_CloseChannel_0(ctx context.Context, marshaler runtime.Mar
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_Lightning_AbandonChannel_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_point": 0, "funding_txid_str": 1, "output_index": 2}, Base: []int{1, 1, 1, 2, 0, 0}, Check: []int{0, 1, 2, 2, 3, 4}}
|
||||
)
|
||||
|
||||
func request_Lightning_AbandonChannel_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq AbandonChannelRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["channel_point.funding_txid_str"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_point.funding_txid_str")
|
||||
}
|
||||
|
||||
err = runtime.PopulateFieldFromPath(&protoReq, "channel_point.funding_txid_str", val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_point.funding_txid_str", err)
|
||||
}
|
||||
|
||||
val, ok = pathParams["channel_point.output_index"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_point.output_index")
|
||||
}
|
||||
|
||||
err = runtime.PopulateFieldFromPath(&protoReq, "channel_point.output_index", val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_point.output_index", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_Lightning_AbandonChannel_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.AbandonChannel(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Lightning_SendPaymentSync_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq SendRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -1220,6 +1266,35 @@ func RegisterLightningHandler(ctx context.Context, mux *runtime.ServeMux, conn *
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_Lightning_AbandonChannel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Lightning_AbandonChannel_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Lightning_AbandonChannel_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Lightning_SendPaymentSync_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
@ -1745,6 +1820,8 @@ var (
|
||||
|
||||
pattern_Lightning_CloseChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "channels", "channel_point.funding_txid_str", "channel_point.output_index"}, ""))
|
||||
|
||||
pattern_Lightning_AbandonChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "channels", "channel_point.funding_txid_str", "channel_point.output_index"}, ""))
|
||||
|
||||
pattern_Lightning_SendPaymentSync_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "channels", "transactions"}, ""))
|
||||
|
||||
pattern_Lightning_SendToRouteSync_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "channels", "transactions", "route"}, ""))
|
||||
@ -1809,6 +1886,8 @@ var (
|
||||
|
||||
forward_Lightning_CloseChannel_0 = runtime.ForwardResponseStream
|
||||
|
||||
forward_Lightning_AbandonChannel_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Lightning_SendPaymentSync_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Lightning_SendToRouteSync_0 = runtime.ForwardResponseMessage
|
||||
|
@ -389,6 +389,19 @@ service Lightning {
|
||||
};
|
||||
}
|
||||
|
||||
/** lncli: `abandonchannel`
|
||||
AbandonChannel removes all channel state from the database except for a
|
||||
close summary. This method can be used to get rid of permanently unusable
|
||||
channels due to bugs fixed in newer versions of lnd. Only available
|
||||
when in debug builds of lnd.
|
||||
*/
|
||||
rpc AbandonChannel (AbandonChannelRequest) returns (AbandonChannelResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/v1/channels/{channel_point.funding_txid_str}/{channel_point.output_index}"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/** lncli: `sendpayment`
|
||||
SendPayment dispatches a bi-directional streaming RPC for sending payments
|
||||
through the Lightning Network. A single RPC invocation creates a persistent
|
||||
@ -991,6 +1004,7 @@ message ChannelCloseSummary {
|
||||
REMOTE_FORCE_CLOSE = 2;
|
||||
BREACH_CLOSE = 3;
|
||||
FUNDING_CANCELED = 4;
|
||||
ABANDONED = 5;
|
||||
}
|
||||
|
||||
/// Details on how the channel was closed.
|
||||
@ -1003,6 +1017,7 @@ message ClosedChannelsRequest {
|
||||
bool remote_force = 3;
|
||||
bool breach = 4;
|
||||
bool funding_canceled = 5;
|
||||
bool abandoned = 6;
|
||||
}
|
||||
|
||||
message ClosedChannelsResponse {
|
||||
@ -1820,6 +1835,14 @@ message DeleteAllPaymentsRequest {
|
||||
message DeleteAllPaymentsResponse {
|
||||
}
|
||||
|
||||
message AbandonChannelRequest {
|
||||
ChannelPoint channel_point = 1;
|
||||
}
|
||||
|
||||
message AbandonChannelResponse {
|
||||
}
|
||||
|
||||
|
||||
message DebugLevelRequest {
|
||||
bool show = 1;
|
||||
string level_spec = 2;
|
||||
|
@ -195,6 +195,13 @@
|
||||
"required": false,
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "abandoned",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
@ -275,13 +282,13 @@
|
||||
},
|
||||
"/v1/channels/{channel_point.funding_txid_str}/{channel_point.output_index}": {
|
||||
"delete": {
|
||||
"summary": "* lncli: `closechannel`\nCloseChannel attempts to close an active channel identified by its channel\noutpoint (ChannelPoint). The actions of this method can additionally be\naugmented to attempt a force close after a timeout period in the case of an\ninactive peer. If a non-force close (cooperative closure) is requested,\nthen the user can specify either a target number of blocks until the\nclosure transaction is confirmed, or a manual fee rate. If neither are\nspecified, then a default lax, block confirmation target is used.",
|
||||
"operationId": "CloseChannel",
|
||||
"summary": "* lncli: `abandonchannel`\nAbandonChannel removes all channel state from the database except for a\nclose summary. This method can be used to get rid of permanently unusable\nchannels due to bugs fixed in newer versions of lnd. Only available\nwhen in debug builds of lnd.",
|
||||
"operationId": "AbandonChannel",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "(streaming responses)",
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/lnrpcCloseStatusUpdate"
|
||||
"$ref": "#/definitions/lnrpcAbandonChannelResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -970,7 +977,8 @@
|
||||
"LOCAL_FORCE_CLOSE",
|
||||
"REMOTE_FORCE_CLOSE",
|
||||
"BREACH_CLOSE",
|
||||
"FUNDING_CANCELED"
|
||||
"FUNDING_CANCELED",
|
||||
"ABANDONED"
|
||||
],
|
||||
"default": "COOPERATIVE_CLOSE"
|
||||
},
|
||||
@ -1092,6 +1100,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnrpcAbandonChannelResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"lnrpcAddInvoiceResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
80
rpcserver.go
80
rpcserver.go
@ -201,6 +201,10 @@ var (
|
||||
Entity: "offchain",
|
||||
Action: "write",
|
||||
}},
|
||||
"/lnrpc.Lightning/AbandonChannel": {{
|
||||
Entity: "offchain",
|
||||
Action: "write",
|
||||
}},
|
||||
"/lnrpc.Lightning/GetInfo": {{
|
||||
Entity: "info",
|
||||
Action: "read",
|
||||
@ -1200,9 +1204,56 @@ out:
|
||||
return nil
|
||||
}
|
||||
|
||||
// fetchActiveChannel attempts to locate a channel identified by its channel
|
||||
// AbandonChannel removes all channel state from the database except for a
|
||||
// close summary. This method can be used to get rid of permanently unusable
|
||||
// channels due to bugs fixed in newer versions of lnd.
|
||||
func (r *rpcServer) AbandonChannel(ctx context.Context,
|
||||
in *lnrpc.AbandonChannelRequest) (*lnrpc.AbandonChannelResponse, error) {
|
||||
|
||||
if !DebugBuild {
|
||||
return nil, fmt.Errorf("AbandonChannel RPC call only " +
|
||||
"available in debug builds")
|
||||
}
|
||||
|
||||
index := in.ChannelPoint.OutputIndex
|
||||
txidHash, err := getChanPointFundingTxid(in.GetChannelPoint())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txid, err := chainhash.NewHash(txidHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chanPoint := wire.NewOutPoint(txid, index)
|
||||
|
||||
dbChan, err := r.fetchOpenDbChannel(*chanPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
summary := &channeldb.ChannelCloseSummary{
|
||||
ChanPoint: *chanPoint,
|
||||
ChainHash: dbChan.ChainHash,
|
||||
RemotePub: dbChan.IdentityPub,
|
||||
Capacity: dbChan.Capacity,
|
||||
CloseType: channeldb.Abandoned,
|
||||
ShortChanID: dbChan.ShortChannelID,
|
||||
IsPending: false,
|
||||
}
|
||||
|
||||
err = dbChan.CloseChannel(summary)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &lnrpc.AbandonChannelResponse{}, nil
|
||||
}
|
||||
|
||||
// fetchOpenDbChannel attempts to locate a channel identified by its channel
|
||||
// point from the database's set of all currently opened channels.
|
||||
func (r *rpcServer) fetchActiveChannel(chanPoint wire.OutPoint) (*lnwallet.LightningChannel, error) {
|
||||
func (r *rpcServer) fetchOpenDbChannel(chanPoint wire.OutPoint) (
|
||||
*channeldb.OpenChannel, error) {
|
||||
|
||||
dbChannels, err := r.server.chanDB.FetchAllChannels()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1224,7 +1275,22 @@ func (r *rpcServer) fetchActiveChannel(chanPoint wire.OutPoint) (*lnwallet.Light
|
||||
return nil, fmt.Errorf("unable to find channel")
|
||||
}
|
||||
|
||||
// Otherwise, we create a fully populated channel state machine which
|
||||
return dbChan, nil
|
||||
}
|
||||
|
||||
// fetchActiveChannel attempts to locate a channel identified by its channel
|
||||
// point from the database's set of all currently opened channels and
|
||||
// return it as a fully popuplated state machine
|
||||
func (r *rpcServer) fetchActiveChannel(chanPoint wire.OutPoint) (
|
||||
*lnwallet.LightningChannel, error) {
|
||||
|
||||
dbChan, err := r.fetchOpenDbChannel(chanPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the channel is successfully fetched from the database,
|
||||
// we create a fully populated channel state machine which
|
||||
// uses the db channel as backing storage.
|
||||
return lnwallet.NewLightningChannel(
|
||||
r.server.cc.wallet.Cfg.Signer, nil, dbChan,
|
||||
@ -1619,7 +1685,8 @@ func (r *rpcServer) ClosedChannels(ctx context.Context,
|
||||
|
||||
// Show all channels when no filter flags are set.
|
||||
filterResults := in.Cooperative || in.LocalForce ||
|
||||
in.RemoteForce || in.Breach || in.FundingCanceled
|
||||
in.RemoteForce || in.Breach || in.FundingCanceled ||
|
||||
in.Abandoned
|
||||
|
||||
resp := &lnrpc.ClosedChannelsResponse{}
|
||||
|
||||
@ -1670,6 +1737,11 @@ func (r *rpcServer) ClosedChannels(ctx context.Context,
|
||||
continue
|
||||
}
|
||||
closeType = lnrpc.ChannelCloseSummary_FUNDING_CANCELED
|
||||
case channeldb.Abandoned:
|
||||
if filterResults && !in.Abandoned {
|
||||
continue
|
||||
}
|
||||
closeType = lnrpc.ChannelCloseSummary_ABANDONED
|
||||
}
|
||||
|
||||
channel := &lnrpc.ChannelCloseSummary{
|
||||
|
Loading…
Reference in New Issue
Block a user