Showing 2 of 3 files from the diff.

@@ -237,13 +237,12 @@
Loading
237 237
					let mut total_fee = $starting_fee_msat as u64;
238 238
					let hm_entry = dist.entry(&$src_node_id);
239 239
					let old_entry = hm_entry.or_insert_with(|| {
240 -
						let node = network.get_nodes().get(&$src_node_id).unwrap();
241 240
						let mut fee_base_msat = u32::max_value();
242 241
						let mut fee_proportional_millionths = u32::max_value();
243 -
						if let Some(fees) = node.lowest_inbound_channel_fees {
242 +
						if let Some(fees) = network.get_nodes().get(&$src_node_id).and_then(|node| node.lowest_inbound_channel_fees) {
244 243
							fee_base_msat = fees.base_msat;
245 244
							fee_proportional_millionths = fees.proportional_millionths;
246 -
						};
245 +
						}
247 246
						(u64::max_value(),
248 247
							fee_base_msat,
249 248
							fee_proportional_millionths,
@@ -342,21 +341,26 @@
Loading
342 341
	}
343 342
344 343
	for hop in last_hops.iter() {
345 -
		if first_hops.is_none() || hop.src_node_id != *our_node_id { // first_hop overrules last_hops
346 -
			if network.get_nodes().get(&hop.src_node_id).is_some() {
347 -
				if first_hops.is_some() {
348 -
					if let Some(&(ref first_hop, ref features)) = first_hop_targets.get(&hop.src_node_id) {
349 -
						// Currently there are no channel-context features defined, so we are a
350 -
						// bit lazy here. In the future, we should pull them out via our
351 -
						// ChannelManager, but there's no reason to waste the space until we
352 -
						// need them.
353 -
						add_entry!(first_hop, *our_node_id , hop.src_node_id, dummy_directional_info, features.to_context(), 0);
354 -
					}
355 -
				}
356 -
				// BOLT 11 doesn't allow inclusion of features for the last hop hints, which
357 -
				// really sucks, cause we're gonna need that eventually.
358 -
				add_entry!(hop.short_channel_id, hop.src_node_id, target, hop, ChannelFeatures::empty(), 0);
359 -
			}
344 +
		let have_hop_src_in_graph =
345 +
			if let Some(&(ref first_hop, ref features)) = first_hop_targets.get(&hop.src_node_id) {
346 +
				// If this hop connects to a node with which we have a direct channel, ignore the
347 +
				// network graph and add both the hop and our direct channel to the candidate set:
348 +
				//
349 +
				// Currently there are no channel-context features defined, so we are a
350 +
				// bit lazy here. In the future, we should pull them out via our
351 +
				// ChannelManager, but there's no reason to waste the space until we
352 +
				// need them.
353 +
				add_entry!(first_hop, *our_node_id , hop.src_node_id, dummy_directional_info, features.to_context(), 0);
354 +
				true
355 +
			} else {
356 +
				// In any other case, only add the hop if the source is in the regular network
357 +
				// graph:
358 +
				network.get_nodes().get(&hop.src_node_id).is_some()
359 +
			};
360 +
		if have_hop_src_in_graph {
361 +
			// BOLT 11 doesn't allow inclusion of features for the last hop hints, which
362 +
			// really sucks, cause we're gonna need that eventually.
363 +
			add_entry!(hop.short_channel_id, hop.src_node_id, target, hop, ChannelFeatures::empty(), 0);
360 364
		}
361 365
	}
362 366
@@ -412,7 +416,7 @@
Loading
412 416
#[cfg(test)]
413 417
mod tests {
414 418
	use routing::router::{get_route, RouteHint, RoutingFees};
415 -
	use routing::network_graph::NetGraphMsgHandler;
419 +
	use routing::network_graph::{NetworkGraph, NetGraphMsgHandler};
416 420
	use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
417 421
	use ln::msgs::{ErrorAction, LightningError, OptionalField, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler,
418 422
	   NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate};
@@ -1222,4 +1226,54 @@
Loading
1222 1226
		assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
1223 1227
		assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
1224 1228
	}
1229 +
1230 +
	#[test]
1231 +
	fn unannounced_path_test() {
1232 +
		// We should be able to send a payment to a destination without any help of a routing graph
1233 +
		// if we have a channel with a common counterparty that appears in the first and last hop
1234 +
		// hints.
1235 +
		let source_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&hex::decode(format!("{:02}", 41).repeat(32)).unwrap()[..]).unwrap());
1236 +
		let middle_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&hex::decode(format!("{:02}", 42).repeat(32)).unwrap()[..]).unwrap());
1237 +
		let target_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&hex::decode(format!("{:02}", 43).repeat(32)).unwrap()[..]).unwrap());
1238 +
1239 +
		// If we specify a channel to a middle hop, that overrides our local channel view and that gets used
1240 +
		let last_hops = vec![RouteHint {
1241 +
			src_node_id: middle_node_id,
1242 +
			short_channel_id: 8,
1243 +
			fees: RoutingFees {
1244 +
				base_msat: 1000,
1245 +
				proportional_millionths: 0,
1246 +
			},
1247 +
			cltv_expiry_delta: (8 << 8) | 1,
1248 +
			htlc_minimum_msat: 0,
1249 +
		}];
1250 +
		let our_chans = vec![channelmanager::ChannelDetails {
1251 +
			channel_id: [0; 32],
1252 +
			short_channel_id: Some(42),
1253 +
			remote_network_id: middle_node_id,
1254 +
			counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
1255 +
			channel_value_satoshis: 100000,
1256 +
			user_id: 0,
1257 +
			outbound_capacity_msat: 100000,
1258 +
			inbound_capacity_msat: 100000,
1259 +
			is_live: true,
1260 +
		}];
1261 +
		let route = get_route(&source_node_id, &NetworkGraph::new(), &target_node_id, Some(&our_chans.iter().collect::<Vec<_>>()), &last_hops.iter().collect::<Vec<_>>(), 100, 42, Arc::new(test_utils::TestLogger::new())).unwrap();
1262 +
1263 +
		assert_eq!(route.paths[0].len(), 2);
1264 +
1265 +
		assert_eq!(route.paths[0][0].pubkey, middle_node_id);
1266 +
		assert_eq!(route.paths[0][0].short_channel_id, 42);
1267 +
		assert_eq!(route.paths[0][0].fee_msat, 1000);
1268 +
		assert_eq!(route.paths[0][0].cltv_expiry_delta, (8 << 8) | 1);
1269 +
		assert_eq!(route.paths[0][0].node_features.le_flags(), &[0b11]);
1270 +
		assert_eq!(route.paths[0][0].channel_features.le_flags(), &[0; 0]); // We can't learn any flags from invoices, sadly
1271 +
1272 +
		assert_eq!(route.paths[0][1].pubkey, target_node_id);
1273 +
		assert_eq!(route.paths[0][1].short_channel_id, 8);
1274 +
		assert_eq!(route.paths[0][1].fee_msat, 100);
1275 +
		assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
1276 +
		assert_eq!(route.paths[0][1].node_features.le_flags(), &[0; 0]); // We dont pass flags in from invoices yet
1277 +
		assert_eq!(route.paths[0][1].channel_features.le_flags(), &[0; 0]); // We can't learn any flags from invoices, sadly
1278 +
	}
1225 1279
}

@@ -562,9 +562,14 @@
Loading
562 562
		}
563 563
	}
564 564
565 -
	/// For an already known node (from channel announcements), update its stored properties from a given node announcement
565 +
	/// For an already known node (from channel announcements), update its stored properties from a given node announcement.
566 +
	///
567 +
	/// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's
568 +
	/// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept
569 +
	/// routing messages without checking their signatures.
570 +
	///
566 571
	/// Announcement signatures are checked here only if Secp256k1 object is provided.
567 -
	fn update_node_from_announcement(&mut self, msg: &msgs::NodeAnnouncement, secp_ctx: Option<&Secp256k1<secp256k1::VerifyOnly>>) -> Result<bool, LightningError> {
572 +
	pub fn update_node_from_announcement<T: secp256k1::Verification>(&mut self, msg: &msgs::NodeAnnouncement, secp_ctx: Option<&Secp256k1<T>>) -> Result<bool, LightningError> {
568 573
		if let Some(sig_verifier) = secp_ctx {
569 574
			let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
570 575
			secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &msg.contents.node_id);
@@ -594,13 +599,27 @@
Loading
594 599
		}
595 600
	}
596 601
597 -
	/// For a new or already known (from previous announcement) channel, store or update channel info.
598 -
	/// Also store nodes (if not stored yet) the channel is between, and make node aware of this channel.
599 -
	/// Checking utxo on-chain is useful if we receive an update for already known channel id,
600 -
	/// which is probably result of a reorg. In that case, we update channel info only if the
601 -
	/// utxo was checked, otherwise stick to the existing update, to prevent DoS risks.
602 +
	/// Store or update channel info from a channel announcement.
603 +
	///
604 +
	/// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's
605 +
	/// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept
606 +
	/// routing messages without checking their signatures.
607 +
	///
608 +
	/// If the channel has been confirmed to exist on chain (with correctly-formatted scripts on
609 +
	/// chain), set utxo_value to the value of the output on chain, otherwise leave it as None.
610 +
	/// The UTXO value is then used in routing calculation if we have no better information on the
611 +
	/// maximum HTLC value that can be sent over the channel.
612 +
	///
613 +
	/// Further, setting utxo_value to Some indicates that the announcement message is genuine,
614 +
	/// allowing us to update existing channel data in the case of reorgs or to replace bogus
615 +
	/// channel data generated by a DoS attacker.
616 +
	///
602 617
	/// Announcement signatures are checked here only if Secp256k1 object is provided.
603 -
	fn update_channel_from_announcement(&mut self, msg: &msgs::ChannelAnnouncement, utxo_value: Option<u64>, secp_ctx: Option<&Secp256k1<secp256k1::VerifyOnly>>) -> Result<bool, LightningError> {
618 +
	pub fn update_channel_from_announcement<T: secp256k1::Verification>(&mut self, msg: &msgs::ChannelAnnouncement, utxo_value: Option<u64>, secp_ctx: Option<&Secp256k1<T>>) -> Result<bool, LightningError> {
619 +
		if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 {
620 +
			return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError});
621 +
		}
622 +
604 623
		if let Some(sig_verifier) = secp_ctx {
605 624
			let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
606 625
			secp_verify_sig!(sig_verifier, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1);
@@ -699,8 +718,13 @@
Loading
699 718
	}
700 719
701 720
	/// For an already known (from announcement) channel, update info about one of the directions of a channel.
721 +
	///
722 +
	/// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's
723 +
	/// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept
724 +
	/// routing messages without checking their signatures.
725 +
	///
702 726
	/// Announcement signatures are checked here only if Secp256k1 object is provided.
703 -
	fn update_channel(&mut self, msg: &msgs::ChannelUpdate, secp_ctx: Option<&Secp256k1<secp256k1::VerifyOnly>>) -> Result<bool, LightningError> {
727 +
	pub fn update_channel(&mut self, msg: &msgs::ChannelUpdate, secp_ctx: Option<&Secp256k1<secp256k1::VerifyOnly>>) -> Result<bool, LightningError> {
704 728
		let dest_node_id;
705 729
		let chan_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
706 730
		let chan_was_enabled;
@@ -716,8 +740,8 @@
Loading
716 740
					if let Some(capacity_sats) = channel.capacity_sats {
717 741
						// It's possible channel capacity is available now, although it wasn't available at announcement (so the field is None).
718 742
						// Don't query UTXO set here to reduce DoS risks.
719 -
						if htlc_maximum_msat > capacity_sats * 1000 {
720 -
							return Err(LightningError{err: "htlc_maximum_msat is larger than channel capacity".to_owned(), action: ErrorAction::IgnoreError});
743 +
						if capacity_sats > MAX_VALUE_MSAT / 1000 || htlc_maximum_msat > capacity_sats * 1000 {
744 +
							return Err(LightningError{err: "htlc_maximum_msat is larger than channel capacity or capacity is bogus".to_owned(), action: ErrorAction::IgnoreError});
721 745
						}
722 746
					}
723 747
				}
@@ -1302,7 +1326,7 @@
Loading
1302 1326
1303 1327
		match net_graph_msg_handler.handle_channel_update(&valid_channel_update) {
1304 1328
			Ok(_) => panic!(),
1305 -
			Err(e) => assert_eq!(e.err, "htlc_maximum_msat is larger than channel capacity")
1329 +
			Err(e) => assert_eq!(e.err, "htlc_maximum_msat is larger than channel capacity or capacity is bogus")
1306 1330
		};
1307 1331
		unsigned_channel_update.htlc_maximum_msat = OptionalField::Absent;
1308 1332
Files Coverage
lightning/src 91.41%
Project Totals (37 files) 91.41%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading