From 199e37a44faa10cf613018e47183667a0442ffdb Mon Sep 17 00:00:00 2001 From: t-bast Date: Mon, 11 Dec 2023 09:30:17 +0100 Subject: [PATCH 1/2] Catch invoice decoding exceptions There are a few requirements checked in our secp256k1 wrappers that may throw exceptions on invalid inputs. It's generally a good idea to catch exceptions when validating external, untrusted inputs. --- .../acinq/lightning/payment/PaymentRequest.kt | 6 +- .../payment/PaymentRequestTestsCommon.kt | 91 +++++++++---------- 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/payment/PaymentRequest.kt b/src/commonMain/kotlin/fr/acinq/lightning/payment/PaymentRequest.kt index 8bee3b7aa..76496e595 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/payment/PaymentRequest.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/payment/PaymentRequest.kt @@ -174,7 +174,7 @@ data class PaymentRequest( return loop(input, listOf()) } - fun read(input: String): PaymentRequest { + fun read(input: String): Try = runTrying { val (hrp, data) = Bech32.decode(input) val prefix = prefixes.values.find { hrp.startsWith(it) } ?: throw IllegalArgumentException("unknown prefix $hrp") val amount = decodeAmount(hrp.drop(prefix.length)) @@ -217,8 +217,8 @@ data class PaymentRequest( loop(data.drop(7).dropLast(104)) val pr = PaymentRequest(prefix, amount, timestamp, nodeId, tags, sigandrecid.toByteVector()) - require(pr.signedPreimage().contentEquals(tohash)) - return pr + require(pr.signedPreimage().contentEquals(tohash)) { "invoice isn't canonically encoded" } + pr } fun decodeAmount(input: String): MilliSatoshi? { diff --git a/src/commonTest/kotlin/fr/acinq/lightning/payment/PaymentRequestTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/lightning/payment/PaymentRequestTestsCommon.kt index 3280bb640..ee8627c3e 100644 --- a/src/commonTest/kotlin/fr/acinq/lightning/payment/PaymentRequestTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/lightning/payment/PaymentRequestTestsCommon.kt @@ -66,7 +66,7 @@ class PaymentRequestTestsCommon : LightningTestSuite() { 100_000_000_000_000.msat to "lnbcrt10001pj8wd3rsp5cv2vayxnm7d4783r0477rstzpkl7n4ftmalgu9v8akzf0nhqrs3qpp5vednenalh0v6gzxpzrdxf9cepv4274vc0tax5389cjq0zv9qvs9sdqqxqyjw5qcqp29qyysgqk5f8um72jlnw9unjltdgxw9e2fvec0cxq05tcwuen2jpu42q4p9pt2djk2ysu62nkpg49km59wrexm0wt3msevz53fr2tfnqxf5sdnqpu8th97", ) testCases.forEach { (amount, ref) -> - val invoice = PaymentRequest.read(ref) + val invoice = PaymentRequest.read(ref).get() assertEquals(amount, invoice.amount) val encoded = invoice.write() assertEquals(ref, encoded) @@ -75,9 +75,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `Please make a donation of any amount using payment_hash 0001020304050607080900010203040506070809000102030405060708090102 to me at 03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad`() { - val ref = - "lnbc1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq9qrsgq357wnc5r2ueh7ck6q93dj32dlqnls087fxdwk8qakdyafkq3yap9us6v52vjjsrvywa6rt52cm9r9zqt8r2t7mlcwspyetp5h2tztugp9lfyql" - val pr = PaymentRequest.read(ref) + val ref = "lnbc1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq9qrsgq357wnc5r2ueh7ck6q93dj32dlqnls087fxdwk8qakdyafkq3yap9us6v52vjjsrvywa6rt52cm9r9zqt8r2t7mlcwspyetp5h2tztugp9lfyql" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, null) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -93,9 +92,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `Please send 3 USD for a cup of coffee to the same peer within 1 minute`() { - val ref = - "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu9qrsgquk0rl77nj30yxdy8j9vdx85fkpmdla2087ne0xh8nhedh8w27kyke0lp53ut353s06fv3qfegext0eh0ymjpf39tuven09sam30g4vgpfna3rh" - val pr = PaymentRequest.read(ref) + val ref = "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu9qrsgquk0rl77nj30yxdy8j9vdx85fkpmdla2087ne0xh8nhedh8w27kyke0lp53ut353s06fv3qfegext0eh0ymjpf39tuven09sam30g4vgpfna3rh" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(250000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -112,9 +110,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `Please send 250000 sat for a cup of nonsense to the same peer within one minute`() { - val ref = - "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpu9qrsgqhtjpauu9ur7fw2thcl4y9vfvh4m9wlfyz2gem29g5ghe2aak2pm3ps8fdhtceqsaagty2vph7utlgj48u0ged6a337aewvraedendscp573dxr" - val pr = PaymentRequest.read(ref) + val ref = "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpu9qrsgqhtjpauu9ur7fw2thcl4y9vfvh4m9wlfyz2gem29g5ghe2aak2pm3ps8fdhtceqsaagty2vph7utlgj48u0ged6a337aewvraedendscp573dxr" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(250000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -130,9 +127,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `Now send 24 USD for an entire list of things -- hashed`() { - val ref = - "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs9qrsgq7ea976txfraylvgzuxs8kgcw23ezlrszfnh8r6qtfpr6cxga50aj6txm9rxrydzd06dfeawfk6swupvz4erwnyutnjq7x39ymw6j38gp7ynn44" - val pr = PaymentRequest.read(ref) + val ref = "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs9qrsgq7ea976txfraylvgzuxs8kgcw23ezlrszfnh8r6qtfpr6cxga50aj6txm9rxrydzd06dfeawfk6swupvz4erwnyutnjq7x39ymw6j38gp7ynn44" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(2000000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -153,9 +149,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `The same on testnet with a fallback address mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP`() { - val ref = - "lntb20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfpp3x9et2e20v6pu37c5d9vax37wxq72un989qrsgqdj545axuxtnfemtpwkc45hx9d2ft7x04mt8q7y6t0k2dge9e7h8kpy9p34ytyslj3yu569aalz2xdk8xkd7ltxqld94u8h2esmsmacgpghe9k8" - val pr = PaymentRequest.read(ref) + val ref = "lntb20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfpp3x9et2e20v6pu37c5d9vax37wxq72un989qrsgqdj545axuxtnfemtpwkc45hx9d2ft7x04mt8q7y6t0k2dge9e7h8kpy9p34ytyslj3yu569aalz2xdk8xkd7ltxqld94u8h2esmsmacgpghe9k8" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lntb") assertEquals(pr.amount, MilliSatoshi(2000000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -176,9 +171,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `On mainnet with fallback address 1RustyRX2oai4EYYDpQGWvEL62BBGqN9T with extra routing info to go via nodes 029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255 then 039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255`() { - val ref = - "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq9qrsgqdfjcdk6w3ak5pca9hwfwfh63zrrz06wwfya0ydlzpgzxkn5xagsqz7x9j4jwe7yj7vaf2k9lqsdk45kts2fd0fkr28am0u4w95tt2nsq76cqw0" - val pr = PaymentRequest.read(ref) + val ref = "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq9qrsgqdfjcdk6w3ak5pca9hwfwfh63zrrz06wwfya0ydlzpgzxkn5xagsqz7x9j4jwe7yj7vaf2k9lqsdk45kts2fd0fkr28am0u4w95tt2nsq76cqw0" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(2000000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -209,9 +203,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `On mainnet with fallback p2sh address 3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX`() { - val ref = - "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppj3a24vwu6r8ejrss3axul8rxldph2q7z99qrsgqz6qsgww34xlatfj6e3sngrwfy3ytkt29d2qttr8qz2mnedfqysuqypgqex4haa2h8fx3wnypranf3pdwyluftwe680jjcfp438u82xqphf75ym" - val pr = PaymentRequest.read(ref) + val ref = "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppj3a24vwu6r8ejrss3axul8rxldph2q7z99qrsgqz6qsgww34xlatfj6e3sngrwfy3ytkt29d2qttr8qz2mnedfqysuqypgqex4haa2h8fx3wnypranf3pdwyluftwe680jjcfp438u82xqphf75ym" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(2000000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -232,9 +225,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `On mainnet with fallback p2wpkh address bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4`() { - val ref = - "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppqw508d6qejxtdg4y5r3zarvary0c5xw7k9qrsgqt29a0wturnys2hhxpner2e3plp6jyj8qx7548zr2z7ptgjjc7hljm98xhjym0dg52sdrvqamxdezkmqg4gdrvwwnf0kv2jdfnl4xatsqmrnsse" - val pr = PaymentRequest.read(ref) + val ref = "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppqw508d6qejxtdg4y5r3zarvary0c5xw7k9qrsgqt29a0wturnys2hhxpner2e3plp6jyj8qx7548zr2z7ptgjjc7hljm98xhjym0dg52sdrvqamxdezkmqg4gdrvwwnf0kv2jdfnl4xatsqmrnsse" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(2000000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -255,9 +247,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `On mainnet with fallback p2wsh address bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3`() { - val ref = - "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q9qrsgq9vlvyj8cqvq6ggvpwd53jncp9nwc47xlrsnenq2zp70fq83qlgesn4u3uyf4tesfkkwwfg3qs54qe426hp3tz7z6sweqdjg05axsrjqp9yrrwc" - val pr = PaymentRequest.read(ref) + val ref = "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q9qrsgq9vlvyj8cqvq6ggvpwd53jncp9nwc47xlrsnenq2zp70fq83qlgesn4u3uyf4tesfkkwwfg3qs54qe426hp3tz7z6sweqdjg05axsrjqp9yrrwc" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(2000000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -278,9 +269,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `On mainnet with fallback p2wsh address bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3 and a minimum htlc cltv expiry of 12`() { - val ref = - "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygscqpvpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q9qrsgq999fraffdzl6c8j7qd325dfurcq7vl0mfkdpdvve9fy3hy4lw0x9j3zcj2qdh5e5pyrp6cncvmxrhchgey64culwmjtw9wym74xm6xqqevh9r0" - val pr = PaymentRequest.read(ref) + val ref = "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygscqpvpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q9qrsgq999fraffdzl6c8j7qd325dfurcq7vl0mfkdpdvve9fy3hy4lw0x9j3zcj2qdh5e5pyrp6cncvmxrhchgey64culwmjtw9wym74xm6xqqevh9r0" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(2000000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -309,12 +299,12 @@ class PaymentRequestTestsCommon : LightningTestSuite() { // All upper-case "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2a25dxl5hrntdtn6zvydt7d66hyzsyhqs4wdynavys42xgl6sgx9c4g7me86a27t07mdtfry458rtjr0v92cnmswpsjscgt2vcse3sgpz3uapa".uppercase(), // With ignored fields - // TODO commented out because it contains a version 19 bech32 faalback address which we consider as invalid + // TODO commented out because it contains a version 19 bech32 fallback address which we consider as invalid // TODO: do we change Bech32.decode() to ignore such addresses ? // "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2qrqqqfppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhpnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqspnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnp5qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnpkqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqz599y53s3ujmcfjp5xrdap68qxymkqphwsexhmhr8wdz5usdzkzrse33chw6dlp3jhuhge9ley7j2ayx36kawe7kmgg8sv5ugdyusdcqzn8z9x" ) refs.forEach { ref -> - val pr = PaymentRequest.read(ref) + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(2500000000L)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -330,9 +320,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `On mainnet please send 30 USD for coffee beans to the same peer which supports features 8 14 99 and 100 using secret 0x1111111111111111111111111111111111111111111111111111111111111111`() { - val ref = - "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q4psqqqqqqqqqqqqqqqqsgqtqyx5vggfcsll4wu246hz02kp85x4katwsk9639we5n5yngc3yhqkm35jnjw4len8vrnqnf5ejh0mzj9n3vz2px97evektfm2l6wqccp3y7372" - val pr = PaymentRequest.read(ref) + val ref = "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q4psqqqqqqqqqqqqqqqqsgqtqyx5vggfcsll4wu246hz02kp85x4katwsk9639we5n5yngc3yhqkm35jnjw4len8vrnqnf5ejh0mzj9n3vz2px97evektfm2l6wqccp3y7372" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(2500000000L)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -348,9 +337,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `On mainnet please send 96 7878 534 msat for a list of items within one week amount in pico BTC`() { - val ref = - "lnbc9678785340p1pwmna7lpp5gc3xfm08u9qy06djf8dfflhugl6p7lgza6dsjxq454gxhj9t7a0sd8dgfkx7cmtwd68yetpd5s9xar0wfjn5gpc8qhrsdfq24f5ggrxdaezqsnvda3kkum5wfjkzmfqf3jkgem9wgsyuctwdus9xgrcyqcjcgpzgfskx6eqf9hzqnteypzxz7fzypfhg6trddjhygrcyqezcgpzfysywmm5ypxxjemgw3hxjmn8yptk7untd9hxwg3q2d6xjcmtv4ezq7pqxgsxzmnyyqcjqmt0wfjjq6t5v4khxsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsxqyjw5qcqp2rzjq0gxwkzc8w6323m55m4jyxcjwmy7stt9hwkwe2qxmy8zpsgg7jcuwz87fcqqeuqqqyqqqqlgqqqqn3qq9q9qrsgqrvgkpnmps664wgkp43l22qsgdw4ve24aca4nymnxddlnp8vh9v2sdxlu5ywdxefsfvm0fq3sesf08uf6q9a2ke0hc9j6z6wlxg5z5kqpu2v9wz" - val pr = PaymentRequest.read(ref) + val ref = "lnbc9678785340p1pwmna7lpp5gc3xfm08u9qy06djf8dfflhugl6p7lgza6dsjxq454gxhj9t7a0sd8dgfkx7cmtwd68yetpd5s9xar0wfjn5gpc8qhrsdfq24f5ggrxdaezqsnvda3kkum5wfjkzmfqf3jkgem9wgsyuctwdus9xgrcyqcjcgpzgfskx6eqf9hzqnteypzxz7fzypfhg6trddjhygrcyqezcgpzfysywmm5ypxxjemgw3hxjmn8yptk7untd9hxwg3q2d6xjcmtv4ezq7pqxgsxzmnyyqcjqmt0wfjjq6t5v4khxsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsxqyjw5qcqp2rzjq0gxwkzc8w6323m55m4jyxcjwmy7stt9hwkwe2qxmy8zpsgg7jcuwz87fcqqeuqqqyqqqqlgqqqqn3qq9q9qrsgqrvgkpnmps664wgkp43l22qsgdw4ve24aca4nymnxddlnp8vh9v2sdxlu5ywdxefsfvm0fq3sesf08uf6q9a2ke0hc9j6z6wlxg5z5kqpu2v9wz" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(967878534)) assertEquals(pr.paymentHash, ByteVector32("462264ede7e14047e9b249da94fefc47f41f7d02ee9b091815a5506bc8abf75f")) @@ -383,9 +371,8 @@ class PaymentRequestTestsCommon : LightningTestSuite() { @Test fun `On mainnet please send 1000000 sat with payment metadata 0x01fafaf0`() { - val ref = - "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgq7hf8he7ecf7n4ffphs6awl9t6676rrclv9ckg3d3ncn7fct63p6s365duk5wrk202cfy3aj5xnnp5gs3vrdvruverwwq7yzhkf5a3xqpd05wjc" - val pr = PaymentRequest.read(ref) + val ref = "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgq7hf8he7ecf7n4ffphs6awl9t6676rrclv9ckg3d3ncn7fct63p6s365duk5wrk202cfy3aj5xnnp5gs3vrdvruverwwq7yzhkf5a3xqpd05wjc" + val pr = PaymentRequest.read(ref).get() assertEquals(pr.prefix, "lnbc") assertEquals(pr.amount, MilliSatoshi(1000000000)) assertEquals(pr.paymentHash, ByteVector32("0001020304050607080900010203040506070809000102030405060708090102")) @@ -416,10 +403,14 @@ class PaymentRequestTestsCommon : LightningTestSuite() { // Invalid multiplier. "lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqrrzc4cvfue4zp3hggxp47ag7xnrlr8vgcmkjxk3j5jqethnumgkpqp23z9jclu3v0a7e0aruz366e9wqdykw6dxhdzcjjhldxq0w6wgqcnu43j", // Invalid sub-millisatoshi precision. - "lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgq0lzc236j96a95uv0m3umg28gclm5lqxtqqwk32uuk4k6673k6n5kfvx3d2h8s295fad45fdhmusm8sjudfhlf6dcsxmfvkeywmjdkxcp99202x" + "lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgq0lzc236j96a95uv0m3umg28gclm5lqxtqqwk32uuk4k6673k6n5kfvx3d2h8s295fad45fdhmusm8sjudfhlf6dcsxmfvkeywmjdkxcp99202x", + // Missing payment secret. + "lnbc1qqygh9qpp5s7zxqqqqqqqqqqqqpjqqqqqqqqqqqqqqqqqqcqpjqqqsqqqqqqqqdqqqqqqqqqqqqqqqqqqqqqqqqqqqqquqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzxqqqqqqqqqqqqqqqy6f523d", + // Invalid signature public key recovery id. + "lnbc1qqqqpqqnp4qqqlftcw9qqqqqqqqqqqqygh9qpp5qpp5s7zxqqqqcqpjpqqygh9qpp5s7zxqqqqcqpjpqqlqqqqqqqqqqqqcqqpqqqqqqqqqqqsqqqqqqqqdqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlqqqcqpjptfqptfqptfqpqqqqqqqqqqqqqqqqqqq8ddm0a" ) refs.forEach { - assertFails { PaymentRequest.read(it) } + assertTrue(PaymentRequest.read(it).isFailure) } } @@ -441,7 +432,7 @@ class PaymentRequestTestsCommon : LightningTestSuite() { ).sign(priv) val serialized = pr.write() - val pr1 = PaymentRequest.read(serialized) + val pr1 = PaymentRequest.read(serialized).get() val unknownTag = pr1.tags.find { it is PaymentRequest.TaggedField.UnknownTag } assertEquals(21, unknownTag!!.tag) } @@ -464,7 +455,7 @@ class PaymentRequestTestsCommon : LightningTestSuite() { mapOf(Feature.VariableLengthOnion to FeatureSupport.Mandatory, Feature.PaymentSecret to FeatureSupport.Mandatory, Feature.AnchorOutputs to FeatureSupport.Mandatory), setOf(UnknownFeature(121), UnknownFeature(156)) ) - val pr = PaymentRequest.read(createInvoiceUnsafe(features = features).write()) + val pr = PaymentRequest.read(createInvoiceUnsafe(features = features).write()).get() assertEquals(Features(pr.features), features) assertEquals(Features(pr.features).invoiceFeatures(), features.remove(Feature.AnchorOutputs)) } @@ -502,14 +493,14 @@ class PaymentRequestTestsCommon : LightningTestSuite() { assertNotNull(pr.paymentSecret) assertEquals(ByteVector("024100"), pr.features) - val pr1 = PaymentRequest.read(pr.write()) + val pr1 = PaymentRequest.read(pr.write()).get() assertEquals(pr1.paymentSecret, pr.paymentSecret) // An invoice without the payment secret feature should be rejected - assertFails { PaymentRequest.read("lnbc40n1pw9qjvwpp5qq3w2ln6krepcslqszkrsfzwy49y0407hvks30ec6pu9s07jur3sdpstfshq5n9v9jzucm0d5s8vmm5v5s8qmmnwssyj3p6yqenwdencqzysxqrrss7ju0s4dwx6w8a95a9p2xc5vudl09gjl0w2n02sjrvffde632nxwh2l4w35nqepj4j5njhh4z65wyfc724yj6dn9wajvajfn5j7em6wsq2elakl") } + assertTrue(PaymentRequest.read("lnbc40n1pw9qjvwpp5qq3w2ln6krepcslqszkrsfzwy49y0407hvks30ec6pu9s07jur3sdpstfshq5n9v9jzucm0d5s8vmm5v5s8qmmnwssyj3p6yqenwdencqzysxqrrss7ju0s4dwx6w8a95a9p2xc5vudl09gjl0w2n02sjrvffde632nxwh2l4w35nqepj4j5njhh4z65wyfc724yj6dn9wajvajfn5j7em6wsq2elakl").isFailure) // An invoice that sets the payment secret feature bit must provide a payment secret. - assertFails { PaymentRequest.read("lnbc1230p1pwljzn3pp5qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqdq52dhk6efqd9h8vmmfvdjs9qypqsqylvwhf7xlpy6xpecsnpcjjuuslmzzgeyv90mh7k7vs88k2dkxgrkt75qyfjv5ckygw206re7spga5zfd4agtdvtktxh5pkjzhn9dq2cqz9upw7") } + assertTrue(PaymentRequest.read("lnbc1230p1pwljzn3pp5qyqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqdq52dhk6efqd9h8vmmfvdjs9qypqsqylvwhf7xlpy6xpecsnpcjjuuslmzzgeyv90mh7k7vs88k2dkxgrkt75qyfjv5ckygw206re7spga5zfd4agtdvtktxh5pkjzhn9dq2cqz9upw7").isFailure) // Invoices must use a payment secret. assertFails { @@ -533,7 +524,7 @@ class PaymentRequestTestsCommon : LightningTestSuite() { assertNotNull(pr.descriptionHash) assertNull(pr.description) - val pr1 = PaymentRequest.read(pr.write()) + val pr1 = PaymentRequest.read(pr.write()).get() assertEquals(pr1.descriptionHash, pr.descriptionHash) assertNull(pr1.description) } From 164a45a7f4b9f26e4c1a6a23f1b6c7a37d51b9bd Mon Sep 17 00:00:00 2001 From: t-bast Date: Tue, 19 Dec 2023 10:45:33 +0100 Subject: [PATCH 2/2] Update bitcoin-kmp and secp256k1-kmp --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index bf62dea54..fc67c5e44 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,7 +33,7 @@ kotlin { val commonMain by sourceSets.getting { dependencies { - api("fr.acinq.bitcoin:bitcoin-kmp:0.14.0") // when upgrading, keep secp256k1-kmp-jni-jvm in sync below + api("fr.acinq.bitcoin:bitcoin-kmp:0.15.0") // when upgrading, keep secp256k1-kmp-jni-jvm in sync below api("org.kodein.log:canard:0.18.0") api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion") api("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion") @@ -63,7 +63,7 @@ kotlin { api(ktor("client-okhttp")) api(ktor("network")) api(ktor("network-tls")) - implementation("fr.acinq.secp256k1:secp256k1-kmp-jni-jvm:0.11.0") + implementation("fr.acinq.secp256k1:secp256k1-kmp-jni-jvm:0.12.0") implementation("org.slf4j:slf4j-api:1.7.36") api("org.xerial:sqlite-jdbc:3.32.3.2") }