[invoice] Update doctest example invoices to real LDK invoices
[rust-lightning] / lightning-invoice / src / de.rs
index 3610bc4b67fab01f11283aed957c1fe71ccb4731..2ed356dafb8d3959b0c43cebed8ccdc161e69f39 100644 (file)
@@ -12,7 +12,7 @@ use bitcoin_hashes::Hash;
 use bitcoin_hashes::sha256;
 use lightning::ln::PaymentSecret;
 use lightning::routing::network_graph::RoutingFees;
-use lightning::routing::router::RouteHintHop;
+use lightning::routing::router::{RouteHint, RouteHintHop};
 
 use num_traits::{CheckedAdd, CheckedMul};
 
@@ -21,7 +21,7 @@ use secp256k1::recovery::{RecoveryId, RecoverableSignature};
 use secp256k1::key::PublicKey;
 
 use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiry, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
-       SemanticError, RouteHint, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawInvoice, constants, SignedRawInvoice,
+       SemanticError, PrivateRoute, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawInvoice, constants, SignedRawInvoice,
        RawDataPart, CreationError, InvoiceFeatures};
 
 use self::hrp_sm::parse_hrp;
@@ -185,6 +185,7 @@ impl FromStr for super::Currency {
                        "tb" => Ok(Currency::BitcoinTestnet),
                        "bcrt" => Ok(Currency::Regtest),
                        "sb" => Ok(Currency::Simnet),
+                       "tbs" => Ok(Currency::Signet),
                        _ => Err(ParseError::UnknownCurrency)
                }
        }
@@ -208,10 +209,18 @@ impl FromStr for SiPrefix {
 /// ```
 /// use lightning_invoice::Invoice;
 ///
-/// let invoice = "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp\
-///    l2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d7\
-///    3gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ec\
-///    ky03ylcqca784w";
+///
+/// let invoice = "lnbc100p1psj9jhxdqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q0d3p2sfluzdx45tqcs\
+/// h2pu5qc7lgq0xs578ngs6s0s68ua4h7cvspp5q6rmq35js88zp5dvwrv9m459tnk2zunwj5jalqtyxqulh0l\
+/// 5gflssp5nf55ny5gcrfl30xuhzj3nphgj27rstekmr9fw3ny5989s300gyus9qyysgqcqpcrzjqw2sxwe993\
+/// h5pcm4dxzpvttgza8zhkqxpgffcrf5v25nwpr3cmfg7z54kuqq8rgqqqqqqqq2qqqqq9qq9qrzjqd0ylaqcl\
+/// j9424x9m8h2vcukcgnm6s56xfgu3j78zyqzhgs4hlpzvznlugqq9vsqqqqqqqlgqqqqqeqq9qrzjqwldmj9d\
+/// ha74df76zhx6l9we0vjdquygcdt3kssupehe64g6yyp5yz5rhuqqwccqqyqqqqlgqqqqjcqq9qrzjqf9e58a\
+/// guqr0rcun0ajlvmzq3ek63cw2w282gv3z5uupmuwvgjtq2z55qsqqg6qqqyqqqrtnqqqzq3cqygrzjqvphms\
+/// ywntrrhqjcraumvc4y6r8v4z5v593trte429v4hredj7ms5z52usqq9ngqqqqqqqlgqqqqqqgq9qrzjq2v0v\
+/// p62g49p7569ev48cmulecsxe59lvaw3wlxm7r982zxa9zzj7z5l0cqqxusqqyqqqqlgqqqqqzsqygarl9fh3\
+/// 8s0gyuxjjgux34w75dnc6xp2l35j7es3jd4ugt3lu0xzre26yg5m7ke54n2d5sym4xcmxtl8238xxvw5h5h5\
+/// j5r6drg6k6zcqj0fcwg";
 ///
 /// assert!(invoice.parse::<Invoice>().is_ok());
 /// ```
@@ -227,10 +236,17 @@ impl FromStr for Invoice {
 /// ```
 /// use lightning_invoice::*;
 ///
-/// let invoice = "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp\
-///    l2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d7\
-///    3gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ec\
-///    ky03ylcqca784w";
+/// let invoice = "lnbc100p1psj9jhxdqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q0d3p2sfluzdx45tqcs\
+/// h2pu5qc7lgq0xs578ngs6s0s68ua4h7cvspp5q6rmq35js88zp5dvwrv9m459tnk2zunwj5jalqtyxqulh0l\
+/// 5gflssp5nf55ny5gcrfl30xuhzj3nphgj27rstekmr9fw3ny5989s300gyus9qyysgqcqpcrzjqw2sxwe993\
+/// h5pcm4dxzpvttgza8zhkqxpgffcrf5v25nwpr3cmfg7z54kuqq8rgqqqqqqqq2qqqqq9qq9qrzjqd0ylaqcl\
+/// j9424x9m8h2vcukcgnm6s56xfgu3j78zyqzhgs4hlpzvznlugqq9vsqqqqqqqlgqqqqqeqq9qrzjqwldmj9d\
+/// ha74df76zhx6l9we0vjdquygcdt3kssupehe64g6yyp5yz5rhuqqwccqqyqqqqlgqqqqjcqq9qrzjqf9e58a\
+/// guqr0rcun0ajlvmzq3ek63cw2w282gv3z5uupmuwvgjtq2z55qsqqg6qqqyqqqrtnqqqzq3cqygrzjqvphms\
+/// ywntrrhqjcraumvc4y6r8v4z5v593trte429v4hredj7ms5z52usqq9ngqqqqqqqlgqqqqqqgq9qrzjq2v0v\
+/// p62g49p7569ev48cmulecsxe59lvaw3wlxm7r982zxa9zzj7z5l0cqqxusqqyqqqqlgqqqqqzsqygarl9fh3\
+/// 8s0gyuxjjgux34w75dnc6xp2l35j7es3jd4ugt3lu0xzre26yg5m7ke54n2d5sym4xcmxtl8238xxvw5h5h5\
+/// j5r6drg6k6zcqj0fcwg";
 ///
 /// let parsed_1 = invoice.parse::<Invoice>();
 ///
@@ -249,7 +265,13 @@ impl FromStr for SignedRawInvoice {
        type Err = ParseError;
 
        fn from_str(s: &str) -> Result<Self, Self::Err> {
-               let (hrp, data) = bech32::decode(s)?;
+               let (hrp, data, var) = bech32::decode(s)?;
+
+               if var == bech32::Variant::Bech32m {
+                       // Consider Bech32m addresses to be "Invalid Checksum", since that is what we'd get if
+                       // we didn't support Bech32m (which lightning does not use).
+                       return Err(ParseError::Bech32Error(bech32::Error::InvalidChecksum));
+               }
 
                if data.len() < 104 {
                        return Err(ParseError::TooShortDataPart);
@@ -432,8 +454,8 @@ impl FromBase32 for TaggedField {
                                Ok(TaggedField::MinFinalCltvExpiry(MinFinalCltvExpiry::from_base32(field_data)?)),
                        constants::TAG_FALLBACK =>
                                Ok(TaggedField::Fallback(Fallback::from_base32(field_data)?)),
-                       constants::TAG_ROUTE =>
-                               Ok(TaggedField::Route(RouteHint::from_base32(field_data)?)),
+                       constants::TAG_PRIVATE_ROUTE =>
+                               Ok(TaggedField::PrivateRoute(PrivateRoute::from_base32(field_data)?)),
                        constants::TAG_PAYMENT_SECRET =>
                                Ok(TaggedField::PaymentSecret(PaymentSecret::from_base32(field_data)?)),
                        constants::TAG_FEATURES =>
@@ -557,10 +579,10 @@ impl FromBase32 for Fallback {
        }
 }
 
-impl FromBase32 for RouteHint {
+impl FromBase32 for PrivateRoute {
        type Err = ParseError;
 
-       fn from_base32(field_data: &[u5]) -> Result<RouteHint, ParseError> {
+       fn from_base32(field_data: &[u5]) -> Result<PrivateRoute, ParseError> {
                let bytes = Vec::<u8>::from_base32(field_data)?;
 
                if bytes.len() % 51 != 0 {
@@ -592,7 +614,7 @@ impl FromBase32 for RouteHint {
                        route_hops.push(hop);
                }
 
-               Ok(RouteHint(route_hops))
+               Ok(PrivateRoute(RouteHint(route_hops)))
        }
 }
 
@@ -774,6 +796,7 @@ mod test {
                assert_eq!("tb".parse::<Currency>(), Ok(Currency::BitcoinTestnet));
                assert_eq!("bcrt".parse::<Currency>(), Ok(Currency::Regtest));
                assert_eq!("sb".parse::<Currency>(), Ok(Currency::Simnet));
+               assert_eq!("tbs".parse::<Currency>(), Ok(Currency::Signet));
                assert_eq!("something_else".parse::<Currency>(), Err(ParseError::UnknownCurrency))
        }
 
@@ -928,8 +951,8 @@ mod test {
        #[test]
        fn test_parse_route() {
                use lightning::routing::network_graph::RoutingFees;
-               use lightning::routing::router::RouteHintHop;
-               use ::RouteHint;
+               use lightning::routing::router::{RouteHint, RouteHintHop};
+               use ::PrivateRoute;
                use bech32::FromBase32;
                use de::parse_int_be;
 
@@ -974,10 +997,10 @@ mod test {
                        htlc_maximum_msat: None
                });
 
-               assert_eq!(RouteHint::from_base32(&input), Ok(RouteHint(expected)));
+               assert_eq!(PrivateRoute::from_base32(&input), Ok(PrivateRoute(RouteHint(expected))));
 
                assert_eq!(
-                       RouteHint::from_base32(&[u5::try_from_u8(0).unwrap(); 40][..]),
+                       PrivateRoute::from_base32(&[u5::try_from_u8(0).unwrap(); 40][..]),
                        Err(ParseError::UnexpectedEndOfTaggedFields)
                );
        }