From d4136002c13e27e675d19a274572953d90c7bd9c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 7 Jun 2021 11:16:36 +0200 Subject: [PATCH] lnwallet: only set funding TX witness if we publish During the final part of the channel funding negotiation we only need to assemble the full funding TX with the witness if we are going to publish the transaction ourselves. If the final funding TX is published externally we don't need this information. This will make it possible to skip the verify process for fully externally funded PSBT channels. --- lnwallet/chanfunding/psbt_assembler.go | 20 ++++++++++--- lnwallet/wallet.go | 39 +++++++++++++++----------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/lnwallet/chanfunding/psbt_assembler.go b/lnwallet/chanfunding/psbt_assembler.go index 1317d36c0..3498785e6 100644 --- a/lnwallet/chanfunding/psbt_assembler.go +++ b/lnwallet/chanfunding/psbt_assembler.go @@ -139,6 +139,11 @@ type PsbtIntent struct { // NOTE: This channel must always be buffered. PsbtReady chan error + // shouldPublish specifies if the intent assumes its assembler should + // publish the transaction once the channel funding has completed. If + // this is set to false then the finalize step can be skipped. + shouldPublish bool + // signalPsbtReady is a Once guard to make sure the PsbtReady channel is // only closed exactly once. signalPsbtReady sync.Once @@ -449,6 +454,12 @@ func (i *PsbtIntent) Outputs() []*wire.TxOut { } } +// ShouldPublishFundingTX returns true if the intent assumes that its assembler +// should publish the funding TX once the funding negotiation is complete. +func (i *PsbtIntent) ShouldPublishFundingTX() bool { + return i.shouldPublish +} + // PsbtAssembler is a type of chanfunding.Assembler wherein the funding // transaction is constructed outside of lnd by using partially signed bitcoin // transactions (PSBT). @@ -500,10 +511,11 @@ func (p *PsbtAssembler) ProvisionChannel(req *Request) (Intent, error) { ShimIntent: ShimIntent{ localFundingAmt: p.fundingAmt, }, - State: PsbtShimRegistered, - BasePsbt: p.basePsbt, - PsbtReady: make(chan error, 1), - netParams: p.netParams, + State: PsbtShimRegistered, + BasePsbt: p.basePsbt, + PsbtReady: make(chan error, 1), + shouldPublish: p.shouldPublish, + netParams: p.netParams, } // A simple sanity check to ensure the provisioned request matches the diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index b0ba460f4..e15b1512b 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -1454,9 +1454,11 @@ func (l *LightningWallet) handleChanPointReady(req *continueContributionMsg) { // is needed to construct and publish the full funding transaction. intent := pendingReservation.fundingIntent if psbtIntent, ok := intent.(*chanfunding.PsbtIntent); ok { - // With our keys bound, we can now construct+sign the final - // funding transaction and also obtain the chanPoint that - // creates the channel. + // With our keys bound, we can now construct and possibly sign + // the final funding transaction and also obtain the chanPoint + // that creates the channel. We _have_ to call CompileFundingTx + // even if we don't publish ourselves as that sets the actual + // funding outpoint in stone for this channel. fundingTx, err := psbtIntent.CompileFundingTx() if err != nil { req.err <- fmt.Errorf("unable to construct funding "+ @@ -1470,23 +1472,26 @@ func (l *LightningWallet) handleChanPointReady(req *continueContributionMsg) { return } - // Finally, we'll populate the relevant information in our - // pendingReservation so the rest of the funding flow can - // continue as normal. - pendingReservation.fundingTx = fundingTx pendingReservation.partialState.FundingOutpoint = *chanPointPtr chanPoint = *chanPointPtr - pendingReservation.ourFundingInputScripts = make( - []*input.Script, 0, len(ourContribution.Inputs), - ) - for _, txIn := range fundingTx.TxIn { - pendingReservation.ourFundingInputScripts = append( - pendingReservation.ourFundingInputScripts, - &input.Script{ - Witness: txIn.Witness, - SigScript: txIn.SignatureScript, - }, + + // Finally, we'll populate the relevant information in our + // pendingReservation so the rest of the funding flow can + // continue as normal in case we are going to publish ourselves. + if psbtIntent.ShouldPublishFundingTX() { + pendingReservation.fundingTx = fundingTx + pendingReservation.ourFundingInputScripts = make( + []*input.Script, 0, len(ourContribution.Inputs), ) + for _, txIn := range fundingTx.TxIn { + pendingReservation.ourFundingInputScripts = append( + pendingReservation.ourFundingInputScripts, + &input.Script{ + Witness: txIn.Witness, + SigScript: txIn.SignatureScript, + }, + ) + } } }