diff --git a/fundingmanager.go b/fundingmanager.go index 9df9da84d..0ede97209 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -1722,8 +1722,8 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) { return case shortChanID, ok = <-confChan: if !ok { - fndgLog.Errorf("waiting for funding confirmation" + - " failed") + fndgLog.Errorf("waiting for funding " + + "confirmation failed") return } } @@ -1893,8 +1893,9 @@ func makeFundingScript(channel *channeldb.OpenChannel) ([]byte, error) { // when a channel has become active for lightning transactions. // The wait can be canceled by closing the cancelChan. In case of success, // a *lnwire.ShortChannelID will be passed to confChan. -func (f *fundingManager) waitForFundingConfirmation(completeChan *channeldb.OpenChannel, - cancelChan <-chan struct{}, confChan chan<- *lnwire.ShortChannelID) { +func (f *fundingManager) waitForFundingConfirmation( + completeChan *channeldb.OpenChannel, cancelChan <-chan struct{}, + confChan chan<- *lnwire.ShortChannelID) { defer close(confChan) @@ -1904,16 +1905,19 @@ func (f *fundingManager) waitForFundingConfirmation(completeChan *channeldb.Open fundingScript, err := makeFundingScript(completeChan) if err != nil { fndgLog.Errorf("unable to create funding script for "+ - "ChannelPoint(%v): %v", completeChan.FundingOutpoint, err) + "ChannelPoint(%v): %v", completeChan.FundingOutpoint, + err) return } numConfs := uint32(completeChan.NumConfsRequired) confNtfn, err := f.cfg.Notifier.RegisterConfirmationsNtfn( - &txid, fundingScript, numConfs, completeChan.FundingBroadcastHeight, + &txid, fundingScript, numConfs, + completeChan.FundingBroadcastHeight, ) if err != nil { fndgLog.Errorf("Unable to register for confirmation of "+ - "ChannelPoint(%v): %v", completeChan.FundingOutpoint, err) + "ChannelPoint(%v): %v", completeChan.FundingOutpoint, + err) return } @@ -1928,14 +1932,17 @@ func (f *fundingManager) waitForFundingConfirmation(completeChan *channeldb.Open select { case confDetails, ok = <-confNtfn.Confirmed: // fallthrough + case <-cancelChan: fndgLog.Warnf("canceled waiting for funding confirmation, "+ "stopping funding flow for ChannelPoint(%v)", completeChan.FundingOutpoint) return + case <-f.quit: fndgLog.Warnf("fundingManager shutting down, stopping funding "+ - "flow for ChannelPoint(%v)", completeChan.FundingOutpoint) + "flow for ChannelPoint(%v)", + completeChan.FundingOutpoint) return } @@ -1948,6 +1955,18 @@ func (f *fundingManager) waitForFundingConfirmation(completeChan *channeldb.Open fundingPoint := completeChan.FundingOutpoint chanID := lnwire.NewChanIDFromOutPoint(&fundingPoint) + if int(fundingPoint.Index) >= len(confDetails.Tx.TxOut) { + fndgLog.Warnf("Funding point index does not exist for "+ + "ChannelPoint(%v)", completeChan.FundingOutpoint) + return + } + + outputAmt := btcutil.Amount(confDetails.Tx.TxOut[fundingPoint.Index].Value) + if outputAmt != completeChan.Capacity { + fndgLog.Warnf("Invalid output value for ChannelPoint(%v)", + completeChan.FundingOutpoint) + return + } fndgLog.Infof("ChannelPoint(%v) is now active: ChannelID(%x)", fundingPoint, chanID[:]) @@ -2742,7 +2761,6 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { var ( peerKey = msg.peer.IdentityKey() localAmt = msg.localFundingAmt - capacity = localAmt minHtlc = msg.minHtlc remoteCsvDelay = msg.remoteCsvDelay ) @@ -2756,10 +2774,11 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { ourDustLimit = defaultLitecoinDustLimit } - fndgLog.Infof("Initiating fundingRequest(localAmt=%v, remoteAmt=%v, "+ - "capacity=%v, chainhash=%v, peer=%x, dustLimit=%v, min_confs=%v)", - localAmt, msg.pushAmt, capacity, msg.chainHash, - peerKey.SerializeCompressed(), ourDustLimit, msg.minConfs) + fndgLog.Infof("Initiating fundingRequest(local_amt=%v "+ + "(subtract_fees=%v), push_amt=%v, chain_hash=%v, peer=%x, "+ + "dust_limit=%v, min_confs=%v)", localAmt, msg.subtractFees, + msg.pushAmt, msg.chainHash, peerKey.SerializeCompressed(), + ourDustLimit, msg.minConfs) // First, we'll query the fee estimator for a fee that should get the // commitment transaction confirmed by the next few blocks (conf target @@ -2786,6 +2805,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { ChainHash: &msg.chainHash, NodeID: peerKey, NodeAddr: msg.peer.Address(), + SubtractFees: msg.subtractFees, LocalFundingAmt: localAmt, RemoteFundingAmt: 0, CommitFeePerKw: commitFeePerKw, @@ -2801,6 +2821,12 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { return } + // Now that we have successfully reserved funds for this channel in the + // wallet, we can fetch the final channel capacity. This is done at + // this point since the final capacity might change in case of + // SubtractFees=true. + capacity := reservation.Capacity() + // Obtain a new pending channel ID which is used to track this // reservation throughout its lifetime. chanID := f.nextPendingChanID() diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 02fab50da..555d0ded7 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -515,6 +515,13 @@ func (r *ChannelReservation) FundingOutpoint() *wire.OutPoint { return &r.partialState.FundingOutpoint } +// Capacity returns the channel capacity for this reservation. +func (r *ChannelReservation) Capacity() btcutil.Amount { + r.RLock() + defer r.RUnlock() + return r.partialState.Capacity +} + // Cancel abandons this channel reservation. This method should be called in // the scenario that communications with the counterparty break down. Upon // cancellation, all resources previously reserved for this pending payment diff --git a/server.go b/server.go index 4e19ce148..01c0079cb 100644 --- a/server.go +++ b/server.go @@ -2979,6 +2979,7 @@ type openChanReq struct { chainHash chainhash.Hash + subtractFees bool localFundingAmt btcutil.Amount pushAmt lnwire.MilliSatoshi