1
0
mirror of https://github.com/ACINQ/eclair.git synced 2024-11-19 01:43:22 +01:00

Cleanup of RouteBlinding feature (#2856)

RouteBlinding is not an invoice feature.
This commit is contained in:
Thomas HUET 2024-05-22 10:47:18 +02:00 committed by GitHub
parent bbd52fab02
commit b73a009a1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 12 additions and 51 deletions

View File

@ -249,7 +249,7 @@ object Features {
val mandatory = 22 val mandatory = 22
} }
case object RouteBlinding extends Feature with InitFeature with NodeFeature with Bolt11Feature { case object RouteBlinding extends Feature with InitFeature with NodeFeature {
val rfcName = "option_route_blinding" val rfcName = "option_route_blinding"
val mandatory = 24 val mandatory = 24
} }

View File

@ -158,7 +158,6 @@ object Bolt11Invoice {
paymentMetadata: Option[ByteVector] = None, paymentMetadata: Option[ByteVector] = None,
features: Features[Bolt11Feature] = defaultFeatures): Bolt11Invoice = { features: Features[Bolt11Feature] = defaultFeatures): Bolt11Invoice = {
require(features.hasFeature(Features.PaymentSecret, Some(FeatureSupport.Mandatory)), "invoices must require a payment secret") require(features.hasFeature(Features.PaymentSecret, Some(FeatureSupport.Mandatory)), "invoices must require a payment secret")
require(!features.hasFeature(Features.RouteBlinding), "bolt11 invoices cannot use route blinding")
val prefix = prefixes(chainHash) val prefix = prefixes(chainHash)
val tags = { val tags = {
val defaultTags = List( val defaultTags = List(

View File

@ -47,11 +47,7 @@ case class Bolt12Invoice(records: TlvStream[InvoiceTlv]) extends Invoice {
val description: Option[String] = invoiceRequest.offer.description val description: Option[String] = invoiceRequest.offer.description
override val createdAt: TimestampSecond = records.get[InvoiceCreatedAt].get.timestamp override val createdAt: TimestampSecond = records.get[InvoiceCreatedAt].get.timestamp
override val relativeExpiry: FiniteDuration = FiniteDuration(records.get[InvoiceRelativeExpiry].map(_.seconds).getOrElse(DEFAULT_EXPIRY_SECONDS), TimeUnit.SECONDS) override val relativeExpiry: FiniteDuration = FiniteDuration(records.get[InvoiceRelativeExpiry].map(_.seconds).getOrElse(DEFAULT_EXPIRY_SECONDS), TimeUnit.SECONDS)
override val features: Features[InvoiceFeature] = { override val features: Features[InvoiceFeature] = records.get[InvoiceFeatures].map(_.features.invoiceFeatures()).getOrElse(Features.empty)
val f = records.get[InvoiceFeatures].map(_.features.invoiceFeatures()).getOrElse(Features.empty)
// We add invoice features that are implicitly required for Bolt 12 (the spec doesn't allow explicitly setting them).
f.add(Features.VariableLengthOnion, FeatureSupport.Mandatory).add(Features.RouteBlinding, FeatureSupport.Mandatory)
}
val blindedPaths: Seq[PaymentBlindedRoute] = records.get[InvoicePaths].get.paths.zip(records.get[InvoiceBlindedPay].get.paymentInfo).map { case (route, info) => PaymentBlindedRoute(route, info) } val blindedPaths: Seq[PaymentBlindedRoute] = records.get[InvoicePaths].get.paths.zip(records.get[InvoiceBlindedPay].get.paymentInfo).map { case (route, info) => PaymentBlindedRoute(route, info) }
val fallbacks: Option[Seq[FallbackAddress]] = records.get[InvoiceFallbacks].map(_.addresses) val fallbacks: Option[Seq[FallbackAddress]] = records.get[InvoiceFallbacks].map(_.addresses)
val signature: ByteVector64 = records.get[Signature].get.signature val signature: ByteVector64 = records.get[Signature].get.signature
@ -172,11 +168,7 @@ case class MinimalBolt12Invoice(records: TlvStream[InvoiceTlv]) extends Invoice
val description: Option[String] = records.get[OfferDescription].map(_.description) val description: Option[String] = records.get[OfferDescription].map(_.description)
override val createdAt: TimestampSecond = records.get[InvoiceCreatedAt].get.timestamp override val createdAt: TimestampSecond = records.get[InvoiceCreatedAt].get.timestamp
override val relativeExpiry: FiniteDuration = FiniteDuration(records.get[InvoiceRelativeExpiry].map(_.seconds).getOrElse(Bolt12Invoice.DEFAULT_EXPIRY_SECONDS), TimeUnit.SECONDS) override val relativeExpiry: FiniteDuration = FiniteDuration(records.get[InvoiceRelativeExpiry].map(_.seconds).getOrElse(Bolt12Invoice.DEFAULT_EXPIRY_SECONDS), TimeUnit.SECONDS)
override val features: Features[InvoiceFeature] = { override val features: Features[InvoiceFeature] = records.get[InvoiceFeatures].map(_.features.invoiceFeatures()).getOrElse(Features[InvoiceFeature](Features.BasicMultiPartPayment -> FeatureSupport.Optional))
val f = records.get[InvoiceFeatures].map(_.features.invoiceFeatures()).getOrElse(Features[InvoiceFeature](Features.BasicMultiPartPayment -> FeatureSupport.Optional))
// We add invoice features that are implicitly required for Bolt 12 (the spec doesn't allow explicitly setting them).
f.add(Features.VariableLengthOnion, FeatureSupport.Mandatory).add(Features.RouteBlinding, FeatureSupport.Mandatory)
}
override def toString: String = { override def toString: String = {
val data = OfferCodecs.invoiceTlvCodec.encode(records).require.bytes val data = OfferCodecs.invoiceTlvCodec.encode(records).require.bytes

View File

@ -345,7 +345,7 @@ object MultiPartHandler {
expirySeconds = Some(expirySeconds), expirySeconds = Some(expirySeconds),
extraHops = r.extraHops, extraHops = r.extraHops,
paymentMetadata = Some(paymentMetadata), paymentMetadata = Some(paymentMetadata),
features = featuresTrampolineOpt.remove(Features.RouteBlinding) features = featuresTrampolineOpt
) )
context.log.debug("generated invoice={} from amount={}", invoice.toString, r.amount_opt) context.log.debug("generated invoice={} from amount={}", invoice.toString, r.amount_opt)
nodeParams.db.payments.addIncomingPayment(invoice, paymentPreimage, r.paymentType) nodeParams.db.payments.addIncomingPayment(invoice, paymentPreimage, r.paymentType)

View File

@ -320,7 +320,7 @@ class JsonSerializersSpec extends TestKitBaseClass with AnyFunSuiteLike with Mat
test("Bolt 12 invoice") { test("Bolt 12 invoice") {
val ref = "lni1qqsf4h8fsnpjkj057gjg9c3eqhv889440xh0z6f5kng9vsaad8pgq7sgqsdjuqsqpgxk66twd9kkzmpqdanxvetjzcss83y2e9lqnu7tht4ntvp24fksw26hwf5yrg6dyk2jz472efs2rjh42qsxlc5vp2m0rvmjcxn2y34wv0m5lyc7sdj7zksgn35dvxgqqqqqqqzjqsdjupkjtqssx05572ha26x39rczan5yft22pgwa72jw8gytavkm5ydn7yf5kpgh5zsq83y2e9lqnu7tht4ntvp24fksw26hwf5yrg6dyk2jz472efs2rjh4q2rd3ny0elv9m7mh38xxwe6ypfheeqeqlwgft05r6dhc50gtw0nv2qgrrl9x2qzzqvwukam32mhkdqrvwwcp5l6jcnnnezdq69vz8gdvvgmsqwk3efqf3f6gmf0ul63940awz429rdhhsts86s0r30e5nffwhrqw90xgxf7f60sm7tcclvyqwz7cer5q9223madstdy2p5q6y8qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqf2qheqqqqq2gprrgshynfszqyk2sgpvkrnmq53kv7r52rpnmtmd9ukredsnygsnymsurdy6e9la6l4hyz4qgxewqmftqggrcj9vjlsf709m46e4kq425mg89dthy6zp5dxjt9fp2l9v5c9pet6lqsx4k5r7rsld3hhe87psyy5cnhhzt4dz838f75734mted7pdsrflpvys23tkafmhctf3musnsaa42h6qjdggyqlhtevutzzpzlnwd8alq" val ref = "lni1qqsf4h8fsnpjkj057gjg9c3eqhv889440xh0z6f5kng9vsaad8pgq7sgqsdjuqsqpgxk66twd9kkzmpqdanxvetjzcss83y2e9lqnu7tht4ntvp24fksw26hwf5yrg6dyk2jz472efs2rjh42qsxlc5vp2m0rvmjcxn2y34wv0m5lyc7sdj7zksgn35dvxgqqqqqqqzjqsdjupkjtqssx05572ha26x39rczan5yft22pgwa72jw8gytavkm5ydn7yf5kpgh5zsq83y2e9lqnu7tht4ntvp24fksw26hwf5yrg6dyk2jz472efs2rjh4q2rd3ny0elv9m7mh38xxwe6ypfheeqeqlwgft05r6dhc50gtw0nv2qgrrl9x2qzzqvwukam32mhkdqrvwwcp5l6jcnnnezdq69vz8gdvvgmsqwk3efqf3f6gmf0ul63940awz429rdhhsts86s0r30e5nffwhrqw90xgxf7f60sm7tcclvyqwz7cer5q9223madstdy2p5q6y8qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqf2qheqqqqq2gprrgshynfszqyk2sgpvkrnmq53kv7r52rpnmtmd9ukredsnygsnymsurdy6e9la6l4hyz4qgxewqmftqggrcj9vjlsf709m46e4kq425mg89dthy6zp5dxjt9fp2l9v5c9pet6lqsx4k5r7rsld3hhe87psyy5cnhhzt4dz838f75734mted7pdsrflpvys23tkafmhctf3musnsaa42h6qjdggyqlhtevutzzpzlnwd8alq"
val pr = Invoice.fromString(ref).get val pr = Invoice.fromString(ref).get
JsonSerializers.serialization.write(pr)(JsonSerializers.formats) shouldBe """{"amount":456001234,"nodeId":"03c48ac97e09f3cbbaeb35b02aaa6d072b57726841a34d25952157caca60a1caf5","paymentHash":"2cb0e7b052366787450c33daf6d2f2c3cb6132221326e1c1b49ac97fdd7eb720","description":"minimal offer","features":{"activated":{"var_onion_optin":"mandatory","option_route_blinding":"mandatory"},"unknown":[]},"blindedPaths":[{"introductionNodeId":"03c48ac97e09f3cbbaeb35b02aaa6d072b57726841a34d25952157caca60a1caf5","blindedNodeIds":["031fca650042031dcb777156ef66806c73b01a7f52c4e73c89a0d15823a1ac6237"]}],"createdAt":1665412681,"expiresAt":1665412981,"serialized":"lni1qqsf4h8fsnpjkj057gjg9c3eqhv889440xh0z6f5kng9vsaad8pgq7sgqsdjuqsqpgxk66twd9kkzmpqdanxvetjzcss83y2e9lqnu7tht4ntvp24fksw26hwf5yrg6dyk2jz472efs2rjh42qsxlc5vp2m0rvmjcxn2y34wv0m5lyc7sdj7zksgn35dvxgqqqqqqqzjqsdjupkjtqssx05572ha26x39rczan5yft22pgwa72jw8gytavkm5ydn7yf5kpgh5zsq83y2e9lqnu7tht4ntvp24fksw26hwf5yrg6dyk2jz472efs2rjh4q2rd3ny0elv9m7mh38xxwe6ypfheeqeqlwgft05r6dhc50gtw0nv2qgrrl9x2qzzqvwukam32mhkdqrvwwcp5l6jcnnnezdq69vz8gdvvgmsqwk3efqf3f6gmf0ul63940awz429rdhhsts86s0r30e5nffwhrqw90xgxf7f60sm7tcclvyqwz7cer5q9223madstdy2p5q6y8qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqf2qheqqqqq2gprrgshynfszqyk2sgpvkrnmq53kv7r52rpnmtmd9ukredsnygsnymsurdy6e9la6l4hyz4qgxewqmftqggrcj9vjlsf709m46e4kq425mg89dthy6zp5dxjt9fp2l9v5c9pet6lqsx4k5r7rsld3hhe87psyy5cnhhzt4dz838f75734mted7pdsrflpvys23tkafmhctf3musnsaa42h6qjdggyqlhtevutzzpzlnwd8alq"}""" JsonSerializers.serialization.write(pr)(JsonSerializers.formats) shouldBe """{"amount":456001234,"nodeId":"03c48ac97e09f3cbbaeb35b02aaa6d072b57726841a34d25952157caca60a1caf5","paymentHash":"2cb0e7b052366787450c33daf6d2f2c3cb6132221326e1c1b49ac97fdd7eb720","description":"minimal offer","features":{"activated":{},"unknown":[]},"blindedPaths":[{"introductionNodeId":"03c48ac97e09f3cbbaeb35b02aaa6d072b57726841a34d25952157caca60a1caf5","blindedNodeIds":["031fca650042031dcb777156ef66806c73b01a7f52c4e73c89a0d15823a1ac6237"]}],"createdAt":1665412681,"expiresAt":1665412981,"serialized":"lni1qqsf4h8fsnpjkj057gjg9c3eqhv889440xh0z6f5kng9vsaad8pgq7sgqsdjuqsqpgxk66twd9kkzmpqdanxvetjzcss83y2e9lqnu7tht4ntvp24fksw26hwf5yrg6dyk2jz472efs2rjh42qsxlc5vp2m0rvmjcxn2y34wv0m5lyc7sdj7zksgn35dvxgqqqqqqqzjqsdjupkjtqssx05572ha26x39rczan5yft22pgwa72jw8gytavkm5ydn7yf5kpgh5zsq83y2e9lqnu7tht4ntvp24fksw26hwf5yrg6dyk2jz472efs2rjh4q2rd3ny0elv9m7mh38xxwe6ypfheeqeqlwgft05r6dhc50gtw0nv2qgrrl9x2qzzqvwukam32mhkdqrvwwcp5l6jcnnnezdq69vz8gdvvgmsqwk3efqf3f6gmf0ul63940awz429rdhhsts86s0r30e5nffwhrqw90xgxf7f60sm7tcclvyqwz7cer5q9223madstdy2p5q6y8qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqf2qheqqqqq2gprrgshynfszqyk2sgpvkrnmq53kv7r52rpnmtmd9ukredsnygsnymsurdy6e9la6l4hyz4qgxewqmftqggrcj9vjlsf709m46e4kq425mg89dthy6zp5dxjt9fp2l9v5c9pet6lqsx4k5r7rsld3hhe87psyy5cnhhzt4dz838f75734mted7pdsrflpvys23tkafmhctf3musnsaa42h6qjdggyqlhtevutzzpzlnwd8alq"}"""
} }
test("GlobalBalance serializer") { test("GlobalBalance serializer") {

View File

@ -652,7 +652,7 @@ class Bolt11InvoiceSpec extends AnyFunSuite {
} }
test("no unknown feature in invoice") { test("no unknown feature in invoice") {
val invoiceFeatures = TestConstants.Alice.nodeParams.features.bolt11Features().remove(RouteBlinding) val invoiceFeatures = TestConstants.Alice.nodeParams.features.bolt11Features()
assert(invoiceFeatures.unknown.nonEmpty) assert(invoiceFeatures.unknown.nonEmpty)
val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(123 msat), ByteVector32.One, priv, Left("Some invoice"), CltvExpiryDelta(18), features = invoiceFeatures) val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(123 msat), ByteVector32.One, priv, Left("Some invoice"), CltvExpiryDelta(18), features = invoiceFeatures)
assert(invoice.features == Features(PaymentSecret -> Mandatory, BasicMultiPartPayment -> Optional, PaymentMetadata -> Optional, VariableLengthOnion -> Mandatory)) assert(invoice.features == Features(PaymentSecret -> Mandatory, BasicMultiPartPayment -> Optional, PaymentMetadata -> Optional, VariableLengthOnion -> Mandatory))

View File

@ -213,7 +213,7 @@ class Bolt12InvoiceSpec extends AnyFunSuite {
val chain = Block.TestnetGenesisBlock.hash val chain = Block.TestnetGenesisBlock.hash
val amount = 123456 msat val amount = 123456 msat
val description = "invoice with many fields" val description = "invoice with many fields"
val features = Features[Feature](Features.VariableLengthOnion -> FeatureSupport.Mandatory, Features.RouteBlinding -> FeatureSupport.Mandatory) val features = Features.empty
val issuer = "alice" val issuer = "alice"
val nodeKey = PrivateKey(hex"998cf8ecab46f949bb960813b79d3317cabf4193452a211795cd8af1b9a25d90") val nodeKey = PrivateKey(hex"998cf8ecab46f949bb960813b79d3317cabf4193452a211795cd8af1b9a25d90")
val path = createPaymentBlindedRoute(nodeKey.publicKey, PrivateKey(hex"f0442c17bdd2cefe4a4ede210f163b068bb3fea6113ffacea4f322de7aa9737b"), hex"76030536ba732cdc4e7bb0a883750bab2e88cb3dddd042b1952c44b4849c86bb").copy(paymentInfo = PaymentInfo(2345 msat, 765, CltvExpiryDelta(324), 1000 msat, amount, Features.empty)) val path = createPaymentBlindedRoute(nodeKey.publicKey, PrivateKey(hex"f0442c17bdd2cefe4a4ede210f163b068bb3fea6113ffacea4f322de7aa9737b"), hex"76030536ba732cdc4e7bb0a883750bab2e88cb3dddd042b1952c44b4849c86bb").copy(paymentInfo = PaymentInfo(2345 msat, 765, CltvExpiryDelta(324), 1000 msat, amount, Features.empty))

View File

@ -171,7 +171,6 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, privKey, invoiceReq, createEmptyReceivingRoute(), router.ref, preimage, pathId)) sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, privKey, invoiceReq, createEmptyReceivingRoute(), router.ref, preimage, pathId))
router.expectNoMessage(50 millis) router.expectNoMessage(50 millis)
val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice
assert(invoice.features.hasFeature(RouteBlinding, Some(Mandatory)))
// Offer invoices shouldn't be stored in the DB until we receive a payment for it. // Offer invoices shouldn't be stored in the DB until we receive a payment for it.
assert(nodeParams.db.payments.getIncomingPayment(invoice.paymentHash).isEmpty) assert(nodeParams.db.payments.getIncomingPayment(invoice.paymentHash).isEmpty)
@ -290,7 +289,6 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
assert(invoice.amount == 25_000.msat) assert(invoice.amount == 25_000.msat)
assert(invoice.nodeId == privKey.publicKey) assert(invoice.nodeId == privKey.publicKey)
assert(invoice.blindedPaths.nonEmpty) assert(invoice.blindedPaths.nonEmpty)
assert(invoice.features.hasFeature(RouteBlinding, Some(Mandatory)))
assert(invoice.description.contains("a blinded coffee please")) assert(invoice.description.contains("a blinded coffee please"))
assert(invoice.invoiceRequest.offer == offer) assert(invoice.invoiceRequest.offer == offer)
assert(invoice.blindedPaths.length == 3) assert(invoice.blindedPaths.length == 3)
@ -472,7 +470,6 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
sender.send(handlerWithRouteBlinding, ReceiveStandardPayment(sender.ref, Some(1000 msat), Left("non blinded payment"))) sender.send(handlerWithRouteBlinding, ReceiveStandardPayment(sender.ref, Some(1000 msat), Left("non blinded payment")))
val invoice = sender.expectMsgType[Bolt11Invoice] val invoice = sender.expectMsgType[Bolt11Invoice]
assert(!invoice.features.hasFeature(RouteBlinding))
val packet = createBlindedPacket(1000 msat, invoice.paymentHash, defaultExpiry, CltvExpiry(nodeParams.currentBlockHeight), randomBytes32()) val packet = createBlindedPacket(1000 msat, invoice.paymentHash, defaultExpiry, CltvExpiry(nodeParams.currentBlockHeight), randomBytes32())
sender.send(handlerWithRouteBlinding, packet) sender.send(handlerWithRouteBlinding, packet)
@ -492,7 +489,6 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
val invoiceReq = InvoiceRequest(offer, 5000 msat, 1, featuresWithRouteBlinding.bolt12Features(), randomKey(), Block.RegtestGenesisBlock.hash) val invoiceReq = InvoiceRequest(offer, 5000 msat, 1, featuresWithRouteBlinding.bolt12Features(), randomKey(), Block.RegtestGenesisBlock.hash)
sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, randomBytes32(), randomBytes32())) sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, randomBytes32(), randomBytes32()))
val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice
assert(invoice.features.hasFeature(RouteBlinding, Some(Mandatory)))
val add = UpdateAddHtlc(ByteVector32.One, 0, 5000 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None) val add = UpdateAddHtlc(ByteVector32.One, 0, 5000 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, add.amountMsat, add.cltvExpiry, randomBytes32(), None))) sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, add.amountMsat, add.cltvExpiry, randomBytes32(), None)))
@ -511,7 +507,6 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
val pathId = randomBytes32() val pathId = randomBytes32()
sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, preimage, pathId)) sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, preimage, pathId))
val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice
assert(invoice.features.hasFeature(RouteBlinding, Some(Mandatory)))
assert(nodeParams.db.payments.getIncomingPayment(invoice.paymentHash).isEmpty) assert(nodeParams.db.payments.getIncomingPayment(invoice.paymentHash).isEmpty)
val packet = createBlindedPacket(5000 msat, invoice.paymentHash, defaultExpiry, CltvExpiry(nodeParams.currentBlockHeight), pathId) val packet = createBlindedPacket(5000 msat, invoice.paymentHash, defaultExpiry, CltvExpiry(nodeParams.currentBlockHeight), pathId)
@ -535,7 +530,6 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
val invoiceReq = InvoiceRequest(offer, 5000 msat, 1, featuresWithRouteBlinding.bolt12Features(), randomKey(), Block.RegtestGenesisBlock.hash) val invoiceReq = InvoiceRequest(offer, 5000 msat, 1, featuresWithRouteBlinding.bolt12Features(), randomKey(), Block.RegtestGenesisBlock.hash)
sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, preimage, pathId)) sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, preimage, pathId))
val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice
assert(invoice.features.hasFeature(RouteBlinding, Some(Mandatory)))
val packet = createBlindedPacket(5000 msat, invoice.paymentHash, defaultExpiry, CltvExpiry(nodeParams.currentBlockHeight), pathId) val packet = createBlindedPacket(5000 msat, invoice.paymentHash, defaultExpiry, CltvExpiry(nodeParams.currentBlockHeight), pathId)
sender.send(handlerWithRouteBlinding, packet) sender.send(handlerWithRouteBlinding, packet)
@ -556,7 +550,6 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
val pathId = randomBytes32() val pathId = randomBytes32()
sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, preimage, pathId)) sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, preimage, pathId))
val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice
assert(invoice.features.hasFeature(RouteBlinding, Some(Mandatory)))
// We test the case where the HTLC's cltv_expiry is lower than expected and doesn't meet the min_final_expiry_delta. // We test the case where the HTLC's cltv_expiry is lower than expected and doesn't meet the min_final_expiry_delta.
val packet = createBlindedPacket(5000 msat, invoice.paymentHash, defaultExpiry - CltvExpiryDelta(1), defaultExpiry, pathId) val packet = createBlindedPacket(5000 msat, invoice.paymentHash, defaultExpiry - CltvExpiryDelta(1), defaultExpiry, pathId)

View File

@ -54,7 +54,6 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
object Tags { object Tags {
val DisableMPP = "mpp_disabled" val DisableMPP = "mpp_disabled"
val DisableRouteBlinding = "route_blinding_disabled"
val RandomizeFinalExpiry = "random_final_expiry" val RandomizeFinalExpiry = "random_final_expiry"
} }
@ -63,14 +62,12 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
val featuresWithoutMpp: Features[Bolt11Feature] = Features( val featuresWithoutMpp: Features[Bolt11Feature] = Features(
VariableLengthOnion -> Mandatory, VariableLengthOnion -> Mandatory,
PaymentSecret -> Mandatory, PaymentSecret -> Mandatory,
RouteBlinding -> Optional,
) )
val featuresWithMpp: Features[Bolt11Feature] = Features( val featuresWithMpp: Features[Bolt11Feature] = Features(
VariableLengthOnion -> Mandatory, VariableLengthOnion -> Mandatory,
PaymentSecret -> Mandatory, PaymentSecret -> Mandatory,
BasicMultiPartPayment -> Optional, BasicMultiPartPayment -> Optional,
RouteBlinding -> Optional,
) )
val featuresWithTrampoline: Features[Bolt11Feature] = Features( val featuresWithTrampoline: Features[Bolt11Feature] = Features(
@ -80,12 +77,6 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
TrampolinePaymentPrototype -> Optional, TrampolinePaymentPrototype -> Optional,
) )
val featuresWithoutRouteBlinding: Features[Bolt11Feature] = Features(
VariableLengthOnion -> Mandatory,
PaymentSecret -> Mandatory,
BasicMultiPartPayment -> Optional,
)
case class FakePaymentFactory(payFsm: TestProbe, multiPartPayFsm: TestProbe) extends PaymentInitiator.MultiPartPaymentFactory { case class FakePaymentFactory(payFsm: TestProbe, multiPartPayFsm: TestProbe) extends PaymentInitiator.MultiPartPaymentFactory {
// @formatter:off // @formatter:off
override def spawnOutgoingPayment(context: ActorContext, cfg: SendPaymentConfig): ActorRef = { override def spawnOutgoingPayment(context: ActorContext, cfg: SendPaymentConfig): ActorRef = {
@ -102,8 +93,6 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
override def withFixture(test: OneArgTest): Outcome = { override def withFixture(test: OneArgTest): Outcome = {
val features = if (test.tags.contains(Tags.DisableMPP)) { val features = if (test.tags.contains(Tags.DisableMPP)) {
featuresWithoutMpp featuresWithoutMpp
} else if (test.tags.contains(Tags.DisableRouteBlinding)) {
featuresWithoutRouteBlinding
} else { } else {
featuresWithMpp featuresWithMpp
} }
@ -205,7 +194,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
test("forward single-part payment when multi-part deactivated", Tag(Tags.DisableMPP)) { f => test("forward single-part payment when multi-part deactivated", Tag(Tags.DisableMPP)) { f =>
import f._ import f._
val finalExpiryDelta = CltvExpiryDelta(24) val finalExpiryDelta = CltvExpiryDelta(24)
val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(finalAmount), paymentHash, priv_c.privateKey, Left("Some MPP invoice"), finalExpiryDelta, features = featuresWithoutRouteBlinding) val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(finalAmount), paymentHash, priv_c.privateKey, Left("Some MPP invoice"), finalExpiryDelta, features = featuresWithMpp)
val req = SendPaymentToNode(sender.ref, finalAmount, invoice, Nil, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams) val req = SendPaymentToNode(sender.ref, finalAmount, invoice, Nil, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams)
assert(req.finalExpiry(nodeParams) == (finalExpiryDelta + 1).toCltvExpiry(nodeParams.currentBlockHeight)) assert(req.finalExpiry(nodeParams) == (finalExpiryDelta + 1).toCltvExpiry(nodeParams.currentBlockHeight))
sender.send(initiator, req) sender.send(initiator, req)
@ -229,7 +218,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
test("forward multi-part payment") { f => test("forward multi-part payment") { f =>
import f._ import f._
val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(finalAmount), paymentHash, priv_c.privateKey, Left("Some invoice"), CltvExpiryDelta(18), features = featuresWithoutRouteBlinding) val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(finalAmount), paymentHash, priv_c.privateKey, Left("Some invoice"), CltvExpiryDelta(18), features = featuresWithMpp)
val req = SendPaymentToNode(sender.ref, finalAmount + 100.msat, invoice, Nil, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams) val req = SendPaymentToNode(sender.ref, finalAmount + 100.msat, invoice, Nil, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams)
sender.send(initiator, req) sender.send(initiator, req)
val id = sender.expectMsgType[UUID] val id = sender.expectMsgType[UUID]
@ -253,7 +242,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
test("forward multi-part payment with randomized final expiry", Tag(Tags.RandomizeFinalExpiry)) { f => test("forward multi-part payment with randomized final expiry", Tag(Tags.RandomizeFinalExpiry)) { f =>
import f._ import f._
val invoiceFinalExpiryDelta = CltvExpiryDelta(6) val invoiceFinalExpiryDelta = CltvExpiryDelta(6)
val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(finalAmount), paymentHash, priv_c.privateKey, Left("Some invoice"), invoiceFinalExpiryDelta, features = featuresWithoutRouteBlinding) val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(finalAmount), paymentHash, priv_c.privateKey, Left("Some invoice"), invoiceFinalExpiryDelta, features = featuresWithMpp)
val req = SendPaymentToNode(sender.ref, finalAmount, invoice, Nil, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams) val req = SendPaymentToNode(sender.ref, finalAmount, invoice, Nil, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams)
sender.send(initiator, req) sender.send(initiator, req)
val id = sender.expectMsgType[UUID] val id = sender.expectMsgType[UUID]
@ -266,7 +255,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
test("forward multi-part payment with pre-defined route") { f => test("forward multi-part payment with pre-defined route") { f =>
import f._ import f._
val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(finalAmount), paymentHash, priv_c.privateKey, Left("Some invoice"), CltvExpiryDelta(18), features = featuresWithoutRouteBlinding) val invoice = Bolt11Invoice(Block.LivenetGenesisBlock.hash, Some(finalAmount), paymentHash, priv_c.privateKey, Left("Some invoice"), CltvExpiryDelta(18), features = featuresWithMpp)
val route = PredefinedChannelRoute(finalAmount / 2, c, Seq(channelUpdate_ab.shortChannelId, channelUpdate_bc.shortChannelId)) val route = PredefinedChannelRoute(finalAmount / 2, c, Seq(channelUpdate_ab.shortChannelId, channelUpdate_bc.shortChannelId))
val req = SendPaymentToRoute(finalAmount, invoice, Nil, route, None, None, None) val req = SendPaymentToRoute(finalAmount, invoice, Nil, route, None, None, None)
sender.send(initiator, req) sender.send(initiator, req)
@ -363,18 +352,6 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
sender.expectMsg(NoPendingPayment(PaymentIdentifier.PaymentUUID(id))) sender.expectMsg(NoPendingPayment(PaymentIdentifier.PaymentUUID(id)))
} }
test("reject blinded payment when route blinding deactivated", Tag(Tags.DisableRouteBlinding)) { f =>
import f._
val invoice = createBolt12Invoice(Features(BasicMultiPartPayment -> Optional), randomKey())
val resolvedPaths = invoice.blindedPaths.map(path => ResolvedPath(path, path.route.introductionNodeId.asInstanceOf[EncodedNodeId.Plain].publicKey))
val req = SendPaymentToNode(sender.ref, finalAmount, invoice, resolvedPaths, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams)
sender.send(initiator, req)
val id = sender.expectMsgType[UUID]
val fail = sender.expectMsgType[PaymentFailed]
assert(fail.id == id)
assert(fail.failures == LocalFailure(finalAmount, Nil, UnsupportedFeatures(invoice.features)) :: Nil)
}
test("forward trampoline payment") { f => test("forward trampoline payment") { f =>
import f._ import f._
val ignoredRoutingHints = List(List(ExtraHop(b, channelUpdate_bc.shortChannelId, feeBase = 10 msat, feeProportionalMillionths = 1, cltvExpiryDelta = CltvExpiryDelta(12)))) val ignoredRoutingHints = List(List(ExtraHop(b, channelUpdate_bc.shortChannelId, feeBase = 10 msat, feeProportionalMillionths = 1, cltvExpiryDelta = CltvExpiryDelta(12))))
@ -429,7 +406,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
import f._ import f._
// This is disabled because it would let the trampoline node steal the whole payment (if malicious). // This is disabled because it would let the trampoline node steal the whole payment (if malicious).
val routingHints = List(List(Bolt11Invoice.ExtraHop(b, channelUpdate_bc.shortChannelId, 10 msat, 100, CltvExpiryDelta(144)))) val routingHints = List(List(Bolt11Invoice.ExtraHop(b, channelUpdate_bc.shortChannelId, 10 msat, 100, CltvExpiryDelta(144))))
val invoice = Bolt11Invoice(Block.RegtestGenesisBlock.hash, None, paymentHash, priv_a.privateKey, Left("#abittooreckless"), CltvExpiryDelta(18), None, None, routingHints, features = featuresWithoutRouteBlinding) val invoice = Bolt11Invoice(Block.RegtestGenesisBlock.hash, None, paymentHash, priv_a.privateKey, Left("#abittooreckless"), CltvExpiryDelta(18), None, None, routingHints, features = featuresWithMpp)
val trampolineFees = 21_000 msat val trampolineFees = 21_000 msat
val req = SendTrampolinePayment(sender.ref, finalAmount, invoice, b, Seq((trampolineFees, CltvExpiryDelta(12))), routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams) val req = SendTrampolinePayment(sender.ref, finalAmount, invoice, b, Seq((trampolineFees, CltvExpiryDelta(12))), routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams)
sender.send(initiator, req) sender.send(initiator, req)