-
Notifications
You must be signed in to change notification settings - Fork 2.2k
[watchtower/lookout]: on-chain breach monitoring #2124
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
Conversation
dc02c8e
to
b701709
Compare
b701709
to
d9dc2b9
Compare
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.
d9dc2b9
to
4e27940
Compare
There was a problem hiding this 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.
watchtower/wtdb/session_id.go
Outdated
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
watchtower/wtdb/session_id.go
Outdated
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
watchtower/lookout/interface.go
Outdated
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
watchtower/lookout/interface.go
Outdated
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
watchtower/lookout/interface.go
Outdated
There was a problem hiding this comment.
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:
// 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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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!
watchtower/lookout/punisher.go
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spend tracking?
There was a problem hiding this comment.
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
watchtower/lookout/punisher.go
Outdated
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
watchtower/lookout/lookout.go
Outdated
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
watchtower/lookout/lookout.go
Outdated
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
watchtower/lookout/lookout.go
Outdated
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
4e27940
to
bb8cff5
Compare
This commit modifies the blob encryption scheme to use chacha20-poly1305 with a randomized 192-bit nonce. The previous approach used a deterministic nonce scheme, which is being replaced to simplify the requirements of a correct implementation. As a result, each payload gains an addtional 24-bytes prepended to the ciphertext.
The nonce is now passed in as the prefix to the ciphertext, and is generated randomly in calls to Encrypt.
bb8cff5
to
8bc8964
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🧬
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 thewatchtower/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:Some open questions:
watchtower/wtdb
package.Builds on #2122