GEN_TEST router
GEN_TEST zbase32
GEN_TEST indexedmap
+GEN_TEST onion_hop_data
GEN_TEST msg_accept_channel msg_targets::
GEN_TEST msg_announcement_signatures msg_targets::
GEN_TEST msg_error_message msg_targets::
GEN_TEST msg_channel_update msg_targets::
-GEN_TEST msg_onion_hop_data msg_targets::
GEN_TEST msg_ping msg_targets::
GEN_TEST msg_pong msg_targets::
+++ /dev/null
-// This file is Copyright its original authors, visible in version control
-// history.
-//
-// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
-// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
-// You may not use this file except in accordance with one or both of these
-// licenses.
-
-// This file is auto-generated by gen_target.sh based on target_template.txt
-// To modify it, modify target_template.txt and run gen_target.sh instead.
-
-#![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
-
-#[cfg(not(fuzzing))]
-compile_error!("Fuzz targets need cfg=fuzzing");
-
-extern crate lightning_fuzz;
-use lightning_fuzz::msg_targets::msg_onion_hop_data::*;
-
-#[cfg(feature = "afl")]
-#[macro_use] extern crate afl;
-#[cfg(feature = "afl")]
-fn main() {
- fuzz!(|data| {
- msg_onion_hop_data_run(data.as_ptr(), data.len());
- });
-}
-
-#[cfg(feature = "honggfuzz")]
-#[macro_use] extern crate honggfuzz;
-#[cfg(feature = "honggfuzz")]
-fn main() {
- loop {
- fuzz!(|data| {
- msg_onion_hop_data_run(data.as_ptr(), data.len());
- });
- }
-}
-
-#[cfg(feature = "libfuzzer_fuzz")]
-#[macro_use] extern crate libfuzzer_sys;
-#[cfg(feature = "libfuzzer_fuzz")]
-fuzz_target!(|data: &[u8]| {
- msg_onion_hop_data_run(data.as_ptr(), data.len());
-});
-
-#[cfg(feature = "stdin_fuzz")]
-fn main() {
- use std::io::Read;
-
- let mut data = Vec::with_capacity(8192);
- std::io::stdin().read_to_end(&mut data).unwrap();
- msg_onion_hop_data_run(data.as_ptr(), data.len());
-}
-
-#[test]
-fn run_test_cases() {
- use std::fs;
- use std::io::Read;
- use lightning_fuzz::utils::test_logger::StringBuffer;
-
- use std::sync::{atomic, Arc};
- {
- let data: Vec<u8> = vec![0];
- msg_onion_hop_data_run(data.as_ptr(), data.len());
- }
- let mut threads = Vec::new();
- let threads_running = Arc::new(atomic::AtomicUsize::new(0));
- if let Ok(tests) = fs::read_dir("test_cases/msg_onion_hop_data") {
- for test in tests {
- let mut data: Vec<u8> = Vec::new();
- let path = test.unwrap().path();
- fs::File::open(&path).unwrap().read_to_end(&mut data).unwrap();
- threads_running.fetch_add(1, atomic::Ordering::AcqRel);
-
- let thread_count_ref = Arc::clone(&threads_running);
- let main_thread_ref = std::thread::current();
- threads.push((path.file_name().unwrap().to_str().unwrap().to_string(),
- std::thread::spawn(move || {
- let string_logger = StringBuffer::new();
-
- let panic_logger = string_logger.clone();
- let res = if ::std::panic::catch_unwind(move || {
- msg_onion_hop_data_test(&data, panic_logger);
- }).is_err() {
- Some(string_logger.into_string())
- } else { None };
- thread_count_ref.fetch_sub(1, atomic::Ordering::AcqRel);
- main_thread_ref.unpark();
- res
- })
- ));
- while threads_running.load(atomic::Ordering::Acquire) > 32 {
- std::thread::park();
- }
- }
- }
- let mut failed_outputs = Vec::new();
- for (test, thread) in threads.drain(..) {
- if let Some(output) = thread.join().unwrap() {
- println!("\nOutput of {}:\n{}\n", test, output);
- failed_outputs.push(test);
- }
- }
- if !failed_outputs.is_empty() {
- println!("Test cases which failed: ");
- for case in failed_outputs {
- println!("{}", case);
- }
- panic!();
- }
-}
--- /dev/null
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+// This file is auto-generated by gen_target.sh based on target_template.txt
+// To modify it, modify target_template.txt and run gen_target.sh instead.
+
+#![cfg_attr(feature = "libfuzzer_fuzz", no_main)]
+
+#[cfg(not(fuzzing))]
+compile_error!("Fuzz targets need cfg=fuzzing");
+
+extern crate lightning_fuzz;
+use lightning_fuzz::onion_hop_data::*;
+
+#[cfg(feature = "afl")]
+#[macro_use] extern crate afl;
+#[cfg(feature = "afl")]
+fn main() {
+ fuzz!(|data| {
+ onion_hop_data_run(data.as_ptr(), data.len());
+ });
+}
+
+#[cfg(feature = "honggfuzz")]
+#[macro_use] extern crate honggfuzz;
+#[cfg(feature = "honggfuzz")]
+fn main() {
+ loop {
+ fuzz!(|data| {
+ onion_hop_data_run(data.as_ptr(), data.len());
+ });
+ }
+}
+
+#[cfg(feature = "libfuzzer_fuzz")]
+#[macro_use] extern crate libfuzzer_sys;
+#[cfg(feature = "libfuzzer_fuzz")]
+fuzz_target!(|data: &[u8]| {
+ onion_hop_data_run(data.as_ptr(), data.len());
+});
+
+#[cfg(feature = "stdin_fuzz")]
+fn main() {
+ use std::io::Read;
+
+ let mut data = Vec::with_capacity(8192);
+ std::io::stdin().read_to_end(&mut data).unwrap();
+ onion_hop_data_run(data.as_ptr(), data.len());
+}
+
+#[test]
+fn run_test_cases() {
+ use std::fs;
+ use std::io::Read;
+ use lightning_fuzz::utils::test_logger::StringBuffer;
+
+ use std::sync::{atomic, Arc};
+ {
+ let data: Vec<u8> = vec![0];
+ onion_hop_data_run(data.as_ptr(), data.len());
+ }
+ let mut threads = Vec::new();
+ let threads_running = Arc::new(atomic::AtomicUsize::new(0));
+ if let Ok(tests) = fs::read_dir("test_cases/onion_hop_data") {
+ for test in tests {
+ let mut data: Vec<u8> = Vec::new();
+ let path = test.unwrap().path();
+ fs::File::open(&path).unwrap().read_to_end(&mut data).unwrap();
+ threads_running.fetch_add(1, atomic::Ordering::AcqRel);
+
+ let thread_count_ref = Arc::clone(&threads_running);
+ let main_thread_ref = std::thread::current();
+ threads.push((path.file_name().unwrap().to_str().unwrap().to_string(),
+ std::thread::spawn(move || {
+ let string_logger = StringBuffer::new();
+
+ let panic_logger = string_logger.clone();
+ let res = if ::std::panic::catch_unwind(move || {
+ onion_hop_data_test(&data, panic_logger);
+ }).is_err() {
+ Some(string_logger.into_string())
+ } else { None };
+ thread_count_ref.fetch_sub(1, atomic::Ordering::AcqRel);
+ main_thread_ref.unpark();
+ res
+ })
+ ));
+ while threads_running.load(atomic::Ordering::Acquire) > 32 {
+ std::thread::park();
+ }
+ }
+ }
+ let mut failed_outputs = Vec::new();
+ for (test, thread) in threads.drain(..) {
+ if let Some(output) = thread.join().unwrap() {
+ println!("\nOutput of {}:\n{}\n", test, output);
+ failed_outputs.push(test);
+ }
+ }
+ if !failed_outputs.is_empty() {
+ println!("Test cases which failed: ");
+ for case in failed_outputs {
+ println!("{}", case);
+ }
+ panic!();
+ }
+}
pub mod refund_deser;
pub mod router;
pub mod zbase32;
+pub mod onion_hop_data;
pub mod msg_targets;
GEN_TEST lightning::ln::msgs::FundingSigned test_msg_simple ""
GEN_TEST lightning::ln::msgs::GossipTimestampFilter test_msg_simple ""
GEN_TEST lightning::ln::msgs::Init test_msg_simple ""
-GEN_TEST lightning::ln::msgs::OnionHopData test_msg_simple ""
GEN_TEST lightning::ln::msgs::OpenChannel test_msg_simple ""
GEN_TEST lightning::ln::msgs::Ping test_msg_simple ""
GEN_TEST lightning::ln::msgs::Pong test_msg_simple ""
pub mod msg_funding_signed;
pub mod msg_gossip_timestamp_filter;
pub mod msg_init;
-pub mod msg_onion_hop_data;
pub mod msg_open_channel;
pub mod msg_ping;
pub mod msg_pong;
+++ /dev/null
-// This file is Copyright its original authors, visible in version control
-// history.
-//
-// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
-// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
-// You may not use this file except in accordance with one or both of these
-// licenses.
-
-// This file is auto-generated by gen_target.sh based on msg_target_template.txt
-// To modify it, modify msg_target_template.txt and run gen_target.sh instead.
-
-use crate::msg_targets::utils::VecWriter;
-use crate::utils::test_logger;
-
-#[inline]
-pub fn msg_onion_hop_data_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
- test_msg_simple!(lightning::ln::msgs::OnionHopData, data);
-}
-
-#[no_mangle]
-pub extern "C" fn msg_onion_hop_data_run(data: *const u8, datalen: usize) {
- let data = unsafe { std::slice::from_raw_parts(data, datalen) };
- test_msg_simple!(lightning::ln::msgs::OnionHopData, data);
-}
--- /dev/null
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+// This file is auto-generated by gen_target.sh based on msg_target_template.txt
+// To modify it, modify msg_target_template.txt and run gen_target.sh instead.
+
+use crate::utils::test_logger;
+
+#[inline]
+pub fn onion_hop_data_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
+ use lightning::util::ser::Readable;
+ let mut r = ::std::io::Cursor::new(data);
+ let _ = <lightning::ln::msgs::InboundOnionPayload as Readable>::read(&mut r);
+}
+
+#[no_mangle]
+pub extern "C" fn onion_hop_data_run(data: *const u8, datalen: usize) {
+ use lightning::util::ser::Readable;
+ let data = unsafe { std::slice::from_raw_parts(data, datalen) };
+ let mut r = ::std::io::Cursor::new(data);
+ let _ = <lightning::ln::msgs::InboundOnionPayload as Readable>::read(&mut r);
+}
void router_run(const unsigned char* data, size_t data_len);
void zbase32_run(const unsigned char* data, size_t data_len);
void indexedmap_run(const unsigned char* data, size_t data_len);
+void onion_hop_data_run(const unsigned char* data, size_t data_len);
void msg_accept_channel_run(const unsigned char* data, size_t data_len);
void msg_announcement_signatures_run(const unsigned char* data, size_t data_len);
void msg_channel_reestablish_run(const unsigned char* data, size_t data_len);
void msg_update_add_htlc_run(const unsigned char* data, size_t data_len);
void msg_error_message_run(const unsigned char* data, size_t data_len);
void msg_channel_update_run(const unsigned char* data, size_t data_len);
-void msg_onion_hop_data_run(const unsigned char* data, size_t data_len);
void msg_ping_run(const unsigned char* data, size_t data_len);
void msg_pong_run(const unsigned char* data, size_t data_len);
void msg_channel_details_run(const unsigned char* data, size_t data_len);
}
fn construct_fwd_pending_htlc_info(
- &self, msg: &msgs::UpdateAddHTLC, hop_data: msgs::OnionHopData, hop_hmac: [u8; 32],
+ &self, msg: &msgs::UpdateAddHTLC, hop_data: msgs::InboundOnionPayload, hop_hmac: [u8; 32],
new_packet_bytes: [u8; onion_utils::ONION_DATA_LEN], shared_secret: [u8; 32],
next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
) -> Result<PendingHTLCInfo, InboundOnionErr> {
version: 0,
public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
hop_data: new_packet_bytes,
- hmac: hop_hmac.clone(),
+ hmac: hop_hmac,
};
- let short_channel_id = match hop_data.format {
- msgs::OnionHopDataFormat::NonFinalNode { short_channel_id } => short_channel_id,
- msgs::OnionHopDataFormat::FinalNode { .. } => {
+ let (short_channel_id, amt_to_forward, outgoing_cltv_value) = match hop_data {
+ msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } =>
+ (short_channel_id, amt_to_forward, outgoing_cltv_value),
+ msgs::InboundOnionPayload::Receive { .. } =>
return Err(InboundOnionErr {
msg: "Final Node OnionHopData provided for us as an intermediary node",
err_code: 0x4000 | 22,
err_data: Vec::new(),
- })
- },
+ }),
};
Ok(PendingHTLCInfo {
onion_packet: outgoing_packet,
short_channel_id,
},
- payment_hash: msg.payment_hash.clone(),
+ payment_hash: msg.payment_hash,
incoming_shared_secret: shared_secret,
incoming_amt_msat: Some(msg.amount_msat),
- outgoing_amt_msat: hop_data.amt_to_forward,
- outgoing_cltv_value: hop_data.outgoing_cltv_value,
+ outgoing_amt_msat: amt_to_forward,
+ outgoing_cltv_value,
skimmed_fee_msat: None,
})
}
fn construct_recv_pending_htlc_info(
- &self, hop_data: msgs::OnionHopData, shared_secret: [u8; 32], payment_hash: PaymentHash,
+ &self, hop_data: msgs::InboundOnionPayload, shared_secret: [u8; 32], payment_hash: PaymentHash,
amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool,
counterparty_skimmed_fee_msat: Option<u64>,
) -> Result<PendingHTLCInfo, InboundOnionErr> {
- let (payment_data, keysend_preimage, payment_metadata) = match hop_data.format {
- msgs::OnionHopDataFormat::FinalNode { payment_data, keysend_preimage, payment_metadata } =>
- (payment_data, keysend_preimage, payment_metadata),
+ let (payment_data, keysend_preimage, onion_amt_msat, outgoing_cltv_value, payment_metadata) = match hop_data {
+ msgs::InboundOnionPayload::Receive {
+ payment_data, keysend_preimage, amt_msat, outgoing_cltv_value, payment_metadata, ..
+ } =>
+ (payment_data, keysend_preimage, amt_msat, outgoing_cltv_value, payment_metadata),
_ =>
return Err(InboundOnionErr {
err_code: 0x4000|22,
}),
};
// final_incorrect_cltv_expiry
- if hop_data.outgoing_cltv_value > cltv_expiry {
+ if outgoing_cltv_value > cltv_expiry {
return Err(InboundOnionErr {
msg: "Upstream node set CLTV to less than the CLTV set by the sender",
err_code: 18,
// payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
// channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
let current_height: u32 = self.best_block.read().unwrap().height();
- if (hop_data.outgoing_cltv_value as u64) <= current_height as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
+ if (outgoing_cltv_value as u64) <= current_height as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
let mut err_data = Vec::with_capacity(12);
err_data.extend_from_slice(&amt_msat.to_be_bytes());
err_data.extend_from_slice(¤t_height.to_be_bytes());
msg: "The final CLTV expiry is too soon to handle",
});
}
- if (!allow_underpay && hop_data.amt_to_forward > amt_msat) ||
- (allow_underpay && hop_data.amt_to_forward >
+ if (!allow_underpay && onion_amt_msat > amt_msat) ||
+ (allow_underpay && onion_amt_msat >
amt_msat.saturating_add(counterparty_skimmed_fee_msat.unwrap_or(0)))
{
return Err(InboundOnionErr {
payment_data,
payment_preimage,
payment_metadata,
- incoming_cltv_expiry: hop_data.outgoing_cltv_value,
+ incoming_cltv_expiry: outgoing_cltv_value,
}
} else if let Some(data) = payment_data {
PendingHTLCRouting::Receive {
payment_data: data,
payment_metadata,
- incoming_cltv_expiry: hop_data.outgoing_cltv_value,
+ incoming_cltv_expiry: outgoing_cltv_value,
phantom_shared_secret,
}
} else {
payment_hash,
incoming_shared_secret: shared_secret,
incoming_amt_msat: Some(amt_msat),
- outgoing_amt_msat: hop_data.amt_to_forward,
- outgoing_cltv_value: hop_data.outgoing_cltv_value,
+ outgoing_amt_msat: onion_amt_msat,
+ outgoing_cltv_value,
skimmed_fee_msat: counterparty_skimmed_fee_msat,
})
}
};
let (outgoing_scid, outgoing_amt_msat, outgoing_cltv_value, next_packet_pk_opt) = match next_hop {
onion_utils::Hop::Forward {
- next_hop_data: msgs::OnionHopData {
- format: msgs::OnionHopDataFormat::NonFinalNode { short_channel_id }, amt_to_forward,
- outgoing_cltv_value,
+ next_hop_data: msgs::InboundOnionPayload::Forward {
+ short_channel_id, amt_to_forward, outgoing_cltv_value
}, ..
} => {
let next_pk = onion_utils::next_hop_packet_pubkey(&self.secp_ctx,
// We'll do receive checks in [`Self::construct_pending_htlc_info`] so we have access to the
// inbound channel's state.
onion_utils::Hop::Receive { .. } => return Ok((next_hop, shared_secret, None)),
- onion_utils::Hop::Forward {
- next_hop_data: msgs::OnionHopData { format: msgs::OnionHopDataFormat::FinalNode { .. }, .. }, ..
- } => {
+ onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionPayload::Receive { .. }, .. } => {
return_err!("Final Node OnionHopData provided for us as an intermediary node", 0x4000 | 22, &[0; 0]);
}
};
let node = create_network(1, &node_cfg, &node_chanmgr);
let sender_intended_amt_msat = 100;
let extra_fee_msat = 10;
- let hop_data = msgs::OnionHopData {
- amt_to_forward: 100,
+ let hop_data = msgs::InboundOnionPayload::Receive {
+ amt_msat: 100,
outgoing_cltv_value: 42,
- format: msgs::OnionHopDataFormat::FinalNode {
- keysend_preimage: None,
- payment_metadata: None,
- payment_data: Some(msgs::FinalOnionHopData {
- payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
- }),
- }
+ payment_metadata: None,
+ keysend_preimage: None,
+ payment_data: Some(msgs::FinalOnionHopData {
+ payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
+ }),
};
// Check that if the amount we received + the penultimate hop extra fee is less than the sender
// intended amount, we fail the payment.
} else { panic!(); }
// If amt_received + extra_fee is equal to the sender intended amount, we're fine.
- let hop_data = msgs::OnionHopData { // This is the same hop_data as above, OnionHopData doesn't implement Clone
- amt_to_forward: 100,
+ let hop_data = msgs::InboundOnionPayload::Receive { // This is the same payload as above, InboundOnionPayload doesn't implement Clone
+ amt_msat: 100,
outgoing_cltv_value: 42,
- format: msgs::OnionHopDataFormat::FinalNode {
- keysend_preimage: None,
- payment_metadata: None,
- payment_data: Some(msgs::FinalOnionHopData {
- payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
- }),
- }
+ payment_metadata: None,
+ keysend_preimage: None,
+ payment_data: Some(msgs::FinalOnionHopData {
+ payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
+ }),
};
assert!(node[0].node.construct_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]),
sender_intended_amt_msat - extra_fee_msat, 42, None, true, Some(extra_fee_msat)).is_ok());
// These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize
// them from untrusted input):
#[derive(Clone)]
- pub(crate) struct FinalOnionHopData {
- pub(crate) payment_secret: PaymentSecret,
+ pub struct FinalOnionHopData {
+ pub payment_secret: PaymentSecret,
/// The total value, in msat, of the payment as received by the ultimate recipient.
/// Message serialization may panic if this value is more than 21 million Bitcoin.
- pub(crate) total_msat: u64,
+ pub total_msat: u64,
+ }
+
+ pub enum InboundOnionPayload {
+ Forward {
+ short_channel_id: u64,
+ /// The value, in msat, of the payment after this hop's fee is deducted.
+ amt_to_forward: u64,
+ outgoing_cltv_value: u32,
+ },
+ Receive {
+ payment_data: Option<FinalOnionHopData>,
+ payment_metadata: Option<Vec<u8>>,
+ keysend_preimage: Option<PaymentPreimage>,
+ amt_msat: u64,
+ outgoing_cltv_value: u32,
+ },
}
pub(crate) enum OnionHopDataFormat {
}
}
-impl Readable for OnionHopData {
+impl Readable for InboundOnionPayload {
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
let mut amt = HighZeroBytesDroppedBigSize(0u64);
let mut cltv_value = HighZeroBytesDroppedBigSize(0u32);
(5482373484, keysend_preimage, option)
});
- let format = if let Some(short_channel_id) = short_id {
- if payment_data.is_some() { return Err(DecodeError::InvalidValue); }
+ if amt.0 > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
+ if let Some(short_channel_id) = short_id {
+ if payment_data.is_some() { return Err(DecodeError::InvalidValue) }
if payment_metadata.is_some() { return Err(DecodeError::InvalidValue); }
- OnionHopDataFormat::NonFinalNode {
+ Ok(Self::Forward {
short_channel_id,
- }
+ amt_to_forward: amt.0,
+ outgoing_cltv_value: cltv_value.0,
+ })
} else {
if let Some(data) = &payment_data {
if data.total_msat > MAX_VALUE_MSAT {
return Err(DecodeError::InvalidValue);
}
}
- OnionHopDataFormat::FinalNode {
+ Ok(Self::Receive {
payment_data,
payment_metadata: payment_metadata.map(|w| w.0),
keysend_preimage,
- }
- };
-
- if amt.0 > MAX_VALUE_MSAT {
- return Err(DecodeError::InvalidValue);
+ amt_msat: amt.0,
+ outgoing_cltv_value: cltv_value.0,
+ })
}
- Ok(OnionHopData {
- format,
- amt_to_forward: amt.0,
- outgoing_cltv_value: cltv_value.0,
- })
}
}
// ReadableArgs because we need onion_utils::decode_next_hop to accommodate payment packets and
// onion message packets.
-impl ReadableArgs<()> for OnionHopData {
+impl ReadableArgs<()> for InboundOnionPayload {
fn read<R: Read>(r: &mut R, _arg: ()) -> Result<Self, DecodeError> {
<Self as Readable>::read(r)
}
#[test]
fn encoding_nonfinal_onion_hop_data() {
- let mut msg = msgs::OnionHopData {
+ let msg = msgs::OnionHopData {
format: OnionHopDataFormat::NonFinalNode {
short_channel_id: 0xdeadbeef1bad1dea,
},
let encoded_value = msg.encode();
let target_value = hex::decode("1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea").unwrap();
assert_eq!(encoded_value, target_value);
- msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
- if let OnionHopDataFormat::NonFinalNode { short_channel_id } = msg.format {
+
+ let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+ if let msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = inbound_msg {
assert_eq!(short_channel_id, 0xdeadbeef1bad1dea);
+ assert_eq!(amt_to_forward, 0x0badf00d01020304);
+ assert_eq!(outgoing_cltv_value, 0xffffffff);
} else { panic!(); }
- assert_eq!(msg.amt_to_forward, 0x0badf00d01020304);
- assert_eq!(msg.outgoing_cltv_value, 0xffffffff);
}
#[test]
fn encoding_final_onion_hop_data() {
- let mut msg = msgs::OnionHopData {
+ let msg = msgs::OnionHopData {
format: OnionHopDataFormat::FinalNode {
payment_data: None,
payment_metadata: None,
let encoded_value = msg.encode();
let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap();
assert_eq!(encoded_value, target_value);
- msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
- if let OnionHopDataFormat::FinalNode { payment_data: None, .. } = msg.format { } else { panic!(); }
- assert_eq!(msg.amt_to_forward, 0x0badf00d01020304);
- assert_eq!(msg.outgoing_cltv_value, 0xffffffff);
+
+ let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+ if let msgs::InboundOnionPayload::Receive { payment_data: None, amt_msat, outgoing_cltv_value, .. } = inbound_msg {
+ assert_eq!(amt_msat, 0x0badf00d01020304);
+ assert_eq!(outgoing_cltv_value, 0xffffffff);
+ } else { panic!(); }
}
#[test]
fn encoding_final_onion_hop_data_with_secret() {
let expected_payment_secret = PaymentSecret([0x42u8; 32]);
- let mut msg = msgs::OnionHopData {
+ let msg = msgs::OnionHopData {
format: OnionHopDataFormat::FinalNode {
payment_data: Some(FinalOnionHopData {
payment_secret: expected_payment_secret,
let encoded_value = msg.encode();
let target_value = hex::decode("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap();
assert_eq!(encoded_value, target_value);
- msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
- if let OnionHopDataFormat::FinalNode {
+
+ let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+ if let msgs::InboundOnionPayload::Receive {
payment_data: Some(FinalOnionHopData {
payment_secret,
total_msat: 0x1badca1f
}),
+ amt_msat, outgoing_cltv_value,
payment_metadata: None,
keysend_preimage: None,
- } = msg.format {
+ } = inbound_msg {
assert_eq!(payment_secret, expected_payment_secret);
+ assert_eq!(amt_msat, 0x0badf00d01020304);
+ assert_eq!(outgoing_cltv_value, 0xffffffff);
} else { panic!(); }
- assert_eq!(msg.amt_to_forward, 0x0badf00d01020304);
- assert_eq!(msg.outgoing_cltv_value, 0xffffffff);
}
#[test]
// payload length to be encoded over multiple bytes rather than a single u8.
let big_payload = encode_big_payload().unwrap();
let mut rd = Cursor::new(&big_payload[..]);
- <msgs::OnionHopData as Readable>::read(&mut rd).unwrap();
+ <msgs::InboundOnionPayload as Readable>::read(&mut rd).unwrap();
}
// see above test, needs to be a separate method for use of the serialization macros.
fn encode_big_payload() -> Result<Vec<u8>, io::Error> {
pub(crate) enum Hop {
/// This onion payload was for us, not for forwarding to a next-hop. Contains information for
/// verifying the incoming payment.
- Receive(msgs::OnionHopData),
+ Receive(msgs::InboundOnionPayload),
/// This onion payload needs to be forwarded to a next-hop.
Forward {
/// Onion payload data used in forwarding the payment.
- next_hop_data: msgs::OnionHopData,
+ next_hop_data: msgs::InboundOnionPayload,
/// HMAC of the next hop's onion packet.
next_hop_hmac: [u8; 32],
/// Bytes of the onion packet we're forwarding.