watchtower/wtclient: add anchor backup tasks

This commit is contained in:
Conner Fromknecht
2020-11-25 15:05:17 -08:00
parent 97cb030854
commit eb00e496bf
2 changed files with 180 additions and 90 deletions

View File

@@ -39,6 +39,7 @@ import (
type backupTask struct {
id wtdb.BackupID
breachInfo *lnwallet.BreachRetribution
chanType channeldb.ChannelType
// state-dependent variables
@@ -90,18 +91,33 @@ func newBackupTask(chanID *lnwire.ChannelID,
if breachInfo.LocalOutputSignDesc != nil {
var witnessType input.WitnessType
switch {
case chanType.HasAnchors():
witnessType = input.CommitmentToRemoteConfirmed
case chanType.IsTweakless():
witnessType = input.CommitSpendNoDelayTweakless
default:
witnessType = input.CommitmentNoDelay
}
toRemoteInput = input.NewBaseInput(
&breachInfo.LocalOutpoint,
witnessType,
breachInfo.LocalOutputSignDesc,
0,
)
// Anchor channels have a CSV-encumbered to-remote output. We'll
// construct a CSV input in that case and assign the proper CSV
// delay of 1, otherwise we fallback to the a regular P2WKH
// to-remote output for tweaked or tweakless channels.
if chanType.HasAnchors() {
toRemoteInput = input.NewCsvInput(
&breachInfo.LocalOutpoint,
witnessType,
breachInfo.LocalOutputSignDesc,
0, 1,
)
} else {
toRemoteInput = input.NewBaseInput(
&breachInfo.LocalOutpoint,
witnessType,
breachInfo.LocalOutputSignDesc,
0,
)
}
totalAmt += breachInfo.LocalOutputSignDesc.Output.Value
}
@@ -112,6 +128,7 @@ func newBackupTask(chanID *lnwire.ChannelID,
CommitHeight: breachInfo.RevokedStateNum,
},
breachInfo: breachInfo,
chanType: chanType,
toLocalInput: toLocalInput,
toRemoteInput: toRemoteInput,
totalAmt: btcutil.Amount(totalAmt),
@@ -151,13 +168,28 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody) error {
// underestimate the size by one byte. The diferrence in weight
// can cause different output values on the sweep transaction,
// so we mimic the original bug and create signatures using the
// original weight estimate.
weightEstimate.AddWitnessInput(
input.ToLocalPenaltyWitnessSize - 1,
)
// original weight estimate. For anchor channels we'll go ahead
// an use the correct penalty witness when signing our justice
// transactions.
if t.chanType.HasAnchors() {
weightEstimate.AddWitnessInput(
input.ToLocalPenaltyWitnessSize,
)
} else {
weightEstimate.AddWitnessInput(
input.ToLocalPenaltyWitnessSize - 1,
)
}
}
if t.toRemoteInput != nil {
weightEstimate.AddWitnessInput(input.P2WKHWitnessSize)
// Legacy channels (both tweaked and non-tweaked) spend from
// P2WKH output. Anchor channels spend a to-remote confirmed
// P2WSH output.
if t.chanType.HasAnchors() {
weightEstimate.AddWitnessInput(input.ToRemoteConfirmedWitnessSize)
} else {
weightEstimate.AddWitnessInput(input.P2WKHWitnessSize)
}
}
// All justice transactions have a p2wkh output paying to the victim.
@@ -169,6 +201,12 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody) error {
weightEstimate.AddP2WKHOutput()
}
if t.chanType.HasAnchors() != session.Policy.IsAnchorChannel() {
log.Criticalf("Invalid task (has_anchors=%t) for session "+
"(has_anchors=%t)", t.chanType.HasAnchors(),
session.Policy.IsAnchorChannel())
}
// Now, compute the output values depending on whether FlagReward is set
// in the current session's policy.
outputs, err := session.Policy.ComputeJusticeTxOuts(
@@ -225,9 +263,10 @@ func (t *backupTask) craftSessionPayload(
// information. This will either be contain both the to-local and
// to-remote outputs, or only be the to-local output.
inputs := t.inputs()
for prevOutPoint := range inputs {
for prevOutPoint, input := range inputs {
justiceTxn.AddTxIn(&wire.TxIn{
PreviousOutPoint: prevOutPoint,
Sequence: input.BlocksToMaturity(),
})
}
@@ -294,6 +333,8 @@ func (t *backupTask) craftSessionPayload(
case input.CommitSpendNoDelayTweakless:
fallthrough
case input.CommitmentNoDelay:
fallthrough
case input.CommitmentToRemoteConfirmed:
copy(justiceKit.CommitToRemoteSig[:], signature[:])
default:
return hint, nil, fmt.Errorf("invalid witness type: %v",