invoice: swap RouteHop for RouteHint
authorValentine Wallace <vwallace@protonmail.com>
Fri, 16 Apr 2021 20:17:11 +0000 (16:17 -0400)
committerValentine Wallace <vwallace@protonmail.com>
Tue, 20 Apr 2021 20:26:52 +0000 (16:26 -0400)
To prevent naming conflicts in bindings

lightning-invoice/Cargo.toml
lightning-invoice/src/de.rs
lightning-invoice/src/lib.rs
lightning-invoice/src/ser.rs
lightning/src/routing/router.rs

index 47bf9d744dcb91f554a69400521e439759e03f66..758578ca465b5f6cf57e29440e5439002c0ced64 100644 (file)
@@ -10,6 +10,7 @@ readme = "README.md"
 
 [dependencies]
 bech32 = "0.7"
+lightning = { version = "0.0.13", path = "../lightning" }
 secp256k1 = { version = "0.20", features = ["recovery"] }
 num-traits = "0.2.8"
 bitcoin_hashes = "0.9.4"
index d6cb92072bc69fc56815c4ebd713f0ba1d29b562..df92cacd2a47e64c824fc3ce2b7cab87265d1c48 100644 (file)
@@ -10,6 +10,8 @@ use bech32::{u5, FromBase32};
 
 use bitcoin_hashes::Hash;
 use bitcoin_hashes::sha256;
+use lightning::routing::network_graph::RoutingFees;
+use lightning::routing::router::RouteHint;
 
 use num_traits::{CheckedAdd, CheckedMul};
 
@@ -353,7 +355,7 @@ impl FromBase32 for Signature {
        }
 }
 
-fn parse_int_be<T, U>(digits: &[U], base: T) -> Option<T>
+pub(crate) fn parse_int_be<T, U>(digits: &[U], base: T) -> Option<T>
        where T: CheckedAdd + CheckedMul + From<u8> + Default,
              U: Into<u8> + Copy
 {
@@ -575,7 +577,7 @@ impl FromBase32 for Route {
                        return Err(ParseError::UnexpectedEndOfTaggedFields);
                }
 
-               let mut route_hops = Vec::<RouteHop>::new();
+               let mut route_hops = Vec::<RouteHint>::new();
 
                let mut bytes = bytes.as_slice();
                while !bytes.is_empty() {
@@ -585,12 +587,16 @@ impl FromBase32 for Route {
                        let mut channel_id: [u8; 8] = Default::default();
                        channel_id.copy_from_slice(&hop_bytes[33..41]);
 
-                       let hop = RouteHop {
-                               pubkey: PublicKey::from_slice(&hop_bytes[0..33])?,
-                               short_channel_id: channel_id,
-                               fee_base_msat: parse_int_be(&hop_bytes[41..45], 256).expect("slice too big?"),
-                               fee_proportional_millionths: parse_int_be(&hop_bytes[45..49], 256).expect("slice too big?"),
-                               cltv_expiry_delta: parse_int_be(&hop_bytes[49..51], 256).expect("slice too big?")
+                       let hop = RouteHint {
+                               src_node_id: PublicKey::from_slice(&hop_bytes[0..33])?,
+                               short_channel_id: parse_int_be(&channel_id, 256).expect("short chan ID slice too big?"),
+                               fees: RoutingFees {
+                                       base_msat: parse_int_be(&hop_bytes[41..45], 256).expect("slice too big?"),
+                                       proportional_millionths: parse_int_be(&hop_bytes[45..49], 256).expect("slice too big?"),
+                               },
+                               cltv_expiry_delta: parse_int_be(&hop_bytes[49..51], 256).expect("slice too big?"),
+                               htlc_minimum_msat: None,
+                               htlc_maximum_msat: None,
                        };
 
                        route_hops.push(hop);
@@ -931,41 +937,51 @@ mod test {
 
        #[test]
        fn test_parse_route() {
-               use RouteHop;
+               use lightning::routing::network_graph::RoutingFees;
+               use lightning::routing::router::RouteHint;
                use ::Route;
                use bech32::FromBase32;
+               use de::parse_int_be;
 
                let input = from_bech32(
                        "q20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqa\
                        fqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq".as_bytes()
                );
 
-               let mut expected = Vec::<RouteHop>::new();
-               expected.push(RouteHop {
-                       pubkey: PublicKey::from_slice(
+               let mut expected = Vec::<RouteHint>::new();
+               expected.push(RouteHint {
+                       src_node_id: PublicKey::from_slice(
                                &[
                                        0x02u8, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c,
                                        0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3,
                                        0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55
                                ][..]
                        ).unwrap(),
-                       short_channel_id: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
-                       fee_base_msat: 1,
-                       fee_proportional_millionths: 20,
-                       cltv_expiry_delta: 3
+                       short_channel_id: parse_int_be(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08], 256).expect("short chan ID slice too big?"),
+                       fees: RoutingFees {
+                               base_msat: 1,
+                               proportional_millionths: 20,
+                       },
+                       cltv_expiry_delta: 3,
+                       htlc_minimum_msat: None,
+                       htlc_maximum_msat: None
                });
-               expected.push(RouteHop {
-                       pubkey: PublicKey::from_slice(
+               expected.push(RouteHint {
+                       src_node_id: PublicKey::from_slice(
                                &[
                                        0x03u8, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c,
                                        0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3,
                                        0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55
                                ][..]
                        ).unwrap(),
-                       short_channel_id: [0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a],
-                       fee_base_msat: 2,
-                       fee_proportional_millionths: 30,
-                       cltv_expiry_delta: 4
+                       short_channel_id: parse_int_be(&[0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a], 256).expect("short chan ID slice too big?"),
+                       fees: RoutingFees {
+                               base_msat: 2,
+                               proportional_millionths: 30,
+                       },
+                       cltv_expiry_delta: 4,
+                       htlc_minimum_msat: None,
+                       htlc_maximum_msat: None
                });
 
                assert_eq!(Route::from_base32(&input), Ok(Route(expected)));
index e9ca442f2b2006ea5ff343a0d4785ce7dc945899..8820274c38146d26a8c146518b057652054f7a08 100644 (file)
 
 extern crate bech32;
 extern crate bitcoin_hashes;
+extern crate lightning;
 extern crate num_traits;
 extern crate secp256k1;
 
 use bech32::u5;
 use bitcoin_hashes::Hash;
 use bitcoin_hashes::sha256;
+#[cfg(any(doc, test))]
+use lightning::routing::network_graph::RoutingFees;
+use lightning::routing::router::RouteHint;
 
 use secp256k1::key::PublicKey;
 use secp256k1::{Message, Secp256k1};
@@ -383,26 +387,7 @@ pub struct Signature(pub RecoverableSignature);
 /// The encoded route has to be <1024 5bit characters long (<=639 bytes or <=12 hops)
 ///
 #[derive(Eq, PartialEq, Debug, Clone)]
-pub struct Route(Vec<RouteHop>);
-
-/// Node on a private route
-#[derive(Eq, PartialEq, Debug, Clone)]
-pub struct RouteHop {
-       /// Node's public key
-       pub pubkey: PublicKey,
-
-       /// Which channel of this node we would be using
-       pub short_channel_id: [u8; 8],
-
-       /// Fee charged by this node per transaction
-       pub fee_base_msat: u32,
-
-       /// Fee charged by this node proportional to the amount routed
-       pub fee_proportional_millionths: u32,
-
-       /// Delta substracted by this node from incoming cltv_expiry value
-       pub cltv_expiry_delta: u16,
-}
+pub struct Route(Vec<RouteHint>);
 
 /// Tag constants as specified in BOLT11
 #[allow(missing_docs)]
@@ -499,7 +484,7 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool> InvoiceBuilder<D, H, T> {
        }
 
        /// Adds a private route.
-       pub fn route(mut self, route: Vec<RouteHop>) -> Self {
+       pub fn route(mut self, route: Vec<RouteHint>) -> Self {
                match Route::new(route) {
                        Ok(r) => self.tagged_fields.push(TaggedField::Route(r)),
                        Err(e) => self.error = Some(e),
@@ -1159,7 +1144,7 @@ impl ExpiryTime {
 
 impl Route {
        /// Create a new (partial) route from a list of hops
-       pub fn new(hops: Vec<RouteHop>) -> Result<Route, CreationError> {
+       pub fn new(hops: Vec<RouteHint>) -> Result<Route, CreationError> {
                if hops.len() <= 12 {
                        Ok(Route(hops))
                } else {
@@ -1168,21 +1153,21 @@ impl Route {
        }
 
        /// Returrn the underlying vector of hops
-       pub fn into_inner(self) -> Vec<RouteHop> {
+       pub fn into_inner(self) -> Vec<RouteHint> {
                self.0
        }
 }
 
-impl Into<Vec<RouteHop>> for Route {
-       fn into(self) -> Vec<RouteHop> {
+impl Into<Vec<RouteHint>> for Route {
+       fn into(self) -> Vec<RouteHint> {
                self.into_inner()
        }
 }
 
 impl Deref for Route {
-       type Target = Vec<RouteHop>;
+       type Target = Vec<RouteHint>;
 
-       fn deref(&self) -> &Vec<RouteHop> {
+       fn deref(&self) -> &Vec<RouteHint> {
                &self.0
        }
 }
@@ -1458,18 +1443,22 @@ mod test {
                        .build_raw();
                assert_eq!(long_desc_res, Err(CreationError::DescriptionTooLong));
 
-               let route_hop = RouteHop {
-                       pubkey: PublicKey::from_slice(
+               let route_hop = RouteHint {
+                       src_node_id: PublicKey::from_slice(
                                        &[
                                                0x03, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4,
                                                0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a,
                                                0x95, 0xc3, 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55
                                        ][..]
                                ).unwrap(),
-                       short_channel_id: [0; 8],
-                       fee_base_msat: 0,
-                       fee_proportional_millionths: 0,
+                       short_channel_id: 0,
+                       fees: RoutingFees {
+                               base_msat: 0,
+                               proportional_millionths: 0,
+                       },
                        cltv_expiry_delta: 0,
+                       htlc_minimum_msat: None,
+                       htlc_maximum_msat: None,
                };
                let too_long_route = vec![route_hop; 13];
                let long_route_res = builder.clone()
@@ -1505,36 +1494,52 @@ mod test {
                let public_key = PublicKey::from_secret_key(&secp_ctx, &private_key);
 
                let route_1 = vec![
-                       RouteHop {
-                               pubkey: public_key.clone(),
-                               short_channel_id: [123; 8],
-                               fee_base_msat: 2,
-                               fee_proportional_millionths: 1,
+                       RouteHint {
+                               src_node_id: public_key.clone(),
+                               short_channel_id: de::parse_int_be(&[123; 8], 256).expect("short chan ID slice too big?"),
+                               fees: RoutingFees {
+                                       base_msat: 2,
+                                       proportional_millionths: 1,
+                               },
                                cltv_expiry_delta: 145,
+                               htlc_minimum_msat: None,
+                               htlc_maximum_msat: None,
                        },
-                       RouteHop {
-                               pubkey: public_key.clone(),
-                               short_channel_id: [42; 8],
-                               fee_base_msat: 3,
-                               fee_proportional_millionths: 2,
+                       RouteHint {
+                               src_node_id: public_key.clone(),
+                               short_channel_id: de::parse_int_be(&[42; 8], 256).expect("short chan ID slice too big?"),
+                               fees: RoutingFees {
+                                       base_msat: 3,
+                                       proportional_millionths: 2,
+                               },
                                cltv_expiry_delta: 146,
+                               htlc_minimum_msat: None,
+                               htlc_maximum_msat: None,
                        }
                ];
 
                let route_2 = vec![
-                       RouteHop {
-                               pubkey: public_key.clone(),
-                               short_channel_id: [0; 8],
-                               fee_base_msat: 4,
-                               fee_proportional_millionths: 3,
+                       RouteHint {
+                               src_node_id: public_key.clone(),
+                               short_channel_id: 0,
+                               fees: RoutingFees {
+                                       base_msat: 4,
+                                       proportional_millionths: 3,
+                               },
                                cltv_expiry_delta: 147,
+                               htlc_minimum_msat: None,
+                               htlc_maximum_msat: None,
                        },
-                       RouteHop {
-                               pubkey: public_key.clone(),
-                               short_channel_id: [1; 8],
-                               fee_base_msat: 5,
-                               fee_proportional_millionths: 4,
+                       RouteHint {
+                               src_node_id: public_key.clone(),
+                               short_channel_id: de::parse_int_be(&[1; 8], 256).expect("short chan ID slice too big?"),
+                               fees: RoutingFees {
+                                       base_msat: 5,
+                                       proportional_millionths: 4,
+                               },
                                cltv_expiry_delta: 148,
+                               htlc_minimum_msat: None,
+                               htlc_maximum_msat: None,
                        }
                ];
 
index 2b4332f8633bea9c16fd943de8844d99b5b69e68..68fbfcf127acdff376b2210c97a04579d47061e0 100644 (file)
@@ -370,17 +370,21 @@ impl ToBase32 for Route {
                let mut converter = BytesToBase32::new(writer);
 
                for hop in self.iter() {
-                       converter.append(&hop.pubkey.serialize()[..])?;
-                       converter.append(&hop.short_channel_id[..])?;
+                       converter.append(&hop.src_node_id.serialize()[..])?;
+                       let short_channel_id = try_stretch(
+                               encode_int_be_base256(hop.short_channel_id),
+                               8
+                       ).expect("sizeof(u64) == 8");
+                       converter.append(&short_channel_id)?;
 
                        let fee_base_msat = try_stretch(
-                               encode_int_be_base256(hop.fee_base_msat),
+                               encode_int_be_base256(hop.fees.base_msat),
                                4
                        ).expect("sizeof(u32) == 4");
                        converter.append(&fee_base_msat)?;
 
                        let fee_proportional_millionths = try_stretch(
-                               encode_int_be_base256(hop.fee_proportional_millionths),
+                               encode_int_be_base256(hop.fees.proportional_millionths),
                                4
                        ).expect("sizeof(u32) == 4");
                        converter.append(&fee_proportional_millionths)?;
index 0ad307cdf2f17bf1a347b535ebf5009e9a000c14..20028d217ef867ccdee175f0c68b53d01d05fa59 100644 (file)
@@ -117,7 +117,7 @@ impl Readable for Route {
 }
 
 /// A channel descriptor which provides a last-hop route to get_route
-#[derive(Clone)]
+#[derive(Eq, PartialEq, Debug, Clone)]
 pub struct RouteHint {
        /// The node_id of the non-target end of the route
        pub src_node_id: PublicKey,