1
1
package fr.acinq.lightning.db
2
2
3
3
import fr.acinq.bitcoin.*
4
- import fr.acinq.lightning.Lightning
5
4
import fr.acinq.lightning.MilliSatoshi
6
5
import fr.acinq.lightning.ShortChannelId
7
6
import fr.acinq.lightning.channel.ChannelManagementFees
@@ -33,6 +32,7 @@ interface PaymentsDb : IncomingPaymentsDb, OutgoingPaymentsDb {
33
32
}
34
33
35
34
interface IncomingPaymentsDb {
35
+
36
36
/* * Add a new expected incoming payment (not yet received). */
37
37
suspend fun addIncomingPayment (incomingPayment : IncomingPayment )
38
38
@@ -62,29 +62,23 @@ interface OutgoingPaymentsDb {
62
62
/* * Add a new pending outgoing payment (not yet settled). */
63
63
suspend fun addOutgoingPayment (outgoingPayment : OutgoingPayment )
64
64
65
+ /* * Add new partial payments to a pending outgoing payment. */
66
+ suspend fun addLightningOutgoingPaymentParts (parentId : UUID , parts : List <LightningOutgoingPayment .Part >)
67
+
65
68
/* * Get information about an outgoing payment (settled or not). */
66
69
suspend fun getLightningOutgoingPayment (id : UUID ): LightningOutgoingPayment ?
67
70
68
- /* * Get information about a liquidity purchase (for which the funding transaction has been signed). */
69
- suspend fun getInboundLiquidityPurchase (fundingTxId : TxId ): InboundLiquidityOutgoingPayment ?
70
-
71
- /* * Mark an outgoing payment as completed over Lightning. */
72
- suspend fun completeOutgoingPaymentOffchain (id : UUID , preimage : ByteVector32 , completedAt : Long = currentTimestampMillis())
73
-
74
- /* * Mark an outgoing payment as failed. */
75
- suspend fun completeOutgoingPaymentOffchain (id : UUID , finalFailure : FinalFailure , completedAt : Long = currentTimestampMillis())
76
-
77
- /* * Add new partial payments to a pending outgoing payment. */
78
- suspend fun addOutgoingLightningParts (parentId : UUID , parts : List <LightningOutgoingPayment .Part >)
71
+ /* * Get information about an outgoing payment from the id of one of its parts. */
72
+ suspend fun getLightningOutgoingPaymentFromPartId (partId : UUID ): LightningOutgoingPayment ?
79
73
80
- /* * Mark an outgoing payment part as failed . */
81
- suspend fun completeOutgoingLightningPart ( partId : UUID , failure : LightningOutgoingPayment .Part . Status .Failure , completedAt : Long = currentTimestampMillis() )
74
+ /* * Mark a lightning outgoing payment as completed . */
75
+ suspend fun completeLightningOutgoingPayment ( id : UUID , status : LightningOutgoingPayment .Status .Completed )
82
76
83
- /* * Mark an outgoing payment part as succeeded. This should not update the parent payment, since some parts may still be pending . */
84
- suspend fun completeOutgoingLightningPart ( partId : UUID , preimage : ByteVector32 , completedAt : Long = currentTimestampMillis() )
77
+ /* * Mark a lightning outgoing payment part as completed . */
78
+ suspend fun completeLightningOutgoingPaymentPart ( parentId : UUID , partId : UUID , status : LightningOutgoingPayment . Part . Status . Completed )
85
79
86
- /* * Get information about an outgoing payment from the id of one of its parts . */
87
- suspend fun getLightningOutgoingPaymentFromPartId ( partId : UUID ): LightningOutgoingPayment ?
80
+ /* * Get information about a liquidity purchase (for which the funding transaction has been signed) . */
81
+ suspend fun getInboundLiquidityPurchase ( fundingTxId : TxId ): InboundLiquidityOutgoingPayment ?
88
82
89
83
/* * List all the outgoing payment attempts that tried to pay the given payment hash. */
90
84
suspend fun listLightningOutgoingPayments (paymentHash : ByteVector32 ): List <LightningOutgoingPayment >
@@ -329,8 +323,8 @@ data class LightningOutgoingPayment(
329
323
/* * This is the total fees that have been paid to make the payment work. It includes the LN routing fees, the fee for the swap-out service, the mining fees for closing a channel. */
330
324
override val fees: MilliSatoshi = when (status) {
331
325
is Status .Pending -> 0 .msat
332
- is Status .Completed . Failed -> 0 .msat
333
- is Status .Completed . Succeeded . OffChain -> {
326
+ is Status .Failed -> 0 .msat
327
+ is Status .Succeeded -> {
334
328
if (details is Details .SwapOut ) {
335
329
// The swap-out service takes a fee to cover the miner fee. It's the difference between what we paid the service (recipientAmount) and what goes to the address.
336
330
// We also include the routing fee, in case the swap-service is NOT the trampoline node.
@@ -376,15 +370,10 @@ data class LightningOutgoingPayment(
376
370
data object Pending : Status ()
377
371
sealed class Completed : Status () {
378
372
abstract val completedAt: Long
379
-
380
- data class Failed (val reason : FinalFailure , override val completedAt : Long = currentTimestampMillis()) : Completed()
381
- sealed class Succeeded : Completed () {
382
- data class OffChain (
383
- val preimage : ByteVector32 ,
384
- override val completedAt : Long = currentTimestampMillis()
385
- ) : Succeeded()
386
- }
387
373
}
374
+
375
+ data class Succeeded (val preimage : ByteVector32 , override val completedAt : Long = currentTimestampMillis()) : Completed()
376
+ data class Failed (val reason : FinalFailure , override val completedAt : Long = currentTimestampMillis()) : Completed()
388
377
}
389
378
390
379
/* *
@@ -405,44 +394,49 @@ data class LightningOutgoingPayment(
405
394
) {
406
395
sealed class Status {
407
396
data object Pending : Status ()
408
- data class Succeeded (val preimage : ByteVector32 , val completedAt : Long = currentTimestampMillis()) : Status()
409
- data class Failed (val failure : Failure , val completedAt : Long = currentTimestampMillis()) : Status()
410
-
411
- /* *
412
- * User-friendly payment part failure reason, whenever possible.
413
- * Applications should define their own localized message for each of these failure cases.
414
- */
415
- sealed class Failure {
416
- // @formatter:off
417
- /* * The payment is too small: try sending a larger amount. */
418
- data object PaymentAmountTooSmall : Failure () { override fun toString (): String = " the payment amount is too small" }
419
- /* * The user has sufficient balance, but the payment is too big: try sending a smaller amount. */
420
- data object PaymentAmountTooBig : Failure () { override fun toString (): String = " the payment amount is too large" }
421
- /* * The user doesn't have sufficient balance: try sending a smaller amount. */
422
- data object NotEnoughFunds : Failure () { override fun toString (): String = " not enough funds" }
423
- /* * The payment must be retried with more fees to reach the recipient. */
424
- data object NotEnoughFees : Failure () { override fun toString (): String = " routing fees are insufficient" }
425
- /* * The payment expiry specified by the recipient is too far away in the future. */
426
- data object PaymentExpiryTooBig : Failure () { override fun toString (): String = " the payment expiry is too far in the future" }
427
- /* * There are too many pending payments: wait for them to settle and retry. */
428
- data object TooManyPendingPayments : Failure () { override fun toString (): String = " too many pending payments" }
429
- /* * Payments are temporarily paused while a channel is splicing: the payment can be retried after the splice. */
430
- data object ChannelIsSplicing : Failure () { override fun toString (): String = " a splicing operation is in progress" }
431
- /* * The channel is closing: another channel should be created to send the payment. */
432
- data object ChannelIsClosing : Failure () { override fun toString (): String = " channel closing is in progress" }
433
- /* * Remote failure from an intermediate node in the payment route. */
434
- sealed class RouteFailure : Failure ()
435
- /* * A remote node had a temporary failure: the payment may succeed if retried. */
436
- data object TemporaryRemoteFailure : RouteFailure () { override fun toString (): String = " a node in the route had a temporary failure" }
437
- /* * The payment amount could not be relayed to the recipient, most likely because they don't have enough inbound liquidity. */
438
- data object RecipientLiquidityIssue : RouteFailure () { override fun toString (): String = " liquidity issue at the recipient node" }
439
- /* * The payment recipient is offline and could not accept the payment. */
440
- data object RecipientIsOffline : RouteFailure () { override fun toString (): String = " recipient node is offline or unreachable" }
441
- /* * The payment recipient received the payment but rejected it. */
442
- data object RecipientRejectedPayment : Failure () { override fun toString (): String = " recipient node rejected the payment" }
443
- /* * This is an error that cannot be easily interpreted: we don't know what exactly went wrong and cannot correctly inform the user. */
444
- data class Uninterpretable (val message : String ) : Failure() { override fun toString (): String = message }
445
- // @formatter:on
397
+ sealed class Completed : Status () {
398
+ abstract val completedAt: Long
399
+ }
400
+
401
+ data class Succeeded (val preimage : ByteVector32 , override val completedAt : Long = currentTimestampMillis()) : Completed()
402
+ data class Failed (val failure : Failure , override val completedAt : Long = currentTimestampMillis()) : Completed() {
403
+
404
+ /* *
405
+ * User-friendly payment part failure reason, whenever possible.
406
+ * Applications should define their own localized message for each of these failure cases.
407
+ */
408
+ sealed class Failure {
409
+ // @formatter:off
410
+ /* * The payment is too small: try sending a larger amount. */
411
+ data object PaymentAmountTooSmall : Failure () { override fun toString (): String = " the payment amount is too small" }
412
+ /* * The user has sufficient balance, but the payment is too big: try sending a smaller amount. */
413
+ data object PaymentAmountTooBig : Failure () { override fun toString (): String = " the payment amount is too large" }
414
+ /* * The user doesn't have sufficient balance: try sending a smaller amount. */
415
+ data object NotEnoughFunds : Failure () { override fun toString (): String = " not enough funds" }
416
+ /* * The payment must be retried with more fees to reach the recipient. */
417
+ data object NotEnoughFees : Failure () { override fun toString (): String = " routing fees are insufficient" }
418
+ /* * The payment expiry specified by the recipient is too far away in the future. */
419
+ data object PaymentExpiryTooBig : Failure () { override fun toString (): String = " the payment expiry is too far in the future" }
420
+ /* * There are too many pending payments: wait for them to settle and retry. */
421
+ data object TooManyPendingPayments : Failure () { override fun toString (): String = " too many pending payments" }
422
+ /* * Payments are temporarily paused while a channel is splicing: the payment can be retried after the splice. */
423
+ data object ChannelIsSplicing : Failure () { override fun toString (): String = " a splicing operation is in progress" }
424
+ /* * The channel is closing: another channel should be created to send the payment. */
425
+ data object ChannelIsClosing : Failure () { override fun toString (): String = " channel closing is in progress" }
426
+ /* * Remote failure from an intermediate node in the payment route. */
427
+ sealed class RouteFailure : Failure ()
428
+ /* * A remote node had a temporary failure: the payment may succeed if retried. */
429
+ data object TemporaryRemoteFailure : RouteFailure () { override fun toString (): String = " a node in the route had a temporary failure" }
430
+ /* * The payment amount could not be relayed to the recipient, most likely because they don't have enough inbound liquidity. */
431
+ data object RecipientLiquidityIssue : RouteFailure () { override fun toString (): String = " liquidity issue at the recipient node" }
432
+ /* * The payment recipient is offline and could not accept the payment. */
433
+ data object RecipientIsOffline : RouteFailure () { override fun toString (): String = " recipient node is offline or unreachable" }
434
+ /* * The payment recipient received the payment but rejected it. */
435
+ data object RecipientRejectedPayment : Failure () { override fun toString (): String = " recipient node rejected the payment" }
436
+ /* * This is an error that cannot be easily interpreted: we don't know what exactly went wrong and cannot correctly inform the user. */
437
+ data class Uninterpretable (val message : String ) : Failure() { override fun toString (): String = message }
438
+ // @formatter:on
439
+ }
446
440
}
447
441
}
448
442
}
@@ -456,6 +450,25 @@ sealed class OnChainOutgoingPayment : OutgoingPayment() {
456
450
abstract override val createdAt: Long
457
451
abstract val confirmedAt: Long?
458
452
abstract val lockedAt: Long?
453
+ override val completedAt: Long? get() = lockedAt
454
+
455
+ /* * Helper method to facilitate updating child classes */
456
+ fun setLocked (lockedAt : Long ): OnChainOutgoingPayment =
457
+ when (this ) {
458
+ is SpliceOutgoingPayment -> copy(lockedAt = lockedAt)
459
+ is SpliceCpfpOutgoingPayment -> copy(lockedAt = lockedAt)
460
+ is InboundLiquidityOutgoingPayment -> copy(lockedAt = lockedAt)
461
+ is ChannelCloseOutgoingPayment -> copy(lockedAt = lockedAt)
462
+ }
463
+
464
+ /* * Helper method to facilitate updating child classes */
465
+ fun setConfirmed (confirmedAt : Long ): OnChainOutgoingPayment =
466
+ when (this ) {
467
+ is SpliceOutgoingPayment -> copy(confirmedAt = confirmedAt)
468
+ is SpliceCpfpOutgoingPayment -> copy(confirmedAt = confirmedAt)
469
+ is InboundLiquidityOutgoingPayment -> copy(confirmedAt = confirmedAt)
470
+ is ChannelCloseOutgoingPayment -> copy(confirmedAt = confirmedAt)
471
+ }
459
472
}
460
473
461
474
data class SpliceOutgoingPayment (
@@ -471,7 +484,6 @@ data class SpliceOutgoingPayment(
471
484
) : OnChainOutgoingPayment() {
472
485
override val amount: MilliSatoshi = (recipientAmount + miningFees).toMilliSatoshi()
473
486
override val fees: MilliSatoshi = miningFees.toMilliSatoshi()
474
- override val completedAt: Long? = confirmedAt
475
487
}
476
488
477
489
data class SpliceCpfpOutgoingPayment (
@@ -485,7 +497,6 @@ data class SpliceCpfpOutgoingPayment(
485
497
) : OnChainOutgoingPayment() {
486
498
override val amount: MilliSatoshi = miningFees.toMilliSatoshi()
487
499
override val fees: MilliSatoshi = miningFees.toMilliSatoshi()
488
- override val completedAt: Long? = confirmedAt
489
500
}
490
501
491
502
data class InboundLiquidityOutgoingPayment (
@@ -502,7 +513,6 @@ data class InboundLiquidityOutgoingPayment(
502
513
val serviceFees: Satoshi = purchase.fees.serviceFee
503
514
override val fees: MilliSatoshi = (localMiningFees + purchase.fees.total).toMilliSatoshi()
504
515
override val amount: MilliSatoshi = fees
505
- override val completedAt: Long? = lockedAt
506
516
val fundingFee: LiquidityAds .FundingFee = LiquidityAds .FundingFee (purchase.fees.total.toMilliSatoshi(), txId)
507
517
/* *
508
518
* Even in the "from future htlc" case the mining fee corresponding to the previous channel output
@@ -555,7 +565,6 @@ data class ChannelCloseOutgoingPayment(
555
565
) : OnChainOutgoingPayment() {
556
566
override val amount: MilliSatoshi = (recipientAmount + miningFees).toMilliSatoshi()
557
567
override val fees: MilliSatoshi = miningFees.toMilliSatoshi()
558
- override val completedAt: Long? = confirmedAt
559
568
}
560
569
561
570
data class HopDesc (val nodeId : PublicKey , val nextNodeId : PublicKey , val shortChannelId : ShortChannelId ? = null ) {
0 commit comments