Skip to content

Commit c4d771e

Browse files
committed
Adding gossip_queries message structs and serialization.
This adds the message structs and implements Readable and Writeable traits for the standard gossip_queries messages.
1 parent 3defcc8 commit c4d771e

File tree

1 file changed

+346
-0
lines changed

1 file changed

+346
-0
lines changed

lightning/src/ln/msgs.rs

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,71 @@ pub struct ChannelUpdate {
570570
pub contents: UnsignedChannelUpdate,
571571
}
572572

573+
/// A query_channel_range message that can be sent or received from a peer
574+
#[derive(PartialEq, Clone, Debug)]
575+
pub struct QueryChannelRange {
576+
/// The genesis hash of the blockchain being queried
577+
pub chain_hash: BlockHash,
578+
/// The height of the first block to be queried
579+
pub first_blocknum: u32,
580+
/// The number of blocks to include in the query results
581+
pub number_of_blocks: u32,
582+
}
583+
584+
/// A reply_channel_range message that can be sent or received from a peer.
585+
/// Multiple reply_channel_range messages can be sent in reply to a single
586+
/// query_channel_range message.
587+
#[derive(PartialEq, Clone, Debug)]
588+
pub struct ReplyChannelRange {
589+
/// The genesis hash of the blockchain being queried
590+
pub chain_hash: BlockHash,
591+
/// The height of the first block for the range of the reply
592+
pub first_blocknum: u32,
593+
/// The number of blocks included in for the range of the reply
594+
pub number_of_blocks: u32,
595+
/// Indicates if the query was able to be served
596+
pub full_information: bool,
597+
/// The short_channel_ids in the channel range
598+
pub short_channel_ids: Vec<u64>,
599+
}
600+
601+
/// A query_short_channel_ids that can be seent or received from a peer
602+
#[derive(PartialEq, Clone, Debug)]
603+
pub struct QueryShortChannelIds {
604+
/// The genesis hash of the blockchain being queried
605+
pub chain_hash: BlockHash,
606+
/// The short_channel_ids that are being queried
607+
pub short_channel_ids: Vec<u64>,
608+
}
609+
610+
/// A reply_short_channel_ids_end message that can be sent or received from a peer.
611+
/// This message is sent as a reply to a query_short_channel_ids message.
612+
#[derive(PartialEq, Clone, Debug)]
613+
pub struct ReplyShortChannelIdsEnd {
614+
/// The genesis hash of the blockchain that was queried
615+
pub chain_hash: BlockHash,
616+
/// Indicates if the query was able to be served
617+
pub full_information: bool,
618+
}
619+
620+
/// A gossip_timestamp_filter message is used by a node to request
621+
/// gossip relay for messages in the requested time range when the
622+
/// gossip_queries feature has been negotiated.
623+
#[derive(PartialEq, Clone, Debug)]
624+
pub struct GossipTimestampFilter {
625+
/// The genesis hash of the blockchain for channel and node information
626+
pub chain_hash: BlockHash,
627+
/// The starting unix timestamp
628+
pub first_timestamp: u32,
629+
/// The range of information in seconds
630+
pub timestamp_range: u32,
631+
}
632+
633+
/// Encoding type for data compression of collections in gossip queries
634+
enum EncodingType {
635+
Uncompressed = 0x00,
636+
}
637+
573638
/// Used to put an error message in a LightningError
574639
#[derive(Clone)]
575640
pub enum ErrorAction {
@@ -1515,6 +1580,165 @@ impl_writeable_len_match!(NodeAnnouncement, {
15151580
contents
15161581
});
15171582

1583+
impl Readable for QueryShortChannelIds {
1584+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
1585+
let chain_hash: BlockHash = Readable::read(r)?;
1586+
1587+
let mut encoding_len: u16 = Readable::read(r)?;
1588+
let encoding_type: u8 = Readable::read(r)?;
1589+
if encoding_type != EncodingType::Uncompressed as u8 {
1590+
return Err(DecodeError::InvalidValue);
1591+
}
1592+
encoding_len -= 1;
1593+
let mut read_len = 0;
1594+
let mut short_channel_ids = vec![];
1595+
loop {
1596+
if read_len >= encoding_len { break; }
1597+
short_channel_ids.push(Readable::read(r)?);
1598+
read_len += 8;
1599+
}
1600+
1601+
Ok(QueryShortChannelIds {
1602+
chain_hash,
1603+
short_channel_ids,
1604+
})
1605+
}
1606+
}
1607+
1608+
impl Writeable for QueryShortChannelIds {
1609+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
1610+
let encoding_len: u16 = 1 + self.short_channel_ids.len() as u16 * 8;
1611+
w.size_hint(32 + 2 + encoding_len as usize);
1612+
self.chain_hash.write(w)?;
1613+
1614+
encoding_len.write(w)?;
1615+
(EncodingType::Uncompressed as u8).write(w)?;
1616+
for scid in self.short_channel_ids.iter() {
1617+
scid.write(w)?;
1618+
}
1619+
1620+
Ok(())
1621+
}
1622+
}
1623+
1624+
impl Readable for ReplyShortChannelIdsEnd {
1625+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
1626+
let chain_hash: BlockHash = Readable::read(r)?;
1627+
let full_information: bool = Readable::read(r)?;
1628+
Ok(ReplyShortChannelIdsEnd {
1629+
chain_hash,
1630+
full_information,
1631+
})
1632+
}
1633+
}
1634+
1635+
impl Writeable for ReplyShortChannelIdsEnd {
1636+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
1637+
w.size_hint(32 + 1);
1638+
self.chain_hash.write(w)?;
1639+
self.full_information.write(w)?;
1640+
Ok(())
1641+
}
1642+
}
1643+
1644+
impl Readable for QueryChannelRange {
1645+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
1646+
let chain_hash: BlockHash = Readable::read(r)?;
1647+
let first_blocknum: u32 = Readable::read(r)?;
1648+
let number_of_blocks: u32 = Readable::read(r)?;
1649+
Ok(QueryChannelRange {
1650+
chain_hash,
1651+
first_blocknum,
1652+
number_of_blocks
1653+
})
1654+
}
1655+
}
1656+
1657+
impl Writeable for QueryChannelRange {
1658+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
1659+
w.size_hint(32 + 4 + 4);
1660+
self.chain_hash.write(w)?;
1661+
self.first_blocknum.write(w)?;
1662+
self.number_of_blocks.write(w)?;
1663+
Ok(())
1664+
}
1665+
}
1666+
1667+
impl Readable for ReplyChannelRange {
1668+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
1669+
let chain_hash: BlockHash = Readable::read(r)?;
1670+
let first_blocknum: u32 = Readable::read(r)?;
1671+
let number_of_blocks: u32 = Readable::read(r)?;
1672+
let full_information: bool = Readable::read(r)?;
1673+
1674+
let mut encoding_len: u16 = Readable::read(r)?;
1675+
let encoding_type: u8 = Readable::read(r)?;
1676+
if encoding_type != EncodingType::Uncompressed as u8 {
1677+
return Err(DecodeError::InvalidValue);
1678+
}
1679+
encoding_len -= 1;
1680+
let mut read_len = 0;
1681+
let mut short_channel_ids = vec![];
1682+
loop {
1683+
if read_len >= encoding_len { break; }
1684+
short_channel_ids.push(Readable::read(r)?);
1685+
read_len += 8;
1686+
}
1687+
1688+
Ok(ReplyChannelRange {
1689+
chain_hash,
1690+
first_blocknum,
1691+
number_of_blocks,
1692+
full_information,
1693+
short_channel_ids
1694+
})
1695+
}
1696+
}
1697+
1698+
impl Writeable for ReplyChannelRange {
1699+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
1700+
w.size_hint(32 + 4 + 4);
1701+
let encoding_len: u16 = 1 + self.short_channel_ids.len() as u16 * 8;
1702+
w.size_hint(32 + 4 + 4 + 1 + 2 + encoding_len as usize);
1703+
self.chain_hash.write(w)?;
1704+
self.first_blocknum.write(w)?;
1705+
self.number_of_blocks.write(w)?;
1706+
self.full_information.write(w)?;
1707+
1708+
encoding_len.write(w)?;
1709+
(EncodingType::Uncompressed as u8).write(w)?;
1710+
for scid in self.short_channel_ids.iter() {
1711+
scid.write(w)?;
1712+
}
1713+
1714+
Ok(())
1715+
}
1716+
}
1717+
1718+
impl Readable for GossipTimestampFilter {
1719+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
1720+
let chain_hash: BlockHash = Readable::read(r)?;
1721+
let first_timestamp: u32 = Readable::read(r)?;
1722+
let timestamp_range: u32 = Readable::read(r)?;
1723+
Ok(GossipTimestampFilter {
1724+
chain_hash,
1725+
first_timestamp,
1726+
timestamp_range,
1727+
})
1728+
}
1729+
}
1730+
1731+
impl Writeable for GossipTimestampFilter {
1732+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
1733+
w.size_hint(32 + 4 + 4);
1734+
self.chain_hash.write(w)?;
1735+
self.first_timestamp.write(w)?;
1736+
self.timestamp_range.write(w)?;
1737+
Ok(())
1738+
}
1739+
}
1740+
1741+
15181742
#[cfg(test)]
15191743
mod tests {
15201744
use hex;
@@ -2246,4 +2470,126 @@ mod tests {
22462470
assert_eq!(msg.amt_to_forward, 0x0badf00d01020304);
22472471
assert_eq!(msg.outgoing_cltv_value, 0xffffffff);
22482472
}
2473+
2474+
#[test]
2475+
fn encoding_query_channel_range() {
2476+
let mut query_channel_range = msgs::QueryChannelRange {
2477+
chain_hash: BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap(),
2478+
first_blocknum: 100000,
2479+
number_of_blocks: 1500,
2480+
};
2481+
let encoded_value = query_channel_range.encode();
2482+
let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206000186a0000005dc").unwrap();
2483+
assert_eq!(encoded_value, target_value);
2484+
2485+
query_channel_range = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
2486+
assert_eq!(query_channel_range.first_blocknum, 100000);
2487+
assert_eq!(query_channel_range.number_of_blocks, 1500);
2488+
}
2489+
2490+
#[test]
2491+
fn encoding_reply_channel_range() {
2492+
do_encoding_reply_channel_range(0);
2493+
do_encoding_reply_channel_range(1);
2494+
}
2495+
2496+
fn do_encoding_reply_channel_range(encoding_type: u8) {
2497+
let mut target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206000b8a06000005dc01").unwrap();
2498+
let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
2499+
let mut reply_channel_range = msgs::ReplyChannelRange {
2500+
chain_hash: expected_chain_hash,
2501+
first_blocknum: 756230,
2502+
number_of_blocks: 1500,
2503+
full_information: true,
2504+
short_channel_ids: vec![0x000000000000008e, 0x0000000000003c69, 0x000000000045a6c4],
2505+
};
2506+
2507+
if encoding_type == 0 {
2508+
target_value.append(&mut hex::decode("001900000000000000008e0000000000003c69000000000045a6c4").unwrap());
2509+
let encoded_value = reply_channel_range.encode();
2510+
assert_eq!(encoded_value, target_value);
2511+
2512+
reply_channel_range = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
2513+
assert_eq!(reply_channel_range.chain_hash, expected_chain_hash);
2514+
assert_eq!(reply_channel_range.first_blocknum, 756230);
2515+
assert_eq!(reply_channel_range.number_of_blocks, 1500);
2516+
assert_eq!(reply_channel_range.full_information, true);
2517+
assert_eq!(reply_channel_range.short_channel_ids[0], 0x000000000000008e);
2518+
assert_eq!(reply_channel_range.short_channel_ids[1], 0x0000000000003c69);
2519+
assert_eq!(reply_channel_range.short_channel_ids[2], 0x000000000045a6c4);
2520+
} else {
2521+
target_value.append(&mut hex::decode("001601789c636000833e08659309a65878be010010a9023a").unwrap());
2522+
let result: Result<msgs::ReplyChannelRange, msgs::DecodeError> = Readable::read(&mut Cursor::new(&target_value[..]));
2523+
if result.is_ok() {
2524+
panic!("Expected decode failure with unsupported zlib encoding");
2525+
};
2526+
}
2527+
}
2528+
2529+
#[test]
2530+
fn encoding_query_short_channel_ids() {
2531+
do_encoding_query_short_channel_ids(0);
2532+
do_encoding_query_short_channel_ids(1);
2533+
}
2534+
2535+
fn do_encoding_query_short_channel_ids(encoding_type: u8) {
2536+
let mut target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206").unwrap();
2537+
let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
2538+
let mut query_short_channel_ids = msgs::QueryShortChannelIds {
2539+
chain_hash: expected_chain_hash,
2540+
short_channel_ids: vec![0x0000000000008e, 0x0000000000003c69, 0x000000000045a6c4],
2541+
};
2542+
2543+
if encoding_type == 0 {
2544+
target_value.append(&mut hex::decode("001900000000000000008e0000000000003c69000000000045a6c4").unwrap());
2545+
let encoded_value = query_short_channel_ids.encode();
2546+
assert_eq!(encoded_value, target_value);
2547+
2548+
query_short_channel_ids = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
2549+
assert_eq!(query_short_channel_ids.chain_hash, expected_chain_hash);
2550+
assert_eq!(query_short_channel_ids.short_channel_ids[0], 0x000000000000008e);
2551+
assert_eq!(query_short_channel_ids.short_channel_ids[1], 0x0000000000003c69);
2552+
assert_eq!(query_short_channel_ids.short_channel_ids[2], 0x000000000045a6c4);
2553+
} else {
2554+
target_value.append(&mut hex::decode("001601789c636000833e08659309a65878be010010a9023a").unwrap());
2555+
let result: Result<msgs::ReplyChannelRange, msgs::DecodeError> = Readable::read(&mut Cursor::new(&target_value[..]));
2556+
if result.is_ok() {
2557+
panic!("Expected decode failure with unsupported zlib encoding");
2558+
};
2559+
}
2560+
}
2561+
2562+
#[test]
2563+
fn encoding_reply_short_channel_ids_end() {
2564+
let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
2565+
let mut reply_short_channel_ids_end = msgs::ReplyShortChannelIdsEnd {
2566+
chain_hash: expected_chain_hash,
2567+
full_information: true,
2568+
};
2569+
let encoded_value = reply_short_channel_ids_end.encode();
2570+
let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e220601").unwrap();
2571+
assert_eq!(encoded_value, target_value);
2572+
2573+
reply_short_channel_ids_end = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
2574+
assert_eq!(reply_short_channel_ids_end.chain_hash, expected_chain_hash);
2575+
assert_eq!(reply_short_channel_ids_end.full_information, true);
2576+
}
2577+
2578+
#[test]
2579+
fn encoding_gossip_timestamp_filter(){
2580+
let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
2581+
let mut gossip_timestamp_filter = msgs::GossipTimestampFilter {
2582+
chain_hash: expected_chain_hash,
2583+
first_timestamp: 1590000000,
2584+
timestamp_range: 0xffff_ffff,
2585+
};
2586+
let encoded_value = gossip_timestamp_filter.encode();
2587+
let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e22065ec57980ffffffff").unwrap();
2588+
assert_eq!(encoded_value, target_value);
2589+
2590+
gossip_timestamp_filter = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
2591+
assert_eq!(gossip_timestamp_filter.chain_hash, expected_chain_hash);
2592+
assert_eq!(gossip_timestamp_filter.first_timestamp, 1590000000);
2593+
assert_eq!(gossip_timestamp_filter.timestamp_range, 0xffff_ffff);
2594+
}
22492595
}

0 commit comments

Comments
 (0)