You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Req+check payment secrets for inbound payments pre-PaymentReceived
Our current PaymentReceived API is incredibly easy to mis-use -
the "obvious" way to implement a client is to always call
`ChannelManager::claim_funds` in response to a `PaymentReceived`
event. However, users are *required* to check the payment secret
and value against the expected values before claiming in order to
avoid a number of potentially funds-losing attacks.
Instead, if we rely on payment secrets being pre-registered with
the ChannelManager before we receive HTLCs for a payment we can
simply check the payment secrets and never generate
`PaymentReceived` events if they do not match. Further, when the
user knows the value to expect in advance, we can have them
register it as well, allowing us to check it for them.
Other implementations already require payment secrets for inbound
payments, so this shouldn't materially lose compatibility.
let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
1998
+
.or_insert(Vec::new());
1999
+
htlcs.push(claimable_htlc);
2000
+
for htlc in htlcs.iter(){
2001
+
total_value += htlc.value;
2002
+
if htlc.payment_data.total_msat != payment_data.total_msat{
2003
+
total_value = msgs::MAX_VALUE_MSAT;
2004
+
}
2005
+
if total_value >= msgs::MAX_VALUE_MSAT{break;}
2006
+
}
2007
+
if total_value >= msgs::MAX_VALUE_MSAT || total_value > payment_data.total_msat{
2008
+
log_trace!(self.logger,"Failing HTLCs with payment_hash {} as the total value {} ran over expected value {}", log_bytes!(payment_hash.0), total_value, payment_data.total_msat);
2009
+
for htlc in htlcs.iter(){
2010
+
fail_htlc!(htlc);
2011
+
}
2012
+
}elseif total_value == payment_data.total_msat{
2013
+
// Only ever generate at most one PaymentReceived
2014
+
// per registered payment_hash, even if it isn't
2015
+
// claimed.
2016
+
inbound_payment.remove_entry();
2017
+
new_events.push(events::Event::PaymentReceived{
2018
+
payment_hash,
2019
+
payment_secret:Some(payment_data.payment_secret),
2020
+
amt: total_value,
2021
+
});
2022
+
}
2023
+
}
2024
+
},
2025
+
};
1997
2026
},
1998
2027
HTLCForwardInfo::AddHTLC{ .. } => {
1999
2028
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
Copy file name to clipboardExpand all lines: lightning/src/ln/onion_route_tests.rs
+5-2Lines changed: 5 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -268,9 +268,8 @@ fn test_onion_failure() {
268
268
}
269
269
let channels = [create_announced_chan_between_nodes(&nodes,0,1,InitFeatures::known(),InitFeatures::known()),create_announced_chan_between_nodes(&nodes,1,2,InitFeatures::known(),InitFeatures::known())];
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
272
271
let logger = test_utils::TestLogger::new();
273
-
let route = get_route(&nodes[0].node.get_our_node_id(),&net_graph_msg_handler.network_graph.read().unwrap(),&nodes[2].node.get_our_node_id(),Some(InvoiceFeatures::known()),None,&Vec::new(),40000,TEST_FINAL_CLTV,&logger).unwrap();
272
+
let route = get_route(&nodes[0].node.get_our_node_id(),&nodes[0].net_graph_msg_handler.network_graph.read().unwrap(),&nodes[2].node.get_our_node_id(),Some(InvoiceFeatures::known()),None,&Vec::new(),40000,TEST_FINAL_CLTV,&logger).unwrap();
0 commit comments