Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
thomash-acinq committed Jan 8, 2025
1 parent 0b8e1b5 commit b8611f6
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 14 deletions.
4 changes: 2 additions & 2 deletions eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala
Original file line number Diff line number Diff line change
Expand Up @@ -389,11 +389,11 @@ class EclairImpl(appKit: Kit) extends Eclair with Logging {

override def disableOffer(offer: Offer)(implicit timeout: Timeout): Unit = {
appKit.offerManager ! OfferManager.DisableOffer(offer)
appKit.nodeParams.db.offers.disableOffer(offer)
appKit.nodeParams.db.managedOffers.disableOffer(offer)
}

override def listOffers(onlyActive: Boolean = true)(implicit timeout: Timeout): Future[Seq[Offer]] = Future {
appKit.nodeParams.db.offers.listOffers(onlyActive).map(_.offer)
appKit.nodeParams.db.managedOffers.listOffers(onlyActive).map(_.offer)
}

override def newAddress(): Future[String] = {
Expand Down
1 change: 1 addition & 0 deletions eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ class Setup(val datadir: File,
register = system.actorOf(SimpleSupervisor.props(Register.props(), "register", SupervisorStrategy.Resume))
offerManager = system.spawn(Behaviors.supervise(OfferManager(nodeParams, router, paymentTimeout = 1 minute)).onFailure(typed.SupervisorStrategy.resume), name = "offer-manager")
defaultOfferHandler = system.spawn(Behaviors.supervise(DefaultHandler(nodeParams, router)).onFailure(typed.SupervisorStrategy.resume), name = "default-offer-handler")
_ = for (offer <- nodeParams.db.managedOffers.listOffers(onlyActive = true)) offerManager ! OfferManager.RegisterOffer(offer.offer, None, offer.pathId_opt, defaultOfferHandler)
paymentHandler = system.actorOf(SimpleSupervisor.props(PaymentHandler.props(nodeParams, register, offerManager), "payment-handler", SupervisorStrategy.Resume))
triggerer = system.spawn(Behaviors.supervise(AsyncPaymentTriggerer()).onFailure(typed.SupervisorStrategy.resume), name = "async-payment-triggerer")
peerReadyManager = system.spawn(Behaviors.supervise(PeerReadyManager()).onFailure(typed.SupervisorStrategy.restart), name = "peer-ready-manager")
Expand Down
10 changes: 5 additions & 5 deletions eclair-core/src/main/scala/fr/acinq/eclair/db/Databases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ trait Databases {
def channels: ChannelsDb
def peers: PeersDb
def payments: PaymentsDb
def offers: OffersDb
def managedOffers: OffersDb
def pendingCommands: PendingCommandsDb
def liquidity: LiquidityDb
//@formatter:on
Expand All @@ -67,7 +67,7 @@ object Databases extends Logging {
channels: SqliteChannelsDb,
peers: SqlitePeersDb,
payments: SqlitePaymentsDb,
offers: SqliteOffersDb,
managedOffers: SqliteOffersDb,
pendingCommands: SqlitePendingCommandsDb,
private val backupConnection: Connection) extends Databases with FileBackup {
override def backup(backupFile: File): Unit = SqliteUtils.using(backupConnection.createStatement()) {
Expand All @@ -87,7 +87,7 @@ object Databases extends Logging {
channels = new SqliteChannelsDb(eclairJdbc),
peers = new SqlitePeersDb(eclairJdbc),
payments = new SqlitePaymentsDb(eclairJdbc),
offers = new SqliteOffersDb(eclairJdbc),
managedOffers = new SqliteOffersDb(eclairJdbc),
pendingCommands = new SqlitePendingCommandsDb(eclairJdbc),
backupConnection = eclairJdbc
)
Expand All @@ -100,7 +100,7 @@ object Databases extends Logging {
channels: PgChannelsDb,
peers: PgPeersDb,
payments: PgPaymentsDb,
offers: PgOffersDb,
managedOffers: PgOffersDb,
pendingCommands: PgPendingCommandsDb,
dataSource: HikariDataSource,
lock: PgLock) extends Databases with ExclusiveLock {
Expand Down Expand Up @@ -161,7 +161,7 @@ object Databases extends Logging {
channels = new PgChannelsDb,
peers = new PgPeersDb,
payments = new PgPaymentsDb,
offers = new PgOffersDb,
managedOffers = new PgOffersDb,
pendingCommands = new PgPendingCommandsDb,
dataSource = ds,
lock = lock)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ case class DualDatabases(primary: Databases, secondary: Databases) extends Datab
override val channels: ChannelsDb = DualChannelsDb(primary.channels, secondary.channels)
override val peers: PeersDb = DualPeersDb(primary.peers, secondary.peers)
override val payments: PaymentsDb = DualPaymentsDb(primary.payments, secondary.payments)
override val offers: OffersDb = DualOffersDb(primary.offers, secondary.offers)
override val managedOffers: OffersDb = DualOffersDb(primary.managedOffers, secondary.managedOffers)
override val pendingCommands: PendingCommandsDb = DualPendingCommandsDb(primary.pendingCommands, secondary.pendingCommands)
override val liquidity: LiquidityDb = DualLiquidityDb(primary.liquidity, secondary.liquidity)

Expand Down
15 changes: 15 additions & 0 deletions eclair-core/src/main/scala/fr/acinq/eclair/db/OffersDb.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,25 @@ import fr.acinq.eclair.wire.protocol.OfferTypes.Offer

case class OfferData(offer: Offer, pathId_opt: Option[ByteVector32])

/**
* Database for offers fully managed by eclair, as opposed to offers managed by a plugin.
*/
trait OffersDb {
/**
* Add an offer managed by eclair.
* @param pathId_opt If the offer uses a blinded path, this is the corresponding pathId.
*/
def addOffer(offer: Offer, pathId_opt: Option[ByteVector32]): Unit

/**
* Disable an offer. The offer is still stored but new invoice requests and new payment attempts for already emitted
* invoices will be rejected. To reenable an offer, use `addOffer`.
*/
def disableOffer(offer: Offer): Unit

/**
* List offers managed by eclair.
* @param onlyActive Whether to return only active offers or also disabled ones.
*/
def listOffers(onlyActive: Boolean): Seq[OfferData]
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import akka.actor.typed.scaladsl.Behaviors
import akka.actor.{ActorRef, typed}
import akka.util.Collections
import fr.acinq.eclair.crypto.Sphinx.RouteBlinding.BlindedRoute
import fr.acinq.eclair.payment.receive.MultiPartHandler.ReceivingRoute
import fr.acinq.eclair.payment.receive.MultiPartHandler.{DummyBlindedHop, ReceivingRoute}
import fr.acinq.eclair.router.Router
import fr.acinq.eclair.router.Router.BlindedRouteRequest
import fr.acinq.eclair.wire.protocol.OfferTypes
Expand All @@ -41,7 +41,7 @@ object DefaultHandler {
replyTo ! OfferManager.InvoiceRequestActor.ApproveRequest(amount, Seq(route), None)
case OfferTypes.BlindedPath(BlindedRoute(firstNodeId: EncodedNodeId.WithPublicKey, _, _)) =>
val routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams
router ! BlindedRouteRequest(context.spawnAnonymous(waitForRoute(nodeParams, replyTo, amount)), firstNodeId.publicKey, nodeParams.nodeId, amount, routeParams, pathsToFind = 2)
router ! BlindedRouteRequest(context.spawnAnonymous(waitForRoute(nodeParams, replyTo, amount, routeParams.boundaries.maxRouteLength)), firstNodeId.publicKey, nodeParams.nodeId, amount, routeParams, pathsToFind = 2)
case OfferTypes.BlindedPath(BlindedRoute(_: EncodedNodeId.ShortChannelIdDir, _, _)) =>
context.log.error("unexpected managed offer with compact first node id")
replyTo ! OfferManager.InvoiceRequestActor.RejectRequest("internal error")
Expand All @@ -54,12 +54,18 @@ object DefaultHandler {
)
}

def waitForRoute(nodeParams: NodeParams, replyTo: typed.ActorRef[OfferManager.InvoiceRequestActor.Command], amount: MilliSatoshi): Behavior[Router.PaymentRouteResponse] = {
def waitForRoute(nodeParams: NodeParams, replyTo: typed.ActorRef[OfferManager.InvoiceRequestActor.Command], amount: MilliSatoshi, maxRouteLength: Int): Behavior[Router.PaymentRouteResponse] = {
Behaviors.receiveMessage {
case Router.RouteResponse(routes) =>
val receivingRoutes = routes.map(route => {
val nodes = route.hops.head.nodeId +: route.hops.map(_.nextNodeId)
ReceivingRoute(nodes, nodeParams.channelConf.maxExpiryDelta, dummyHops = ???)
val maxFeeBase = route.hops.map(_.params.relayFees.feeBase).max
val maxFeeProportional = route.hops.map(_.params.relayFees.feeProportionalMillionths).max
val maxCltvExpiryDelta = route.hops.map(_.params.cltvExpiryDelta).max
val dummyHops = (1 to maxRouteLength - route.hops.size).map(i => {
DummyBlindedHop()
})
ReceivingRoute(nodes, nodeParams.channelConf.maxExpiryDelta, dummyHops)
})
replyTo ! OfferManager.InvoiceRequestActor.ApproveRequest(amount, receivingRoutes, None)
Behaviors.stopped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ private class OfferCreator(context: ActorContext[OfferCreator.Command],
}

private def registerOffer(offer: Offer, pathId_opt: Option[ByteVector32]): Behavior[Command] = {
nodeParams.db.offers.addOffer(offer, pathId_opt)
nodeParams.db.managedOffers.addOffer(offer, pathId_opt)
offerManager ! OfferManager.RegisterOffer(offer, None, pathId_opt, defaultOfferHandler)
replyTo ! Right(offer)
Behaviors.stopped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ sealed trait TestDatabases extends Databases {
override def channels: ChannelsDb = db.channels
override def peers: PeersDb = db.peers
override def payments: PaymentsDb = db.payments
override def offers: OffersDb = db.offers
override def managedOffers: OffersDb = db.managedOffers
override def pendingCommands: PendingCommandsDb = db.pendingCommands
override def liquidity: LiquidityDb = db.liquidity
def close(): Unit
Expand Down

0 comments on commit b8611f6

Please sign in to comment.