Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

watchtower: support taproot channel commitments #7733

Merged
merged 11 commits into from
Jan 19, 2024

Conversation

ellemouton
Copy link
Collaborator

@ellemouton ellemouton commented May 28, 2023

In this PR, the watchtower server and client are updated to support backing up taproot channels.


This change is Reviewable

@ellemouton ellemouton marked this pull request as draft May 28, 2023 07:30
@saubyk saubyk added this to the v0.17.0 milestone May 30, 2023
@ellemouton ellemouton changed the base branch from simple-taproot-chans-staging to taprootTowerRef May 31, 2023 08:23
@ellemouton ellemouton self-assigned this May 31, 2023
Copy link
Collaborator

@saubyk saubyk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK

@saubyk saubyk modified the milestones: v0.17.0, v0.17.1 Jun 15, 2023
@saubyk saubyk added the P1 MUST be fixed or reviewed label Aug 8, 2023
@saubyk saubyk modified the milestones: High Priority, v0.18.0 Aug 8, 2023
@ellemouton ellemouton changed the base branch from taprootTowerRef to master August 23, 2023 10:06
@ellemouton ellemouton force-pushed the taprootTowers branch 3 times, most recently from ea83003 to af36303 Compare August 29, 2023 07:20
@ellemouton ellemouton marked this pull request as ready for review August 29, 2023 07:24
@ellemouton ellemouton changed the title [WIP] watchtower: support taproot channel commitments watchtower: support taproot channel commitments Aug 29, 2023
@ellemouton ellemouton force-pushed the taprootTowers branch 3 times, most recently from e885b37 to 128fec5 Compare November 28, 2023 12:08
@ellemouton ellemouton requested a review from Roasbeef December 6, 2023 06:46
Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Dig the prepatory refactors to smooth out the integration of this channel type to the tower, as well as others.

No major comments, but still need to get more up to speed with the latest state of the codebase, as has been a while since I've reviewed anything here.

One thing I think we'll want to do to is have any instances of a new taproot blob or commitment type instead be taprootStaging. That final script change may not actually go through, but we should make sure to hedge things out a bit.

watchtower/blob/commitments.go Outdated Show resolved Hide resolved
watchtower/blob/commitments.go Outdated Show resolved Hide resolved
watchtower/blob/type.go Outdated Show resolved Hide resolved
watchtower/blob/commitments.go Outdated Show resolved Hide resolved
watchtower/blob/justice_kit.go Outdated Show resolved Hide resolved
watchtower/blob/justice_kit_test.go Show resolved Hide resolved
watchtower/blob/justice_kit_test.go Outdated Show resolved Hide resolved
// In case of a taproot output any signature is always a Schnorr
// signature, based on the new tapscript sighash algorithm.
if txscript.IsPayToTaproot(signDesc.Output.PkScript) {
sigHashes := txscript.NewTxSigHashes(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've copied this over in a few places in the codebase, perhaps we can try to unify with an internal/mock package?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you mean the entire mock signer? dont think we can do that since it would cause an import package between input and internal/mock.

I guess another option is just to extend input.MockSigner so that we can re-use it here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh true re import cycle, I think I ran into the same thing when adding musig2 awareness in the first place...

Perhaps we can just make a new issue here to attempt to conslidate the mock signers in a single place. We don't update it all that often, but it can def burn some dev time when something small changes, and one mock signer works, but not the other.

watchtower/wtclient/session_negotiator.go Outdated Show resolved Hide resolved
server.go Outdated Show resolved Hide resolved
Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🐟

Reviewable status: 0 of 33 files reviewed, 24 unresolved discussions (waiting on @ellemouton and @yyforyongyu)


watchtower/wtpolicy/policy.go line 127 at r4 (raw file):

// FeatureBits returns the watchtower feature bits required for the given
// policy.
func (p *Policy) FeatureBits() []lnwire.FeatureBit {

👍

@lightninglabs-deploy
Copy link

@yyforyongyu: review reminder

Copy link
Member

@yyforyongyu yyforyongyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice 🎉 Left a few nits and questions, my main comment is there seems to be some test cases that won't be hit because how we check channel types.

input/script_utils.go Show resolved Hide resolved
@@ -400,3 +415,222 @@ func (b *justiceKitPacketV0) decode(r io.Reader) error {

return nil
}

// justiceKitPacketV1 is lé Blob of Justice for taproot channels.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is :neckbeard:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a fancy-shamnsy way of saying "the" 😂

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left this in cause that's the original way that Connor wrote it and I thought it was funny :) but it's already in the interface comment so will remove it here 😉

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol TIL

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my two sats here: "le" is the French masculine word for "the". But because just "le" doesn't look very French, I assume the acute accent was added (and I believe all of this is from Sponge Bob if I'm not mistaken).

watchtower/blob/justice_kit_packet.go Outdated Show resolved Hide resolved
// JusticeKit interface.
var _ JusticeKit = (*taprootJusticeKit)(nil)

// newTaprootJusticeKit constructs a new anchorJusticeKit.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// newTaprootJusticeKit constructs a new anchorJusticeKit.
// newTaprootJusticeKit constructs a new taprootJusticeKit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops!

watchtower/blob/justice_kit.go Outdated Show resolved Hide resolved
@@ -114,26 +116,44 @@ type Policy struct {
}

// String returns a human-readable description of the current policy.
func (p Policy) String() string {
func (p *Policy) String() string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was just to make my IDE happy 😝 in general seems to be better to have pointer receivers to avoid some unexpected behaviour

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turns out this actually does need to stay like this or else the log line doesnt print properly 🙃 so changed it back

itest/lnd_revocation_test.go Outdated Show resolved Hide resolved
server.go Show resolved Hide resolved
watchtower/wtclient/backup_task_internal_test.go Outdated Show resolved Hide resolved
// IsAnchorChannel returns true if the session policy requires anchor channels.
func (p Policy) IsAnchorChannel() bool {
func (p *Policy) IsAnchorChannel() bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wondering whether we should restrict the method IsAnchorChannel, and all its occurrence, to only return true if this channel is anchor type, and not taproot type - should help to avoid misusing as we now have to always keep in mind to check IsTaproot first before check IsAnchor in a switch statement, maybe we should do this on ChannelType - future PRs tho.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so for this instance (ie, in towers alone) it does actually just mean anchors. So this will return false for a taproot blob type.

but agreed that the we should make this the standard everywhere :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so for this instance (ie, in towers alone) it does actually just mean anchors. So this will return false for a taproot blob type.

Yeah I do notice that the feature bit is 101 and 11, tho not sure about how to properly define a feature bit, as it seems that technically if anchor is a feature, then taproot chan should be 111 since it has this feature - unknown implications here, but I prefer the end result here as we can clearly distinguish the two channels. Meanwhile this shouldn't be an issue for feature negotiation since both are lnd? I think if both sides understand and use the same defined feature bits we are fine, eg, they won't send us a 111.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i guess it's slightly different in this tower protocol cause the tower only cares about commit types as a whole since this completely changes the justice kit etc.

Meanwhile this shouldn't be an issue for feature negotiation since both are lnd?

yeah - currently the code for this is the spec. So this is fine for 2 lnd nodes, yeah 👍

Factor out the building of the delay and revoke scripts from
NewLocalCommitScriptTree so that they can be re-used later on.
This commit adds a new FlagTaprootChannel Flag which is then used to
construct a new blob Type: TypeAltruistTaprootCommit. New watchtower
feature bits are also added (4/5).
In preparation for the new Taproot commitment type being supported by
watchtowers, we add a new justice packet type.
Copy link
Contributor

coderabbitai bot commented Jan 18, 2024

Important

Auto Review Skipped

Auto reviews are limited to the following labels: llm-review. Please add one of these labels to enable auto reviews.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository.

To trigger a single review, invoke the @coderabbitai review command.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link
Collaborator Author

@ellemouton ellemouton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @yyforyongyu!! 🚀

Updated!

@@ -400,3 +415,222 @@ func (b *justiceKitPacketV0) decode(r io.Reader) error {

return nil
}

// justiceKitPacketV1 is lé Blob of Justice for taproot channels.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a fancy-shamnsy way of saying "the" 😂

@@ -400,3 +415,222 @@ func (b *justiceKitPacketV0) decode(r io.Reader) error {

return nil
}

// justiceKitPacketV1 is lé Blob of Justice for taproot channels.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left this in cause that's the original way that Connor wrote it and I thought it was funny :) but it's already in the interface comment so will remove it here 😉

// JusticeKit interface.
var _ JusticeKit = (*taprootJusticeKit)(nil)

// newTaprootJusticeKit constructs a new anchorJusticeKit.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops!

watchtower/blob/commitments.go Show resolved Hide resolved
watchtower/blob/commitments.go Show resolved Hide resolved
watchtower/wtclient/backup_task_internal_test.go Outdated Show resolved Hide resolved
@@ -114,26 +116,44 @@ type Policy struct {
}

// String returns a human-readable description of the current policy.
func (p Policy) String() string {
func (p *Policy) String() string {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was just to make my IDE happy 😝 in general seems to be better to have pointer receivers to avoid some unexpected behaviour

// IsAnchorChannel returns true if the session policy requires anchor channels.
func (p Policy) IsAnchorChannel() bool {
func (p *Policy) IsAnchorChannel() bool {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so for this instance (ie, in towers alone) it does actually just mean anchors. So this will return false for a taproot blob type.

but agreed that the we should make this the standard everywhere :)

server.go Show resolved Hide resolved
itest/lnd_revocation_test.go Outdated Show resolved Hide resolved
Copy link
Member

@yyforyongyu yyforyongyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Welcome towers to the taproot gang 😎

// IsAnchorChannel returns true if the session policy requires anchor channels.
func (p Policy) IsAnchorChannel() bool {
func (p *Policy) IsAnchorChannel() bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so for this instance (ie, in towers alone) it does actually just mean anchors. So this will return false for a taproot blob type.

Yeah I do notice that the feature bit is 101 and 11, tho not sure about how to properly define a feature bit, as it seems that technically if anchor is a feature, then taproot chan should be 111 since it has this feature - unknown implications here, but I prefer the end result here as we can clearly distinguish the two channels. Meanwhile this shouldn't be an issue for feature negotiation since both are lnd? I think if both sides understand and use the same defined feature bits we are fine, eg, they won't send us a 111.

@ellemouton ellemouton merged commit 0a29b37 into lightningnetwork:master Jan 19, 2024
24 of 25 checks passed
@ellemouton ellemouton deleted the taprootTowers branch January 19, 2024 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 MUST be fixed or reviewed taproot chans watchtower
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

6 participants