From 0313dcfc896ed5c07b9a688cc3d109d4b21af239 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 24 Dec 2016 18:47:09 -0600 Subject: [PATCH] lnwallet: thread through tx conf details in ChannelReservation.DispatchChan() This commit slightly modifies the channel reservation workflow to expose the new information conerning the exact confirmation location of the channel provided by the ChainNotifier. The DispatchChan() method of the ChannelReservation now also returns the blockHeight and txIndex where the transaction was ultimately confirmed. This information will be needed by the fundingManager so it can properly generate the authenticated channel announcement proofs. --- lnwallet/interface_test.go | 23 ++++++++++++++++------- lnwallet/reservation.go | 21 +++++++++++++-------- lnwallet/wallet.go | 27 ++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 18 deletions(-) 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