mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-26 01:33:02 +01:00
Merge pull request #8426 from breez/expose-closing-tx
Expose closing tx in waiting_close_channels
This commit is contained in:
commit
dd7b186622
@ -1445,7 +1445,14 @@ var pendingChannelsCommand = cli.Command{
|
||||
Name: "pendingchannels",
|
||||
Category: "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 {
|
||||
@ -1453,7 +1460,10 @@ func pendingChannels(ctx *cli.Context) error {
|
||||
client, cleanUp := getClient(ctx)
|
||||
defer cleanUp()
|
||||
|
||||
req := &lnrpc.PendingChannelsRequest{}
|
||||
includeRawTx := ctx.Bool("include_raw_tx")
|
||||
req := &lnrpc.PendingChannelsRequest{
|
||||
IncludeRawTx: includeRawTx,
|
||||
}
|
||||
resp, err := client.PendingChannels(ctxc, req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -187,6 +187,10 @@
|
||||
[MinConf](https://github.com/lightningnetwork/lnd/pull/8097)(minimum number
|
||||
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
|
||||
|
||||
* [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
|
||||
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
|
||||
|
||||
* [Remove Litecoin code](https://github.com/lightningnetwork/lnd/pull/7867).
|
||||
@ -287,6 +295,7 @@
|
||||
* Carla Kirk-Cohen
|
||||
* Elle Mouton
|
||||
* ErikEk
|
||||
* Jesse de Wit
|
||||
* Keagan McClelland
|
||||
* Marcos Fernandez Perez
|
||||
* Matt Morehouse
|
||||
|
@ -2,6 +2,7 @@ package itest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
@ -141,7 +142,24 @@ func testCommitmentTransactionDeadline(ht *lntest.HarnessTest) {
|
||||
// Now that the channel has been force closed, it should show
|
||||
// up in the PendingChannels RPC under the waiting close
|
||||
// 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.
|
||||
expectedNumTxes := 1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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) {
|
||||
var protoReq PendingChannelsRequest
|
||||
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))
|
||||
return msg, metadata, err
|
||||
|
||||
@ -599,6 +610,13 @@ func local_request_Lightning_PendingChannels_0(ctx context.Context, marshaler ru
|
||||
var protoReq PendingChannelsRequest
|
||||
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)
|
||||
return msg, metadata, err
|
||||
|
||||
|
@ -2636,6 +2636,9 @@ message PendingHTLC {
|
||||
}
|
||||
|
||||
message PendingChannelsRequest {
|
||||
// Indicates whether to include the raw transaction hex for
|
||||
// waiting_close_channels.
|
||||
bool include_raw_tx = 1;
|
||||
}
|
||||
message PendingChannelsResponse {
|
||||
message PendingChannel {
|
||||
@ -2733,6 +2736,10 @@ message PendingChannelsResponse {
|
||||
|
||||
// The transaction id of the closing transaction
|
||||
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 {
|
||||
|
@ -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": [
|
||||
"Lightning"
|
||||
]
|
||||
@ -3140,6 +3149,10 @@
|
||||
"closing_txid": {
|
||||
"type": "string",
|
||||
"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."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -131,7 +131,9 @@ func (h *HarnessRPC) PendingChannels() *lnrpc.PendingChannelsResponse {
|
||||
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
pendingChansRequest := &lnrpc.PendingChannelsRequest{}
|
||||
pendingChansRequest := &lnrpc.PendingChannelsRequest{
|
||||
IncludeRawTx: true,
|
||||
}
|
||||
resp, err := h.LN.PendingChannels(ctxt, pendingChansRequest)
|
||||
|
||||
// TODO(yy): We may get a `unable to find arbitrator` error from the
|
||||
|
63
rpcserver.go
63
rpcserver.go
@ -3718,8 +3718,8 @@ func (r *rpcServer) fetchPendingForceCloseChannels() (pendingForceClose,
|
||||
// fetchWaitingCloseChannels queries the database for a list of channels
|
||||
// that have their closing transactions broadcast but not confirmed yet.
|
||||
// The returned result is used in the response of the PendingChannels RPC.
|
||||
func (r *rpcServer) fetchWaitingCloseChannels() (waitingCloseChannels,
|
||||
int64, error) {
|
||||
func (r *rpcServer) fetchWaitingCloseChannels(
|
||||
includeRawTx bool) (waitingCloseChannels, int64, error) {
|
||||
|
||||
// We'll also fetch all channels that are open, but have had their
|
||||
// commitment broadcasted, meaning they are waiting for the closing
|
||||
@ -3734,43 +3734,42 @@ func (r *rpcServer) fetchWaitingCloseChannels() (waitingCloseChannels,
|
||||
result := make(waitingCloseChannels, 0)
|
||||
limboBalance := int64(0)
|
||||
|
||||
// getClosingTx is a helper closure that tries to find the closing txid
|
||||
// of a given waiting close channel. Notice that if the remote closes
|
||||
// the channel, we may not have the closing txid.
|
||||
getClosingTx := func(c *channeldb.OpenChannel) (string, error) {
|
||||
// getClosingTx is a helper closure that tries to find the closing tx of
|
||||
// a given waiting close channel. Notice that if the remote closes the
|
||||
// channel, we may not have the closing tx.
|
||||
getClosingTx := func(c *channeldb.OpenChannel) (*wire.MsgTx, error) {
|
||||
var (
|
||||
tx *wire.MsgTx
|
||||
err error
|
||||
)
|
||||
|
||||
// First, we try to locate the force closing txid. If not
|
||||
// found, we will then try to find its coop closing txid.
|
||||
// First, we try to locate the force closing tx. If not found,
|
||||
// we will then try to find its coop closing tx.
|
||||
tx, err = c.BroadcastedCommitment()
|
||||
if err == nil {
|
||||
return tx.TxHash().String(), nil
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// If the error returned is not ErrNoCloseTx, something
|
||||
// unexpected happened and we will return the error.
|
||||
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()
|
||||
if err == nil {
|
||||
return tx.TxHash().String(), nil
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// Return the error if it's not ErrNoCloseTx.
|
||||
if err != channeldb.ErrNoCloseTx {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Otherwise return an empty txid. This can happen if the
|
||||
// remote broadcast the closing txid and we haven't recorded it
|
||||
// yet.
|
||||
return "", nil
|
||||
// Otherwise return an empty tx. This can happen if the remote
|
||||
// broadcast the closing tx and we haven't recorded it yet.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for _, waitingClose := range channels {
|
||||
@ -3830,12 +3829,12 @@ func (r *rpcServer) fetchWaitingCloseChannels() (waitingCloseChannels,
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Get the closing txid.
|
||||
// NOTE: the closing txid could be empty here if it's the
|
||||
// remote broadcasted the closing tx.
|
||||
closingTxid, err := getClosingTx(waitingClose)
|
||||
// Get the closing tx.
|
||||
// NOTE: the closing tx could be nil here if it's the remote
|
||||
// that broadcasted the closing tx.
|
||||
closingTx, err := getClosingTx(waitingClose)
|
||||
if err != nil {
|
||||
rpcsLog.Errorf("unable to find closing txid for "+
|
||||
rpcsLog.Errorf("unable to find closing tx for "+
|
||||
"channel:%s, %v",
|
||||
waitingClose.ShortChannelID, err)
|
||||
return nil, 0, err
|
||||
@ -3857,11 +3856,27 @@ func (r *rpcServer) fetchWaitingCloseChannels() (waitingCloseChannels,
|
||||
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{
|
||||
Channel: channel,
|
||||
LimboBalance: channel.LocalBalance,
|
||||
Commitments: &commitments,
|
||||
ClosingTxid: closingTxid,
|
||||
ClosingTxHex: closingTxHex,
|
||||
}
|
||||
|
||||
// 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
|
||||
// commitment broadcasted, meaning they are waiting for the closing
|
||||
// transaction to confirm.
|
||||
waitingCloseChannels, limbo, err := r.fetchWaitingCloseChannels()
|
||||
waitingCloseChannels, limbo, err := r.fetchWaitingCloseChannels(
|
||||
in.IncludeRawTx,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user