contractcourt: add spend path helpers in timeout/success resolver

This commit adds a few helper methods to decide how the htlc output
should be spent.
This commit is contained in:
yyforyongyu
2024-11-14 02:28:56 +08:00
parent 1f2cfc6a60
commit 10e5a43e46
2 changed files with 65 additions and 18 deletions

View File

@@ -634,7 +634,7 @@ func (h *htlcTimeoutResolver) spendHtlcOutput() (
// HTLC transaction that is signed using sighash SINGLE|ANYONECANPAY
// (the case for anchor type channels). In this case we can re-sign it
// and attach fees at will. We let the sweeper handle this job.
case h.htlcResolution.SignDetails != nil && !h.outputIncubating:
case h.isZeroFeeOutput() && !h.outputIncubating:
if err := h.sweepSecondLevelTx(); err != nil {
log.Errorf("Sending timeout tx to sweeper: %v", err)
@@ -643,7 +643,7 @@ func (h *htlcTimeoutResolver) spendHtlcOutput() (
// If this is a remote commitment there's no second level timeout txn,
// and we can just send this directly to the sweeper.
case h.htlcResolution.SignedTimeoutTx == nil && !h.outputIncubating:
case h.isRemoteCommitOutput() && !h.outputIncubating:
if err := h.sweepDirectHtlcOutput(); err != nil {
log.Errorf("Sending direct spend to sweeper: %v", err)
@@ -653,7 +653,7 @@ func (h *htlcTimeoutResolver) spendHtlcOutput() (
// If we have a SignedTimeoutTx but no SignDetails, this is a local
// commitment for a non-anchor channel, so we'll send it to the utxo
// nursery.
case h.htlcResolution.SignDetails == nil && !h.outputIncubating:
case h.isLegacyOutput() && !h.outputIncubating:
if err := h.sendSecondLevelTxLegacy(); err != nil {
log.Errorf("Sending timeout tx to nursery: %v", err)
@@ -769,7 +769,7 @@ func (h *htlcTimeoutResolver) handleCommitSpend(
// If the sweeper is handling the second level transaction, wait for
// the CSV and possible CLTV lock to expire, before sweeping the output
// on the second-level.
case h.htlcResolution.SignDetails != nil:
case h.isZeroFeeOutput():
waitHeight := h.deriveWaitHeight(
h.htlcResolution.CsvDelay, commitSpend,
)
@@ -851,7 +851,7 @@ func (h *htlcTimeoutResolver) handleCommitSpend(
// Finally, if this was an output on our commitment transaction, we'll
// wait for the second-level HTLC output to be spent, and for that
// transaction itself to confirm.
case h.htlcResolution.SignedTimeoutTx != nil:
case !h.isRemoteCommitOutput():
log.Infof("%T(%v): waiting for nursery/sweeper to spend CSV "+
"delayed output", h, claimOutpoint)
@@ -1232,7 +1232,7 @@ func (h *htlcTimeoutResolver) consumeSpendEvents(resultChan chan *spendResult,
// continue the loop.
hasPreimage := isPreimageSpend(
h.isTaproot(), spendDetail,
h.htlcResolution.SignedTimeoutTx != nil,
!h.isRemoteCommitOutput(),
)
if !hasPreimage {
log.Debugf("HTLC output %s spent doesn't "+
@@ -1260,3 +1260,31 @@ func (h *htlcTimeoutResolver) consumeSpendEvents(resultChan chan *spendResult,
}
}
}
// isRemoteCommitOutput returns a bool to indicate whether the htlc output is
// on the remote commitment.
func (h *htlcTimeoutResolver) isRemoteCommitOutput() bool {
// If we don't have a timeout transaction, then this means that this is
// an output on the remote party's commitment transaction.
return h.htlcResolution.SignedTimeoutTx == nil
}
// isZeroFeeOutput returns a boolean indicating whether the htlc output is from
// a anchor-enabled channel, which uses the sighash SINGLE|ANYONECANPAY.
func (h *htlcTimeoutResolver) isZeroFeeOutput() bool {
// If we have non-nil SignDetails, this means it has a 2nd level HTLC
// transaction that is signed using sighash SINGLE|ANYONECANPAY (the
// case for anchor type channels). In this case we can re-sign it and
// attach fees at will.
return h.htlcResolution.SignedTimeoutTx != nil &&
h.htlcResolution.SignDetails != nil
}
// isLegacyOutput returns a boolean indicating whether the htlc output is from
// a non-anchor-enabled channel.
func (h *htlcTimeoutResolver) isLegacyOutput() bool {
// If we have a SignedTimeoutTx but no SignDetails, this is a local
// commitment for a non-anchor channel.
return h.htlcResolution.SignedTimeoutTx != nil &&
h.htlcResolution.SignDetails == nil
}