diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index b19bae7fe..37395f93a 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -1090,10 +1090,10 @@ func (c *ChannelArbitrator) stateStep( break } - // Now that we know we'll need to act, we'll process the htlc - // actions, then create the structures we need to resolve all + // Now that we know we'll need to act, we'll process all the + // resolvers, then create the structures we need to resolve all // outstanding contracts. - htlcResolvers, pktsToSend, err := c.prepContractResolutions( + resolvers, pktsToSend, err := c.prepContractResolutions( contractResolutions, triggerHeight, trigger, confCommitSet, ) @@ -1103,15 +1103,15 @@ func (c *ChannelArbitrator) stateStep( return StateError, closeTx, err } - log.Debugf("ChannelArbitrator(%v): sending resolution message=%v", - c.cfg.ChanPoint, - newLogClosure(func() string { - return spew.Sdump(pktsToSend) - })) - // With the commitment broadcast, we'll then send over all // messages we can send immediately. if len(pktsToSend) != 0 { + log.Debugf("ChannelArbitrator(%v): sending "+ + "resolution message=%v", c.cfg.ChanPoint, + newLogClosure(func() string { + return spew.Sdump(pktsToSend) + })) + err := c.cfg.DeliverResolutionMsg(pktsToSend...) if err != nil { log.Errorf("unable to send pkts: %v", err) @@ -1120,16 +1120,16 @@ func (c *ChannelArbitrator) stateStep( } log.Debugf("ChannelArbitrator(%v): inserting %v contract "+ - "resolvers", c.cfg.ChanPoint, len(htlcResolvers)) + "resolvers", c.cfg.ChanPoint, len(resolvers)) - err = c.log.InsertUnresolvedContracts(nil, htlcResolvers...) + err = c.log.InsertUnresolvedContracts(nil, resolvers...) if err != nil { return StateError, closeTx, err } // Finally, we'll launch all the required contract resolvers. // Once they're all resolved, we're no longer needed. - c.launchResolvers(htlcResolvers) + c.launchResolvers(resolvers) nextState = StateWaitingFullResolution diff --git a/contractcourt/htlc_success_resolver.go b/contractcourt/htlc_success_resolver.go index 5d30b365a..26a906ce4 100644 --- a/contractcourt/htlc_success_resolver.go +++ b/contractcourt/htlc_success_resolver.go @@ -417,20 +417,8 @@ func (h *htlcSuccessResolver) resolveRemoteCommitOutput() ( // with the published one. } - // Regardless of whether an existing transaction was found or newly - // constructed, we'll broadcast the sweep transaction to the network. - label := labels.MakeLabel( - labels.LabelTypeChannelClose, &h.ShortChanID, - ) - err := h.PublishTx(h.sweepTx, label) - if err != nil { - log.Infof("%T(%x): unable to publish tx: %v", - h, h.htlc.RHash[:], err) - return nil, err - } - - // With the sweep transaction broadcast, we'll wait for its - // confirmation. + // Register the confirmation notification before broadcasting the sweep + // transaction. sweepTXID := h.sweepTx.TxHash() sweepScript := h.sweepTx.TxOut[0].PkScript confNtfn, err := h.Notifier.RegisterConfirmationsNtfn( @@ -440,8 +428,22 @@ func (h *htlcSuccessResolver) resolveRemoteCommitOutput() ( return nil, err } - log.Infof("%T(%x): waiting for sweep tx (txid=%v) to be "+ - "confirmed", h, h.htlc.RHash[:], sweepTXID) + // Regardless of whether an existing transaction was found or newly + // constructed, we'll broadcast the sweep transaction to the network. + label := labels.MakeLabel( + labels.LabelTypeChannelClose, &h.ShortChanID, + ) + err = h.PublishTx(h.sweepTx, label) + if err != nil { + log.Infof("%T(%x): unable to publish tx: %v", + h, h.htlc.RHash[:], err) + confNtfn.Cancel() + + return nil, err + } + + log.Infof("%T(%x): waiting for sweep tx (txid=%v) to be confirmed", h, + h.htlc.RHash[:], sweepTXID) select { case _, ok := <-confNtfn.Confirmed: diff --git a/input/input.go b/input/input.go index 98ae2c056..64a9530d9 100644 --- a/input/input.go +++ b/input/input.go @@ -1,6 +1,8 @@ package input import ( + "fmt" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -69,6 +71,11 @@ type TxInfo struct { Weight int64 } +// String returns a human readable version of the tx info. +func (t *TxInfo) String() string { + return fmt.Sprintf("fee=%v, weight=%v", t.Fee, t.Weight) +} + // SignDetails is a struct containing information needed to resign certain // inputs. It is used to re-sign 2nd level HTLC transactions that uses the // SINGLE|ANYONECANPAY sighash type, as we have a signature provided by our diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 376586dee..4f53d2098 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -98,8 +98,13 @@ type ParamsUpdate struct { // String returns a human readable interpretation of the sweep parameters. func (p Params) String() string { - return fmt.Sprintf("fee=%v, force=%v, exclusive_group=%v", - p.Fee, p.Force, p.ExclusiveGroup) + if p.ExclusiveGroup != nil { + return fmt.Sprintf("fee=%v, force=%v, exclusive_group=%v", + p.Fee, p.Force, *p.ExclusiveGroup) + } + + return fmt.Sprintf("fee=%v, force=%v, exclusive_group=nil", + p.Fee, p.Force) } // pendingInput is created when an input reaches the main loop for the first @@ -439,9 +444,10 @@ func (s *UtxoSweeper) SweepInput(input input.Input, absoluteTimeLock, _ := input.RequiredLockTime() log.Infof("Sweep request received: out_point=%v, witness_type=%v, "+ "relative_time_lock=%v, absolute_time_lock=%v, amount=%v, "+ - "params=(%v)", input.OutPoint(), input.WitnessType(), - input.BlocksToMaturity(), absoluteTimeLock, - btcutil.Amount(input.SignDesc().Output.Value), params) + "parent=(%v), params=(%v)", input.OutPoint(), + input.WitnessType(), input.BlocksToMaturity(), absoluteTimeLock, + btcutil.Amount(input.SignDesc().Output.Value), + input.UnconfParent(), params) sweeperInput := &sweepInputMessage{ input: input,