use util::events::{MessageSendEvent, MessageSendEventsProvider};
use util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK};
-use std::{cmp, fmt};
+use prelude::*;
+use alloc::collections::{BTreeMap, btree_map::Entry as BtreeEntry};
+use core::{cmp, fmt};
use std::sync::{RwLock, RwLockReadGuard};
-use std::sync::atomic::{AtomicUsize, Ordering};
+use core::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;
-use std::collections::BTreeMap;
-use std::collections::btree_map::Entry as BtreeEntry;
-use std::ops::Deref;
+use core::ops::Deref;
use bitcoin::hashes::hex::ToHex;
/// The maximum number of extra bytes which we do not understand in a gossip message before we will
};
}
-impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger {
+impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger {
fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, LightningError> {
self.network_graph.write().unwrap().update_node_from_announcement(msg, &self.secp_ctx)?;
Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY &&
let mut pending_events = self.pending_events.lock().unwrap();
let batch_count = batches.len();
for (batch_index, batch) in batches.into_iter().enumerate() {
- // Per spec, the initial first_blocknum needs to be <= the query's first_blocknum.
- // Use the query's values since we don't use pre-processed reply ranges.
- let first_blocknum = if batch_index == 0 {
- msg.first_blocknum
- }
- // Subsequent replies must be >= the last sent first_blocknum. Use the first block
- // in the new batch. Batches beyond the first one cannot be empty.
- else {
- block_from_scid(batch.first().unwrap())
- };
-
- // Per spec, the last end_blocknum needs to be >= the query's end_blocknum. Last
- // reply calculates difference between the query's end_blocknum and the start of the reply.
- // Overflow safe since end_blocknum=msg.first_block_num+msg.number_of_blocks and first_blocknum
- // will be either msg.first_blocknum or a higher block height.
+ // Per spec, the initial first_blocknum needs to be <= the query's first_blocknum and subsequent
+ // must be >= the prior reply. We'll simplify this by using zero since its still spec compliant and
+ // sequence completion is now explicitly.
+ let first_blocknum = 0;
+
+ // Per spec, the final end_blocknum needs to be >= the query's end_blocknum, so we'll use the
+ // query's value. Prior batches must use the number of blocks that fit into the message. We'll
+ // base this off the last SCID in the batch since we've somewhat abusing first_blocknum.
let number_of_blocks = if batch_index == batch_count-1 {
- msg.end_blocknum() - first_blocknum
- }
- // Prior replies should use the number of blocks that fit into the reply. Overflow
- // safe since first_blocknum is always <= last SCID's block.
- else {
- block_from_scid(batch.last().unwrap()) - first_blocknum + 1
+ msg.end_blocknum()
+ } else {
+ block_from_scid(batch.last().unwrap()) + 1
};
// Only true for the last message in a sequence
fn get_and_clear_pending_msg_events(&self) -> Vec<MessageSendEvent> {
let mut ret = Vec::new();
let mut pending_events = self.pending_events.lock().unwrap();
- std::mem::swap(&mut ret, &mut pending_events);
+ core::mem::swap(&mut ret, &mut pending_events);
ret
}
}
}
}
-impl_writeable!(DirectionalChannelInfo, 0, {
- last_update,
- enabled,
- cltv_expiry_delta,
- htlc_minimum_msat,
- htlc_maximum_msat,
- fees,
- last_update_message
-});
+impl_writeable_tlv_based!(DirectionalChannelInfo, {
+ (0, last_update),
+ (2, enabled),
+ (4, cltv_expiry_delta),
+ (6, htlc_minimum_msat),
+ (8, htlc_maximum_msat),
+ (10, fees),
+ (12, last_update_message),
+}, {}, {});
#[derive(Clone, Debug, PartialEq)]
/// Details about a channel (both directions).
}
}
-impl_writeable!(ChannelInfo, 0, {
- features,
- node_one,
- one_to_two,
- node_two,
- two_to_one,
- capacity_sats,
- announcement_message
-});
+impl_writeable_tlv_based!(ChannelInfo, {
+ (0, features),
+ (2, node_one),
+ (4, one_to_two),
+ (6, node_two),
+ (8, two_to_one),
+ (10, capacity_sats),
+ (12, announcement_message),
+}, {}, {});
/// Fees for routing via a given channel or a node
pub proportional_millionths: u32,
}
-impl Readable for RoutingFees{
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<RoutingFees, DecodeError> {
- let base_msat: u32 = Readable::read(reader)?;
- let proportional_millionths: u32 = Readable::read(reader)?;
- Ok(RoutingFees {
- base_msat,
- proportional_millionths,
- })
- }
-}
-
-impl Writeable for RoutingFees {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- self.base_msat.write(writer)?;
- self.proportional_millionths.write(writer)?;
- Ok(())
- }
-}
+impl_writeable_tlv_based!(RoutingFees, {(0, base_msat), (2, proportional_millionths)}, {}, {});
#[derive(Clone, Debug, PartialEq)]
/// Information received in the latest node_announcement from this node.
pub announcement_message: Option<NodeAnnouncement>
}
-impl Writeable for NodeAnnouncementInfo {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- self.features.write(writer)?;
- self.last_update.write(writer)?;
- self.rgb.write(writer)?;
- self.alias.write(writer)?;
- (self.addresses.len() as u64).write(writer)?;
- for ref addr in &self.addresses {
- addr.write(writer)?;
- }
- self.announcement_message.write(writer)?;
- Ok(())
- }
-}
-
-impl Readable for NodeAnnouncementInfo {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<NodeAnnouncementInfo, DecodeError> {
- let features = Readable::read(reader)?;
- let last_update = Readable::read(reader)?;
- let rgb = Readable::read(reader)?;
- let alias = Readable::read(reader)?;
- let addresses_count: u64 = Readable::read(reader)?;
- let mut addresses = Vec::with_capacity(cmp::min(addresses_count, MAX_ALLOC_SIZE / 40) as usize);
- for _ in 0..addresses_count {
- match Readable::read(reader) {
- Ok(Ok(addr)) => { addresses.push(addr); },
- Ok(Err(_)) => return Err(DecodeError::InvalidValue),
- Err(DecodeError::ShortRead) => return Err(DecodeError::BadLengthDescriptor),
- _ => unreachable!(),
- }
- }
- let announcement_message = Readable::read(reader)?;
- Ok(NodeAnnouncementInfo {
- features,
- last_update,
- rgb,
- alias,
- addresses,
- announcement_message
- })
- }
-}
+impl_writeable_tlv_based!(NodeAnnouncementInfo, {
+ (0, features),
+ (2, last_update),
+ (4, rgb),
+ (6, alias),
+}, {
+ (8, announcement_message),
+}, {
+ (10, addresses),
+});
#[derive(Clone, Debug, PartialEq)]
/// Details about a node in the network, known from the network announcement.
}
}
-impl Writeable for NodeInfo {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- (self.channels.len() as u64).write(writer)?;
- for ref chan in self.channels.iter() {
- chan.write(writer)?;
- }
- self.lowest_inbound_channel_fees.write(writer)?;
- self.announcement_info.write(writer)?;
- Ok(())
- }
-}
-
-const MAX_ALLOC_SIZE: u64 = 64*1024;
+impl_writeable_tlv_based!(NodeInfo, {}, {
+ (0, lowest_inbound_channel_fees),
+ (2, announcement_info),
+}, {
+ (4, channels),
+});
-impl Readable for NodeInfo {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<NodeInfo, DecodeError> {
- let channels_count: u64 = Readable::read(reader)?;
- let mut channels = Vec::with_capacity(cmp::min(channels_count, MAX_ALLOC_SIZE / 8) as usize);
- for _ in 0..channels_count {
- channels.push(Readable::read(reader)?);
- }
- let lowest_inbound_channel_fees = Readable::read(reader)?;
- let announcement_info = Readable::read(reader)?;
- Ok(NodeInfo {
- channels,
- lowest_inbound_channel_fees,
- announcement_info,
- })
- }
-}
+const SERIALIZATION_VERSION: u8 = 1;
+const MIN_SERIALIZATION_VERSION: u8 = 1;
impl Writeable for NetworkGraph {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+ write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
+
self.genesis_hash.write(writer)?;
(self.channels.len() as u64).write(writer)?;
for (ref chan_id, ref chan_info) in self.channels.iter() {
node_id.write(writer)?;
node_info.write(writer)?;
}
+
+ write_tlv_fields!(writer, {}, {});
Ok(())
}
}
impl Readable for NetworkGraph {
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<NetworkGraph, DecodeError> {
+ let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
+
let genesis_hash: BlockHash = Readable::read(reader)?;
let channels_count: u64 = Readable::read(reader)?;
let mut channels = BTreeMap::new();
let node_info = Readable::read(reader)?;
nodes.insert(node_id, node_info);
}
+ read_tlv_fields!(reader, {}, {});
+
Ok(NetworkGraph {
genesis_hash,
channels,
use bitcoin::secp256k1::key::{PublicKey, SecretKey};
use bitcoin::secp256k1::{All, Secp256k1};
+ use prelude::*;
use std::sync::Arc;
fn create_net_graph_msg_handler() -> (Secp256k1<All>, NetGraphMsgHandler<Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>) {
// used for testing resumption on same block
scids.push(scid_from_parts(108001, 1, 0).unwrap());
- scids.push(scid_from_parts(108001, 2, 0).unwrap());
for scid in scids {
let unsigned_announcement = UnsignedChannelAnnouncement {
vec![
ReplyChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 0xffffff,
- number_of_blocks: 1,
+ first_blocknum: 0,
+ number_of_blocks: 0x01000000,
sync_complete: true,
short_channel_ids: vec![]
},
&node_id_2,
QueryChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 0x00800000,
+ first_blocknum: 1000,
number_of_blocks: 1000,
},
true,
vec![
ReplyChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 0x00800000,
- number_of_blocks: 1000,
+ first_blocknum: 0,
+ number_of_blocks: 2000,
sync_complete: true,
short_channel_ids: vec![],
}
vec![
ReplyChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 0xfe0000,
- number_of_blocks: 0xffffffff - 0xfe0000,
+ first_blocknum: 0,
+ number_of_blocks: 0xffffffff,
sync_complete: true,
short_channel_ids: vec![
0xfffffe_ffffff_ffff, // max
vec![
ReplyChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 100000,
- number_of_blocks: 8000,
+ first_blocknum: 0,
+ number_of_blocks: 108000,
sync_complete: true,
short_channel_ids: (100000..=107999)
.map(|block| scid_from_parts(block, 0, 0).unwrap())
vec![
ReplyChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 100000,
- number_of_blocks: 8000,
+ first_blocknum: 0,
+ number_of_blocks: 108000,
sync_complete: false,
short_channel_ids: (100000..=107999)
.map(|block| scid_from_parts(block, 0, 0).unwrap())
},
ReplyChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 108000,
- number_of_blocks: 1,
+ first_blocknum: 0,
+ number_of_blocks: 108001,
sync_complete: true,
short_channel_ids: vec![
scid_from_parts(108000, 0, 0).unwrap(),
vec![
ReplyChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 100002,
- number_of_blocks: 8000,
+ first_blocknum: 0,
+ number_of_blocks: 108002,
sync_complete: false,
short_channel_ids: (100002..=108001)
.map(|block| scid_from_parts(block, 0, 0).unwrap())
},
ReplyChannelRange {
chain_hash: chain_hash.clone(),
- first_blocknum: 108001,
- number_of_blocks: 1,
+ first_blocknum: 0,
+ number_of_blocks: 108002,
sync_complete: true,
short_channel_ids: vec![
scid_from_parts(108001, 1, 0).unwrap(),
- scid_from_parts(108001, 2, 0).unwrap(),
],
}
]
assert!(result.is_err());
}
}
+
+#[cfg(all(test, feature = "unstable"))]
+mod benches {
+ use super::*;
+
+ use test::Bencher;
+ use std::io::Read;
+
+ #[bench]
+ fn read_network_graph(bench: &mut Bencher) {
+ let mut d = ::routing::router::test_utils::get_route_file().unwrap();
+ let mut v = Vec::new();
+ d.read_to_end(&mut v).unwrap();
+ bench.iter(|| {
+ let _ = NetworkGraph::read(&mut std::io::Cursor::new(&v)).unwrap();
+ });
+ }
+
+ #[bench]
+ fn write_network_graph(bench: &mut Bencher) {
+ let mut d = ::routing::router::test_utils::get_route_file().unwrap();
+ let net_graph = NetworkGraph::read(&mut d).unwrap();
+ bench.iter(|| {
+ let _ = net_graph.encode();
+ });
+ }
+}