Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ trait PaymentsDb {

def getPaymentRequest(paymentHash: ByteVector32): Option[PaymentRequest]

// returns non paid payment request
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that comment is true, it will return all payment requests included the ones that have been paid

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In SqlitePaymentDb#L158 we filter for received_at IS NULL so this retrieves only non paid payment requests, note that we update the record setting received_at when receiving a payment.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok my bad.... I think we're good to go!

def getPendingPaymentRequestAndPreimage(paymentHash: ByteVector32): Option[(ByteVector32, PaymentRequest)]

def listPaymentRequests(from: Long, to: Long): Seq[PaymentRequest]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class LocalPaymentHandler(nodeParams: NodeParams) extends Actor with ActorLoggin
// it must not be greater than two times the requested amount.
// see https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#failure-messages
paymentRequest.amount match {
case _ if paymentRequest.isExpired =>
sender ! CMD_FAIL_HTLC(htlc.id, Right(IncorrectOrUnknownPaymentDetails(htlc.amountMsat)), commit = true)
case _ if htlc.cltvExpiry < minFinalExpiry =>
sender ! CMD_FAIL_HTLC(htlc.id, Right(FinalExpiryTooSoon), commit = true)
case Some(amount) if MilliSatoshi(htlc.amountMsat) < amount =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@

package fr.acinq.eclair.payment

import java.math.BigInteger

import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey}
import fr.acinq.bitcoin.{MilliSatoshi, _}
import fr.acinq.eclair.ShortChannelId
import fr.acinq.eclair.payment.PaymentRequest._
import scodec.Codec
import scodec.bits.{BitVector, ByteOrdering, ByteVector}
import scodec.codecs.{list, ubyte}

import scala.concurrent.duration._
import scala.compat.Platform
import scala.util.Try

/**
Expand Down Expand Up @@ -78,6 +77,11 @@ case class PaymentRequest(prefix: String, amount: Option[MilliSatoshi], timestam
case cltvExpiry: PaymentRequest.MinFinalCltvExpiry => cltvExpiry.toLong
}

def isExpired: Boolean = expiry match {
case Some(expiryTime) => timestamp + expiryTime <= Platform.currentTime.milliseconds.toSeconds
case None => timestamp + DEFAULT_EXPIRY_SECONDS <= Platform.currentTime.milliseconds.toSeconds
}

/**
*
* @return the hash of this payment request
Expand Down Expand Up @@ -106,6 +110,8 @@ case class PaymentRequest(prefix: String, amount: Option[MilliSatoshi], timestam

object PaymentRequest {

val DEFAULT_EXPIRY_SECONDS = 3600

val prefixes = Map(
Block.RegtestGenesisBlock.hash -> "lnbcrt",
Block.TestnetGenesisBlock.hash -> "lntb",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class PaymentHandlerSpec extends TestKit(ActorSystem("test")) with FunSuiteLike
val pr = sender.expectMsgType[PaymentRequest]
assert(nodeParams.db.payments.getIncomingPayment(pr.paymentHash).isEmpty)
assert(nodeParams.db.payments.getPendingPaymentRequestAndPreimage(pr.paymentHash).isDefined)
assert(!nodeParams.db.payments.getPendingPaymentRequestAndPreimage(pr.paymentHash).get._2.isExpired)

val add = UpdateAddHtlc(ByteVector32(ByteVector.fill(32)(1)), 0, amountMsat.amount, pr.paymentHash, expiry, ByteVector.empty)
sender.send(handler, add)
Expand Down Expand Up @@ -149,4 +150,24 @@ class PaymentHandlerSpec extends TestKit(ActorSystem("test")) with FunSuiteLike
sender.send(handler, ReceivePayment(Some(MilliSatoshi(42000)), "1 coffee without routing info"))
assert(sender.expectMsgType[PaymentRequest].routingInfo === Nil)
}

test("LocalPaymentHandler should reject incoming payments if the payment request is expired") {
val nodeParams = Alice.nodeParams
val handler = TestActorRef[LocalPaymentHandler](LocalPaymentHandler.props(nodeParams))
val sender = TestProbe()
val eventListener = TestProbe()
system.eventStream.subscribe(eventListener.ref, classOf[PaymentReceived])

val amountMsat = MilliSatoshi(42000)
val expiry = Globals.blockCount.get() + 12

sender.send(handler, ReceivePayment(Some(amountMsat), "some desc", expirySeconds_opt = Some(0)))
val pr = sender.expectMsgType[PaymentRequest]

val add = UpdateAddHtlc(ByteVector32(ByteVector.fill(32)(1)), 0, amountMsat.amount, pr.paymentHash, expiry, ByteVector.empty)
sender.send(handler, add)

sender.expectMsgType[CMD_FAIL_HTLC]
assert(nodeParams.db.payments.getIncomingPayment(pr.paymentHash).isEmpty)
}
}