Skip to content

Commit

Permalink
Fix version in part serializer and fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dpad85 committed May 22, 2024
1 parent e9224fa commit 0c1529b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import kotlinx.serialization.json.Json

enum class OutgoingPartStatusTypeVersion {
SUCCEEDED_V0,
/* Obsolete, do not use anymore. Failed parts are now typed, with a code and an option string message. */
@Deprecated("Obsolete, do not use anymore. Failed parts are now typed, with a code and an option string message.")
FAILED_V0,
FAILED_V1,
}
Expand All @@ -47,6 +47,7 @@ sealed class OutgoingPartStatusData {
}

sealed class Failed : OutgoingPartStatusData() {
@Deprecated("Use V1 instead")
@Serializable
data class V0(val remoteFailureCode: Int?, val details: String) : Failed()

Expand Down Expand Up @@ -100,21 +101,21 @@ fun LightningOutgoingPayment.Part.Status.Succeeded.mapToDb() = OutgoingPartStatu
Json.encodeToString(OutgoingPartStatusData.Succeeded.V0(preimage)).toByteArray(Charsets.UTF_8)

fun LightningOutgoingPayment.Part.Status.Failure.mapToDb(): Pair<OutgoingPartStatusTypeVersion, ByteArray> {
val code = when (this) {
is LightningOutgoingPayment.Part.Status.Failure.Uninterpretable -> 0
is LightningOutgoingPayment.Part.Status.Failure.PaymentAmountTooSmall -> 1
is LightningOutgoingPayment.Part.Status.Failure.PaymentAmountTooBig -> 2
is LightningOutgoingPayment.Part.Status.Failure.NotEnoughFunds -> 3
is LightningOutgoingPayment.Part.Status.Failure.NotEnoughFees -> 4
is LightningOutgoingPayment.Part.Status.Failure.PaymentExpiryTooBig -> 5
is LightningOutgoingPayment.Part.Status.Failure.TooManyPendingPayments -> 6
is LightningOutgoingPayment.Part.Status.Failure.ChannelIsSplicing -> 7
is LightningOutgoingPayment.Part.Status.Failure.ChannelIsClosing -> 8
is LightningOutgoingPayment.Part.Status.Failure.TemporaryRemoteFailure -> 9
is LightningOutgoingPayment.Part.Status.Failure.RecipientLiquidityIssue -> 10
is LightningOutgoingPayment.Part.Status.Failure.RecipientIsOffline -> 11
is LightningOutgoingPayment.Part.Status.Failure.RecipientRejectedPayment -> 12
val (code, details) = when (this) {
is LightningOutgoingPayment.Part.Status.Failure.Uninterpretable -> 0 to message
is LightningOutgoingPayment.Part.Status.Failure.PaymentAmountTooSmall -> 1 to null
is LightningOutgoingPayment.Part.Status.Failure.PaymentAmountTooBig -> 2 to null
is LightningOutgoingPayment.Part.Status.Failure.NotEnoughFunds -> 3 to null
is LightningOutgoingPayment.Part.Status.Failure.NotEnoughFees -> 4 to null
is LightningOutgoingPayment.Part.Status.Failure.PaymentExpiryTooBig -> 5 to null
is LightningOutgoingPayment.Part.Status.Failure.TooManyPendingPayments -> 6 to null
is LightningOutgoingPayment.Part.Status.Failure.ChannelIsSplicing -> 7 to null
is LightningOutgoingPayment.Part.Status.Failure.ChannelIsClosing -> 8 to null
is LightningOutgoingPayment.Part.Status.Failure.TemporaryRemoteFailure -> 9 to null
is LightningOutgoingPayment.Part.Status.Failure.RecipientLiquidityIssue -> 10 to null
is LightningOutgoingPayment.Part.Status.Failure.RecipientIsOffline -> 11 to null
is LightningOutgoingPayment.Part.Status.Failure.RecipientRejectedPayment -> 12 to null
}
return OutgoingPartStatusTypeVersion.FAILED_V0 to
Json.encodeToString(OutgoingPartStatusData.Failed.V0(code, "")).toByteArray(Charsets.UTF_8)
return OutgoingPartStatusTypeVersion.FAILED_V1 to
Json.encodeToString(OutgoingPartStatusData.Failed.V1(code, details)).toByteArray(Charsets.UTF_8)
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ sealed class OutgoingStatusData {
FinalFailure.InvalidPaymentId::class.simpleName -> FinalFailure.InvalidPaymentId
FinalFailure.NoAvailableChannels::class.simpleName -> FinalFailure.NoAvailableChannels
FinalFailure.InsufficientBalance::class.simpleName -> FinalFailure.InsufficientBalance
FinalFailure.NoRouteToRecipient::class.simpleName -> FinalFailure.NoRouteToRecipient
FinalFailure.RecipientUnreachable::class.simpleName -> FinalFailure.RecipientUnreachable
FinalFailure.RetryExhausted::class.simpleName -> FinalFailure.RetryExhausted
FinalFailure.WalletRestarted::class.simpleName -> FinalFailure.WalletRestarted
FinalFailure.AlreadyPaid::class.simpleName -> FinalFailure.AlreadyPaid
FinalFailure.ChannelClosing::class.simpleName -> FinalFailure.ChannelClosing
FinalFailure.ChannelOpening::class.simpleName -> FinalFailure.ChannelOpening
FinalFailure.ChannelNotConnected::class.simpleName -> FinalFailure.ChannelNotConnected
FinalFailure.FeaturesNotSupported::class.simpleName -> FinalFailure.FeaturesNotSupported
else -> FinalFailure.UnknownError
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import fr.acinq.lightning.payment.FinalFailure
import fr.acinq.lightning.utils.sat
import fr.acinq.lightning.wire.PermanentNodeFailure
import fr.acinq.phoenix.db.payments.*
import io.ktor.utils.io.charsets.Charsets
import io.ktor.utils.io.core.toByteArray
import kotlin.test.Test
import kotlin.test.assertEquals

Expand Down Expand Up @@ -64,17 +66,26 @@ class OutgoingPaymentDbTypeVersionTest {
}

@Test
fun outgoing_part_status_failed_channelexception() {
val status = LightningOutgoingPayment.Part.Status.Failed(null, InvalidFinalScript(channelId1).details(), completedAt = 123)
val deserialized = OutgoingPartStatusData.deserialize(OutgoingPartStatusTypeVersion.FAILED_V0, status.mapToDb().second, completedAt = 123)
fun outgoing_part_status_failed_part() {
val status = LightningOutgoingPayment.Part.Status.Failed(LightningOutgoingPayment.Part.Status.Failure.ChannelIsClosing, completedAt = 123)
val deserialized = OutgoingPartStatusData.deserialize(OutgoingPartStatusTypeVersion.FAILED_V1, status.failure.mapToDb().second, completedAt = 123)
assertEquals(status, deserialized)

val status2 = LightningOutgoingPayment.Part.Status.Failed(LightningOutgoingPayment.Part.Status.Failure.Uninterpretable("lorem ipsum"), completedAt = 123)
val deserialized2 = OutgoingPartStatusData.deserialize(OutgoingPartStatusTypeVersion.FAILED_V1, status2.failure.mapToDb().second, completedAt = 123)
assertEquals(status2, deserialized2)
}

@Test
fun outgoing_part_status_failed_remotefailure() {
val status = LightningOutgoingPayment.Part.Status.Failed(PermanentNodeFailure.code, PermanentNodeFailure.message, completedAt = 345)
val deserialized = OutgoingPartStatusData.deserialize(OutgoingPartStatusTypeVersion.FAILED_V0, status.mapToDb().second, completedAt = 345)
assertEquals(status, deserialized)
fun outgoing_part_status_failed_channelexception_legacy() {
val serialized = """
{"remoteFailureCode":8243,"details":"payment fee was below the minimum required by the trampoline node"}
""".trimIndent()
val deserialized = OutgoingPartStatusData.deserialize(OutgoingPartStatusTypeVersion.FAILED_V0, serialized.toByteArray(Charsets.UTF_8), completedAt = 123)
val expected = LightningOutgoingPayment.Part.Status.Failed(
LightningOutgoingPayment.Part.Status.Failure.Uninterpretable("payment fee was below the minimum required by the trampoline node"), completedAt = 123
)
assertEquals(expected, deserialized)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,17 +255,17 @@ class SqlitePaymentsDatabaseTest {
val onePartFailed = p.copy(
parts = listOf(
p.parts[0].copy(
status = LightningOutgoingPayment.Part.Status.Failed(TemporaryNodeFailure.code, TemporaryNodeFailure.message, 110)
status = LightningOutgoingPayment.Part.Status.Failed(LightningOutgoingPayment.Part.Status.Failure.TemporaryRemoteFailure, 110)
),
p.parts[1]
)
)
db.completeOutgoingLightningPart(p.parts[0].id, Either.Right(TemporaryNodeFailure), 110)
db.completeOutgoingLightningPart(p.parts[0].id, LightningOutgoingPayment.Part.Status.Failure.TemporaryRemoteFailure, 110)
assertEquals(onePartFailed, db.getLightningOutgoingPayment(p.id))
p.parts.forEach { assertEquals(onePartFailed, db.getLightningOutgoingPaymentFromPartId(it.id)) }

// Updating non-existing parts should fail.
assertFalse { db.outQueries.updateLightningPart(UUID.randomUUID(), Either.Right(TemporaryNodeFailure), 110) }
assertFalse { db.outQueries.updateLightningPart(UUID.randomUUID(), LightningOutgoingPayment.Part.Status.Failure.TemporaryRemoteFailure, 110) }
assertFalse { db.outQueries.updateLightningPart(UUID.randomUUID(), randomBytes32(), 110) }

// Additional parts must have a unique id.
Expand Down Expand Up @@ -373,17 +373,17 @@ class SqlitePaymentsDatabaseTest {
val channelId = randomBytes32()
val partsFailed = p.copy(
parts = listOf(
p.parts[0].copy(status = OutgoingPaymentFailure.convertFailure(Either.Right(TemporaryNodeFailure), 110)),
p.parts[1].copy(status = OutgoingPaymentFailure.convertFailure(Either.Left(TooManyAcceptedHtlcs(channelId, 10)), 111)),
p.parts[0].copy(status = LightningOutgoingPayment.Part.Status.Failed(LightningOutgoingPayment.Part.Status.Failure.TemporaryRemoteFailure, 110)),
p.parts[1].copy(status = LightningOutgoingPayment.Part.Status.Failed(LightningOutgoingPayment.Part.Status.Failure.TooManyPendingPayments, 111)),
)
)
db.completeOutgoingLightningPart(p.parts[0].id, Either.Right(TemporaryNodeFailure), 110)
db.completeOutgoingLightningPart(p.parts[1].id, Either.Left(TooManyAcceptedHtlcs(channelId, 10)), 111)
db.completeOutgoingLightningPart(p.parts[0].id, LightningOutgoingPayment.Part.Status.Failure.TemporaryRemoteFailure, 110)
db.completeOutgoingLightningPart(p.parts[1].id, LightningOutgoingPayment.Part.Status.Failure.TooManyPendingPayments, 111)
assertEquals(partsFailed, db.getLightningOutgoingPayment(p.id))
p.parts.forEach { assertEquals(partsFailed, db.getLightningOutgoingPaymentFromPartId(it.id)) }

val paymentStatus = LightningOutgoingPayment.Status.Completed.Failed(
reason = FinalFailure.NoRouteToRecipient,
reason = FinalFailure.RecipientUnreachable,
completedAt = 120
)
val paymentFailed = partsFailed.copy(status = paymentStatus)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ class CloudDataTest {
amount = 500_005.msat,
route = listOf(HopDesc(a, b)),
status = LightningOutgoingPayment.Part.Status.Failed(
remoteFailureCode = 418,
details = "I'm a teapot"
LightningOutgoingPayment.Part.Status.Failure.Uninterpretable("I'm a teapot")
)
)
val outgoingPayment = LightningOutgoingPayment(
Expand Down

0 comments on commit 0c1529b

Please sign in to comment.