+ fn construct_recv_pending_htlc_info(&self, hop_data: msgs::OnionHopData, shared_secret: [u8; 32],
+ payment_hash: PaymentHash, amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>) -> Result<PendingHTLCInfo, ReceiveError>
+ {
+ // final_incorrect_cltv_expiry
+ if hop_data.outgoing_cltv_value != cltv_expiry {
+ return Err(ReceiveError {
+ msg: "Upstream node set CLTV to the wrong value",
+ err_code: 18,
+ err_data: byte_utils::be32_to_array(cltv_expiry).to_vec()
+ })
+ }
+ // final_expiry_too_soon
+ // We have to have some headroom to broadcast on chain if we have the preimage, so make sure
+ // we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
+ // Also, ensure that, in the case of an unknown preimage for the received payment hash, our
+ // payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
+ // channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
+ if (hop_data.outgoing_cltv_value as u64) <= self.best_block.read().unwrap().height() as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
+ return Err(ReceiveError {
+ err_code: 17,
+ err_data: Vec::new(),
+ msg: "The final CLTV expiry is too soon to handle",
+ });
+ }
+ if hop_data.amt_to_forward > amt_msat {
+ return Err(ReceiveError {
+ err_code: 19,
+ err_data: byte_utils::be64_to_array(amt_msat).to_vec(),
+ msg: "Upstream node sent less than we were supposed to receive in payment",
+ });
+ }
+
+ let routing = match hop_data.format {
+ msgs::OnionHopDataFormat::Legacy { .. } => {
+ return Err(ReceiveError {
+ err_code: 0x4000|0x2000|3,
+ err_data: Vec::new(),
+ msg: "We require payment_secrets",
+ });
+ },
+ msgs::OnionHopDataFormat::NonFinalNode { .. } => {
+ return Err(ReceiveError {
+ err_code: 0x4000|22,
+ err_data: Vec::new(),
+ msg: "Got non final data with an HMAC of 0",
+ });
+ },
+ msgs::OnionHopDataFormat::FinalNode { payment_data, keysend_preimage } => {
+ if payment_data.is_some() && keysend_preimage.is_some() {
+ return Err(ReceiveError {
+ err_code: 0x4000|22,
+ err_data: Vec::new(),
+ msg: "We don't support MPP keysend payments",
+ });
+ } else if let Some(data) = payment_data {
+ PendingHTLCRouting::Receive {
+ payment_data: data,
+ incoming_cltv_expiry: hop_data.outgoing_cltv_value,
+ phantom_shared_secret,
+ }
+ } else if let Some(payment_preimage) = keysend_preimage {
+ // We need to check that the sender knows the keysend preimage before processing this
+ // payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
+ // could discover the final destination of X, by probing the adjacent nodes on the route
+ // with a keysend payment of identical payment hash to X and observing the processing
+ // time discrepancies due to a hash collision with X.
+ let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
+ if hashed_preimage != payment_hash {
+ return Err(ReceiveError {
+ err_code: 0x4000|22,
+ err_data: Vec::new(),
+ msg: "Payment preimage didn't match payment hash",
+ });
+ }
+
+ PendingHTLCRouting::ReceiveKeysend {
+ payment_preimage,
+ incoming_cltv_expiry: hop_data.outgoing_cltv_value,
+ }
+ } else {
+ return Err(ReceiveError {
+ err_code: 0x4000|0x2000|3,
+ err_data: Vec::new(),
+ msg: "We require payment_secrets",
+ });
+ }
+ },
+ };
+ Ok(PendingHTLCInfo {
+ routing,
+ payment_hash,
+ incoming_shared_secret: shared_secret,
+ amt_to_forward: amt_msat,
+ outgoing_cltv_value: hop_data.outgoing_cltv_value,
+ })
+ }
+