@@ -22,7 +22,7 @@ import akka.actor.typed.scaladsl.Behaviors
2222import akka .actor .typed .scaladsl .adapter .ClassicActorContextOps
2323import akka .actor .{ActorContext , ActorRef , PoisonPill , Status }
2424import akka .event .{DiagnosticLoggingAdapter , LoggingAdapter }
25- import fr .acinq .bitcoin .{ByteVector32 , Crypto }
25+ import fr .acinq .bitcoin .{ByteVector32 , ByteVector64 , Crypto }
2626import fr .acinq .eclair .channel .{CMD_FAIL_HTLC , CMD_FULFILL_HTLC , RES_SUCCESS }
2727import fr .acinq .eclair .db ._
2828import fr .acinq .eclair .payment .Monitoring .{Metrics , Tags }
@@ -71,7 +71,13 @@ class MultiPartHandler(nodeParams: NodeParams, register: ActorRef, db: IncomingP
7171 Metrics .PaymentFailed .withTag(Tags .Direction , Tags .Directions .Received ).withTag(Tags .Failure , Tags .FailureType (cmdFail)).increment()
7272 PendingCommandsDb .safeSend(register, nodeParams.db.pendingCommands, p.add.channelId, cmdFail)
7373 case None =>
74- log.info(" received payment for amount={} totalAmount={}" , p.add.amountMsat, p.payload.totalAmount)
74+ // We log whether the sender included the payment metadata field.
75+ // We always set it in our invoices to test whether senders support it.
76+ // Once all incoming payments correctly set that field, we can make it mandatory.
77+ p.payload.paymentMetadata match {
78+ case Some (paymentMetadata) => log.info(" received payment for amount={} totalAmount={} paymentMetadata={}" , p.add.amountMsat, p.payload.totalAmount, paymentMetadata.toHex)
79+ case None => log.info(" received payment for amount={} totalAmount={} without payment metadata" , p.add.amountMsat, p.payload.totalAmount)
80+ }
7581 pendingPayments.get(p.add.paymentHash) match {
7682 case Some ((_, handler)) =>
7783 handler ! MultiPartPaymentFSM .HtlcPart (p.payload.totalAmount, p.add)
@@ -223,12 +229,25 @@ object MultiPartHandler {
223229 val paymentPreimage = paymentPreimage_opt.getOrElse(randomBytes32())
224230 val paymentHash = Crypto .sha256(paymentPreimage)
225231 val expirySeconds = expirySeconds_opt.getOrElse(nodeParams.paymentRequestExpiry.toSeconds)
232+ val paymentMetadata = Some (ByteVector64 .Zeroes .bytes)
226233 val invoiceFeatures = {
227234 val activatedInvoiceFeatures = nodeParams.features.invoiceFeatures().activated.map { case (f, s) => f.supportBit(s) }.toSet
228235 val allInvoiceFeatures = if (nodeParams.enableTrampolinePayment) activatedInvoiceFeatures + Features .TrampolinePayment .optional else activatedInvoiceFeatures
229236 allInvoiceFeatures.toSeq
230237 }
231- val paymentRequest = PaymentRequest (nodeParams.chainHash, amount_opt, paymentHash, nodeParams.privateKey, description, nodeParams.minFinalExpiryDelta, fallbackAddress_opt, expirySeconds = Some (expirySeconds), extraHops = extraHops, features = PaymentRequestFeatures (invoiceFeatures : _* ))
238+ val paymentRequest = PaymentRequest (
239+ nodeParams.chainHash,
240+ amount_opt,
241+ paymentHash,
242+ nodeParams.privateKey,
243+ description,
244+ nodeParams.minFinalExpiryDelta,
245+ fallbackAddress_opt,
246+ expirySeconds = Some (expirySeconds),
247+ extraHops = extraHops,
248+ paymentMetadata = paymentMetadata,
249+ features = PaymentRequestFeatures (invoiceFeatures : _* )
250+ )
232251 context.log.debug(" generated payment request={} from amount={}" , PaymentRequest .write(paymentRequest), amount_opt)
233252 nodeParams.db.payments.addIncomingPayment(paymentRequest, paymentPreimage, paymentType)
234253 paymentRequest
0 commit comments