lncli: allow final transaction as raw hex in PSBT funding flow

This commit is contained in:
Oliver Gugger 2020-09-07 18:02:42 +02:00
parent c4ada8a592
commit 154dc1af66
No known key found for this signature in database
GPG Key ID: 8E4256593F177720

@ -1,6 +1,7 @@
package main package main
import ( import (
"bytes"
"context" "context"
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
@ -11,6 +12,7 @@ import (
"strings" "strings"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnwallet/chanfunding" "github.com/lightningnetwork/lnd/lnwallet/chanfunding"
@ -43,9 +45,9 @@ Base64 encoded PSBT: `
userMsgSign = ` userMsgSign = `
PSBT verified by lnd, please continue the funding flow by signing the PSBT by PSBT verified by lnd, please continue the funding flow by signing the PSBT by
all required parties/devices. Once the transaction is fully signed, paste it all required parties/devices. Once the transaction is fully signed, paste it
again here. again here either in base64 PSBT or hex encoded raw wire TX format.
Base64 encoded signed PSBT: ` Signed base64 encoded PSBT or hex encoded raw wire TX: `
) )
// TODO(roasbeef): change default number of confirmations // TODO(roasbeef): change default number of confirmations
@ -505,7 +507,7 @@ func openChannelPsbt(ctx *cli.Context, client lnrpc.LightningClient,
return fmt.Errorf("reading from console "+ return fmt.Errorf("reading from console "+
"failed: %v", err) "failed: %v", err)
} }
psbt, err := base64.StdEncoding.DecodeString( fundedPsbt, err := base64.StdEncoding.DecodeString(
strings.TrimSpace(psbtBase64), strings.TrimSpace(psbtBase64),
) )
if err != nil { if err != nil {
@ -515,7 +517,7 @@ func openChannelPsbt(ctx *cli.Context, client lnrpc.LightningClient,
verifyMsg := &lnrpc.FundingTransitionMsg{ verifyMsg := &lnrpc.FundingTransitionMsg{
Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{ Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{
PsbtVerify: &lnrpc.FundingPsbtVerify{ PsbtVerify: &lnrpc.FundingPsbtVerify{
FundedPsbt: psbt, FundedPsbt: fundedPsbt,
PendingChanId: pendingChanID[:], PendingChanId: pendingChanID[:],
}, },
}, },
@ -531,7 +533,7 @@ func openChannelPsbt(ctx *cli.Context, client lnrpc.LightningClient,
fmt.Print(userMsgSign) fmt.Print(userMsgSign)
// Read the signed PSBT and send it to lnd. // Read the signed PSBT and send it to lnd.
psbtBase64, err = readLine(quit) finalTxStr, err := readLine(quit)
if err == io.EOF { if err == io.EOF {
return nil return nil
} }
@ -539,22 +541,16 @@ func openChannelPsbt(ctx *cli.Context, client lnrpc.LightningClient,
return fmt.Errorf("reading from console "+ return fmt.Errorf("reading from console "+
"failed: %v", err) "failed: %v", err)
} }
psbt, err = base64.StdEncoding.DecodeString( finalizeMsg, err := finalizeMsgFromString(
strings.TrimSpace(psbtBase64), finalTxStr, pendingChanID[:],
) )
if err != nil { if err != nil {
return fmt.Errorf("base64 decode failed: %v", return err
err)
} }
finalizeMsg := &lnrpc.FundingTransitionMsg{ transitionMsg := &lnrpc.FundingTransitionMsg{
Trigger: &lnrpc.FundingTransitionMsg_PsbtFinalize{ Trigger: finalizeMsg,
PsbtFinalize: &lnrpc.FundingPsbtFinalize{
SignedPsbt: psbt,
PendingChanId: pendingChanID[:],
},
},
} }
err = sendFundingState(ctxc, ctx, finalizeMsg) err = sendFundingState(ctxc, ctx, transitionMsg)
if err != nil { if err != nil {
return fmt.Errorf("finalizing PSBT funding "+ return fmt.Errorf("finalizing PSBT funding "+
"flow failed: %v", err) "flow failed: %v", err)
@ -686,3 +682,41 @@ func sendFundingState(cancelCtx context.Context, cliCtx *cli.Context,
_, err := client.FundingStateStep(cancelCtx, msg) _, err := client.FundingStateStep(cancelCtx, msg)
return err return err
} }
// finalizeMsgFromString creates the final message for the PsbtFinalize step
// from either a hex encoded raw wire transaction or a base64 encoded PSBT
// packet.
func finalizeMsgFromString(tx string,
pendingChanID []byte) (*lnrpc.FundingTransitionMsg_PsbtFinalize, error) {
rawTx, err := hex.DecodeString(strings.TrimSpace(tx))
if err == nil {
// Hex decoding succeeded so we assume we have a raw wire format
// transaction. Let's submit that instead of a PSBT packet.
tx := &wire.MsgTx{}
err := tx.Deserialize(bytes.NewReader(rawTx))
if err != nil {
return nil, fmt.Errorf("deserializing as raw wire "+
"transaction failed: %v", err)
}
return &lnrpc.FundingTransitionMsg_PsbtFinalize{
PsbtFinalize: &lnrpc.FundingPsbtFinalize{
FinalRawTx: rawTx,
PendingChanId: pendingChanID,
},
}, nil
}
// If the string isn't a hex encoded transaction, we assume it must be
// a base64 encoded PSBT packet.
psbtBytes, err := base64.StdEncoding.DecodeString(strings.TrimSpace(tx))
if err != nil {
return nil, fmt.Errorf("base64 decode failed: %v", err)
}
return &lnrpc.FundingTransitionMsg_PsbtFinalize{
PsbtFinalize: &lnrpc.FundingPsbtFinalize{
SignedPsbt: psbtBytes,
PendingChanId: pendingChanID,
},
}, nil
}