lndclient: add closed channels to lnd client

pull/221/head
carla 4 years ago
parent 11a04e65ff
commit c1a9889e4d
No known key found for this signature in database
GPG Key ID: 4CA7FE54A6213C91

@ -50,6 +50,9 @@ type LightningClient interface {
// ListChannels retrieves all channels of the backing lnd node.
ListChannels(ctx context.Context) ([]ChannelInfo, error)
// ClosedChannels returns all closed channels of the backing lnd node.
ClosedChannels(ctx context.Context) ([]ClosedChannel, error)
// ChannelBackup retrieves the backup for a particular channel. The
// backup is returned as an encrypted chanbackup.Single payload.
ChannelBackup(context.Context, wire.OutPoint) ([]byte, error)
@ -109,6 +112,138 @@ type ChannelInfo struct {
Uptime time.Duration
}
// ClosedChannel represents a channel that has been closed.
type ClosedChannel struct {
// ChannelPoint is the funding outpoint of the channel.
ChannelPoint string
// ChannelID holds the unique channel ID for the channel. The first 3
// bytes are the block height, the next 3 the index within the block,
// and the last 2 bytes are the output index for the channel.
ChannelID uint64
// ClosingTxHash is the tx hash of the close transaction for the channel.
ClosingTxHash string
// CloseType is the type of channel closure.
CloseType CloseType
// OpenInitiator is true if we opened the channel. This value is not
// always available (older channels do not have it).
OpenInitiator Initiator
// Initiator indicates which party initiated the channel close. Since
// this value is not always set in the rpc response, we also make a best
// effort attempt to set it based on CloseType.
CloseInitiator Initiator
// PubKeyBytes is the raw bytes of the public key of the remote node.
PubKeyBytes route.Vertex
// Capacity is the total amount of funds held in this channel.
Capacity btcutil.Amount
// SettledBalance is the amount we were paid out directly in this
// channel close. Note that this does not include cases where we need to
// sweep our commitment or htlcs.
SettledBalance btcutil.Amount
}
// CloseType is an enum which represents the types of closes our channels may
// have. This type maps to the rpc value.
type CloseType uint8
const (
// CloseTypeCooperative represents cooperative closes.
CloseTypeCooperative CloseType = iota
// CloseTypeLocalForce represents force closes that we initiated.
CloseTypeLocalForce
// CloseTypeRemoteForce represents force closes that our peer initiated.
CloseTypeRemoteForce
// CloseTypeBreach represents breach closes from our peer.
CloseTypeBreach
// CloseTypeFundingCancelled represents channels which were never
// created because their funding transaction was cancelled.
CloseTypeFundingCancelled
// CloseTypeAbandoned represents a channel that was abandoned.
CloseTypeAbandoned
)
// String returns the string representation of a close type.
func (c CloseType) String() string {
switch c {
case CloseTypeCooperative:
return "Cooperative"
case CloseTypeLocalForce:
return "Local Force"
case CloseTypeRemoteForce:
return "Remote Force"
case CloseTypeBreach:
return "Breach"
case CloseTypeFundingCancelled:
return "Funding Cancelled"
case CloseTypeAbandoned:
return "Abandoned"
default:
return "Unknown"
}
}
// Initiator indicates the party that opened or closed a channel. This enum is
// used for cases where we may not have a full set of initiator information
// available over rpc (this is the case for older channels).
type Initiator uint8
const (
// InitiatorUnrecorded is set when we do not know the open/close
// initiator for a channel, this is the case when the channel was
// closed before lnd started tracking initiators.
InitiatorUnrecorded Initiator = iota
// InitiatorLocal is set when we initiated a channel open or close.
InitiatorLocal
// InitiatorRemote is set when the remote party initiated a chanel open
// or close.
InitiatorRemote
// InitiatorBoth is set in the case where both parties initiated a
// cooperative close (this is possible with multiple rounds of
// negotiation).
InitiatorBoth
)
// String provides the string represenetation of a close initiator.
func (c Initiator) String() string {
switch c {
case InitiatorUnrecorded:
return "Unrecorded"
case InitiatorLocal:
return "Local"
case InitiatorRemote:
return "Remote"
case InitiatorBoth:
return "Both"
default:
return fmt.Sprintf("unknown initiator: %d", c)
}
}
var (
// ErrMalformedServerResponse is returned when the swap and/or prepay
// invoice is malformed.
@ -583,6 +718,130 @@ func (s *lightningClient) ListChannels(ctx context.Context) (
return result, nil
}
// ClosedChannels returns a list of our closed channels.
func (s *lightningClient) ClosedChannels(ctx context.Context) ([]ClosedChannel,
error) {
rpcCtx, cancel := context.WithTimeout(ctx, rpcTimeout)
defer cancel()
response, err := s.client.ClosedChannels(
s.adminMac.WithMacaroonAuth(rpcCtx),
&lnrpc.ClosedChannelsRequest{},
)
if err != nil {
return nil, err
}
channels := make([]ClosedChannel, len(response.Channels))
for i, channel := range response.Channels {
remote, err := route.NewVertexFromStr(channel.RemotePubkey)
if err != nil {
return nil, err
}
closeType, err := rpcCloseType(channel.CloseType)
if err != nil {
return nil, err
}
openInitiator, err := getInitiator(channel.OpenInitiator)
if err != nil {
return nil, err
}
closeInitiator, err := rpcCloseInitiator(
channel.CloseInitiator, closeType,
)
if err != nil {
return nil, err
}
channels[i] = ClosedChannel{
ChannelPoint: channel.ChannelPoint,
ChannelID: channel.ChanId,
ClosingTxHash: channel.ClosingTxHash,
CloseType: closeType,
OpenInitiator: openInitiator,
CloseInitiator: closeInitiator,
PubKeyBytes: remote,
Capacity: btcutil.Amount(channel.Capacity),
SettledBalance: btcutil.Amount(channel.SettledBalance),
}
}
return channels, nil
}
// rpcCloseType maps a rpc close type to our local enum.
func rpcCloseType(t lnrpc.ChannelCloseSummary_ClosureType) (CloseType, error) {
switch t {
case lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE:
return CloseTypeCooperative, nil
case lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE:
return CloseTypeLocalForce, nil
case lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE:
return CloseTypeRemoteForce, nil
case lnrpc.ChannelCloseSummary_BREACH_CLOSE:
return CloseTypeBreach, nil
case lnrpc.ChannelCloseSummary_FUNDING_CANCELED:
return CloseTypeFundingCancelled, nil
case lnrpc.ChannelCloseSummary_ABANDONED:
return CloseTypeAbandoned, nil
default:
return 0, fmt.Errorf("unknown close type: %v", t)
}
}
// rpcCloseInitiator maps a close initiator to our local type. Since this field
// is not always set in lnd for older channels, also use our close type to infer
// who initiated the close when we have force closes.
func rpcCloseInitiator(initiator lnrpc.Initiator,
closeType CloseType) (Initiator, error) {
// Since our close type is always set on the rpc, we first check whether
// we can figure out the close initiator from this value. This is only
// possible for force closes/breaches.
switch closeType {
case CloseTypeLocalForce:
return InitiatorLocal, nil
case CloseTypeRemoteForce, CloseTypeBreach:
return InitiatorRemote, nil
}
// Otherwise, we check whether our initiator field is set, and fail only
// if we have an unknown type.
return getInitiator(initiator)
}
// getInitiator maps a rpc initiator value to our initiator enum.
func getInitiator(initiator lnrpc.Initiator) (Initiator, error) {
switch initiator {
case lnrpc.Initiator_INITIATOR_LOCAL:
return InitiatorLocal, nil
case lnrpc.Initiator_INITIATOR_REMOTE:
return InitiatorRemote, nil
case lnrpc.Initiator_INITIATOR_BOTH:
return InitiatorBoth, nil
case lnrpc.Initiator_INITIATOR_UNKNOWN:
return InitiatorUnrecorded, nil
default:
return InitiatorUnrecorded, fmt.Errorf("unknown "+
"initiator: %v", initiator)
}
}
// ChannelBackup retrieves the backup for a particular channel. The backup is
// returned as an encrypted chanbackup.Single payload.
func (s *lightningClient) ChannelBackup(ctx context.Context,

@ -175,6 +175,13 @@ func (h *mockLightningClient) ListChannels(ctx context.Context) (
return h.lnd.Channels, nil
}
// ClosedChannels returns a list of our closed channels.
func (h *mockLightningClient) ClosedChannels(_ context.Context) ([]lndclient.ClosedChannel,
error) {
return h.lnd.ClosedChannels, nil
}
// ChannelBackup retrieves the backup for a particular channel. The
// backup is returned as an encrypted chanbackup.Single payload.
func (h *mockLightningClient) ChannelBackup(context.Context, wire.OutPoint) ([]byte, error) {

@ -163,7 +163,8 @@ type LndMockServices struct {
// keyed by hash string.
Invoices map[lntypes.Hash]*lndclient.Invoice
Channels []lndclient.ChannelInfo
Channels []lndclient.ChannelInfo
ClosedChannels []lndclient.ClosedChannel
WaitForFinished func()

Loading…
Cancel
Save