Skip to content

watchtower: anchor channel support#4782

Merged
Roasbeef merged 15 commits into
lightningnetwork:masterfrom
cfromknecht:anchor-wtserver
Dec 1, 2020
Merged

watchtower: anchor channel support#4782
Roasbeef merged 15 commits into
lightningnetwork:masterfrom
cfromknecht:anchor-wtserver

Conversation

@cfromknecht
Copy link
Copy Markdown
Contributor

@cfromknecht cfromknecht commented Nov 18, 2020

This PR adds watchtower client support for anchor channels. Previously, no backup
was attempted for anchor channels meaning that, under certain breach scenarios, they
are more vulnerable then the legacy channels. This PR resolves this lingering gap in the
security features lnd offers for the two channel types, making the security of anchor
channels equal or better than the legacy channel type across the relevant dimensions.
This gives us the confidence to make anchor channels the default channel type in 0.12
since it offers a universal improvement to our users regardless of their node configuration.

Summary of changes:

  • adds a new blob.FlagAnchorChannel bit communicated during session negotiation
  • modifies the wtclient's signing logic to generate valid signatures for anchor justice txns
  • adds wtwire.AnchorCommit feature bits for determining client/server feature support
  • adds separate AnchorTowerClient for anchor channels to use to back up their states. this
    allows us to reuse most of the existing tower logic without needing to add a greater degree of
    multiplexing internally
  • exposes both the legacy TowerClient and AnchorTowerClient via rpc

TODO:

  • add wtclient unit test cases
  • stricter feature bit/blob type assertions in wtserver
  • move remainder of wtclient package over to prefix logging
  • lncli integration

Builds on #4781

@cfromknecht cfromknecht added this to the 0.12.0 milestone Nov 18, 2020
@cfromknecht cfromknecht changed the title Anchor wtserver watchtower: anchor channel support Nov 18, 2020
Copy link
Copy Markdown
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.

First pass, need to revisit the codebase as a whole before the second pass as it's been a while since I've reviewed code in this area. At a high level though, I think the duplicate client route in the short-term makes the set of changes quite easy to follow, and it can eventually be generalized to a specific channel for each possibly future channel type.

Comment thread htlcswitch/interfaces.go Outdated
Comment thread watchtower/wtclient/backup_task_internal_test.go Outdated
Comment thread watchtower/wtclient/backup_task.go Outdated
Comment thread htlcswitch/link.go Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Alternatively, this could be abstracted to use something similar to the session filter higher level function: the link calls something like TowerClient(chanType) and has that return the proper tower client. Once we also add more commitment types, this'll allow the link to be less cluttered by this selection logic.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i was also thinking of another approach, where the peer selects the appropriate tower client to give to the link. since the two clients share the same interface, the link can be completely unaware as to which is the underlying. main benefit would be less code changes in the link and no function invocation overhead

Comment thread lnrpc/wtclientrpc/wtclient.proto Outdated
Copy link
Copy Markdown
Contributor

@halseth halseth left a comment

Choose a reason for hiding this comment

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

quick first pass

Comment thread watchtower/wtclient/backup_task.go Outdated
Comment thread watchtower/wtclient/backup_task.go Outdated
Comment thread watchtower/wtclient/backup_task_internal_test.go Outdated
Comment thread server.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what is the reason we need it to be separate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Currently each "client" has a full pipeline that is capable of processing backups for a specific channel type, each maintains its own set tower candidates/state machines/session queues/etc. The option was either to multiplex inside the client, but that seemed pretty invasive and more risky given that the full flow operates pretty reliably today. We decided to go with the approach of just spinning up two separate clients so that each is fully isolated and we know their wont be any unexpected bugs introduced there.

Down the road, the goal would be to add another layer of multiplexing between the links and the "clients", which facilitates sending channel updates to the correct pipelines. For now since we only have two, it is easier just to expose the multiplexing in the link/peer. However, as we start to add more channel types, e.g. anchor-zero-fee-htlc, anchor-taproot, etc, we plan on circling back so that lnd just sees one unified megaclient that handles everything under the hood.

Comment thread htlcswitch/link.go Outdated
Copy link
Copy Markdown
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.

Changes looking really solid now! Main thing I want to do before merge is update my own client to get a feel for if we're missing anything UX wise on the CLI with the new set of commands.

LGTM ☄️

Comment thread watchtower/wtclient/backup_task.go
Comment thread peer/brontide.go
Comment thread lnrpc/wtclientrpc/wtclient.proto
Comment thread lntest/itest/lnd_test.go
Copy link
Copy Markdown
Contributor

@halseth halseth left a comment

Choose a reason for hiding this comment

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

Looks very good! Just a few questions really, otherwise this LGTM 💯

// transactions.
if t.chanType.HasAnchors() {
weightEstimate.AddWitnessInput(
input.ToLocalPenaltyWitnessSize,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, yeah this is something I must keep in mind when changing weight estimate constants: #4775

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah, definitely a little subtle that some of these are now fixed params in the wt protocol. will double check that #4775 doesn't touch any of the required constants for anchors

Comment thread htlcswitch/link.go
Comment thread peer/brontide.go

chanType := lnChan.State().ChanType

// Select the appropriate tower client based on the channel type. It's
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice 😀

Comment thread subrpcserver_config.go
subCfgValue := extractReflectValue(subCfg)

if towerClient != nil {
if towerClient != nil && anchorTowerClient != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why &&? Because none or both are active?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah, currently it's only possible to activate both. we could do them separately if we think that's better

/*
The client type from which to retrieve the active offering policy.
*/
PolicyType policy_type = 1;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could instead return a list of all active policies?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the only way you can distinguish them atm would be to parse the blob-type feature bits, which seems less user friendly imo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants