Skip to content

Commit 3460250

Browse files
wip
1 parent 32f98e4 commit 3460250

File tree

8 files changed

+469
-202
lines changed

8 files changed

+469
-202
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,11 +2063,57 @@ where
20632063
}
20642064
}
20652065

2066-
fn construct_recv_pending_htlc_info(&self, hop_data: msgs::OnionHopData, shared_secret: [u8; 32],
2066+
fn construct_fwd_pending_htlc_info(
2067+
&self, curr_packet_pubkey: PublicKey, hop_data: msgs::InboundPayload, hop_hmac: [u8; 32],
2068+
new_packet_bytes: [u8; onion_utils::ONION_DATA_LEN], shared_secret: [u8; 32],
2069+
payment_hash: PaymentHash, amt_msat: u64, cltv_expiry: u32
2070+
) -> Result<PendingHTLCInfo, ReceiveError> {
2071+
let outgoing_packet = msgs::OnionPacket {
2072+
version: 0,
2073+
public_key: onion_utils::next_hop_packet_pubkey(&self.secp_ctx, curr_packet_pubkey, &shared_secret),
2074+
hop_data: new_packet_bytes,
2075+
hmac: hop_hmac,
2076+
};
2077+
2078+
let (short_channel_id, amt_to_forward, outgoing_cltv_value) = match hop_data {
2079+
msgs::InboundPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } =>
2080+
(short_channel_id, amt_to_forward, outgoing_cltv_value),
2081+
msgs::InboundPayload::Receive { .. } =>
2082+
return Err(ReceiveError {
2083+
msg: "Final Node OnionHopData provided for us as an intermediary node",
2084+
err_code: 0x4000 | 22,
2085+
err_data: vec![],
2086+
}),
2087+
_ => todo!()
2088+
};
2089+
2090+
Ok(PendingHTLCInfo {
2091+
routing: PendingHTLCRouting::Forward {
2092+
onion_packet: outgoing_packet,
2093+
short_channel_id,
2094+
},
2095+
payment_hash,
2096+
incoming_shared_secret: shared_secret,
2097+
incoming_amt_msat: Some(amt_msat),
2098+
outgoing_amt_msat: amt_to_forward,
2099+
outgoing_cltv_value,
2100+
})
2101+
}
2102+
2103+
fn construct_recv_pending_htlc_info(&self, hop_data: msgs::InboundPayload, shared_secret: [u8; 32],
20672104
payment_hash: PaymentHash, amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>) -> Result<PendingHTLCInfo, ReceiveError>
20682105
{
2106+
let (amt_to_forward, outgoing_cltv_value) = match hop_data {
2107+
msgs::InboundPayload::Receive { amt_to_forward, outgoing_cltv_value, .. } => (amt_to_forward, outgoing_cltv_value),
2108+
_ =>
2109+
return Err(ReceiveError {
2110+
err_code: 0x4000|22,
2111+
err_data: Vec::new(),
2112+
msg: "Got non final data with an HMAC of 0",
2113+
}),
2114+
};
20692115
// final_incorrect_cltv_expiry
2070-
if hop_data.outgoing_cltv_value != cltv_expiry {
2116+
if outgoing_cltv_value != cltv_expiry {
20712117
return Err(ReceiveError {
20722118
msg: "Upstream node set CLTV to the wrong value",
20732119
err_code: 18,
@@ -2082,7 +2128,7 @@ where
20822128
// payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
20832129
// channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
20842130
let current_height: u32 = self.best_block.read().unwrap().height();
2085-
if (hop_data.outgoing_cltv_value as u64) <= current_height as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
2131+
if (outgoing_cltv_value as u64) <= current_height as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
20862132
let mut err_data = Vec::with_capacity(12);
20872133
err_data.extend_from_slice(&amt_msat.to_be_bytes());
20882134
err_data.extend_from_slice(&current_height.to_be_bytes());
@@ -2091,23 +2137,16 @@ where
20912137
msg: "The final CLTV expiry is too soon to handle",
20922138
});
20932139
}
2094-
if hop_data.amt_to_forward > amt_msat {
2140+
if amt_to_forward > amt_msat {
20952141
return Err(ReceiveError {
20962142
err_code: 19,
20972143
err_data: amt_msat.to_be_bytes().to_vec(),
20982144
msg: "Upstream node sent less than we were supposed to receive in payment",
20992145
});
21002146
}
21012147

2102-
let routing = match hop_data.format {
2103-
msgs::OnionHopDataFormat::NonFinalNode { .. } => {
2104-
return Err(ReceiveError {
2105-
err_code: 0x4000|22,
2106-
err_data: Vec::new(),
2107-
msg: "Got non final data with an HMAC of 0",
2108-
});
2109-
},
2110-
msgs::OnionHopDataFormat::FinalNode { payment_data, keysend_preimage } => {
2148+
let routing = match hop_data {
2149+
msgs::InboundPayload::Receive { payment_data, keysend_preimage, .. } => {
21112150
if payment_data.is_some() && keysend_preimage.is_some() {
21122151
return Err(ReceiveError {
21132152
err_code: 0x4000|22,
@@ -2117,7 +2156,7 @@ where
21172156
} else if let Some(data) = payment_data {
21182157
PendingHTLCRouting::Receive {
21192158
payment_data: data,
2120-
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
2159+
incoming_cltv_expiry: outgoing_cltv_value,
21212160
phantom_shared_secret,
21222161
}
21232162
} else if let Some(payment_preimage) = keysend_preimage {
@@ -2137,7 +2176,7 @@ where
21372176

21382177
PendingHTLCRouting::ReceiveKeysend {
21392178
payment_preimage,
2140-
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
2179+
incoming_cltv_expiry: outgoing_cltv_value,
21412180
}
21422181
} else {
21432182
return Err(ReceiveError {
@@ -2147,14 +2186,15 @@ where
21472186
});
21482187
}
21492188
},
2189+
_ => todo!()
21502190
};
21512191
Ok(PendingHTLCInfo {
21522192
routing,
21532193
payment_hash,
21542194
incoming_shared_secret: shared_secret,
21552195
incoming_amt_msat: Some(amt_msat),
21562196
outgoing_amt_msat: amt_msat,
2157-
outgoing_cltv_value: hop_data.outgoing_cltv_value,
2197+
outgoing_cltv_value,
21582198
})
21592199
}
21602200

@@ -2229,32 +2269,10 @@ where
22292269
}
22302270
},
22312271
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
2232-
let new_pubkey = msg.onion_routing_packet.public_key.unwrap();
2233-
let outgoing_packet = msgs::OnionPacket {
2234-
version: 0,
2235-
public_key: onion_utils::next_hop_packet_pubkey(&self.secp_ctx, new_pubkey, &shared_secret),
2236-
hop_data: new_packet_bytes,
2237-
hmac: next_hop_hmac.clone(),
2238-
};
2239-
2240-
let short_channel_id = match next_hop_data.format {
2241-
msgs::OnionHopDataFormat::NonFinalNode { short_channel_id } => short_channel_id,
2242-
msgs::OnionHopDataFormat::FinalNode { .. } => {
2243-
return_err!("Final Node OnionHopData provided for us as an intermediary node", 0x4000 | 22, &[0;0]);
2244-
},
2245-
};
2246-
2247-
PendingHTLCStatus::Forward(PendingHTLCInfo {
2248-
routing: PendingHTLCRouting::Forward {
2249-
onion_packet: outgoing_packet,
2250-
short_channel_id,
2251-
},
2252-
payment_hash: msg.payment_hash.clone(),
2253-
incoming_shared_secret: shared_secret,
2254-
incoming_amt_msat: Some(msg.amount_msat),
2255-
outgoing_amt_msat: next_hop_data.amt_to_forward,
2256-
outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
2257-
})
2272+
match self.construct_fwd_pending_htlc_info(msg.onion_routing_packet.public_key.unwrap(), next_hop_data, next_hop_hmac, new_packet_bytes, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry) {
2273+
Ok(info) => PendingHTLCStatus::Forward(info),
2274+
Err(ReceiveError { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
2275+
}
22582276
}
22592277
};
22602278

@@ -2465,15 +2483,15 @@ where
24652483
self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv_bytes)
24662484
}
24672485

2468-
fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>, session_priv_bytes: [u8; 32]) -> Result<(), APIError> {
2486+
fn send_payment_along_path(&self, path: &Path, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>, session_priv_bytes: [u8; 32]) -> Result<(), APIError> {
24692487
// The top-level caller should hold the total_consistency_lock read lock.
24702488
debug_assert!(self.total_consistency_lock.try_write().is_err());
24712489

2472-
log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id);
2490+
log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.hops.first().unwrap().short_channel_id);
24732491
let prng_seed = self.entropy_source.get_secure_random_bytes();
24742492
let session_priv = SecretKey::from_slice(&session_priv_bytes[..]).expect("RNG is busted");
24752493

2476-
let onion_keys = onion_utils::construct_onion_keys(&self.secp_ctx, &path, &session_priv)
2494+
let onion_keys = onion_utils::construct_onion_keys(&self.secp_ctx, &path.hops, &session_priv)
24772495
.map_err(|_| APIError::InvalidRoute{err: "Pubkey along hop was maliciously selected".to_owned()})?;
24782496
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, payment_secret, cur_height, keysend_preimage)?;
24792497
if onion_utils::route_size_insane(&onion_payloads) {
@@ -2482,7 +2500,7 @@ where
24822500
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, prng_seed, payment_hash);
24832501

24842502
let err: Result<(), _> = loop {
2485-
let (counterparty_node_id, id) = match self.short_to_chan_info.read().unwrap().get(&path.first().unwrap().short_channel_id) {
2503+
let (counterparty_node_id, id) = match self.short_to_chan_info.read().unwrap().get(&path.hops.first().unwrap().short_channel_id) {
24862504
None => return Err(APIError::ChannelUnavailable{err: "No channel available with first hop!".to_owned()}),
24872505
Some((cp_id, chan_id)) => (cp_id.clone(), chan_id.clone()),
24882506
};
@@ -2499,7 +2517,7 @@ where
24992517
let funding_txo = chan.get().get_funding_txo().unwrap();
25002518
let send_res = chan.get_mut().send_htlc_and_commit(htlc_msat, payment_hash.clone(),
25012519
htlc_cltv, HTLCSource::OutboundRoute {
2502-
path: path.clone(),
2520+
path: path.hops.clone(), // TODO do we need to pass in the whole Path?
25032521
session_priv: session_priv.clone(),
25042522
first_hop_htlc_msat: htlc_msat,
25052523
payment_id,

0 commit comments

Comments
 (0)