Skip to content

Fix in checking channel_reserve #189

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

Closed
wants to merge 9 commits into from

Conversation

yuntai
Copy link
Contributor

@yuntai yuntai commented Sep 19, 2018

No description provided.

@@ -2609,8 +2609,8 @@ impl Channel {
if htlc_outbound_value_msat + amount_msat > self.their_max_htlc_value_in_flight_msat {
return Err(HandleError{err: "Cannot send value that would put us over our max HTLC value in flight", action: None});
}
// Check their_channel_reserve_satoshis:
if htlc_inbound_value_msat + htlc_outbound_value_msat + amount_msat + (self.channel_value_satoshis * 1000 - self.value_to_self_msat) > (self.channel_value_satoshis - self.their_channel_reserve_satoshis) * 1000 {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The previous eqn seems double counting htlc_inbound_value_msat and htlc_outbound_value_msat?

@TheBlueMatt
Copy link
Collaborator

Hmm, we definitely need to be subtracting pending HTLCs from the value_to_self_msat here (since any pending HTLCs can't count towards channel reserve and aren't included in value_to_self_msat), though it looks pretty awkward and I'd buy that its wrong. Can you add a test either way?

@yuntai yuntai force-pushed the 201809-channel-reserve branch 2 times, most recently from c8fef0b to a3e103c Compare September 22, 2018 14:30
@yuntai
Copy link
Contributor Author

yuntai commented Sep 25, 2018

Since value_to_self_msat is adjusted when revoke_and_ack'd, when evaluating this condition, value_to_self contains pending outgoing htlc values, so, yes, they need to be subtracted. But pending incoming htlc values have nothing to do with value_to_self_msat at this point.

New conditions are the same except not including value for incoming HTLC to be subtracted from value_to_self_msat. The conditions are just tighter (more money available). Also, I added outgoing value in the pending_cell.

Hard to figure a good test for this.
One thing I could think of is to add debug_assert!(self.value_to_self_msat >= channel_reserve) inside revoke_and_ack(when debited) and make fuzz catch any error.

@TheBlueMatt
Copy link
Collaborator

Hmm, ok, yes, I buy that the new version is correct, but really needs tests. One thing you could do it add a debug_assert in build_commitment_transaction that the finally-calculated value_to_self and value_to_remote match channel reserves (which is broader than revoke_and_ack), though I don't like relying on fuzz testing for that as the full_stack_target is still way too broad to reliably find things like that.

If you did that and also added a number of tests which tested sending one less than and one more than the limit in the ChannelManager network tests (incl various states like awaiting-revoke, etc) then we'd probably be OK.

Testing the holding cell updates is going to be much harder, I think, though, cause free_holding_cell_htlcs handles the error case instead of sending the new HTLC.

}
}

// Check self.their_channel_reserve_satoshis (i.e our channel reserve):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure that that is any more clear...maybe s/our channel reserve/the amount we must keep as reserve for them to have something to claim if we misbehave/?

@yuntai yuntai force-pushed the 201809-channel-reserve branch from a3e103c to af89dc1 Compare October 1, 2018 11:06
@yuntai
Copy link
Contributor Author

yuntai commented Oct 1, 2018

still need another test involving holding cell.

@yuntai
Copy link
Contributor Author

yuntai commented Oct 2, 2018

Testing the holding cell updates is going to be much harder, I think, though, cause free_holding_cell_htlcs handles the error case instead of sending the new HTLC.

I'm not clear about this. HTLCUpdateAwaitingACK::FailHTLC won't be affecting to_self_value_msat ever?
HTLCUpdateAwaitingACK::ClaimHTLC will increase to_self_value_msat later on but including this as + to to_self_value_msat when evaluating channel reserve condition with anticipation that we will get money soon will increase the chance of channel reserve violation error from the remote.

and max_htlc_value_in_flight_msat
@yuntai yuntai force-pushed the 201809-channel-reserve branch from ab13c24 to 0000294 Compare October 2, 2018 07:09
@yuntai
Copy link
Contributor Author

yuntai commented Oct 2, 2018

added a test scenario with holding cell.

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

Nice! Changes look good and I tried to falsify the tests a bit and they caught it.

@@ -2725,7 +2763,7 @@ impl Channel {
return Err(HandleError{err: "Cannot send an HTLC while disconnected", action: Some(ErrorAction::IgnoreError)});
}

let (_, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat) = self.get_pending_htlc_stats(false);
let (_, outbound_htlc_count, htlc_outbound_value_msat, _) = self.get_pending_htlc_stats(false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oops, with this and the change to split up pending_htlcs into two vecs it probably makes sense to get rid of get_pending_htlc_stats - currently all callsites make it iterate over both HTLC vecs but only care about the results from one.

use ln::msgs::HandleError;

macro_rules! get_channel_value_stat {
($node: expr, $channel_id: expr) => {{
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: indentation is wrong around here.

macro_rules! get_route_and_payment_hash {
($recv_value: expr) => {{
let route = nodes[0].router.get_route(&nodes.last().unwrap().node.get_our_node_id(), None, &Vec::new(), $recv_value, TEST_FINAL_CLTV).unwrap();
let payment_preimage = [*nodes[0].network_payment_count.borrow(); 32];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be able to use get_payment_preimage_hash!!

@TheBlueMatt
Copy link
Collaborator

You can also take the change at TheBlueMatt@1f31e03 if you want, its a pretty aggressive check but once it gets adapted to udpate_fee/etc it may make sense to have something more aggressive like that.

@yuntai yuntai force-pushed the 201809-channel-reserve branch from 0000294 to 5f1b366 Compare October 3, 2018 01:18
@yuntai
Copy link
Contributor Author

yuntai commented Oct 3, 2018

Took TheBlueMatt/rust-lightning@1f31e03 and others fixed.

@TheBlueMatt
Copy link
Collaborator

Will take as #206.

@TheBlueMatt TheBlueMatt closed this Oct 6, 2018
TheBlueMatt added a commit that referenced this pull request Oct 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants