Skip to content

Conversation

cfromknecht
Copy link
Contributor

This PR introduces the watchtower/lookout package, which handles the responsibility of monitoring the chain for possible breaches and responding by decrypting and broadcasting any justice transactions that its clients had previously uploaded. Together with the watchtower/server, which receives and stores encrypted blobs from clients, this represents that second primary service enabling the tower to act on behalf of the tower's clients.

At a high level, the lookout service receives input via two sources: block events and it's database. Incoming state updates are continually written to the database, and are made available to the lookout as soon as the tower successfully persists the encrypted blob. As new blocks come in, the tower searches for any breach hints matching the txid prefixes contained in the newly found block. If any matches are generated from the query, the lookout service will dispatch an attempt to decrypt and sweep the transaction on behalf of the user.

Some slight modifications have been made to the watchtower/blob package, most notably:

  • introducing support for padded sweep adresses
  • properly generating DER-encoded signatures for use in breach input witness stacks

Some open questions:

  • What is the ideal reward function for the tower? Currently only a proportional cut is taken, though perhaps a base + proportional is more suitable. As such, some edge cases around how to handle dust outputs are not accounted for in this PR. The intention is to revist these edge cases after some feedback and when finishing up full persistence in the watchtower/wtdb package.
  • Should we apply any sort of input/output sorting (a la BIP69) to the justice transactions? It is certainly possible, though would be interested in hearing thoughts on whether it's necessary considering the justice transactions are somewhat identifiable anyway.

Builds on #2122

@Roasbeef Roasbeef added enhancement Improvements to existing features / behaviour safety General label for issues/PRs related to the safety of using the software security General label for issues/PRs related to the security of the software watchtower P2 should be fixed if one has time labels Oct 31, 2018
This commit fixes an issue with the witness stack
construction for to-local and to-remote inputs,
that would cause the justice kit to return
signatures as fixed-size, 64-byte signatures.
The correct behavior is to return DER-encoded
signatures so that they will properly verify on
the network, since the consensus rules won't
be able to understand the fixed-size variant.
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.

One small step for lnd, one giant leap for the Lightning Network! ⚡️🚀

I've completed an initial pass, will likely do another to cover the set of unit tests added. The only major comment concerns the nonce generation. I'm a bit weary of using a sequence based nonce, as it puts a lot of responsibility on the client to ensure it doesn't send with a duplicate nonce lest it leaks plaintext blobs.

Copy link
Member

Choose a reason for hiding this comment

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

API design level comment: blob isn't the most descriptive name for a package. It's possible to ensure isolation at the unit test level, yet still intermingle components within a unified package.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure what you mean by the last comment, can you explain?

Copy link
Member

Choose a reason for hiding this comment

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

What measures will we take on the client side in order to ensure this never happens? It seems certain fault cases on the client side could possibly cause it to re-encrypt with the same nonce sequence.

As an alternative, we can use randomized 192-bit (24 byte) nonce. I'm planning to go this route with the encrypted static backups. The chacha API in crypto/x also exposes an variant with larger nonces: https://godoc.org/golang.org/x/crypto/chacha20poly1305#NewX

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice! Wasn't aware that the 192-bit variant was exposed, I agree the randomization is the safer approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

with the existing nonce generation, the protections would be to use truly ephemeral keys (instead of HD keys) and to persist an encrypted update under for the session/seqnum so it can be resent on startup. arguably the first should still be done with a randomized nonce, though it does simplify the latter at the expense of tower storage

Copy link
Member

Choose a reason for hiding this comment

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

Method name doesn't mach the godoc comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

Copy link
Member

Choose a reason for hiding this comment

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

Why not give it the entire block? As is, the block epochs just contain height+hash. If we give this method the entire block, then we don't require it to do any network I/O, and also it can be extended to batch search blocks.

On the second parameter: doesn't the database know the entire set of breach hints? So we can simplify to just take a set of blocks?

To be correct, a breach hint should be provided for each transaction included at the provided block epoch.
So we call this once we already know that the set of transactions has a breach within the block?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This just a database query, there's no network I/O here. The breach hints passed in are constructed from the block, though they could be constructed from multiple blocks.

The block epoch is passed just so that the database can record the last processed block height, so after startup it knows where to begin searching. i'm thinking about just making this a separate db call though.

Copy link
Member

Choose a reason for hiding this comment

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

Why not just use something like:

Suggested change
// EpochSource delivers an in-order stream of blocks as they are seen on the
type EpochSource interface {
RegisterBlockEpochNtfn(*BlockEpoch) (*BlockEpochEvent, error)
Start() error
Stop() error
}

So a simplified interface that includes only the methods of the greater ChainNotifier interface that we actually care about.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure i follow, are you suggesting we'd pass in the notifier? at this point, it will have already been started and it's lifecycle would be tied to the watchtower

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i removed the epoch stream entirely, so that block fetching happens w/in the lookout. i think the testabilty is roughly equivalent, but spares a lot of code duplication!

Copy link
Member

Choose a reason for hiding this comment

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

Spend tracking?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

just a reminder to add persistent tracking of published justice txns and then monitor for spends to see if ours confirms or not. I've updated the comment to be more precise

Copy link
Member

Choose a reason for hiding this comment

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

Seems important? Otherwise, it'll keep attempting to re-broadcast on restart?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we won't rebroadcast at the moment, but these should be implemented together in a following PR

Copy link
Member

Choose a reason for hiding this comment

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

So it'll rescan all blocks since the last time a breached happend? Seems a bit wasteful, and instead we can rescan blocks based on the session height of a client to ensure that we don't miss any breaches that might've happend while they were down, just in case they missed a blob send.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it'll rescan since the last epoch that caused a db query

Copy link
Member

Choose a reason for hiding this comment

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

Similar Q as earlier: we shouldn't need to?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

Copy link
Member

Choose a reason for hiding this comment

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

Why vars? (here and below)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

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 🧬

@Roasbeef Roasbeef merged commit 2f0bc5c into lightningnetwork:master Nov 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improvements to existing features / behaviour P2 should be fixed if one has time safety General label for issues/PRs related to the safety of using the software security General label for issues/PRs related to the security of the software watchtower
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants