diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 6126fa15..7c9d243f 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -536,8 +536,8 @@ func (l *LightningWallet) PsbtFundingVerify(pid [32]byte, // PsbtFundingFinalize looks up a previously registered funding intent by its // pending channel ID and tries to advance the state machine by finalizing the // passed PSBT. -func (l *LightningWallet) PsbtFundingFinalize(pid [32]byte, - packet *psbt.Packet) error { +func (l *LightningWallet) PsbtFundingFinalize(pid [32]byte, packet *psbt.Packet, + rawTx *wire.MsgTx) error { l.intentMtx.Lock() defer l.intentMtx.Unlock() @@ -551,9 +551,23 @@ func (l *LightningWallet) PsbtFundingFinalize(pid [32]byte, if !ok { return fmt.Errorf("incompatible funding intent") } - err := psbtIntent.Finalize(packet) - if err != nil { - return fmt.Errorf("error finalizing PSBT: %v", err) + + // Either the PSBT or the raw TX must be set. + switch { + case packet != nil && rawTx == nil: + err := psbtIntent.Finalize(packet) + if err != nil { + return fmt.Errorf("error finalizing PSBT: %v", err) + } + + case rawTx != nil && packet == nil: + err := psbtIntent.FinalizeRawTX(rawTx) + if err != nil { + return fmt.Errorf("error finalizing raw TX: %v", err) + } + + default: + return fmt.Errorf("either a PSBT or raw TX must be specified") } return nil diff --git a/rpcserver.go b/rpcserver.go index c45f4419..c09c6733 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -6738,19 +6738,50 @@ func (r *rpcServer) FundingStateStep(ctx context.Context, // the final PSBT to the previously verified one and if nothing // unexpected was changed, continue the channel opening process. case in.GetPsbtFinalize() != nil: + msg := in.GetPsbtFinalize() rpcsLog.Debugf("Finalizing PSBT for pending_id=%x", - in.GetPsbtFinalize().PendingChanId) + msg.PendingChanId) copy(pendingChanID[:], in.GetPsbtFinalize().PendingChanId) - packet, err := psbt.NewFromRawBytes( - bytes.NewReader(in.GetPsbtFinalize().SignedPsbt), false, + + var ( + packet *psbt.Packet + rawTx *wire.MsgTx + err error ) - if err != nil { - return nil, fmt.Errorf("error parsing psbt: %v", err) + + // Either the signed PSBT or the raw transaction need to be set + // but not both at the same time. + switch { + case len(msg.SignedPsbt) > 0 && len(msg.FinalRawTx) > 0: + return nil, fmt.Errorf("cannot set both signed PSBT " + + "and final raw TX at the same time") + + case len(msg.SignedPsbt) > 0: + packet, err = psbt.NewFromRawBytes( + bytes.NewReader(in.GetPsbtFinalize().SignedPsbt), + false, + ) + if err != nil { + return nil, fmt.Errorf("error parsing psbt: %v", + err) + } + + case len(msg.FinalRawTx) > 0: + rawTx = &wire.MsgTx{} + err = rawTx.Deserialize(bytes.NewReader(msg.FinalRawTx)) + if err != nil { + return nil, fmt.Errorf("error parsing final "+ + "raw TX: %v", err) + } + + default: + return nil, fmt.Errorf("PSBT or raw transaction to " + + "finalize missing") } err = r.server.cc.wallet.PsbtFundingFinalize( - pendingChanID, packet, + pendingChanID, packet, rawTx, ) if err != nil { return nil, err