}
}
+/// A "set" of addresses which enforces that there can be only up to one of each net address type.
+pub struct NetAddressSet {
+ v4: Option<NetAddress>,
+ v6: Option<NetAddress>,
+ onion2: Option<NetAddress>,
+ onion3: Option<NetAddress>,
+}
+impl NetAddressSet {
+ /// Creates a new, empty, NetAddressSet
+ pub fn new() -> Self {
+ NetAddressSet { v4: None, v6: None, onion2: None, onion3: None }
+ }
+
+ /// Sets the IPv4 socket address in this set, overwriting any previous IPv4 socket addresses
+ /// (if any).
+ pub fn set_v4(&mut self, addr: [u8; 4], port: u16) {
+ self.v4 = Some(NetAddress::IPv4 { addr, port });
+ }
+ /// Sets the IPv6 socket address in this set, overwriting any previous IPv4 socket addresses
+ /// (if any).
+ pub fn set_v6(&mut self, addr: [u8; 16], port: u16) {
+ self.v6 = Some(NetAddress::IPv6 { addr, port });
+ }
+ /// Sets the Tor Onion v2 socket address in this set, overwriting any previous IPv4 socket
+ /// address (if any).
+ pub fn set_onion_v2(&mut self, addr: [u8; 10], port: u16) {
+ self.onion2 = Some(NetAddress::OnionV2 { addr, port });
+ }
+ /// Sets the Tor Onion v3 socket address in this set, overwriting any previous IPv4 socket
+ /// address (if any).
+ pub fn set_onion_v3(&mut self, ed25519_pubkey: [u8; 32], checksum: u16, version: u8, port: u16) {
+ self.onion3 = Some(NetAddress::OnionV3 { ed25519_pubkey, checksum, version, port });
+ }
+
+ pub(crate) fn to_vec(mut self) -> Vec<NetAddress> {
+ let mut res = Vec::new();
+ if let Some(addr) = self.v4.take() {
+ res.push(addr);
+ }
+ if let Some(addr) = self.v6.take() {
+ res.push(addr);
+ }
+ if let Some(addr) = self.onion2.take() {
+ res.push(addr);
+ }
+ if let Some(addr) = self.onion3.take() {
+ res.push(addr);
+ }
+ res
+ }
+}
+
impl Writeable for NetAddress {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
match self {
mod fuzzy_internal_msgs {
// 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: [u8; 32],
+ pub(crate) total_msat: u64,
+ }
pub(crate) enum OnionHopDataFormat {
Legacy { // aka Realm-0
NonFinalNode {
short_channel_id: u64,
},
- FinalNode,
+ FinalNode {
+ payment_data: Option<FinalOnionHopData>,
+ },
}
pub struct OnionHopData {
onion_routing_packet
});
+impl_writeable!(FinalOnionHopData, 32+8, {
+ payment_secret,
+ total_msat
+});
+
impl Writeable for OnionHopData {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
w.size_hint(33);
(6, short_channel_id)
});
},
- OnionHopDataFormat::FinalNode => {
- encode_varint_length_prefixed_tlv!(w, {
- (2, HighZeroBytesDroppedVarInt(self.amt_to_forward)),
- (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value))
- });
+ OnionHopDataFormat::FinalNode { ref payment_data } => {
+ if let &Some(ref final_data) = payment_data {
+ encode_varint_length_prefixed_tlv!(w, {
+ (2, HighZeroBytesDroppedVarInt(self.amt_to_forward)),
+ (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value)),
+ (8, final_data)
+ });
+ } else {
+ encode_varint_length_prefixed_tlv!(w, {
+ (2, HighZeroBytesDroppedVarInt(self.amt_to_forward)),
+ (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value))
+ });
+ }
},
}
match self.format {
let mut amt = HighZeroBytesDroppedVarInt(0u64);
let mut cltv_value = HighZeroBytesDroppedVarInt(0u32);
let mut short_id: Option<u64> = None;
+ let mut payment_data: Option<FinalOnionHopData> = None;
decode_tlv!(&mut rd, {
(2, amt),
(4, cltv_value)
}, {
- (6, short_id)
+ (6, short_id),
+ (8, payment_data)
});
rd.eat_remaining().map_err(|_| DecodeError::ShortRead)?;
let format = if let Some(short_channel_id) = short_id {
+ if payment_data.is_some() { return Err(DecodeError::InvalidValue); }
OnionHopDataFormat::NonFinalNode {
short_channel_id,
}
} else {
- OnionHopDataFormat::FinalNode
+ OnionHopDataFormat::FinalNode {
+ payment_data
+ }
};
(format, amt.0, cltv_value.0)
} else {
#[test]
fn encoding_final_onion_hop_data() {
let mut msg = msgs::OnionHopData {
- format: OnionHopDataFormat::FinalNode,
+ format: OnionHopDataFormat::FinalNode {
+ payment_data: None,
+ },
amt_to_forward: 0x0badf00d01020304,
outgoing_cltv_value: 0xffffffff,
};
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 = msg.format { } else { panic!(); }
+ 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);
}