Skip to content

Commit 3628b43

Browse files
committed
Remove quantity
1 parent bc5697a commit 3628b43

File tree

7 files changed

+36
-75
lines changed

7 files changed

+36
-75
lines changed

eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ trait Eclair {
122122

123123
def receive(description: Either[String, ByteVector32], amount_opt: Option[MilliSatoshi], expire_opt: Option[Long], fallbackAddress_opt: Option[String], paymentPreimage_opt: Option[ByteVector32], privateChannelIds_opt: Option[List[ByteVector32]])(implicit timeout: Timeout): Future[Bolt11Invoice]
124124

125-
def createOffer(description_opt: Option[String], amount_opt: Option[MilliSatoshi], expiry_opt: Option[TimestampSecond], issuer_opt: Option[String], availableQuantity_opt: Option[Long], firstNodeId_opt: Option[PublicKey], hideNodeId: Boolean)(implicit timeout: Timeout): Future[Offer]
125+
def createOffer(description_opt: Option[String], amount_opt: Option[MilliSatoshi], expiry_opt: Option[TimestampSecond], issuer_opt: Option[String], firstNodeId_opt: Option[PublicKey], hideNodeId: Boolean)(implicit timeout: Timeout): Future[Offer]
126126

127127
def disableOffer(offer: Offer)(implicit timeout: Timeout): Unit
128128

@@ -378,9 +378,9 @@ class EclairImpl(appKit: Kit) extends Eclair with Logging {
378378
}
379379
}
380380

381-
override def createOffer(description_opt: Option[String], amount_opt: Option[MilliSatoshi], expiry_opt: Option[TimestampSecond], issuer_opt: Option[String], availableQuantity_opt: Option[Long], firstNodeId_opt: Option[PublicKey], hideNodeId: Boolean)(implicit timeout: Timeout): Future[Offer] = {
381+
override def createOffer(description_opt: Option[String], amount_opt: Option[MilliSatoshi], expiry_opt: Option[TimestampSecond], issuer_opt: Option[String], firstNodeId_opt: Option[PublicKey], hideNodeId: Boolean)(implicit timeout: Timeout): Future[Offer] = {
382382
val offerCreator = appKit.system.spawnAnonymous(OfferCreator(appKit.nodeParams, appKit.router, appKit.offerManager, appKit.defaultOfferHandler))
383-
offerCreator.ask[Either[String, Offer]](replyTo => OfferCreator.Create(replyTo, description_opt, amount_opt, expiry_opt, issuer_opt, availableQuantity_opt, firstNodeId_opt, hideNodeId))
383+
offerCreator.ask[Either[String, Offer]](replyTo => OfferCreator.Create(replyTo, description_opt, amount_opt, expiry_opt, issuer_opt, firstNodeId_opt, hideNodeId))
384384
.flatMap {
385385
case Left(errorMessage) => Future.failed(new Exception(errorMessage))
386386
case Right(offer) => Future.successful(offer)

eclair-core/src/main/scala/fr/acinq/eclair/db/DualDatabases.scala

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -405,26 +405,16 @@ case class DualOffersDb(primary: OffersDb, secondary: OffersDb) extends OffersDb
405405

406406
private implicit val ec: ExecutionContext = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("db-offers").build()))
407407

408-
override def addOffer(offer: OfferTypes.Offer, pathId_opt: Option[ByteVector32], quantityAvailable: Long): Unit = {
409-
runAsync(secondary.addOffer(offer, pathId_opt, quantityAvailable))
410-
primary.addOffer(offer, pathId_opt, quantityAvailable)
408+
override def addOffer(offer: OfferTypes.Offer, pathId_opt: Option[ByteVector32]): Unit = {
409+
runAsync(secondary.addOffer(offer, pathId_opt))
410+
primary.addOffer(offer, pathId_opt)
411411
}
412412

413413
override def disableOffer(offer: OfferTypes.Offer): Unit = {
414414
runAsync(secondary.disableOffer(offer))
415415
primary.disableOffer(offer)
416416
}
417417

418-
override def getAvailableQuantity(offer: OfferTypes.Offer): Long = {
419-
runAsync(secondary.getAvailableQuantity(offer))
420-
primary.getAvailableQuantity(offer)
421-
}
422-
423-
override def setAvailableQuantity(offer: OfferTypes.Offer, quantityAvailable: Long): Unit = {
424-
runAsync(secondary.setAvailableQuantity(offer, quantityAvailable))
425-
primary.setAvailableQuantity(offer, quantityAvailable)
426-
}
427-
428418
override def listOffers(onlyActive: Boolean): Seq[OfferData] = {
429419
runAsync(secondary.listOffers(onlyActive))
430420
primary.listOffers(onlyActive)

eclair-core/src/main/scala/fr/acinq/eclair/db/OffersDb.scala

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,12 @@ package fr.acinq.eclair.db
1919
import fr.acinq.bitcoin.scalacompat.ByteVector32
2020
import fr.acinq.eclair.wire.protocol.OfferTypes.Offer
2121

22-
case class OfferData(offer: Offer, pathId_opt: Option[ByteVector32], quantityAvailable: Long)
22+
case class OfferData(offer: Offer, pathId_opt: Option[ByteVector32])
2323

2424
trait OffersDb {
25-
def addOffer(offer: Offer, pathId_opt: Option[ByteVector32], quantityAvailable: Long): Unit
25+
def addOffer(offer: Offer, pathId_opt: Option[ByteVector32]): Unit
2626

2727
def disableOffer(offer: Offer): Unit
2828

29-
def getAvailableQuantity(offer: Offer): Long
30-
31-
// Must only be called from the `DefaultHandler` actor to prevent data races.
32-
def setAvailableQuantity(offer: Offer, quantityAvailable: Long): Unit
33-
3429
def listOffers(onlyActive: Boolean): Seq[OfferData]
3530
}

eclair-core/src/main/scala/fr/acinq/eclair/db/pg/PgOffersDb.scala

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class PgOffersDb(implicit ds: DataSource, lock: PgLock) extends OffersDb with Lo
4545
case None =>
4646
statement.executeUpdate("CREATE SCHEMA offers")
4747

48-
statement.executeUpdate("CREATE TABLE offers.managed (offer_id TEXT NOT NULL PRIMARY KEY, offer TEXT NOT NULL, path_id TEXT, created_at TIMESTAMP WITH TIME ZONE NOT NULL, is_active BOOLEAN NOT NULL, quantity_available BIGINT NOT NULL)")
48+
statement.executeUpdate("CREATE TABLE offers.managed (offer_id TEXT NOT NULL PRIMARY KEY, offer TEXT NOT NULL, path_id TEXT, created_at TIMESTAMP WITH TIME ZONE NOT NULL, is_active BOOLEAN NOT NULL)")
4949

5050
statement.executeUpdate("CREATE INDEX offer_is_active_idx ON offers.managed(is_active)")
5151
case Some(CURRENT_VERSION) => () // table is up-to-date, nothing to do
@@ -55,16 +55,15 @@ class PgOffersDb(implicit ds: DataSource, lock: PgLock) extends OffersDb with Lo
5555
}
5656
}
5757

58-
override def addOffer(offer: OfferTypes.Offer, pathId_opt: Option[ByteVector32], quantityAvailable: Long): Unit = withMetrics("offers/add", DbBackends.Postgres){
58+
override def addOffer(offer: OfferTypes.Offer, pathId_opt: Option[ByteVector32]): Unit = withMetrics("offers/add", DbBackends.Postgres){
5959
withLock { pg =>
60-
using(pg.prepareStatement("INSERT INTO offers.managed (offer_id, offer, path_id, created_at, is_active, quantity_available) VALUES (?, ?, ?, NOW, TRUE, ?)")) { statement =>
60+
using(pg.prepareStatement("INSERT INTO offers.managed (offer_id, offer, path_id, created_at, is_active) VALUES (?, ?, ?, NOW, TRUE)")) { statement =>
6161
statement.setString(1, offer.offerId.toHex)
6262
statement.setString(2, offer.toString)
6363
pathId_opt match {
6464
case Some(pathId) => statement.setString(3, pathId.toHex)
6565
case None => statement.setNull(3, java.sql.Types.VARCHAR)
6666
}
67-
statement.setLong(4, quantityAvailable)
6867

6968
statement.executeUpdate()
7069
}
@@ -73,9 +72,5 @@ class PgOffersDb(implicit ds: DataSource, lock: PgLock) extends OffersDb with Lo
7372

7473
override def disableOffer(offer: OfferTypes.Offer): Unit = ???
7574

76-
override def getAvailableQuantity(offer: OfferTypes.Offer): Long = ???
77-
78-
override def setAvailableQuantity(offer: OfferTypes.Offer, quantityAvailable: Long): Unit = ???
79-
8075
override def listOffers(onlyActive: Boolean): Seq[OfferData] = ???
8176
}

eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteOffersDb.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,9 @@ import java.sql.Connection
2525

2626
class SqliteOffersDb(val sqlite: Connection) extends OffersDb with Logging {
2727

28-
override def addOffer(offer: OfferTypes.Offer, pathId_opt: Option[ByteVector32], quantityAvailable: Long): Unit = ???
28+
override def addOffer(offer: OfferTypes.Offer, pathId_opt: Option[ByteVector32]): Unit = ???
2929

3030
override def disableOffer(offer: OfferTypes.Offer): Unit = ???
3131

32-
override def getAvailableQuantity(offer: OfferTypes.Offer): Long = ???
33-
34-
override def setAvailableQuantity(offer: OfferTypes.Offer, quantityAvailable: Long): Unit = ???
35-
3632
override def listOffers(onlyActive: Boolean): Seq[OfferData] = ???
3733
}

eclair-core/src/main/scala/fr/acinq/eclair/payment/offer/DefaultHandler.scala

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,32 +34,21 @@ object DefaultHandler {
3434
Behaviors.setup(context =>
3535
Behaviors.receiveMessage {
3636
case OfferManager.HandleInvoiceRequest(replyTo, invoiceRequest) =>
37-
if (nodeParams.db.offers.getAvailableQuantity(invoiceRequest.offer) >= invoiceRequest.quantity) {
38-
val amount = invoiceRequest.amount.getOrElse(10_000_000.msat)
39-
invoiceRequest.offer.contactInfos.head match {
40-
case OfferTypes.RecipientNodeId(nodeId) =>
41-
val route = ReceivingRoute(Seq(nodeId), nodeParams.channelConf.maxExpiryDelta)
42-
replyTo ! OfferManager.InvoiceRequestActor.ApproveRequest(amount, Seq(route), None)
43-
case OfferTypes.BlindedPath(BlindedRoute(firstNodeId: EncodedNodeId.WithPublicKey, _, _)) =>
44-
val routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams
45-
router ! BlindedRouteRequest(context.spawnAnonymous(waitForRoute(nodeParams, replyTo, amount)), firstNodeId.publicKey, nodeParams.nodeId, amount, routeParams, pathsToFind = 2)
46-
case OfferTypes.BlindedPath(BlindedRoute(_: EncodedNodeId.ShortChannelIdDir, _, _)) =>
47-
context.log.error("unexpected managed offer with compact first node id")
48-
replyTo ! OfferManager.InvoiceRequestActor.RejectRequest("internal error")
49-
}
50-
} else {
51-
replyTo ! OfferManager.InvoiceRequestActor.RejectRequest("quantity unavailable for this offer")
37+
val amount = invoiceRequest.amount.getOrElse(10_000_000.msat)
38+
invoiceRequest.offer.contactInfos.head match {
39+
case OfferTypes.RecipientNodeId(nodeId) =>
40+
val route = ReceivingRoute(Seq(nodeId), nodeParams.channelConf.maxExpiryDelta)
41+
replyTo ! OfferManager.InvoiceRequestActor.ApproveRequest(amount, Seq(route), None)
42+
case OfferTypes.BlindedPath(BlindedRoute(firstNodeId: EncodedNodeId.WithPublicKey, _, _)) =>
43+
val routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams
44+
router ! BlindedRouteRequest(context.spawnAnonymous(waitForRoute(nodeParams, replyTo, amount)), firstNodeId.publicKey, nodeParams.nodeId, amount, routeParams, pathsToFind = 2)
45+
case OfferTypes.BlindedPath(BlindedRoute(_: EncodedNodeId.ShortChannelIdDir, _, _)) =>
46+
context.log.error("unexpected managed offer with compact first node id")
47+
replyTo ! OfferManager.InvoiceRequestActor.RejectRequest("internal error")
5248
}
5349
Behaviors.same
54-
case OfferManager.HandlePayment(replyTo, offer, invoiceData) =>
55-
val availableQuantity = nodeParams.db.offers.getAvailableQuantity(offer)
56-
if (availableQuantity >= invoiceData.quantity) {
57-
// Only this actor reads and writes the available quantity so there is no data race.
58-
nodeParams.db.offers.setAvailableQuantity(offer, availableQuantity - invoiceData.quantity)
59-
replyTo ! OfferManager.PaymentActor.AcceptPayment()
60-
} else {
61-
replyTo ! OfferManager.PaymentActor.RejectPayment("quantity unavailable for this offer")
62-
}
50+
case OfferManager.HandlePayment(replyTo, _, _) =>
51+
replyTo ! OfferManager.PaymentActor.AcceptPayment()
6352
Behaviors.same
6453
}
6554
)

eclair-core/src/main/scala/fr/acinq/eclair/payment/offer/OfferCreator.scala

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ object OfferCreator {
3636
amount_opt: Option[MilliSatoshi],
3737
expiry_opt: Option[TimestampSecond],
3838
issuer_opt: Option[String],
39-
availableQuantity_opt: Option[Long],
4039
firstNodeId_opt: Option[PublicKey],
4140
hideNodeId: Boolean) extends Command
4241

@@ -46,8 +45,8 @@ object OfferCreator {
4645

4746
def apply(nodeParams: NodeParams, router: ActorRef, offerManager: typed.ActorRef[OfferManager.Command], defaultOfferHandler: typed.ActorRef[OfferManager.HandlerCommand]): Behavior[Command] =
4847
Behaviors.receivePartial {
49-
case (context, Create(replyTo, description_opt, amount_opt, expiry_opt, issuer_opt, availableQuantity_opt, firstNodeId, hideNodeId)) =>
50-
new OfferCreator(context, replyTo, nodeParams, router, offerManager, defaultOfferHandler).init(description_opt, amount_opt, expiry_opt, issuer_opt, availableQuantity_opt, firstNodeId, hideNodeId)
48+
case (context, Create(replyTo, description_opt, amount_opt, expiry_opt, issuer_opt, firstNodeId, hideNodeId)) =>
49+
new OfferCreator(context, replyTo, nodeParams, router, offerManager, defaultOfferHandler).init(description_opt, amount_opt, expiry_opt, issuer_opt, firstNodeId, hideNodeId)
5150
}
5251
}
5352

@@ -63,7 +62,6 @@ private class OfferCreator(context: ActorContext[OfferCreator.Command],
6362
amount_opt: Option[MilliSatoshi],
6463
expiry_opt: Option[TimestampSecond],
6564
issuer_opt: Option[String],
66-
availableQuantity_opt: Option[Long],
6765
firstNodeId_opt: Option[PublicKey],
6866
hideNodeId: Boolean): Behavior[Command] = {
6967
if (amount_opt.nonEmpty && description_opt.isEmpty) {
@@ -76,47 +74,45 @@ private class OfferCreator(context: ActorContext[OfferCreator.Command],
7674
description_opt.map(OfferDescription),
7775
expiry_opt.map(OfferAbsoluteExpiry),
7876
issuer_opt.map(OfferIssuer),
79-
availableQuantity_opt.map(_ => OfferQuantityMax(0)),
8077
).flatten
81-
val quantityAvailable = availableQuantity_opt.getOrElse(Long.MaxValue)
8278
firstNodeId_opt match {
8379
case Some(firstNodeId) =>
8480
router ! Router.MessageRouteRequest(context.messageAdapter(RouteResponseWrapper(_)), firstNodeId, nodeParams.nodeId, Set.empty)
85-
waitForRoute(tlvs, quantityAvailable)
81+
waitForRoute(tlvs)
8682
case None if hideNodeId =>
8783
router ! Router.GetCentralNode(context.messageAdapter(FirstNodeWrapper(_)))
88-
waitForFirstNode(tlvs, quantityAvailable)
84+
waitForFirstNode(tlvs)
8985
case None =>
9086
val offer = Offer(TlvStream(tlvs + OfferNodeId(nodeParams.nodeId)))
91-
registerOffer(offer, None, quantityAvailable)
87+
registerOffer(offer, None)
9288

9389
}
9490
}
9591
}
9692

97-
private def waitForFirstNode(tlvs: Set[OfferTlv], quantityAvailable: Long): Behavior[Command] = {
93+
private def waitForFirstNode(tlvs: Set[OfferTlv]): Behavior[Command] = {
9894
Behaviors.receiveMessagePartial {
9995
case FirstNodeWrapper(firstNodeId) =>
10096
router ! Router.MessageRouteRequest(context.messageAdapter(RouteResponseWrapper(_)), firstNodeId, nodeParams.nodeId, Set.empty)
101-
waitForRoute(tlvs, quantityAvailable)
97+
waitForRoute(tlvs)
10298
}
10399
}
104100

105-
private def waitForRoute(tlvs: Set[OfferTlv], quantityAvailable: Long): Behavior[Command] = {
101+
private def waitForRoute(tlvs: Set[OfferTlv]): Behavior[Command] = {
106102
Behaviors.receiveMessagePartial {
107103
case RouteResponseWrapper(Router.MessageRoute(intermediateNodes, _)) =>
108104
val pathId = randomBytes32()
109105
val paths = Seq(OnionMessages.buildRoute(randomKey(), intermediateNodes.map(IntermediateNode(_)), Recipient(nodeParams.nodeId, Some(pathId))).route)
110106
val offer = Offer(TlvStream(tlvs + OfferPaths(paths)))
111-
registerOffer(offer, Some(pathId), quantityAvailable)
107+
registerOffer(offer, Some(pathId))
112108
case RouteResponseWrapper(Router.MessageRouteNotFound(_)) =>
113109
replyTo ! Left("No route found")
114110
Behaviors.stopped
115111
}
116112
}
117113

118-
private def registerOffer(offer: Offer, pathId_opt: Option[ByteVector32], quantityAvailable: Long): Behavior[Command] = {
119-
nodeParams.db.offers.addOffer(offer, pathId_opt, quantityAvailable)
114+
private def registerOffer(offer: Offer, pathId_opt: Option[ByteVector32]): Behavior[Command] = {
115+
nodeParams.db.offers.addOffer(offer, pathId_opt)
120116
offerManager ! OfferManager.RegisterOffer(offer, None, pathId_opt, defaultOfferHandler)
121117
replyTo ! Right(offer)
122118
Behaviors.stopped

0 commit comments

Comments
 (0)