-
Notifications
You must be signed in to change notification settings - Fork 405
Drop Result for ChannelMessageHandler methods #398
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
I think I like this idea, pending making sure every callsite can actually support this, but why not just do it inside handle_error!()? It seems to me you can just do all the logic we have now, but instead of returning the LightningError, we can just push it as an event (as long as its the last thing that happens during the message processing). |
b8c3a2f
to
d02a615
Compare
493f667
to
a565e9c
Compare
@@ -429,19 +429,21 @@ pub struct ChannelDetails { | |||
} | |||
|
|||
macro_rules! handle_error { | |||
($self: ident, $internal: expr) => { | |||
($self: ident, $internal: expr, $their_node_id: expr, $locked_channel_state: expr) => { |
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, this does end up taking an extra lock in the happy case. Maybe split the macro into handle_error_locked and handle_error_unlocked?
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.
They were 2 callsites where we may don't have an error, modify a bit to avoid superfluous lock tacking if this is the case. Better than yet another error macro
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? No, nearly ever message-handling callsite this is the case?
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.
Ah yeah corrected, it's a bit ugly rn but ofc I'm still planning a dry-up following PR
64d3f58
to
07fc987
Compare
fuzz/src/chanmon_consistency.rs
Outdated
@@ -516,6 +506,10 @@ pub fn do_test(data: &[u8]) { | |||
// Can be generated due to a payment forward being rejected due to a | |||
// channel having previously failed a monitor update | |||
}, | |||
events::MessageSendEvent::HandleError { .. } => { |
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 really needs to check that the error in question is an IgnoreError action, and panic otherwise.
fuzz/src/chanmon_consistency.rs
Outdated
@@ -532,6 +526,7 @@ pub fn do_test(data: &[u8]) { | |||
events::MessageSendEvent::SendChannelReestablish { .. } => {}, | |||
events::MessageSendEvent::SendFundingLocked { .. } => {}, | |||
events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {}, | |||
events::MessageSendEvent::HandleError { .. } => {}, |
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.
Same here - this indicates exactly the type of failure this fuzz target exists to catch.
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.
Oops, still missed this one.
if let Err(msgs::LightningError{err, action: msgs::ErrorAction::IgnoreError }) = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed) { | ||
assert_eq!(err, "Previous monitor update failure prevented generation of RAA"); | ||
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed); | ||
if let MessageSendEvent::HandleError { .. } = nodes[0].node.get_and_clear_pending_msg_events()[0] { |
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.
Can you restore the error-message-checking that was here previously?
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.
Looks like this is still missing the IgnoreError check that was here?
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.
High level looks good but it looks like there were a ton of tests that were removed in this refactor. Can you re-add them (a few are commented, but there appear to be a lot).
7e77375
to
ce12586
Compare
Should be good now, modified Logger trait a bit to access logged lines and so keep test hardness as it is. Also added panic-if-not-IgnoreError in fuzz/src/chanmon_consistency.rs |
Why do you need to extend the visibility of the ChannelManager::logger? Its a shared reference so you should be able to just keep the original copy and check against that, no? |
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 still a little confused about a few of the changes here, sadly. Also see the previous comment about the new logger.
lightning/src/ln/channelmanager.rs
Outdated
Err(APIError::ChannelUnavailable { err: e.err }) | ||
}, | ||
{ | ||
let mut channel_lock = self.channel_state.lock().unwrap(); |
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: just extend the above lock to include this chunk. No reason to release and retake for one if statement in the happy path.
match handle_error!(self, err) { | ||
Ok(_) => unreachable!(), | ||
Err(e) => { | ||
if let msgs::ErrorAction::IgnoreError = e.action { |
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, there's a bunch of places where we match out IgnoreError and don't generate a HandleError event when we're returning an APIError anyway (so they user already saw it, no need to pass it through to peer_handler), but that didn't make it over here. Can you re-enable that somehow? (maybe leave the if, or maybe add a wrapper macro).
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.
IIRC, that was quite intentional. Because you do want to log error even if it's a IgnoreError one but then was planning in further commit to match it out in the handle_error macro to avoid passing for nothing to peer_handler. I think that's good for now to pass it to peer_handler, it's just logged and ignored..
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.
No? The IgnoreErrors that are generated today are all things where you didn't already get back an APIError directly (as the user). There is no need to send duplicative errors (though logging them is, of course, fine IMO).
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 think there is already duplicative errors right now in send_payment/update_fee for the non-IgnoreError cases? Inside handle_error, you don't know if an APIError is going to be returned, so for not generating a HandleError when we're returning an APIError anyway I need to filter out all IgnoreError, and so modify test in consequence again ?
if let Err(msgs::LightningError{err, action: msgs::ErrorAction::IgnoreError }) = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed) { | ||
assert_eq!(err, "Previous monitor update failure prevented generation of RAA"); | ||
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed); | ||
if let MessageSendEvent::HandleError { .. } = nodes[0].node.get_and_clear_pending_msg_events()[0] { |
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.
Looks like this is still missing the IgnoreError check that was here?
if let msgs::LightningError { err, action: msgs::ErrorAction::IgnoreError } = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &updates.commitment_signed).unwrap_err() { | ||
assert_eq!(err, "Failed to update ChannelMonitor"); | ||
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &updates.commitment_signed); | ||
if let MessageSendEvent::HandleError { .. } = nodes[0].node.get_and_clear_pending_msg_events()[0] { |
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.
Same here as above - why not keep the IgnoreError and message-in-HandleError check that was here (in addition to the new log message tests)?
ce12586
to
fa6f891
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.
Oops, there's still quite a few things worth fixing here, IMO. No need to break things "to fix them in a later followup".
fuzz/src/chanmon_consistency.rs
Outdated
@@ -532,6 +526,7 @@ pub fn do_test(data: &[u8]) { | |||
events::MessageSendEvent::SendChannelReestablish { .. } => {}, | |||
events::MessageSendEvent::SendFundingLocked { .. } => {}, | |||
events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {}, | |||
events::MessageSendEvent::HandleError { .. } => {}, |
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.
Oops, still missed this one.
lightning/src/util/logger.rs
Outdated
@@ -119,6 +119,8 @@ impl<'a> Record<'a> { | |||
pub trait Logger: Sync + Send { | |||
/// Logs the `Record` | |||
fn log(&self, record: &Record); | |||
/// Assert log count (used to harden test) | |||
fn assert_log(&self, module: String, line: String, count: usize); |
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.
Oof, please dont expose a testing-only method in the public interface.
fuzz/src/chanmon_consistency.rs
Outdated
@@ -565,6 +570,7 @@ pub fn do_test(data: &[u8]) { | |||
}, | |||
events::MessageSendEvent::SendFundingLocked { .. } => false, | |||
events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => false, | |||
events::MessageSendEvent::HandleError { .. } => false, |
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.
Oops, should also check this one for IgnoreError
fuzz/src/chanmon_consistency.rs
Outdated
events::MessageSendEvent::HandleError { action, .. } => { | ||
// Can be generated at any processing step to send back an error, disconnect | ||
// peer or just ignore | ||
match action { |
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 that these could be significantly more succinct with just a match for events::MessageSendEvent::HandleError { action: ErrorAction::IgnoreError, .. } instead of a general one.
if let Err(msgs::LightningError{err, action: msgs::ErrorAction::IgnoreError }) = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed) { | ||
assert_eq!(err, "Previous monitor update failure prevented generation of RAA"); | ||
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed); | ||
if let MessageSendEvent::HandleError { ref action, .. } = nodes[0].node.get_and_clear_pending_msg_events()[0] { |
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 (and in many other places) only checks the first error, if there are more than one.
match handle_error!(self, err) { | ||
Ok(_) => unreachable!(), | ||
Err(e) => { | ||
if let msgs::ErrorAction::IgnoreError = e.action { |
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.
No? The IgnoreErrors that are generated today are all things where you didn't already get back an APIError directly (as the user). There is no need to send duplicative errors (though logging them is, of course, fine IMO).
cc422e8
to
4837917
Compare
Extend mock Node with logger.
Simplify interfaces between ChannelMessageHandler and PeerManager, by switching all ChannelMessageHandler errors to HandleError sent internally instead of being return. With further refactors in Router and PeerChannelEncryptor, errors management on the PeerManager-side won't be splitted between try_potential_handleerror and HandleError processing. Inside ChannelManager, we now log MsgHandleErrInternal and send ErrorAction to PeerManager. On a high-level, it should allow client using API to be more flexible by polling events instead of waiting function call returns. We also update handle_error macro to take channel_state_lock from caller which should avoid some deadlock potential for some edges cases. Filter out IgnoreError in handle_error macro, update test in consequence.
4837917
to
a15ec7a
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.
Will take as #439 with the following nits changed.
@@ -1116,71 +1119,62 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> { | |||
|
|||
let _ = self.total_consistency_lock.read().unwrap(); | |||
|
|||
let err: Result<(), _> = loop { | |||
{ |
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, the new scope here is unnecessary.
@@ -1197,8 +1191,8 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> { | |||
let _ = self.total_consistency_lock.read().unwrap(); | |||
|
|||
let (mut chan, msg, chan_monitor) = { | |||
let mut channel_state = self.channel_state.lock().unwrap(); | |||
let (res, chan) = { |
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 scope can go away now that its not releasing the lock.
let mut channel_state_lock = self.channel_state.lock().unwrap(); | ||
for (their_node_id, err) in handle_errors.drain(..) { | ||
match handle_error!(self, err, their_node_id, channel_state_lock) { | ||
Ok(_) => {}, |
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.
Dummy match?
Err(APIError::APIMisuseError { err: e.err }) | ||
}, | ||
{ | ||
let mut channel_state_lock = self.channel_state.lock().unwrap(); |
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.
No need to drop the lock before here and add a new scope.
let res = self.internal_open_channel(their_node_id, their_local_features, msg); | ||
if res.is_err() { | ||
let mut channel_state_lock = self.channel_state.lock().unwrap(); | ||
if let Err(_) = handle_error!(self, res, *their_node_id, channel_state_lock) {} |
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 can be a bit more succinct with just let _ = handle_error!().
commitment_signed_dance!(nodes[1], nodes[2], payment_event.commitment_msg, false); | ||
|
||
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure); | ||
expect_pending_htlcs_forwardable!(nodes[1]); | ||
check_added_monitors!(nodes[1], 1); | ||
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); |
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.
lol you added an extra line to do the same thing :(. Also, there's a bunch of let msg_events = ... assert!(msg_events.len(), 0) that could be rewritten as just a .is_empty().
} | ||
} else { panic!(); } | ||
|
||
assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); |
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, seem to have lost this?
@@ -491,8 +495,8 @@ macro_rules! commitment_signed_dance { | |||
}; | |||
check_added_monitors!($node_b, 1); | |||
if $fail_backwards { | |||
assert!($node_a.node.get_and_clear_pending_events().is_empty()); | |||
assert!($node_a.node.get_and_clear_pending_msg_events().is_empty()); | |||
//assert!($node_a.node.get_and_clear_pending_events().is_empty()); |
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.
Looks like you didn't finish working on this?
let msgs::ErrorMessage {ref channel_id, ..} = msg; | ||
assert_eq!(*channel_id, chan_1.2); | ||
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &node_0_2nd_reestablish); | ||
if let MessageSendEvent::HandleError { ref action, .. } = nodes[1].node.get_and_clear_pending_msg_events()[0] { |
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 check that there's only one msg event here.
if let &MessageSendEvent::HandleError { ref action, .. } = handle_error { | ||
match action { | ||
&ErrorAction::SendErrorMessage { ref msg } => { | ||
assert_eq!(msg.data, "Remote HTLC add would put them over their reserve value"); |
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.
You can DRY this pattern up a ton (and fix a few cases where you forgot the trailing } else { panic!() }) by moving these matches into the macro.
Further work to simplify our error management by removing ChannelMessageHandler errors and instead sending back HandleError for the P2PHandler.
If user, need more errors we should return APIErrors, but at least we should be have a clear distinction between errors for the user and errors sent to the peer.