diff --git a/itest/lnd_revocation_test.go b/itest/lnd_revocation_test.go index b5727408ea..7bc4874f35 100644 --- a/itest/lnd_revocation_test.go +++ b/itest/lnd_revocation_test.go @@ -667,30 +667,24 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntest.HarnessTest) { // asserts that Willy responds by broadcasting the justice transaction on // Carol's behalf sweeping her funds without a reward. func testRevokedCloseRetributionAltruistWatchtower(ht *lntest.HarnessTest) { - testCases := []struct { - name string - anchors bool - }{{ - name: "anchors", - anchors: true, - }, { - name: "legacy", - anchors: false, - }} - - for _, tc := range testCases { - tc := tc + for _, commitType := range []lnrpc.CommitmentType{ + lnrpc.CommitmentType_LEGACY, + lnrpc.CommitmentType_ANCHORS, + lnrpc.CommitmentType_SIMPLE_TAPROOT, + } { + testName := fmt.Sprintf("%v", commitType.String()) + ct := commitType testFunc := func(ht *lntest.HarnessTest) { testRevokedCloseRetributionAltruistWatchtowerCase( - ht, tc.anchors, + ht, ct, ) } - success := ht.Run(tc.name, func(tt *testing.T) { + success := ht.Run(testName, func(tt *testing.T) { st := ht.Subtest(tt) st.RunTestCase(&lntest.TestCase{ - Name: tc.name, + Name: testName, TestFunc: testFunc, }) }) @@ -708,7 +702,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntest.HarnessTest) { } func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, - anchors bool) { + commitType lnrpc.CommitmentType) { const ( chanAmt = funding.MaxBtcFundingAmount @@ -719,18 +713,19 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, // Since we'd like to test some multi-hop failure scenarios, we'll // introduce another node into our test network: Carol. - carolArgs := []string{"--hodl.exit-settle"} - if anchors { - carolArgs = append(carolArgs, "--protocol.anchors") - } + carolArgs := lntest.NodeArgsForCommitType(commitType) + carolArgs = append(carolArgs, "--hodl.exit-settle") + carol := ht.NewNode("Carol", carolArgs) // Willy the watchtower will protect Dave from Carol's breach. He will // remain online in order to punish Carol on Dave's behalf, since the // breach will happen while Dave is offline. willy := ht.NewNode( - "Willy", []string{"--watchtower.active", - "--watchtower.externalip=" + externalIP}, + "Willy", []string{ + "--watchtower.active", + "--watchtower.externalip=" + externalIP, + }, ) willyInfo := willy.RPC.GetInfoWatchtower() @@ -753,13 +748,8 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, // Dave will be the breached party. We set --nolisten to ensure Carol // won't be able to connect to him and trigger the channel data // protection logic automatically. - daveArgs := []string{ - "--nolisten", - "--wtclient.active", - } - if anchors { - daveArgs = append(daveArgs, "--protocol.anchors") - } + daveArgs := lntest.NodeArgsForCommitType(commitType) + daveArgs = append(carolArgs, "--nolisten", "--wtclient.active") dave := ht.NewNode("Dave", daveArgs) addTowerReq := &wtclientrpc.AddTowerRequest{ @@ -785,11 +775,15 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, // closure by Carol, we'll first open up a channel between them with a // 0.5 BTC value. params := lntest.OpenChannelParams{ - Amt: 3 * (chanAmt / 4), - PushAmt: chanAmt / 4, + Amt: 3 * (chanAmt / 4), + PushAmt: chanAmt / 4, + CommitmentType: commitType, + Private: true, } chanPoint := ht.OpenChannel(dave, carol, params) + ht.Logf("ELLE: Channel is open") + // With the channel open, we'll create a few invoices for Carol that // Dave will pay to in order to advance the state of the channel. carolPayReqs, _, _ := ht.CreatePayReqs(carol, paymentAmt, numInvoices) @@ -822,6 +816,8 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, // remaining payment hashes. ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint) + ht.Logf("ELLE: Payments complete") + daveBalResp := dave.RPC.WalletBalance() davePreSweepBalance := daveBalResp.ConfirmedBalance @@ -840,6 +836,8 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, }, defaultTimeout) require.NoError(ht, err, "unable to verify backup task completed") + ht.Logf("ELLE: updates were backed up") + // Shutdown Dave to simulate going offline for an extended period of // time. Once he's not watching, Carol will try to breach the channel. restart := ht.SuspendNode(dave) @@ -908,7 +906,7 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, willyBalResp := willy.RPC.WalletBalance() if willyBalResp.ConfirmedBalance != 0 { - return fmt.Errorf("Expected Willy to have no funds "+ + return fmt.Errorf("expected Willy to have no funds "+ "after justice transaction was mined, found %v", willyBalResp) } @@ -934,7 +932,7 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, err = wait.NoError(func() error { daveBalResp := dave.RPC.ChannelBalance() if daveBalResp.LocalBalance.Sat != 0 { - return fmt.Errorf("Dave should end up with zero "+ + return fmt.Errorf("dave should end up with zero "+ "channel balance, instead has %d", daveBalResp.LocalBalance.Sat) } @@ -946,7 +944,9 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, ht.AssertNumPendingForceClose(dave, 0) // If this is an anchor channel, Dave would sweep the anchor. - if anchors { + if commitType == lnrpc.CommitmentType_ANCHORS || + commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT { + ht.MineBlocksAndAssertNumTxes(1, 1) } @@ -955,7 +955,7 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, daveBalResp := dave.RPC.WalletBalance() if daveBalResp.ConfirmedBalance <= davePreSweepBalance { - return fmt.Errorf("Dave should have more than %d "+ + return fmt.Errorf("dave should have more than %d "+ "after sweep, instead has %d", davePreSweepBalance, daveBalResp.ConfirmedBalance) diff --git a/peer/brontide.go b/peer/brontide.go index 8f88bbec29..90583d5346 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -946,27 +946,11 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint, return p.cfg.ChainArb.NotifyContractUpdate(*chanPoint, update) } - chanType := lnChan.State().ChanType - // Select the appropriate tower client based on the channel type. It's // okay if the clients are disabled altogether and these values are nil, // as the link will check for nilness before using either. var towerClient htlcswitch.TowerClient - switch { - case chanType.IsTaproot(): - // Leave the tower client as nil for now until the tower client - // has support for taproot channels. - // - // If the user has activated the tower client, then add a log - // to explain that any taproot channel updates wil not be - // backed up to a tower. - if p.cfg.TowerClient != nil { - p.log.Debugf("Updates for channel %s will not be "+ - "backed up to a watchtower as watchtowers "+ - "are not yet taproot channel compatible", - chanPoint) - } - default: + if p.cfg.TowerClient != nil { towerClient = p.cfg.TowerClient } diff --git a/watchtower/blob/justice_kit.go b/watchtower/blob/justice_kit.go index 6452a86711..d8f7770a1d 100644 --- a/watchtower/blob/justice_kit.go +++ b/watchtower/blob/justice_kit.go @@ -367,7 +367,7 @@ func (t *taprootJusticeKit) ToLocalOutputSpendInfo() ([]byte, [][]byte, error) { } witness := make([][]byte, 3) - witness[0] = toLocalSig.Serialize() + witness[0] = append(toLocalSig.Serialize(), byte(txscript.SigHashAll)) witness[1] = revokeScript witness[2] = ctrlBytes @@ -420,7 +420,7 @@ func (t *taprootJusticeKit) ToRemoteOutputSpendInfo() ([]byte, [][]byte, uint32, } witness := make([][]byte, 3) - witness[0] = toRemoteSig.Serialize() + witness[0] = append(toRemoteSig.Serialize(), byte(txscript.SigHashAll)) witness[1] = scriptTree.SettleLeaf.Script witness[2] = ctrl diff --git a/watchtower/wtclient/backup_task.go b/watchtower/wtclient/backup_task.go index a458afecbd..44a82aacbf 100644 --- a/watchtower/wtclient/backup_task.go +++ b/watchtower/wtclient/backup_task.go @@ -213,12 +213,6 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody, } } - if chanType.HasAnchors() != session.Policy.IsAnchorChannel() { - log.Criticalf("Invalid task (has_anchors=%t) for session "+ - "(has_anchors=%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( @@ -334,6 +328,7 @@ func (t *backupTask) craftSessionPayload( switch inp.WitnessType() { case toLocalWitnessType: justiceKit.AddToLocalSig(signature) + case toRemoteWitnessType: justiceKit.AddToRemoteSig(signature) default: diff --git a/watchtower/wtclient/backup_task_internal_test.go b/watchtower/wtclient/backup_task_internal_test.go index acb56d2f70..b0d8faff72 100644 --- a/watchtower/wtclient/backup_task_internal_test.go +++ b/watchtower/wtclient/backup_task_internal_test.go @@ -367,13 +367,13 @@ func TestBackupTask(t *testing.T) { sweepFeeRateNoRewardRemoteDust = 225400 sweepFeeRateRewardRemoteDust = 174100 } else if chanType.IsTaproot() { - expSweepCommitNoRewardBoth = 299167 - expSweepCommitNoRewardLocal = 199469 - expSweepCommitNoRewardRemote = 99532 + expSweepCommitNoRewardBoth = 299165 + expSweepCommitNoRewardLocal = 199468 + expSweepCommitNoRewardRemote = 99531 sweepFeeRateNoRewardRemoteDust = 213200 - expSweepCommitRewardBoth = 295995 - expSweepCommitRewardLocal = 197297 - expSweepCommitRewardRemote = 98360 + expSweepCommitRewardBoth = 295993 + expSweepCommitRewardLocal = 197296 + expSweepCommitRewardRemote = 98359 sweepFeeRateRewardRemoteDust = 167000 } diff --git a/watchtower/wtclient/manager.go b/watchtower/wtclient/manager.go index 32ca84af4a..a54beb9597 100644 --- a/watchtower/wtclient/manager.go +++ b/watchtower/wtclient/manager.go @@ -416,6 +416,7 @@ func (m *Manager) AddTower(address *lnwire.NetAddress) error { defer m.clientsMu.Unlock() for _, client := range m.clients { + log.Infof("ELLE: adding tower to client", client.cfg.Policy) if err := client.addTower(tower); err != nil { return err }