Skip to content

Commit 03d84cb

Browse files
Refactor out decode_next_hop util from ChannelManager::decode_update_add_htlc
This will be used in upcoming commit(s) to facilitate decoding multiple onion layers for multi-node payment receive
1 parent 369fbda commit 03d84cb

File tree

2 files changed

+210
-163
lines changed

2 files changed

+210
-163
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 110 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,10 @@ use bitcoin::blockdata::transaction::Transaction;
2323
use bitcoin::blockdata::constants::genesis_block;
2424
use bitcoin::network::constants::Network;
2525

26-
use bitcoin::hashes::{Hash, HashEngine};
27-
use bitcoin::hashes::hmac::{Hmac, HmacEngine};
26+
use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine};
27+
use bitcoin::hashes::cmp::fixed_time_eq;
2828
use bitcoin::hashes::sha256::Hash as Sha256;
2929
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
30-
use bitcoin::hashes::cmp::fixed_time_eq;
3130
use bitcoin::hash_types::{BlockHash, Txid};
3231

3332
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
@@ -51,19 +50,19 @@ use ln::msgs::NetAddress;
5150
use ln::onion_utils;
5251
use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT, OptionalField};
5352
use chain::keysinterface::{Sign, KeyMaterial, KeysInterface, KeysManager, InMemorySigner};
53+
use util::chacha20::ChaCha20;
5454
use util::config::UserConfig;
5555
use util::events::{EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
5656
use util::{byte_utils, events};
5757
use util::ser::{BigSize, FixedLengthReader, Readable, ReadableArgs, MaybeReadable, Writeable, Writer};
58-
use util::chacha20::{ChaCha20, ChaChaReader};
5958
use util::logger::{Logger, Level};
6059
use util::errors::APIError;
6160

6261
use io;
6362
use prelude::*;
6463
use core::{cmp, mem};
6564
use core::cell::RefCell;
66-
use io::{Cursor, Read};
65+
use io::Read;
6766
use sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard};
6867
use core::convert::TryInto;
6968
use core::sync::atomic::{AtomicUsize, Ordering};
@@ -1761,7 +1760,6 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
17611760
arr.copy_from_slice(&SharedSecret::new(&msg.onion_routing_packet.public_key.unwrap(), &self.our_network_key)[..]);
17621761
arr
17631762
};
1764-
let (rho, mu) = onion_utils::gen_rho_mu_from_shared_secret(&shared_secret);
17651763

17661764
if msg.onion_routing_packet.version != 0 {
17671765
//TODO: Spec doesn't indicate if we should only hash hop_data here (and in other
@@ -1773,13 +1771,6 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
17731771
return_malformed_err!("Unknown onion packet version", 0x8000 | 0x4000 | 4);
17741772
}
17751773

1776-
let mut hmac = HmacEngine::<Sha256>::new(&mu);
1777-
hmac.input(&msg.onion_routing_packet.hop_data);
1778-
hmac.input(&msg.payment_hash.0[..]);
1779-
if !fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &msg.onion_routing_packet.hmac) {
1780-
return_malformed_err!("HMAC Check failed", 0x8000 | 0x4000 | 5);
1781-
}
1782-
17831774
let mut channel_state = None;
17841775
macro_rules! return_err {
17851776
($msg: expr, $err_code: expr, $data: expr) => {
@@ -1797,164 +1788,122 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
17971788
}
17981789
}
17991790

1800-
let mut chacha = ChaCha20::new(&rho, &[0u8; 8]);
1801-
let mut chacha_stream = ChaChaReader { chacha: &mut chacha, read: Cursor::new(&msg.onion_routing_packet.hop_data[..]) };
1802-
let (next_hop_data, next_hop_hmac): (msgs::OnionHopData, _) = {
1803-
match <msgs::OnionHopData as Readable>::read(&mut chacha_stream) {
1804-
Err(err) => {
1805-
let error_code = match err {
1806-
msgs::DecodeError::UnknownVersion => 0x4000 | 1, // unknown realm byte
1807-
msgs::DecodeError::UnknownRequiredFeature|
1808-
msgs::DecodeError::InvalidValue|
1809-
msgs::DecodeError::ShortRead => 0x4000 | 22, // invalid_onion_payload
1810-
_ => 0x2000 | 2, // Should never happen
1811-
};
1812-
return_err!("Unable to decode our hop data", error_code, &[0;0]);
1813-
},
1814-
Ok(msg) => {
1815-
let mut hmac = [0; 32];
1816-
if let Err(_) = chacha_stream.read_exact(&mut hmac[..]) {
1817-
return_err!("Unable to decode hop data", 0x4000 | 22, &[0;0]);
1818-
}
1819-
(msg, hmac)
1820-
},
1821-
}
1791+
let next_hop = match onion_utils::decode_next_hop(shared_secret, &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac, msg.payment_hash) {
1792+
Ok(res) => res,
1793+
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
1794+
return_malformed_err!(err_msg, err_code);
1795+
},
1796+
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code }) => {
1797+
return_err!(err_msg, err_code, &[0; 0]);
1798+
},
18221799
};
18231800

1824-
let pending_forward_info = if next_hop_hmac == [0; 32] {
1825-
#[cfg(test)]
1826-
{
1827-
// In tests, make sure that the initial onion pcket data is, at least, non-0.
1828-
// We could do some fancy randomness test here, but, ehh, whatever.
1829-
// This checks for the issue where you can calculate the path length given the
1830-
// onion data as all the path entries that the originator sent will be here
1831-
// as-is (and were originally 0s).
1832-
// Of course reverse path calculation is still pretty easy given naive routing
1833-
// algorithms, but this fixes the most-obvious case.
1834-
let mut next_bytes = [0; 32];
1835-
chacha_stream.read_exact(&mut next_bytes).unwrap();
1836-
assert_ne!(next_bytes[..], [0; 32][..]);
1837-
chacha_stream.read_exact(&mut next_bytes).unwrap();
1838-
assert_ne!(next_bytes[..], [0; 32][..]);
1839-
}
1840-
1841-
// OUR PAYMENT!
1842-
// final_expiry_too_soon
1843-
// We have to have some headroom to broadcast on chain if we have the preimage, so make sure
1844-
// we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
1845-
// Also, ensure that, in the case of an unknown preimage for the received payment hash, our
1846-
// payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
1847-
// channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
1848-
if (msg.cltv_expiry as u64) <= self.best_block.read().unwrap().height() as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
1849-
return_err!("The final CLTV expiry is too soon to handle", 17, &[0;0]);
1850-
}
1851-
// final_incorrect_htlc_amount
1852-
if next_hop_data.amt_to_forward > msg.amount_msat {
1853-
return_err!("Upstream node sent less than we were supposed to receive in payment", 19, &byte_utils::be64_to_array(msg.amount_msat));
1854-
}
1855-
// final_incorrect_cltv_expiry
1856-
if next_hop_data.outgoing_cltv_value != msg.cltv_expiry {
1857-
return_err!("Upstream node set CLTV to the wrong value", 18, &byte_utils::be32_to_array(msg.cltv_expiry));
1858-
}
1801+
let pending_forward_info = match next_hop {
1802+
onion_utils::Hop::Receive(next_hop_data) => {
1803+
// OUR PAYMENT!
1804+
// final_expiry_too_soon
1805+
// We have to have some headroom to broadcast on chain if we have the preimage, so make sure
1806+
// we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
1807+
// Also, ensure that, in the case of an unknown preimage for the received payment hash, our
1808+
// payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
1809+
// channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
1810+
if (msg.cltv_expiry as u64) <= self.best_block.read().unwrap().height() as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
1811+
return_err!("The final CLTV expiry is too soon to handle", 17, &[0;0]);
1812+
}
1813+
// final_incorrect_htlc_amount
1814+
if next_hop_data.amt_to_forward > msg.amount_msat {
1815+
return_err!("Upstream node sent less than we were supposed to receive in payment", 19, &byte_utils::be64_to_array(msg.amount_msat));
1816+
}
1817+
// final_incorrect_cltv_expiry
1818+
if next_hop_data.outgoing_cltv_value != msg.cltv_expiry {
1819+
return_err!("Upstream node set CLTV to the wrong value", 18, &byte_utils::be32_to_array(msg.cltv_expiry));
1820+
}
18591821

1860-
let routing = match next_hop_data.format {
1861-
msgs::OnionHopDataFormat::Legacy { .. } => return_err!("We require payment_secrets", 0x4000|0x2000|3, &[0;0]),
1862-
msgs::OnionHopDataFormat::NonFinalNode { .. } => return_err!("Got non final data with an HMAC of 0", 0x4000 | 22, &[0;0]),
1863-
msgs::OnionHopDataFormat::FinalNode { payment_data, keysend_preimage } => {
1864-
if payment_data.is_some() && keysend_preimage.is_some() {
1865-
return_err!("We don't support MPP keysend payments", 0x4000|22, &[0;0]);
1866-
} else if let Some(data) = payment_data {
1867-
PendingHTLCRouting::Receive {
1868-
payment_data: data,
1869-
incoming_cltv_expiry: msg.cltv_expiry,
1870-
}
1871-
} else if let Some(payment_preimage) = keysend_preimage {
1872-
// We need to check that the sender knows the keysend preimage before processing this
1873-
// payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
1874-
// could discover the final destination of X, by probing the adjacent nodes on the route
1875-
// with a keysend payment of identical payment hash to X and observing the processing
1876-
// time discrepancies due to a hash collision with X.
1877-
let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
1878-
if hashed_preimage != msg.payment_hash {
1879-
return_err!("Payment preimage didn't match payment hash", 0x4000|22, &[0;0]);
1880-
}
1822+
let routing = match next_hop_data.format {
1823+
msgs::OnionHopDataFormat::Legacy { .. } => return_err!("We require payment_secrets", 0x4000|0x2000|3, &[0;0]),
1824+
msgs::OnionHopDataFormat::NonFinalNode { .. } => return_err!("Got non final data with an HMAC of 0", 0x4000 | 22, &[0;0]),
1825+
msgs::OnionHopDataFormat::FinalNode { payment_data, keysend_preimage } => {
1826+
if payment_data.is_some() && keysend_preimage.is_some() {
1827+
return_err!("We don't support MPP keysend payments", 0x4000|22, &[0;0]);
1828+
} else if let Some(data) = payment_data {
1829+
PendingHTLCRouting::Receive {
1830+
payment_data: data,
1831+
incoming_cltv_expiry: msg.cltv_expiry,
1832+
}
1833+
} else if let Some(payment_preimage) = keysend_preimage {
1834+
// We need to check that the sender knows the keysend preimage before processing this
1835+
// payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
1836+
// could discover the final destination of X, by probing the adjacent nodes on the route
1837+
// with a keysend payment of identical payment hash to X and observing the processing
1838+
// time discrepancies due to a hash collision with X.
1839+
let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
1840+
if hashed_preimage != msg.payment_hash {
1841+
return_err!("Payment preimage didn't match payment hash", 0x4000|22, &[0;0]);
1842+
}
18811843

1882-
PendingHTLCRouting::ReceiveKeysend {
1883-
payment_preimage,
1884-
incoming_cltv_expiry: msg.cltv_expiry,
1844+
PendingHTLCRouting::ReceiveKeysend {
1845+
payment_preimage,
1846+
incoming_cltv_expiry: msg.cltv_expiry,
1847+
}
1848+
} else {
1849+
return_err!("We require payment_secrets", 0x4000|0x2000|3, &[0;0]);
18851850
}
1886-
} else {
1887-
return_err!("We require payment_secrets", 0x4000|0x2000|3, &[0;0]);
1888-
}
1889-
},
1890-
};
1891-
1892-
// Note that we could obviously respond immediately with an update_fulfill_htlc
1893-
// message, however that would leak that we are the recipient of this payment, so
1894-
// instead we stay symmetric with the forwarding case, only responding (after a
1895-
// delay) once they've send us a commitment_signed!
1896-
1897-
PendingHTLCStatus::Forward(PendingHTLCInfo {
1898-
routing,
1899-
payment_hash: msg.payment_hash.clone(),
1900-
incoming_shared_secret: shared_secret,
1901-
amt_to_forward: next_hop_data.amt_to_forward,
1902-
outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
1903-
})
1904-
} else {
1905-
let mut new_packet_data = [0; 20*65];
1906-
let read_pos = chacha_stream.read(&mut new_packet_data).unwrap();
1907-
#[cfg(debug_assertions)]
1908-
{
1909-
// Check two things:
1910-
// a) that the behavior of our stream here will return Ok(0) even if the TLV
1911-
// read above emptied out our buffer and the unwrap() wont needlessly panic
1912-
// b) that we didn't somehow magically end up with extra data.
1913-
let mut t = [0; 1];
1914-
debug_assert!(chacha_stream.read(&mut t).unwrap() == 0);
1915-
}
1916-
// Once we've emptied the set of bytes our peer gave us, encrypt 0 bytes until we
1917-
// fill the onion hop data we'll forward to our next-hop peer.
1918-
chacha_stream.chacha.process_in_place(&mut new_packet_data[read_pos..]);
1919-
1920-
let mut new_pubkey = msg.onion_routing_packet.public_key.unwrap();
1851+
},
1852+
};
19211853

1922-
let blinding_factor = {
1923-
let mut sha = Sha256::engine();
1924-
sha.input(&new_pubkey.serialize()[..]);
1925-
sha.input(&shared_secret);
1926-
Sha256::from_engine(sha).into_inner()
1927-
};
1854+
// Note that we could obviously respond immediately with an update_fulfill_htlc
1855+
// message, however that would leak that we are the recipient of this payment, so
1856+
// instead we stay symmetric with the forwarding case, only responding (after a
1857+
// delay) once they've send us a commitment_signed!
1858+
1859+
PendingHTLCStatus::Forward(PendingHTLCInfo {
1860+
routing,
1861+
payment_hash: msg.payment_hash.clone(),
1862+
incoming_shared_secret: shared_secret,
1863+
amt_to_forward: next_hop_data.amt_to_forward,
1864+
outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
1865+
})
1866+
},
1867+
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
1868+
let mut new_pubkey = msg.onion_routing_packet.public_key.unwrap();
1869+
1870+
let blinding_factor = {
1871+
let mut sha = Sha256::engine();
1872+
sha.input(&new_pubkey.serialize()[..]);
1873+
sha.input(&shared_secret);
1874+
Sha256::from_engine(sha).into_inner()
1875+
};
19281876

1929-
let public_key = if let Err(e) = new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor[..]) {
1930-
Err(e)
1931-
} else { Ok(new_pubkey) };
1877+
let public_key = if let Err(e) = new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor[..]) {
1878+
Err(e)
1879+
} else { Ok(new_pubkey) };
19321880

1933-
let outgoing_packet = msgs::OnionPacket {
1934-
version: 0,
1935-
public_key,
1936-
hop_data: new_packet_data,
1937-
hmac: next_hop_hmac.clone(),
1938-
};
1881+
let outgoing_packet = msgs::OnionPacket {
1882+
version: 0,
1883+
public_key,
1884+
hop_data: new_packet_bytes,
1885+
hmac: next_hop_hmac.clone(),
1886+
};
19391887

1940-
let short_channel_id = match next_hop_data.format {
1941-
msgs::OnionHopDataFormat::Legacy { short_channel_id } => short_channel_id,
1942-
msgs::OnionHopDataFormat::NonFinalNode { short_channel_id } => short_channel_id,
1943-
msgs::OnionHopDataFormat::FinalNode { .. } => {
1944-
return_err!("Final Node OnionHopData provided for us as an intermediary node", 0x4000 | 22, &[0;0]);
1945-
},
1946-
};
1888+
let short_channel_id = match next_hop_data.format {
1889+
msgs::OnionHopDataFormat::Legacy { short_channel_id } => short_channel_id,
1890+
msgs::OnionHopDataFormat::NonFinalNode { short_channel_id } => short_channel_id,
1891+
msgs::OnionHopDataFormat::FinalNode { .. } => {
1892+
return_err!("Final Node OnionHopData provided for us as an intermediary node", 0x4000 | 22, &[0;0]);
1893+
},
1894+
};
19471895

1948-
PendingHTLCStatus::Forward(PendingHTLCInfo {
1949-
routing: PendingHTLCRouting::Forward {
1950-
onion_packet: outgoing_packet,
1951-
short_channel_id,
1952-
},
1953-
payment_hash: msg.payment_hash.clone(),
1954-
incoming_shared_secret: shared_secret,
1955-
amt_to_forward: next_hop_data.amt_to_forward,
1956-
outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
1957-
})
1896+
PendingHTLCStatus::Forward(PendingHTLCInfo {
1897+
routing: PendingHTLCRouting::Forward {
1898+
onion_packet: outgoing_packet,
1899+
short_channel_id,
1900+
},
1901+
payment_hash: msg.payment_hash.clone(),
1902+
incoming_shared_secret: shared_secret,
1903+
amt_to_forward: next_hop_data.amt_to_forward,
1904+
outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
1905+
})
1906+
}
19581907
};
19591908

19601909
channel_state = Some(self.channel_state.lock().unwrap());

0 commit comments

Comments
 (0)