-
Notifications
You must be signed in to change notification settings - Fork 406
Track the full list of outpoints a chanmon wants monitoring for #455
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
Track the full list of outpoints a chanmon wants monitoring for #455
Conversation
955bed5
to
3125760
Compare
3125760
to
5e11836
Compare
lightning/src/ln/channelmonitor.rs
Outdated
// interface knows about the TXOs that we want to be notified of spends of. We could probably | ||
// be smart and derive them from the above storage fields, but its much simpler and more | ||
// Obviously Correct (tm) if we just keep track of them explicitly. | ||
watch_outputs: HashMap<Sha256dHash, Vec<Script>>, |
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.
nit: watch_outputs
sounds more like a boolean. watched_
or monitored_
might be more explicit
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.
Hmm, I dont want to imply that they are watched, only that they must be watched. Went with outputs_to_watch.
lightning/src/ln/channelmonitor.rs
Outdated
@@ -966,6 +982,15 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> { | |||
} | |||
} | |||
|
|||
(self.watch_outputs.len() as u64).write(writer)?; |
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 is quite the write function. It might be prudent to break it out into subroutines so it's easier to navigate.
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.
Agreed. We should probably implement serialize on subtypes so that we can just call the write derive macro, but its not particularly worse here, just still-bad.
@@ -2589,6 +2621,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> { | |||
} | |||
} | |||
self.last_block_hash = block_hash.clone(); | |||
for &(ref txid, ref output_scripts) in watch_outputs.iter() { |
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.
block_connected could definitely use some comments. Is this a function that's supposed to be called on block connection?
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.
Its called by ManyChannelMonitor::block_connected, which is a https://docs.rs/lightning/0.0.10/lightning/chain/chaininterface/trait.ChainListener.html#tymethod.block_connected . Ideally ChannelMonitor would implement ChainListener too, but we're a ways away from that - #474 implements one step, though it still returns two other values (unlike ChainListener). I'll add a commit that comments this state.
5e11836
to
3c10c69
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.
Hmmm I dunno about adding yet-another field for data we already track elsewhere. On the other side it makes testing really easy because if we reuse existent fields we may have ambiguity on which outputs have been effectively confirmed onchain (like it can be either prev local or last local but not both).
Okay for now, but we'll have to refactor and make sense of all this fields at some point..
/// | ||
/// Further, the implementer must also ensure that each output returned in | ||
/// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about | ||
/// any spends of any of the outputs. |
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 set of outputs correspond to in-channel outputs, i.e any output for which LN-specific state is needed to solve them and faithfully execute the protocol. Any miss in registering them may entrain a fund loss"
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'm not sure it matters what the outputs are...maybe in the future we'll register revokeable outputs (which we don't currently do and just send a SpendableOutput event to the user) so that we can identify if we went backwards. I added a note that you may lose funds if you fail just emphasize that it matters, though.
@@ -259,6 +263,11 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys> Simpl | |||
self.chain_monitor.watch_all_txn(); | |||
} | |||
} | |||
for (txid, outputs) in monitor.get_outputs_to_watch().iter() { | |||
for (idx, script) in outputs.iter().enumerate() { |
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.
Note: enumerate
work right now to get outpoint index because we clone the whole output of tx at parsing but if we start to be more picky (like not-watching output in final state like to_remote) it may break
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.
Right, it would need to change the same as the walk of the return value of block_connected would.
// interface knows about the TXOs that we want to be notified of spends of. We could probably | ||
// be smart and derive them from the above storage fields, but its much simpler and more | ||
// Obviously Correct (tm) if we just keep track of them explicitly. | ||
outputs_to_watch: HashMap<Sha256dHash, Vec<Script>>, |
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.
Have you try to implement this with just returning back Script from remote_commitment_txn_on_chain+prev_local_commitment_tx+current_local_signed_commitment_tx? I think it covers all scripts we care about (well there is also outputs on revoked HTLC-txb but that's a bug we don't track them yet)
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 have not. I was aiming for "quick and easy" given we have a ton of ongoing larger patches and refactors in that area coming up, so landing something complicated would be a waste of time, and a bunch of time. Up to you if you want me to try another way, though.
lightning/src/ln/channelmonitor.rs
Outdated
@@ -2394,6 +2394,10 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> { | |||
} | |||
} | |||
|
|||
/// Called by ChannelMonitor::block_connected, which implements ChainListener::block_connected. |
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.
"Should be called by ManyChannelMonitor implementation"
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.
Sadly, it can't be - its not pub (I have a patch for this, but too many in-flight PRs right now). Its only called by SimpleManyChannelMonitor (which is a typo here, now fixed).
3c10c69
to
af4c5a2
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.
ACK af4c5a2
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.
Deferring to @ariard on the approach given he's refactoring the code. Left some minor comments.
Upon deserialization/reload we need to be able to register each outpoint which spends the commitment txo which a channelmonitor believes to be on chain. While our other internal tracking is likely sufficient to regenerate these, its much easier to simply track all outpouts we've ever generated, so we do that here.
This tests, after each functional test, that if we serialize and reload all of our ChannelMonitors we end up tracking the same set of outputs as before.
af4c5a2
to
5fceb0f
Compare
Address Jeff's comments. Will merge after Travis passes. |
Upon deserialization/reload we need to be able to register each
outpoint which spends the commitment txo which a channelmonitor
believes to be on chain. While our other internal tracking is
likely sufficient to regenerate these, its much easier to simply
track all outpouts we've ever generated, so we do that here.