lnwallet + funding: move funding tx publish to fundingmgr

This commit moves the responsibility for publishing the funding tx to
the network from the wallet to the funding manager. This is done to
distinguish the failure of completing the reservation within the wallet
and failure of publishing the transaction.

Earlier we could fail to broadcast the transaction, which would cause us
to fail the funding flow. This is not something we can do directly,
since the CompeteReservation call will mark the channel IsPending in the
databas.e
This commit is contained in:
Johan T. Halseth 2018-07-26 15:16:47 +02:00
parent 8865bcf3d9
commit 2a77b57788
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26
3 changed files with 35 additions and 26 deletions

@ -1539,9 +1539,12 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
// transaction. We'll verify the signature for validity, then commit // transaction. We'll verify the signature for validity, then commit
// the state to disk as we can now open the channel. // the state to disk as we can now open the channel.
commitSig := fmsg.msg.CommitSig.ToSignatureBytes() commitSig := fmsg.msg.CommitSig.ToSignatureBytes()
completeChan, err := resCtx.reservation.CompleteReservation(nil, commitSig) completeChan, err := resCtx.reservation.CompleteReservation(
nil, commitSig,
)
if err != nil { if err != nil {
fndgLog.Errorf("Unable to complete reservation sign complete: %v", err) fndgLog.Errorf("Unable to complete reservation sign "+
"complete: %v", err)
f.failFundingFlow(fmsg.peer, pendingChanID, err) f.failFundingFlow(fmsg.peer, pendingChanID, err)
return return
} }
@ -1550,6 +1553,22 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
// delete it from our set of active reservations. // delete it from our set of active reservations.
f.deleteReservationCtx(peerKey, pendingChanID) f.deleteReservationCtx(peerKey, pendingChanID)
// Broadcast the finalized funding transaction to the network.
fundingTx := completeChan.FundingTxn
fndgLog.Infof("Broadcasting funding tx for ChannelPoint(%v): %v",
completeChan.FundingOutpoint, spew.Sdump(fundingTx))
err = f.cfg.PublishTransaction(fundingTx)
if err != nil {
fndgLog.Errorf("unable to broadcast funding "+
"txn: %v", err)
// We failed to broadcast the funding transaction, but watch
// the channel regardless, in case the transaction made it to
// the network. We will retry broadcast at startup.
// TODO(halseth): retry more often? Handle with CPFP? Just
// delete from the DB?
}
// Now that we have a finalized reservation for this funding flow, // Now that we have a finalized reservation for this funding flow,
// we'll send the to be active channel to the ChainArbitrator so it can // we'll send the to be active channel to the ChainArbitrator so it can
// watch for any on-chin actions before the channel has fully // watch for any on-chin actions before the channel has fully

@ -4,12 +4,12 @@ import (
"net" "net"
"sync" "sync"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
) )
// ChannelContribution is the primary constituent of the funding workflow // ChannelContribution is the primary constituent of the funding workflow
@ -434,11 +434,11 @@ func (r *ChannelReservation) OurSignatures() ([]*InputScript, []byte) {
// https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki. // https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki.
// Additionally, verification is performed in order to ensure that the // Additionally, verification is performed in order to ensure that the
// counterparty supplied a valid signature to our version of the commitment // counterparty supplied a valid signature to our version of the commitment
// transaction. Once this method returns, caller's should then call // transaction. Once this method returns, caller's should broadcast the
// .WaitForChannelOpen() which will block until the funding transaction obtains // created funding transaction, then call .WaitForChannelOpen() which will
// the configured number of confirmations. Once the method unblocks, a // block until the funding transaction obtains the configured number of
// LightningChannel instance is returned, marking the channel available for // confirmations. Once the method unblocks, a LightningChannel instance is
// updates. // returned, marking the channel available for updates.
func (r *ChannelReservation) CompleteReservation(fundingInputScripts []*InputScript, func (r *ChannelReservation) CompleteReservation(fundingInputScripts []*InputScript,
commitmentSig []byte) (*channeldb.OpenChannel, error) { commitmentSig []byte) (*channeldb.OpenChannel, error) {

@ -8,20 +8,20 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcutil/hdkeychain"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcutil/hdkeychain"
"github.com/lightningnetwork/lnd/shachain"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/txsort" "github.com/btcsuite/btcutil/txsort"
"github.com/lightningnetwork/lnd/shachain"
) )
const ( const (
@ -262,15 +262,15 @@ type LightningWallet struct {
// is removed from limbo. Each reservation is tracked by a unique // is removed from limbo. Each reservation is tracked by a unique
// monotonically integer. All requests concerning the channel MUST // monotonically integer. All requests concerning the channel MUST
// carry a valid, active funding ID. // carry a valid, active funding ID.
fundingLimbo map[uint64]*ChannelReservation fundingLimbo map[uint64]*ChannelReservation
limboMtx sync.RWMutex limboMtx sync.RWMutex
// lockedOutPoints is a set of the currently locked outpoint. This // lockedOutPoints is a set of the currently locked outpoint. This
// information is kept in order to provide an easy way to unlock all // information is kept in order to provide an easy way to unlock all
// the currently locked outpoints. // the currently locked outpoints.
lockedOutPoints map[wire.OutPoint]struct{} lockedOutPoints map[wire.OutPoint]struct{}
quit chan struct{} quit chan struct{}
wg sync.WaitGroup wg sync.WaitGroup
@ -1086,16 +1086,6 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
return return
} }
walletLog.Infof("Broadcasting funding tx for ChannelPoint(%v): %v",
res.partialState.FundingOutpoint, spew.Sdump(fundingTx))
// Broadcast the finalized funding transaction to the network.
if err := l.PublishTransaction(fundingTx); err != nil {
msg.err <- err
msg.completeChan <- nil
return
}
msg.completeChan <- res.partialState msg.completeChan <- res.partialState
msg.err <- nil msg.err <- nil
} }