multi: build retribution info in TowerClient

Since the TowerClient now has a callback that it can use to retrieve the
retribution for a certain channel and commit height, let it use this
call back instead of requiring the info to be passed to it through
BackupState.
This commit is contained in:
Elle Mouton 2023-02-02 11:40:33 +02:00
parent 530a8cae5d
commit 458ac32146
No known key found for this signature in database
GPG Key ID: D7D916376026F177
4 changed files with 25 additions and 38 deletions

View File

@ -7,7 +7,6 @@ import (
"github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lnpeer"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/record"
@ -255,11 +254,8 @@ type TowerClient interface {
// state. If the method returns nil, the backup is guaranteed to be // state. If the method returns nil, the backup is guaranteed to be
// successful unless the tower is unavailable and client is force quit, // successful unless the tower is unavailable and client is force quit,
// or the justice transaction would create dust outputs when trying to // or the justice transaction would create dust outputs when trying to
// abide by the negotiated policy. If the channel we're trying to back // abide by the negotiated policy.
// up doesn't have a tweak for the remote party's output, then BackupState(chanID *lnwire.ChannelID, stateNum uint64) error
// isTweakless should be true.
BackupState(*lnwire.ChannelID, *lnwallet.BreachRetribution,
channeldb.ChannelType) error
} }
// InterceptableHtlcForwarder is the interface to set the interceptor // InterceptableHtlcForwarder is the interface to set the interceptor

View File

@ -2022,11 +2022,6 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
// We've received a revocation from the remote chain, if valid, // We've received a revocation from the remote chain, if valid,
// this moves the remote chain forward, and expands our // this moves the remote chain forward, and expands our
// revocation window. // revocation window.
//
// Before advancing our remote chain, we will record the
// current commit tx, which is used by the TowerClient to
// create backups.
oldCommitTx := l.channel.State().RemoteCommitment.CommitTx
// We now process the message and advance our remote commit // We now process the message and advance our remote commit
// chain. // chain.
@ -2063,24 +2058,15 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
// create a backup for the current state. // create a backup for the current state.
if l.cfg.TowerClient != nil { if l.cfg.TowerClient != nil {
state := l.channel.State() state := l.channel.State()
breachInfo, err := lnwallet.NewBreachRetribution(
state, state.RemoteCommitment.CommitHeight-1, 0,
// OldCommitTx is the breaching tx at height-1.
oldCommitTx,
)
if err != nil {
l.fail(LinkFailureError{code: ErrInternalError},
"failed to load breach info: %v", err)
return
}
chanID := l.ChanID() chanID := l.ChanID()
err = l.cfg.TowerClient.BackupState( err = l.cfg.TowerClient.BackupState(
&chanID, breachInfo, state.ChanType, &chanID, state.RemoteCommitment.CommitHeight-1,
) )
if err != nil { if err != nil {
l.fail(LinkFailureError{code: ErrInternalError}, l.fail(LinkFailureError{code: ErrInternalError},
"unable to queue breach backup: %v", err) "unable to queue breach backup: %v",
err)
return return
} }
} }

View File

@ -136,11 +136,8 @@ type Client interface {
// state. If the method returns nil, the backup is guaranteed to be // state. If the method returns nil, the backup is guaranteed to be
// successful unless the client is force quit, or the justice // successful unless the client is force quit, or the justice
// transaction would create dust outputs when trying to abide by the // transaction would create dust outputs when trying to abide by the
// negotiated policy. If the channel we're trying to back up doesn't // negotiated policy.
// have a tweak for the remote party's output, then isTweakless should BackupState(chanID *lnwire.ChannelID, stateNum uint64) error
// be true.
BackupState(*lnwire.ChannelID, *lnwallet.BreachRetribution,
channeldb.ChannelType) error
// Start initializes the watchtower client, allowing it process requests // Start initializes the watchtower client, allowing it process requests
// to backup revoked channel states. // to backup revoked channel states.
@ -805,32 +802,41 @@ func (c *TowerClient) RegisterChannel(chanID lnwire.ChannelID) error {
// - breached outputs contain too little value to sweep at the target sweep // - breached outputs contain too little value to sweep at the target sweep
// fee rate. // fee rate.
func (c *TowerClient) BackupState(chanID *lnwire.ChannelID, func (c *TowerClient) BackupState(chanID *lnwire.ChannelID,
breachInfo *lnwallet.BreachRetribution, stateNum uint64) error {
chanType channeldb.ChannelType) error {
// Retrieve the cached sweep pkscript used for this channel. // Retrieve the cached sweep pkscript used for this channel.
c.backupMu.Lock() c.backupMu.Lock()
summary, ok := c.summaries[*chanID] summary, ok := c.summaries[*chanID]
if !ok { if !ok {
c.backupMu.Unlock() c.backupMu.Unlock()
return ErrUnregisteredChannel return ErrUnregisteredChannel
} }
// Ignore backups that have already been presented to the client. // Ignore backups that have already been presented to the client.
height, ok := c.chanCommitHeights[*chanID] height, ok := c.chanCommitHeights[*chanID]
if ok && breachInfo.RevokedStateNum <= height { if ok && stateNum <= height {
c.backupMu.Unlock() c.backupMu.Unlock()
c.log.Debugf("Ignoring duplicate backup for chanid=%v at "+ c.log.Debugf("Ignoring duplicate backup for chanid=%v at "+
"height=%d", chanID, breachInfo.RevokedStateNum) "height=%d", chanID, stateNum)
return nil return nil
} }
// This backup has a higher commit height than any known backup for this // This backup has a higher commit height than any known backup for this
// channel. We'll update our tip so that we won't accept it again if the // channel. We'll update our tip so that we won't accept it again if the
// link flaps. // link flaps.
c.chanCommitHeights[*chanID] = breachInfo.RevokedStateNum c.chanCommitHeights[*chanID] = stateNum
c.backupMu.Unlock() c.backupMu.Unlock()
// Fetch the breach retribution info and channel type.
breachInfo, chanType, err := c.cfg.BuildBreachRetribution(
*chanID, stateNum,
)
if err != nil {
return err
}
task := newBackupTask( task := newBackupTask(
chanID, breachInfo, summary.SweepPkScript, chanType, chanID, breachInfo, summary.SweepPkScript, chanType,
) )

View File

@ -731,10 +731,9 @@ func (h *testHarness) backupState(id, i uint64, expErr error) {
_, retribution := h.channel(id).getState(i) _, retribution := h.channel(id).getState(i)
chanID := chanIDFromInt(id) chanID := chanIDFromInt(id)
err := h.client.BackupState(
&chanID, retribution, channeldb.SingleFunderBit, err := h.client.BackupState(&chanID, retribution.RevokedStateNum)
) require.ErrorIs(h.t, expErr, err)
require.ErrorIs(h.t, err, expErr)
} }
// sendPayments instructs the channel identified by id to send amt to the remote // sendPayments instructs the channel identified by id to send amt to the remote