breacharbiter: no longer watch for pending close, ChannelArbitrator will

In this commit, we remove all the code win the BreachArbiter that was
dedicated to sweeping output on the remote party’s commitment
transaction, and also responding to unilateral channel closes. We no
longer need to do this, as this is now the duty of the
ChannelArbitrator.
This commit is contained in:
Olaoluwa Osuntokun 2018-01-16 19:56:37 -08:00
parent 31aa7265b7
commit 367231320b
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

@ -218,7 +218,7 @@ func (b *breachArbiter) Start() error {
// Initialize active channel from persisted channel state.
channel, err := lnwallet.NewLightningChannel(nil,
b.cfg.Notifier, b.cfg.Estimator, chanState)
b.cfg.Notifier, nil, chanState)
if err != nil {
brarLog.Errorf("unable to load channel from "+
"disk: %v", err)
@ -230,13 +230,6 @@ func (b *breachArbiter) Start() error {
channelsToWatch = append(channelsToWatch, channel)
}
// Additionally, we'll also want to watch any pending close or force
// close transactions so we can properly mark them as resolved in the
// database.
if err := b.watchForPendingCloseConfs(); err != nil {
return err
}
// Spawn the exactRetribution tasks to monitor and resolve any breaches
// that were loaded from the retribution store.
for chanPoint := range breachRetInfos {
@ -266,71 +259,6 @@ func (b *breachArbiter) Start() error {
return nil
}
// watchForPendingCloseConfs dispatches confirmation notification subscribers
// that mark any pending channels as fully closed when signaled.
func (b *breachArbiter) watchForPendingCloseConfs() error {
pendingCloseChans, err := b.cfg.DB.FetchClosedChannels(true)
if err != nil {
brarLog.Errorf("unable to fetch closing channels: %v", err)
return err
}
for _, pendingClose := range pendingCloseChans {
// If this channel was force closed, and we have a non-zero
// time-locked balance, then the utxoNursery is currently
// watching over it. As a result we don't need to watch over
// it.
if pendingClose.CloseType == channeldb.ForceClose &&
pendingClose.TimeLockedBalance != 0 {
continue
}
brarLog.Infof("Watching for the closure of ChannelPoint(%v)",
pendingClose.ChanPoint)
closeTXID := pendingClose.ClosingTXID
confNtfn, err := b.cfg.Notifier.RegisterConfirmationsNtfn(
&closeTXID, 1, pendingClose.CloseHeight)
if err != nil {
return err
}
b.wg.Add(1)
go func(chanPoint wire.OutPoint) {
defer b.wg.Done()
// In the case that the ChainNotifier is shutting down,
// all subscriber notification channels will be closed,
// generating a nil receive.
select {
case confInfo, ok := <-confNtfn.Confirmed:
if !ok {
return
}
brarLog.Infof("ChannelPoint(%v) is "+
"fully closed, at height: %v",
chanPoint, confInfo.BlockHeight)
// TODO(roasbeef): need to store
// UnilateralCloseSummary on disk so can
// possibly sweep output here
err := b.cfg.DB.MarkChanFullyClosed(&chanPoint)
if err != nil {
brarLog.Errorf("unable to mark channel"+
" as closed: %v", err)
}
case <-b.quit:
return
}
}(pendingClose.ChanPoint)
}
return nil
}
// Stop is an idempotent method that signals the breachArbiter to execute a
// graceful shutdown. This function will block until all goroutines spawned by
// the breachArbiter have gracefully exited.
@ -648,7 +576,8 @@ func (b *breachArbiter) breachObserver(contract *lnwallet.LightningChannel,
// The channel has been closed by a normal means: force closing with
// the latest commitment transaction.
case closeInfo := <-contract.UnilateralClose:
case <-contract.UnilateralCloseSignal:
// Launch a goroutine to cancel out this contract within the
// breachArbiter's main goroutine.
b.wg.Add(1)
@ -662,64 +591,8 @@ func (b *breachArbiter) breachObserver(contract *lnwallet.LightningChannel,
}()
b.cfg.CloseLink(chanPoint, htlcswitch.CloseBreach)
contract.CancelObserver()
contract.Stop()
// Next, we'll launch a goroutine to wait until the closing
// transaction has been confirmed so we can mark the contract
// as resolved in the database. This go routine is _not_ tracked
// by the breach arbiter's wait group since the callback may not
// be executed before shutdown, potentially leading to a
// deadlocks as the arbiter may not be able to finish shutting
// down.
//
// TODO(roasbeef): also notify utxoNursery, might've had
// outbound HTLC's in flight
go waitForChanToClose(uint32(closeInfo.SpendingHeight),
b.cfg.Notifier, nil, chanPoint, closeInfo.SpenderTxHash,
func() {
// As we just detected a channel was closed via
// a unilateral commitment broadcast by the
// remote party, we'll need to sweep our main
// commitment output, and any outstanding
// outgoing HTLC we had as well.
//
// TODO(roasbeef): actually sweep HTLC's *
// ensure reliable confirmation
if closeInfo.SelfOutPoint != nil {
sweepTx, err := b.craftCommitSweepTx(
closeInfo,
)
if err != nil {
brarLog.Errorf("unable to "+
"generate sweep tx: %v",
err)
goto close
}
brarLog.Infof("Sweeping breached "+
"outputs with: %v",
spew.Sdump(sweepTx))
err = b.cfg.PublishTransaction(sweepTx)
if err != nil {
brarLog.Errorf("unable to "+
"broadcast tx: %v", err)
}
}
close:
brarLog.Infof("Force closed ChannelPoint(%v) "+
"is fully closed, updating DB",
chanPoint)
err := b.cfg.DB.MarkChanFullyClosed(chanPoint)
if err != nil {
brarLog.Errorf("unable to mark chan "+
"as closed: %v", err)
}
})
// A read from this channel indicates that a channel breach has been
// detected! So we notify the main coordination goroutine with the
// information needed to bring the counterparty to justice.
@ -1048,35 +921,6 @@ func (b *breachArbiter) createJusticeTx(
return b.sweepSpendableOutputsTxn(txWeight, spendableOutputs...)
}
// craftCommitmentSweepTx creates a transaction to sweep the non-delayed output
// within the commitment transaction that pays to us. We must manually sweep
// this output as it uses a tweaked public key in its pkScript, so the wallet
// won't immediately be aware of it.
//
// TODO(roasbeef): alternative options
// * leave the output in the chain, use as input to future funding tx
// * leave output in the chain, extend wallet to add knowledge of how to claim
func (b *breachArbiter) craftCommitSweepTx(
closeInfo *lnwallet.UnilateralCloseSummary) (*wire.MsgTx, error) {
selfOutput := makeBreachedOutput(
closeInfo.SelfOutPoint,
lnwallet.CommitmentNoDelay,
closeInfo.SelfOutputSignDesc,
)
// Compute the transaction weight of the commit sweep transaction, which
// includes a single input and output.
var weightEstimate lnwallet.TxWeightEstimator
weightEstimate.AddP2WKHOutput()
// Add to_local p2wpkh witness and tx input.
weightEstimate.AddP2WKHInput()
txWeight := uint64(weightEstimate.Weight())
return b.sweepSpendableOutputsTxn(txWeight, &selfOutput)
}
// sweepSpendableOutputsTxn creates a signed transaction from a sequence of
// spendable outputs by sweeping the funds into a single p2wkh output.
func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight uint64,