Merge pull request #8426 from breez/expose-closing-tx

Expose closing tx in waiting_close_channels
This commit is contained in:
Yong 2024-01-30 09:13:17 +08:00 committed by GitHub
commit dd7b186622
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 2020 additions and 1900 deletions

View File

@ -1445,7 +1445,14 @@ var pendingChannelsCommand = cli.Command{
Name: "pendingchannels", Name: "pendingchannels",
Category: "Channels", Category: "Channels",
Usage: "Display information pertaining to pending channels.", Usage: "Display information pertaining to pending channels.",
Action: actionDecorator(pendingChannels), Flags: []cli.Flag{
cli.BoolFlag{
Name: "include_raw_tx",
Usage: "include the raw transaction hex for " +
"waiting_close_channels.",
},
},
Action: actionDecorator(pendingChannels),
} }
func pendingChannels(ctx *cli.Context) error { func pendingChannels(ctx *cli.Context) error {
@ -1453,7 +1460,10 @@ func pendingChannels(ctx *cli.Context) error {
client, cleanUp := getClient(ctx) client, cleanUp := getClient(ctx)
defer cleanUp() defer cleanUp()
req := &lnrpc.PendingChannelsRequest{} includeRawTx := ctx.Bool("include_raw_tx")
req := &lnrpc.PendingChannelsRequest{
IncludeRawTx: includeRawTx,
}
resp, err := client.PendingChannels(ctxc, req) resp, err := client.PendingChannels(ctxc, req)
if err != nil { if err != nil {
return err return err

View File

@ -187,6 +187,10 @@
[MinConf](https://github.com/lightningnetwork/lnd/pull/8097)(minimum number [MinConf](https://github.com/lightningnetwork/lnd/pull/8097)(minimum number
of confirmations) has been added to the `WalletBalance` RPC call. of confirmations) has been added to the `WalletBalance` RPC call.
* `PendingChannels` now optionally returns the
[raw hex of the closing tx](https://github.com/lightningnetwork/lnd/pull/8426)
in `waiting_close_channels`.
## lncli Updates ## lncli Updates
* [Documented all available lncli commands](https://github.com/lightningnetwork/lnd/pull/8181). * [Documented all available lncli commands](https://github.com/lightningnetwork/lnd/pull/8181).
@ -202,6 +206,10 @@
* [Use the default LND value in the buildroute rpc command for the * [Use the default LND value in the buildroute rpc command for the
final cltv delta](https://github.com/lightningnetwork/lnd/pull/8387). final cltv delta](https://github.com/lightningnetwork/lnd/pull/8387).
* `pendingchannels` now optionally returns the
[raw hex of the closing tx](https://github.com/lightningnetwork/lnd/pull/8426)
in `waiting_close_channels`.
## Code Health ## Code Health
* [Remove Litecoin code](https://github.com/lightningnetwork/lnd/pull/7867). * [Remove Litecoin code](https://github.com/lightningnetwork/lnd/pull/7867).
@ -287,6 +295,7 @@
* Carla Kirk-Cohen * Carla Kirk-Cohen
* Elle Mouton * Elle Mouton
* ErikEk * ErikEk
* Jesse de Wit
* Keagan McClelland * Keagan McClelland
* Marcos Fernandez Perez * Marcos Fernandez Perez
* Matt Morehouse * Matt Morehouse

View File

@ -2,6 +2,7 @@ package itest
import ( import (
"bytes" "bytes"
"encoding/hex"
"fmt" "fmt"
"testing" "testing"
@ -141,7 +142,24 @@ func testCommitmentTransactionDeadline(ht *lntest.HarnessTest) {
// Now that the channel has been force closed, it should show // Now that the channel has been force closed, it should show
// up in the PendingChannels RPC under the waiting close // up in the PendingChannels RPC under the waiting close
// section. // section.
ht.AssertChannelWaitingClose(alice, chanPoint) waitingClose := ht.AssertChannelWaitingClose(alice, chanPoint)
// The waiting close channel closing tx hex should be set and
// be valid.
require.NotEmpty(ht, waitingClose.ClosingTxHex)
rawTxBytes, err := hex.DecodeString(waitingClose.ClosingTxHex)
require.NoError(
ht, err,
"waiting close channel closingTxHex invalid hex",
)
rawTx := &wire.MsgTx{}
err = rawTx.Deserialize(bytes.NewReader(rawTxBytes))
require.NoError(
ht, err, "waiting close channel ClosingTxHex invalid",
)
require.Equal(
ht, waitingClose.ClosingTxid, rawTx.TxHash().String(),
)
// We should see Alice's force closing tx in the mempool. // We should see Alice's force closing tx in the mempool.
expectedNumTxes := 1 expectedNumTxes := 1

File diff suppressed because it is too large Load Diff

View File

@ -586,10 +586,21 @@ func local_request_Lightning_GetRecoveryInfo_0(ctx context.Context, marshaler ru
} }
var (
filter_Lightning_PendingChannels_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_Lightning_PendingChannels_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_Lightning_PendingChannels_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq PendingChannelsRequest var protoReq PendingChannelsRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Lightning_PendingChannels_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.PendingChannels(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.PendingChannels(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err return msg, metadata, err
@ -599,6 +610,13 @@ func local_request_Lightning_PendingChannels_0(ctx context.Context, marshaler ru
var protoReq PendingChannelsRequest var protoReq PendingChannelsRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Lightning_PendingChannels_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.PendingChannels(ctx, &protoReq) msg, err := server.PendingChannels(ctx, &protoReq)
return msg, metadata, err return msg, metadata, err

View File

@ -2636,6 +2636,9 @@ message PendingHTLC {
} }
message PendingChannelsRequest { message PendingChannelsRequest {
// Indicates whether to include the raw transaction hex for
// waiting_close_channels.
bool include_raw_tx = 1;
} }
message PendingChannelsResponse { message PendingChannelsResponse {
message PendingChannel { message PendingChannel {
@ -2733,6 +2736,10 @@ message PendingChannelsResponse {
// The transaction id of the closing transaction // The transaction id of the closing transaction
string closing_txid = 4; string closing_txid = 4;
// The raw hex encoded bytes of the closing transaction. Included if
// include_raw_tx in the request is true.
string closing_tx_hex = 5;
} }
message Commitments { message Commitments {

View File

@ -582,6 +582,15 @@
} }
} }
}, },
"parameters": [
{
"name": "include_raw_tx",
"description": "Indicates whether to include the raw transaction hex for\nwaiting_close_channels.",
"in": "query",
"required": false,
"type": "boolean"
}
],
"tags": [ "tags": [
"Lightning" "Lightning"
] ]
@ -3140,6 +3149,10 @@
"closing_txid": { "closing_txid": {
"type": "string", "type": "string",
"title": "The transaction id of the closing transaction" "title": "The transaction id of the closing transaction"
},
"closing_tx_hex": {
"type": "string",
"description": "The raw hex encoded bytes of the closing transaction. Included if\ninclude_raw_tx in the request is true."
} }
} }
}, },

View File

@ -131,7 +131,9 @@ func (h *HarnessRPC) PendingChannels() *lnrpc.PendingChannelsResponse {
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
defer cancel() defer cancel()
pendingChansRequest := &lnrpc.PendingChannelsRequest{} pendingChansRequest := &lnrpc.PendingChannelsRequest{
IncludeRawTx: true,
}
resp, err := h.LN.PendingChannels(ctxt, pendingChansRequest) resp, err := h.LN.PendingChannels(ctxt, pendingChansRequest)
// TODO(yy): We may get a `unable to find arbitrator` error from the // TODO(yy): We may get a `unable to find arbitrator` error from the

View File

@ -3718,8 +3718,8 @@ func (r *rpcServer) fetchPendingForceCloseChannels() (pendingForceClose,
// fetchWaitingCloseChannels queries the database for a list of channels // fetchWaitingCloseChannels queries the database for a list of channels
// that have their closing transactions broadcast but not confirmed yet. // that have their closing transactions broadcast but not confirmed yet.
// The returned result is used in the response of the PendingChannels RPC. // The returned result is used in the response of the PendingChannels RPC.
func (r *rpcServer) fetchWaitingCloseChannels() (waitingCloseChannels, func (r *rpcServer) fetchWaitingCloseChannels(
int64, error) { includeRawTx bool) (waitingCloseChannels, int64, error) {
// We'll also fetch all channels that are open, but have had their // We'll also fetch all channels that are open, but have had their
// commitment broadcasted, meaning they are waiting for the closing // commitment broadcasted, meaning they are waiting for the closing
@ -3734,43 +3734,42 @@ func (r *rpcServer) fetchWaitingCloseChannels() (waitingCloseChannels,
result := make(waitingCloseChannels, 0) result := make(waitingCloseChannels, 0)
limboBalance := int64(0) limboBalance := int64(0)
// getClosingTx is a helper closure that tries to find the closing txid // getClosingTx is a helper closure that tries to find the closing tx of
// of a given waiting close channel. Notice that if the remote closes // a given waiting close channel. Notice that if the remote closes the
// the channel, we may not have the closing txid. // channel, we may not have the closing tx.
getClosingTx := func(c *channeldb.OpenChannel) (string, error) { getClosingTx := func(c *channeldb.OpenChannel) (*wire.MsgTx, error) {
var ( var (
tx *wire.MsgTx tx *wire.MsgTx
err error err error
) )
// First, we try to locate the force closing txid. If not // First, we try to locate the force closing tx. If not found,
// found, we will then try to find its coop closing txid. // we will then try to find its coop closing tx.
tx, err = c.BroadcastedCommitment() tx, err = c.BroadcastedCommitment()
if err == nil { if err == nil {
return tx.TxHash().String(), nil return tx, nil
} }
// If the error returned is not ErrNoCloseTx, something // If the error returned is not ErrNoCloseTx, something
// unexpected happened and we will return the error. // unexpected happened and we will return the error.
if err != channeldb.ErrNoCloseTx { if err != channeldb.ErrNoCloseTx {
return "", err return nil, err
} }
// Otherwise, we continue to locate its coop closing txid. // Otherwise, we continue to locate its coop closing tx.
tx, err = c.BroadcastedCooperative() tx, err = c.BroadcastedCooperative()
if err == nil { if err == nil {
return tx.TxHash().String(), nil return tx, nil
} }
// Return the error if it's not ErrNoCloseTx. // Return the error if it's not ErrNoCloseTx.
if err != channeldb.ErrNoCloseTx { if err != channeldb.ErrNoCloseTx {
return "", err return nil, err
} }
// Otherwise return an empty txid. This can happen if the // Otherwise return an empty tx. This can happen if the remote
// remote broadcast the closing txid and we haven't recorded it // broadcast the closing tx and we haven't recorded it yet.
// yet. return nil, nil
return "", nil
} }
for _, waitingClose := range channels { for _, waitingClose := range channels {
@ -3830,12 +3829,12 @@ func (r *rpcServer) fetchWaitingCloseChannels() (waitingCloseChannels,
return nil, 0, err return nil, 0, err
} }
// Get the closing txid. // Get the closing tx.
// NOTE: the closing txid could be empty here if it's the // NOTE: the closing tx could be nil here if it's the remote
// remote broadcasted the closing tx. // that broadcasted the closing tx.
closingTxid, err := getClosingTx(waitingClose) closingTx, err := getClosingTx(waitingClose)
if err != nil { if err != nil {
rpcsLog.Errorf("unable to find closing txid for "+ rpcsLog.Errorf("unable to find closing tx for "+
"channel:%s, %v", "channel:%s, %v",
waitingClose.ShortChannelID, err) waitingClose.ShortChannelID, err)
return nil, 0, err return nil, 0, err
@ -3857,11 +3856,27 @@ func (r *rpcServer) fetchWaitingCloseChannels() (waitingCloseChannels,
Memo: string(waitingClose.Memo), Memo: string(waitingClose.Memo),
} }
var closingTxid, closingTxHex string
if closingTx != nil {
closingTxid = closingTx.TxHash().String()
if includeRawTx {
var txBuf bytes.Buffer
err = closingTx.Serialize(&txBuf)
if err != nil {
return nil, 0, fmt.Errorf("failed to "+
"serialize closing transaction"+
": %w", err)
}
closingTxHex = hex.EncodeToString(txBuf.Bytes())
}
}
waitingCloseResp := &lnrpc.PendingChannelsResponse_WaitingCloseChannel{ waitingCloseResp := &lnrpc.PendingChannelsResponse_WaitingCloseChannel{
Channel: channel, Channel: channel,
LimboBalance: channel.LocalBalance, LimboBalance: channel.LocalBalance,
Commitments: &commitments, Commitments: &commitments,
ClosingTxid: closingTxid, ClosingTxid: closingTxid,
ClosingTxHex: closingTxHex,
} }
// A close tx has been broadcasted, all our balance will be in // A close tx has been broadcasted, all our balance will be in
@ -3904,7 +3919,9 @@ func (r *rpcServer) PendingChannels(ctx context.Context,
// Third, we fetch all channels that are open, but have had their // Third, we fetch all channels that are open, but have had their
// commitment broadcasted, meaning they are waiting for the closing // commitment broadcasted, meaning they are waiting for the closing
// transaction to confirm. // transaction to confirm.
waitingCloseChannels, limbo, err := r.fetchWaitingCloseChannels() waitingCloseChannels, limbo, err := r.fetchWaitingCloseChannels(
in.IncludeRawTx,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }