X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fonion_utils.rs;h=ea906c9e32af86b2b1d21e3322eba082a4c195ea;hb=a1c92820b0800881e7f4289e3e77dae44f0a0cad;hp=08fe7a73ae6f225df9ca9f873e8da1407689c3d1;hpb=7f765a39bcf1464fab92d19b6ecd6f38e296a30e;p=rust-lightning diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 08fe7a73..ea906c9e 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -242,6 +242,8 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o /// the hops can be of variable length. pub(crate) const ONION_DATA_LEN: usize = 20*65; +pub(super) const INVALID_ONION_BLINDING: u16 = 0x8000 | 0x4000 | 24; + #[inline] fn shift_slice_right(arr: &mut [u8], amt: usize) { for i in (amt..arr.len()).rev() { @@ -321,8 +323,6 @@ fn construct_onion_packet_with_init_noise( let mut pos = 0; for (i, (payload, keys)) in payloads.iter().zip(onion_keys.iter()).enumerate() { - if i == payloads.len() - 1 { break; } - let mut chacha = ChaCha20::new(&keys.rho, &[0u8; 8]); for _ in 0..(packet_data.len() - pos) { // TODO: Batch this. let mut dummy = [0; 1]; @@ -336,6 +336,8 @@ fn construct_onion_packet_with_init_noise( return Err(()); } + if i == payloads.len() - 1 { break; } + res.resize(pos, 0u8); chacha.process_in_place(&mut res); } @@ -502,8 +504,21 @@ pub(super) fn process_onion_failure( Some(hop) => hop, None => { // The failing hop is within a multi-hop blinded path. - error_code_ret = Some(BADONION | PERM | 24); // invalid_onion_blinding - error_packet_ret = Some(vec![0; 32]); + #[cfg(not(test))] { + error_code_ret = Some(BADONION | PERM | 24); // invalid_onion_blinding + error_packet_ret = Some(vec![0; 32]); + } + #[cfg(test)] { + // Actually parse the onion error data in tests so we can check that blinded hops fail + // back correctly. + let err_packet = decrypt_onion_error_packet( + &mut encrypted_packet, shared_secret + ).unwrap(); + error_code_ret = + Some(u16::from_be_bytes(err_packet.failuremsg.get(0..2).unwrap().try_into().unwrap())); + error_packet_ret = Some(err_packet.failuremsg[2..].to_vec()); + } + res = Some(FailureLearnings { network_update: None, short_channel_id: None, payment_failed_permanently: false }); @@ -725,9 +740,11 @@ pub(super) fn process_onion_failure( } #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug +#[cfg_attr(test, derive(PartialEq))] pub(super) struct HTLCFailReason(HTLCFailReasonRepr); #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug +#[cfg_attr(test, derive(PartialEq))] enum HTLCFailReasonRepr { LightningError { err: msgs::OnionErrorPacket, @@ -1004,18 +1021,20 @@ fn decode_next_hop, N: NextPacketBytes>(shared_secret: [u8 if hmac == [0; 32] { #[cfg(test)] { - // In tests, make sure that the initial onion packet data is, at least, non-0. - // We could do some fancy randomness test here, but, ehh, whatever. - // This checks for the issue where you can calculate the path length given the - // onion data as all the path entries that the originator sent will be here - // as-is (and were originally 0s). - // Of course reverse path calculation is still pretty easy given naive routing - // algorithms, but this fixes the most-obvious case. - let mut next_bytes = [0; 32]; - chacha_stream.read_exact(&mut next_bytes).unwrap(); - assert_ne!(next_bytes[..], [0; 32][..]); - chacha_stream.read_exact(&mut next_bytes).unwrap(); - assert_ne!(next_bytes[..], [0; 32][..]); + if chacha_stream.read.position() < hop_data.len() as u64 - 64 { + // In tests, make sure that the initial onion packet data is, at least, non-0. + // We could do some fancy randomness test here, but, ehh, whatever. + // This checks for the issue where you can calculate the path length given the + // onion data as all the path entries that the originator sent will be here + // as-is (and were originally 0s). + // Of course reverse path calculation is still pretty easy given naive routing + // algorithms, but this fixes the most-obvious case. + let mut next_bytes = [0; 32]; + chacha_stream.read_exact(&mut next_bytes).unwrap(); + assert_ne!(next_bytes[..], [0; 32][..]); + chacha_stream.read_exact(&mut next_bytes).unwrap(); + assert_ne!(next_bytes[..], [0; 32][..]); + } } return Ok((msg, None)); // We are the final destination for this packet } else {