Check if invoices contain unknown required features
authorMatt Corallo <git@bluematt.me>
Sun, 22 Aug 2021 19:54:08 +0000 (19:54 +0000)
committerMatt Corallo <git@bluematt.me>
Tue, 31 Aug 2021 21:29:51 +0000 (21:29 +0000)
This adds the final missing BOLT 11 failure test, checking for
unknown required feature flags before accepting an invoice.

lightning-invoice/src/lib.rs
lightning-invoice/tests/ser_de.rs
lightning/src/ln/features.rs

index bcb15245d3f201ad920002f2f3f76d4ea1707cd4..75aac5491513840c433ed17a6b785ff791aa646c 100644 (file)
@@ -1052,7 +1052,9 @@ impl Invoice {
                        None if has_payment_secret => Err(SemanticError::InvalidFeatures),
                        None => Ok(()),
                        Some(TaggedField::Features(features)) => {
-                               if features.supports_payment_secret() && has_payment_secret {
+                               if features.requires_unknown_bits() {
+                                       Err(SemanticError::InvalidFeatures)
+                               } else if features.supports_payment_secret() && has_payment_secret {
                                        Ok(())
                                } else if has_payment_secret {
                                        Err(SemanticError::InvalidFeatures)
index c2f82b0990c9c99ea6c632dab2d000442db12b30..94e75cbc480b1e203a04f1c8cb071db317cbcab6 100644 (file)
@@ -154,6 +154,9 @@ fn deserialize() {
 #[test]
 fn test_bolt_invalid_invoices() {
        // Tests the BOLT 11 invalid invoice test vectors
+       assert_eq!(Invoice::from_str(
+               "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q4psqqqqqqqqqqqqqqqpqsqq40wa3khl49yue3zsgm26jrepqr2eghqlx86rttutve3ugd05em86nsefzh4pfurpd9ek9w2vp95zxqnfe2u7ckudyahsa52q66tgzcp6t2dyk"
+               ), Err(ParseOrSemanticError::SemanticError(SemanticError::InvalidFeatures)));
        assert_eq!(Invoice::from_str(
                "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt"
                ), Err(ParseOrSemanticError::ParseError(ParseError::Bech32Error(bech32::Error::InvalidChecksum))));
index e78fa3d50d2d05c5bfcafe1fd58eb1b654c167f7..c0eb8f68ac541c4ed5181713686141bd7d287139 100644 (file)
@@ -548,7 +548,9 @@ impl<T: sealed::Context> Features<T> {
                &self.flags
        }
 
-       pub(crate) fn requires_unknown_bits(&self) -> bool {
+       /// Returns true if this `Features` object contains unknown feature flags which are set as
+       /// "required".
+       pub fn requires_unknown_bits(&self) -> bool {
                // Bitwise AND-ing with all even bits set except for known features will select required
                // unknown features.
                let byte_count = T::KNOWN_FEATURE_MASK.len();