diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index 8ad7b50e..38c28c4e 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -475,9 +475,13 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness, wallet *lnwallet t.Fatalf("channel state not properly saved") } - // Assert that tha channel opens after a single block. - lnc := assertChannelOpen(t, miner, uint32(numReqConfs), - chanReservation.DispatchChan()) + // Assert that the channel opens after a single block. + lnChan := make(chan *lnwallet.LightningChannel, 1) + go func() { + channel, _, _ := chanReservation.DispatchChan() + lnChan <- channel + }() + lnc := assertChannelOpen(t, miner, uint32(numReqConfs), lnChan) // Now that the channel is open, execute a cooperative closure of the // now open channel. @@ -611,7 +615,7 @@ func testCancelNonExistantReservation(miner *rpctest.Harness, } func testSingleFunderReservationWorkflowInitiator(miner *rpctest.Harness, - lnwallet *lnwallet.LightningWallet, t *testing.T) { + wallet *lnwallet.LightningWallet, t *testing.T) { t.Log("Running single funder workflow initiator test") @@ -627,7 +631,7 @@ func testSingleFunderReservationWorkflowInitiator(miner *rpctest.Harness, // Initialize a reservation for a channel with 4 BTC funded solely by us. fundingAmt := btcutil.Amount(4 * 1e8) - chanReservation, err := lnwallet.InitChannelReservation(fundingAmt, + chanReservation, err := wallet.InitChannelReservation(fundingAmt, fundingAmt, bobNode.id, bobAddr, numReqConfs, 4, 540) if err != nil { t.Fatalf("unable to init channel reservation: %v", err) @@ -729,7 +733,7 @@ func testSingleFunderReservationWorkflowInitiator(miner *rpctest.Harness, // TODO(roasbeef): de-duplicate fundingTx := chanReservation.FinalFundingTx() fundingSha := fundingTx.TxSha() - channels, err := lnwallet.ChannelDB.FetchOpenChannels(bobNode.id) + channels, err := wallet.ChannelDB.FetchOpenChannels(bobNode.id) if err != nil { t.Fatalf("unable to retrieve channel from DB: %v", err) } @@ -746,7 +750,12 @@ func testSingleFunderReservationWorkflowInitiator(miner *rpctest.Harness, channeldb.SingleFunder, channels[0].ChanType) } - assertChannelOpen(t, miner, uint32(numReqConfs), chanReservation.DispatchChan()) + lnChan := make(chan *lnwallet.LightningChannel, 1) + go func() { + channel, _, _ := chanReservation.DispatchChan() + lnChan <- channel + }() + assertChannelOpen(t, miner, uint32(numReqConfs), lnChan) } func testSingleFunderReservationWorkflowResponder(miner *rpctest.Harness, diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index b816829d..b64e3ac0 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -121,10 +121,11 @@ type ChannelReservation struct { // channel should be considered open. numConfsToOpen uint16 - // A channel which will be sent on once the channel is considered - // 'open'. A channel is open once the funding transaction has reached - // a sufficient number of confirmations. - chanOpen chan *LightningChannel + // chanOpen houses a struct containing the channel and additional + // confirmation details will be sent on once the channel is considered + // 'open'. A channel is open once the funding transaction has reached a + // sufficient number of confirmations. + chanOpen chan *openChanDetails wallet *LightningWallet } @@ -208,7 +209,7 @@ func NewChannelReservation(capacity, fundingAmt btcutil.Amount, minFeeRate btcut }, numConfsToOpen: numConfs, reservationID: id, - chanOpen: make(chan *LightningChannel, 1), + chanOpen: make(chan *openChanDetails, 1), wallet: wallet, } } @@ -437,8 +438,12 @@ func (r *ChannelReservation) Cancel() error { // // NOTE: If this method is called before .CompleteReservation(), it will block // indefinitely. -func (r *ChannelReservation) DispatchChan() <-chan *LightningChannel { - return r.chanOpen +func (r *ChannelReservation) DispatchChan() (*LightningChannel, uint32, uint32) { + // TODO(roasbeef): goroutine sending in wallet should be lifted up into + // the fundingMgr + openDetails := <-r.chanOpen + + return openDetails.channel, openDetails.blockHeight, openDetails.txIndex } // FinalizeReservation completes the pending reservation, returning an active @@ -455,5 +460,5 @@ func (r *ChannelReservation) FinalizeReservation() (*LightningChannel, error) { err: errChan, } - return <-r.chanOpen, <-errChan + return (<-r.chanOpen).channel, <-errChan } diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 44d60258..caf249f0 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -934,6 +934,17 @@ func (l *LightningWallet) handleSingleContribution(req *addSingleContributionMsg return } +// openChanDetails contains a "finalized" channel which can be considered +// "open" according to the requested confirmation depth at reservation +// initialization. Additionally, the struct contains additional details +// pertaining to the exact location in the main chain in-which the transaction +// was confirmed. +type openChanDetails struct { + channel *LightningChannel + blockHeight uint32 + txIndex uint32 +} + // handleFundingCounterPartySigs is the final step in the channel reservation // workflow. During this step, we validate *all* the received signatures for // inputs to the funding transaction. If any of these are invalid, we bail, @@ -1212,7 +1223,9 @@ func (l *LightningWallet) handleChannelOpen(req *channelOpenMsg) { channel, _ := NewLightningChannel(l.Signer, l.ChainIO, l.chainNotifier, res.partialState) - res.chanOpen <- channel + res.chanOpen <- &openChanDetails{ + channel: channel, + } req.err <- nil } @@ -1231,9 +1244,13 @@ func (l *LightningWallet) openChannelAfterConfirmations(res *ChannelReservation) // Wait until the specified number of confirmations has been reached, // or the wallet signals a shutdown. + var ( + confDetails *chainntnfs.TxConfirmation + ok bool + ) out: select { - case _, ok := <-confNtfn.Confirmed: + case confDetails, ok = <-confNtfn.Confirmed: // Reading a falsey value for the second parameter indicates that // the notifier is in the process of shutting down. Therefore, we // don't count this as the signal that the funding transaction has @@ -1253,7 +1270,11 @@ out: // TODO(roasbeef): CreationTime once tx is 'open' channel, _ := NewLightningChannel(l.Signer, l.ChainIO, l.chainNotifier, res.partialState) - res.chanOpen <- channel + res.chanOpen <- &openChanDetails{ + channel: channel, + blockHeight: confDetails.BlockHeight, + txIndex: confDetails.TxIndex, + } } // selectCoinsAndChange performs coin selection in order to obtain witness