diff --git a/build.gradle.kts b/build.gradle.kts index 6dce20f..8243e0b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -107,13 +107,9 @@ tasks.withType { sqldelight { databases { - create("ChannelsDatabase") { + create("PhoenixDatabase") { packageName.set("fr.acinq.phoenix.db") - srcDirs.from("src/commonMain/sqldelight/channelsdb") - } - create("PaymentsDatabase") { - packageName.set("fr.acinq.phoenix.db") - srcDirs.from("src/commonMain/sqldelight/paymentsdb") + srcDirs.from("src/commonMain/sqldelight/phoenixdb") } } } diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/Expects.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/Expects.kt index 3a129de..58e6787 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/Expects.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/Expects.kt @@ -6,4 +6,3 @@ import okio.Path expect val homeDirectory: Path expect fun createAppDbDriver(dir: Path): SqlDriver -expect fun createPaymentsDbDriver(dir: Path): SqlDriver diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/Main.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/Main.kt index d9ef111..a2876cd 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/Main.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/Main.kt @@ -1,5 +1,6 @@ package fr.acinq.lightning.bin +import app.cash.sqldelight.EnumColumnAdapter import co.touchlab.kermit.CommonWriter import co.touchlab.kermit.Severity import co.touchlab.kermit.StaticConfig @@ -27,6 +28,7 @@ import fr.acinq.lightning.bin.conf.getOrGenerateSeed import fr.acinq.lightning.bin.conf.readConfFile import fr.acinq.lightning.bin.db.SqliteChannelsDb import fr.acinq.lightning.bin.db.SqlitePaymentsDb +import fr.acinq.lightning.bin.db.payments.LightningOutgoingQueries import fr.acinq.lightning.bin.json.ApiType import fr.acinq.lightning.bin.logs.FileLogWriter import fr.acinq.lightning.blockchain.electrum.ElectrumClient @@ -44,6 +46,7 @@ import fr.acinq.lightning.utils.Connection import fr.acinq.lightning.utils.ServerAddress import fr.acinq.lightning.utils.msat import fr.acinq.lightning.utils.sat +import fr.acinq.phoenix.db.* import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.cio.* @@ -210,14 +213,34 @@ class Phoenixd : CliktCommand() { ) echo(cyan("nodeid: ${nodeParams.nodeId}")) + val driver = createAppDbDriver(datadir) + val database = PhoenixDatabase( + driver = driver, + lightning_outgoing_payment_partsAdapter = Lightning_outgoing_payment_parts.Adapter( + part_routeAdapter = LightningOutgoingQueries.hopDescAdapter, + part_status_typeAdapter = EnumColumnAdapter() + ), + lightning_outgoing_paymentsAdapter = Lightning_outgoing_payments.Adapter( + status_typeAdapter = EnumColumnAdapter(), + details_typeAdapter = EnumColumnAdapter() + ), + incoming_paymentsAdapter = Incoming_payments.Adapter( + origin_typeAdapter = EnumColumnAdapter(), + received_with_typeAdapter = EnumColumnAdapter() + ), + channel_close_outgoing_paymentsAdapter = Channel_close_outgoing_payments.Adapter( + closing_info_typeAdapter = EnumColumnAdapter() + ), + inbound_liquidity_outgoing_paymentsAdapter = Inbound_liquidity_outgoing_payments.Adapter( + lease_typeAdapter = EnumColumnAdapter() + ) + ) + val electrum = ElectrumClient(scope, loggerFactory) - val paymentsDb = SqlitePaymentsDb(loggerFactory, createPaymentsDbDriver(datadir)) val peer = Peer( nodeParams = nodeParams, walletParams = lsp.walletParams, watcher = ElectrumWatcher(electrum, scope, loggerFactory), db = object : Databases { - override val channels: ChannelsDb - get() = SqliteChannelsDb(createAppDbDriver(datadir)) - override val payments: PaymentsDb - get() = paymentsDb + override val channels: ChannelsDb get() = SqliteChannelsDb(driver, database) + override val payments: PaymentsDb get() = SqlitePaymentsDb(database) }, socketBuilder = TcpSocket.Builder(), scope ) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/SqliteChannelsDb.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/SqliteChannelsDb.kt index fc61922..59caa44 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/SqliteChannelsDb.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/SqliteChannelsDb.kt @@ -1,3 +1,19 @@ +/* + * Copyright 2020 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.lightning.bin.db import app.cash.sqldelight.db.SqlDriver @@ -6,14 +22,13 @@ import fr.acinq.lightning.CltvExpiry import fr.acinq.lightning.channel.states.PersistedChannelState import fr.acinq.lightning.db.ChannelsDb import fr.acinq.lightning.serialization.Serialization -import fr.acinq.phoenix.db.ChannelsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -internal class SqliteChannelsDb(private val driver: SqlDriver) : ChannelsDb { +internal class SqliteChannelsDb(val driver: SqlDriver, val database: PhoenixDatabase) : ChannelsDb { - private val database = ChannelsDatabase(driver) - private val queries = database.channelsDatabaseQueries + private val queries = database.channelsQueries override suspend fun addOrUpdateChannel(state: PersistedChannelState) { val channelId = state.channelId.toByteArray() diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/SqlitePaymentsDb.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/SqlitePaymentsDb.kt index 05950fa..aaea790 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/SqlitePaymentsDb.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/SqlitePaymentsDb.kt @@ -16,8 +16,6 @@ package fr.acinq.lightning.bin.db -import app.cash.sqldelight.EnumColumnAdapter -import app.cash.sqldelight.db.SqlDriver import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.Crypto import fr.acinq.bitcoin.TxId @@ -27,8 +25,6 @@ import fr.acinq.lightning.bin.db.payments.LinkTxToPaymentQueries import fr.acinq.lightning.bin.db.payments.PaymentsMetadataQueries import fr.acinq.lightning.channel.ChannelException import fr.acinq.lightning.db.* -import fr.acinq.lightning.logging.LoggerFactory -import fr.acinq.lightning.logging.info import fr.acinq.lightning.payment.FinalFailure import fr.acinq.lightning.utils.* import fr.acinq.lightning.wire.FailureMessage @@ -36,40 +32,10 @@ import fr.acinq.phoenix.db.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -class SqlitePaymentsDb( - loggerFactory: LoggerFactory, - private val driver: SqlDriver, -) : PaymentsDb { - - private val log = loggerFactory.newLogger(this::class) - - private val database = PaymentsDatabase( - driver = driver, - outgoing_payment_partsAdapter = Outgoing_payment_parts.Adapter( - part_routeAdapter = OutgoingQueries.hopDescAdapter, - part_status_typeAdapter = EnumColumnAdapter() - ), - outgoing_paymentsAdapter = Outgoing_payments.Adapter( - status_typeAdapter = EnumColumnAdapter(), - details_typeAdapter = EnumColumnAdapter() - ), - incoming_paymentsAdapter = Incoming_payments.Adapter( - origin_typeAdapter = EnumColumnAdapter(), - received_with_typeAdapter = EnumColumnAdapter() - ), - outgoing_payment_closing_tx_partsAdapter = Outgoing_payment_closing_tx_parts.Adapter( - part_closing_info_typeAdapter = EnumColumnAdapter() - ), - channel_close_outgoing_paymentsAdapter = Channel_close_outgoing_payments.Adapter( - closing_info_typeAdapter = EnumColumnAdapter() - ), - inbound_liquidity_outgoing_paymentsAdapter = Inbound_liquidity_outgoing_payments.Adapter( - lease_typeAdapter = EnumColumnAdapter() - ) - ) +class SqlitePaymentsDb(val database: PhoenixDatabase) : PaymentsDb { private val inQueries = IncomingQueries(database) - private val outQueries = OutgoingQueries(database) + private val lightningOutgoingQueries = LightningOutgoingQueries(database) private val spliceOutQueries = SpliceOutgoingQueries(database) private val channelCloseQueries = ChannelCloseOutgoingQueries(database) private val cpfpQueries = SpliceCpfpOutgoingQueries(database) @@ -82,7 +48,7 @@ class SqlitePaymentsDb( parts: List ) { withContext(Dispatchers.Default) { - outQueries.addLightningParts(parentId, parts) + lightningOutgoingQueries.addLightningParts(parentId, parts) } } @@ -93,7 +59,7 @@ class SqlitePaymentsDb( database.transaction { when (outgoingPayment) { is LightningOutgoingPayment -> { - outQueries.addLightningOutgoingPayment(outgoingPayment) + lightningOutgoingQueries.addLightningOutgoingPayment(outgoingPayment) } is SpliceOutgoingPayment -> { spliceOutQueries.addSpliceOutgoingPayment(outgoingPayment) @@ -128,7 +94,7 @@ class SqlitePaymentsDb( completedAt: Long ) { withContext(Dispatchers.Default) { - outQueries.completePayment(id, LightningOutgoingPayment.Status.Completed.Succeeded.OffChain(preimage, completedAt)) + lightningOutgoingQueries.completePayment(id, LightningOutgoingPayment.Status.Completed.Succeeded.OffChain(preimage, completedAt)) } } @@ -138,7 +104,7 @@ class SqlitePaymentsDb( completedAt: Long ) { withContext(Dispatchers.Default) { - outQueries.completePayment(id, LightningOutgoingPayment.Status.Completed.Failed(finalFailure, completedAt)) + lightningOutgoingQueries.completePayment(id, LightningOutgoingPayment.Status.Completed.Failed(finalFailure, completedAt)) } } @@ -148,7 +114,7 @@ class SqlitePaymentsDb( completedAt: Long ) { withContext(Dispatchers.Default) { - outQueries.updateLightningPart(partId, preimage, completedAt) + lightningOutgoingQueries.updateLightningPart(partId, preimage, completedAt) } } @@ -158,16 +124,16 @@ class SqlitePaymentsDb( completedAt: Long ) { withContext(Dispatchers.Default) { - outQueries.updateLightningPart(partId, failure, completedAt) + lightningOutgoingQueries.updateLightningPart(partId, failure, completedAt) } } override suspend fun getLightningOutgoingPayment(id: UUID): LightningOutgoingPayment? = withContext(Dispatchers.Default) { - outQueries.getPayment(id) + lightningOutgoingQueries.getPayment(id) } override suspend fun getLightningOutgoingPaymentFromPartId(partId: UUID): LightningOutgoingPayment? = withContext(Dispatchers.Default) { - outQueries.getPaymentFromPartId(partId) + lightningOutgoingQueries.getPaymentFromPartId(partId) } // ---- list outgoing @@ -175,7 +141,7 @@ class SqlitePaymentsDb( override suspend fun listLightningOutgoingPayments( paymentHash: ByteVector32 ): List = withContext(Dispatchers.Default) { - outQueries.listLightningOutgoingPayments(paymentHash) + lightningOutgoingQueries.listLightningOutgoingPayments(paymentHash) } // ---- incoming payments diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/ChannelCloseOutgoingQueries.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/ChannelCloseOutgoingQueries.kt index 62a38c5..3f0e553 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/ChannelCloseOutgoingQueries.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/ChannelCloseOutgoingQueries.kt @@ -21,9 +21,9 @@ import fr.acinq.lightning.db.ChannelCloseOutgoingPayment import fr.acinq.lightning.utils.UUID import fr.acinq.lightning.utils.sat import fr.acinq.lightning.utils.toByteVector32 -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase -class ChannelCloseOutgoingQueries(val database: PaymentsDatabase) { +class ChannelCloseOutgoingQueries(val database: PhoenixDatabase) { private val channelCloseQueries = database.channelCloseOutgoingPaymentsQueries fun getChannelCloseOutgoingPayment(id: UUID): ChannelCloseOutgoingPayment? { @@ -74,7 +74,7 @@ class ChannelCloseOutgoingQueries(val database: PaymentsDatabase) { confirmed_at: Long?, locked_at: Long?, channel_id: ByteArray, - closing_info_type: OutgoingPartClosingInfoTypeVersion, + closing_info_type: ClosingInfoTypeVersion, closing_info_blob: ByteArray ): ChannelCloseOutgoingPayment { return ChannelCloseOutgoingPayment( @@ -88,7 +88,7 @@ class ChannelCloseOutgoingQueries(val database: PaymentsDatabase) { confirmedAt = confirmed_at, lockedAt = locked_at, channelId = channel_id.toByteVector32(), - closingType = OutgoingPartClosingInfoData.deserialize(closing_info_type, closing_info_blob), + closingType = ClosingInfoData.deserialize(closing_info_type, closing_info_blob), ) } } diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingPartClosingType.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/ChannelClosingType.kt similarity index 67% rename from src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingPartClosingType.kt rename to src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/ChannelClosingType.kt index 4ba01bf..fce4e74 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingPartClosingType.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/ChannelClosingType.kt @@ -25,24 +25,24 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -enum class OutgoingPartClosingInfoTypeVersion { +enum class ClosingInfoTypeVersion { // basic type, containing only a [ChannelClosingType] field CLOSING_INFO_V0, } -sealed class OutgoingPartClosingInfoData { +sealed class ClosingInfoData { @Serializable data class V0(val closingType: ChannelClosingType) companion object { - fun deserialize(typeVersion: OutgoingPartClosingInfoTypeVersion, blob: ByteArray): ChannelClosingType = DbTypesHelper.decodeBlob(blob) { json, format -> + fun deserialize(typeVersion: ClosingInfoTypeVersion, blob: ByteArray): ChannelClosingType = DbTypesHelper.decodeBlob(blob) { json, format -> when (typeVersion) { - OutgoingPartClosingInfoTypeVersion.CLOSING_INFO_V0 -> format.decodeFromString(json).closingType + ClosingInfoTypeVersion.CLOSING_INFO_V0 -> format.decodeFromString(json).closingType } } } } -fun ChannelCloseOutgoingPayment.mapClosingTypeToDb() = OutgoingPartClosingInfoTypeVersion.CLOSING_INFO_V0 to - Json.encodeToString(OutgoingPartClosingInfoData.V0(this.closingType)).toByteArray(Charsets.UTF_8) +fun ChannelCloseOutgoingPayment.mapClosingTypeToDb() = ClosingInfoTypeVersion.CLOSING_INFO_V0 to + Json.encodeToString(ClosingInfoData.V0(this.closingType)).toByteArray(Charsets.UTF_8) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/InboundLiquidityQueries.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/InboundLiquidityQueries.kt index 798ca68..3600e7e 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/InboundLiquidityQueries.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/InboundLiquidityQueries.kt @@ -21,10 +21,10 @@ import fr.acinq.lightning.db.InboundLiquidityOutgoingPayment import fr.acinq.lightning.utils.UUID import fr.acinq.lightning.utils.sat import fr.acinq.lightning.utils.toByteVector32 -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase -class InboundLiquidityQueries(val database: PaymentsDatabase) { - private val queries = database.inboundLiquidityOutgoingQueries +class InboundLiquidityQueries(val database: PhoenixDatabase) { + private val queries = database.inboundLiquidityOutgoingPaymentsQueries fun add(payment: InboundLiquidityOutgoingPayment) { database.transaction { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/IncomingQueries.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/IncomingQueries.kt index 2c04335..3c91313 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/IncomingQueries.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/IncomingQueries.kt @@ -21,13 +21,12 @@ import app.cash.sqldelight.coroutines.mapToList import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.byteVector32 import fr.acinq.lightning.db.IncomingPayment -import fr.acinq.lightning.utils.msat -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import kotlinx.coroutines.flow.Flow -class IncomingQueries(private val database: PaymentsDatabase) { +class IncomingQueries(private val database: PhoenixDatabase) { private val queries = database.incomingPaymentsQueries diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingDetailsType.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingDetailsType.kt similarity index 51% rename from src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingDetailsType.kt rename to src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingDetailsType.kt index a6b5029..1af6ea2 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingDetailsType.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingDetailsType.kt @@ -35,46 +35,46 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -enum class OutgoingDetailsTypeVersion { +enum class LightningOutgoingDetailsTypeVersion { NORMAL_V0, KEYSEND_V0, SWAPOUT_V0, } -sealed class OutgoingDetailsData { +sealed class LightningOutgoingDetailsData { - sealed class Normal : OutgoingDetailsData() { + sealed class Normal : LightningOutgoingDetailsData() { @Serializable data class V0(val paymentRequest: String) : Normal() } - sealed class KeySend : OutgoingDetailsData() { + sealed class KeySend : LightningOutgoingDetailsData() { @Serializable data class V0(@Serializable val preimage: ByteVector32) : KeySend() } - sealed class SwapOut : OutgoingDetailsData() { + sealed class SwapOut : LightningOutgoingDetailsData() { @Serializable data class V0(val address: String, val paymentRequest: String, @Serializable val swapOutFee: Satoshi) : SwapOut() } companion object { /** Deserialize the details of an outgoing payment. Return null if the details is for a legacy channel closing payment (see [deserializeLegacyClosingDetails]). */ - fun deserialize(typeVersion: OutgoingDetailsTypeVersion, blob: ByteArray): LightningOutgoingPayment.Details? = DbTypesHelper.decodeBlob(blob) { json, format -> + fun deserialize(typeVersion: LightningOutgoingDetailsTypeVersion, blob: ByteArray): LightningOutgoingPayment.Details = DbTypesHelper.decodeBlob(blob) { json, format -> when (typeVersion) { - OutgoingDetailsTypeVersion.NORMAL_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.Normal(Bolt11Invoice.read(it.paymentRequest).get()) } - OutgoingDetailsTypeVersion.KEYSEND_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.KeySend(it.preimage) } - OutgoingDetailsTypeVersion.SWAPOUT_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.SwapOut(it.address, Bolt11Invoice.read(it.paymentRequest).get(), it.swapOutFee) } + LightningOutgoingDetailsTypeVersion.NORMAL_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.Normal(Bolt11Invoice.read(it.paymentRequest).get()) } + LightningOutgoingDetailsTypeVersion.KEYSEND_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.KeySend(it.preimage) } + LightningOutgoingDetailsTypeVersion.SWAPOUT_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.SwapOut(it.address, Bolt11Invoice.read(it.paymentRequest).get(), it.swapOutFee) } } } } } -fun LightningOutgoingPayment.Details.mapToDb(): Pair = when (this) { - is LightningOutgoingPayment.Details.Normal -> OutgoingDetailsTypeVersion.NORMAL_V0 to - Json.encodeToString(OutgoingDetailsData.Normal.V0(paymentRequest.write())).toByteArray(Charsets.UTF_8) - is LightningOutgoingPayment.Details.KeySend -> OutgoingDetailsTypeVersion.KEYSEND_V0 to - Json.encodeToString(OutgoingDetailsData.KeySend.V0(preimage)).toByteArray(Charsets.UTF_8) - is LightningOutgoingPayment.Details.SwapOut -> OutgoingDetailsTypeVersion.SWAPOUT_V0 to - Json.encodeToString(OutgoingDetailsData.SwapOut.V0(address, paymentRequest.write(), swapOutFee)).toByteArray(Charsets.UTF_8) +fun LightningOutgoingPayment.Details.mapToDb(): Pair = when (this) { + is LightningOutgoingPayment.Details.Normal -> LightningOutgoingDetailsTypeVersion.NORMAL_V0 to + Json.encodeToString(LightningOutgoingDetailsData.Normal.V0(paymentRequest.write())).toByteArray(Charsets.UTF_8) + is LightningOutgoingPayment.Details.KeySend -> LightningOutgoingDetailsTypeVersion.KEYSEND_V0 to + Json.encodeToString(LightningOutgoingDetailsData.KeySend.V0(preimage)).toByteArray(Charsets.UTF_8) + is LightningOutgoingPayment.Details.SwapOut -> LightningOutgoingDetailsTypeVersion.SWAPOUT_V0 to + Json.encodeToString(LightningOutgoingDetailsData.SwapOut.V0(address, paymentRequest.write(), swapOutFee)).toByteArray(Charsets.UTF_8) } diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingPartStatusType.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingPartStatusType.kt similarity index 65% rename from src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingPartStatusType.kt rename to src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingPartStatusType.kt index 801a489..e3e970d 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingPartStatusType.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingPartStatusType.kt @@ -31,33 +31,33 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -enum class OutgoingPartStatusTypeVersion { +enum class LightningOutgoingPartStatusTypeVersion { SUCCEEDED_V0, FAILED_V0, } -sealed class OutgoingPartStatusData { +sealed class LightningOutgoingPartStatusData { - sealed class Succeeded : OutgoingPartStatusData() { + sealed class Succeeded : LightningOutgoingPartStatusData() { @Serializable data class V0(@Serializable val preimage: ByteVector32) : Succeeded() } - sealed class Failed : OutgoingPartStatusData() { + sealed class Failed : LightningOutgoingPartStatusData() { @Serializable data class V0(val remoteFailureCode: Int?, val details: String) : Failed() } companion object { fun deserialize( - typeVersion: OutgoingPartStatusTypeVersion, + typeVersion: LightningOutgoingPartStatusTypeVersion, blob: ByteArray, completedAt: Long ): LightningOutgoingPayment.Part.Status = DbTypesHelper.decodeBlob(blob) { json, format -> when (typeVersion) { - OutgoingPartStatusTypeVersion.SUCCEEDED_V0 -> format.decodeFromString(json).let { + LightningOutgoingPartStatusTypeVersion.SUCCEEDED_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Part.Status.Succeeded(it.preimage, completedAt) } - OutgoingPartStatusTypeVersion.FAILED_V0 -> format.decodeFromString(json).let { + LightningOutgoingPartStatusTypeVersion.FAILED_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Part.Status.Failed(it.remoteFailureCode, it.details, completedAt) } } @@ -65,8 +65,8 @@ sealed class OutgoingPartStatusData { } } -fun LightningOutgoingPayment.Part.Status.Succeeded.mapToDb() = OutgoingPartStatusTypeVersion.SUCCEEDED_V0 to - Json.encodeToString(OutgoingPartStatusData.Succeeded.V0(preimage)).toByteArray(Charsets.UTF_8) +fun LightningOutgoingPayment.Part.Status.Succeeded.mapToDb() = LightningOutgoingPartStatusTypeVersion.SUCCEEDED_V0 to + Json.encodeToString(LightningOutgoingPartStatusData.Succeeded.V0(preimage)).toByteArray(Charsets.UTF_8) -fun LightningOutgoingPayment.Part.Status.Failed.mapToDb() = OutgoingPartStatusTypeVersion.FAILED_V0 to - Json.encodeToString(OutgoingPartStatusData.Failed.V0(remoteFailureCode, details)).toByteArray(Charsets.UTF_8) +fun LightningOutgoingPayment.Part.Status.Failed.mapToDb() = LightningOutgoingPartStatusTypeVersion.FAILED_V0 to + Json.encodeToString(LightningOutgoingPartStatusData.Failed.V0(remoteFailureCode, details)).toByteArray(Charsets.UTF_8) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingQueries.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingQueries.kt similarity index 81% rename from src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingQueries.kt rename to src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingQueries.kt index 5f79c77..6c4865b 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingQueries.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingQueries.kt @@ -25,16 +25,15 @@ import fr.acinq.lightning.ShortChannelId import fr.acinq.lightning.channel.ChannelException import fr.acinq.lightning.db.HopDesc import fr.acinq.lightning.db.LightningOutgoingPayment -import fr.acinq.lightning.db.OutgoingPayment import fr.acinq.lightning.payment.OutgoingPaymentFailure import fr.acinq.lightning.utils.* import fr.acinq.lightning.wire.FailureMessage -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase import fr.acinq.secp256k1.Hex -class OutgoingQueries(val database: PaymentsDatabase) { +class LightningOutgoingQueries(val database: PhoenixDatabase) { - private val queries = database.outgoingPaymentsQueries + private val queries = database.lightningOutgoingPaymentsQueries fun addLightningParts(parentId: UUID, parts: List) { if (parts.isEmpty()) return @@ -135,12 +134,10 @@ class OutgoingQueries(val database: PaymentsDatabase) { return result } - /** This method will ignore any parts that are not proper [LightningOutgoingPayment]. */ fun getPaymentFromPartId(partId: UUID): LightningOutgoingPayment? { return queries.getLightningPart(part_id = partId.toString()).executeAsOneOrNull()?.let { part -> queries.getPayment(id = part.part_parent_id, Companion::mapLightningOutgoingPayment).executeAsList() - }?.filterIsInstance()?.let { - // first ignore any legacy channel closing, then group by parent id + }?.let { groupByRawLightningOutgoing(it).firstOrNull() }?.let { filterUselessParts(it) @@ -156,17 +153,13 @@ class OutgoingQueries(val database: PaymentsDatabase) { id = id.toString(), mapper = Companion::mapLightningOutgoingPayment ).executeAsList().let { parts -> - // only take regular LN payments parts, and group them - parts.filterIsInstance().let { - groupByRawLightningOutgoing(it).firstOrNull() - }?.let { + groupByRawLightningOutgoing(parts).firstOrNull()?.let { filterUselessParts(it) } } fun listLightningOutgoingPayments(paymentHash: ByteVector32): List { return queries.listPaymentsForPaymentHash(paymentHash.toByteArray(), Companion::mapLightningOutgoingPayment).executeAsList() - .filterIsInstance() .let { groupByRawLightningOutgoing(it) } } @@ -195,25 +188,23 @@ class OutgoingQueries(val database: PaymentsDatabase) { recipient_amount_msat: Long, recipient_node_id: String, payment_hash: ByteArray, - details_type: OutgoingDetailsTypeVersion, + details_type: LightningOutgoingDetailsTypeVersion, details_blob: ByteArray, created_at: Long, completed_at: Long?, - status_type: OutgoingStatusTypeVersion?, + status_type: LightningOutgoingStatusTypeVersion?, status_blob: ByteArray? ): LightningOutgoingPayment { - val details = OutgoingDetailsData.deserialize(details_type, details_blob) - return if (details != null) { - LightningOutgoingPayment( - id = UUID.fromString(id), - recipientAmount = MilliSatoshi(recipient_amount_msat), - recipient = PublicKey.parse(Hex.decode(recipient_node_id)), - details = details, - parts = listOf(), - status = mapPaymentStatus(status_type, status_blob, completed_at), - createdAt = created_at - ) - } else throw IllegalArgumentException("cannot handle closing payment at this stage, use LegacyChannelCloseHelper") + val details = LightningOutgoingDetailsData.deserialize(details_type, details_blob) + return LightningOutgoingPayment( + id = UUID.fromString(id), + recipientAmount = MilliSatoshi(recipient_amount_msat), + recipient = PublicKey.parse(Hex.decode(recipient_node_id)), + details = details, + parts = listOf(), + status = mapPaymentStatus(status_type, status_blob, completed_at), + createdAt = created_at + ) } @Suppress("UNUSED_PARAMETER") @@ -222,11 +213,11 @@ class OutgoingQueries(val database: PaymentsDatabase) { recipient_amount_msat: Long, recipient_node_id: String, payment_hash: ByteArray, - details_type: OutgoingDetailsTypeVersion, + details_type: LightningOutgoingDetailsTypeVersion, details_blob: ByteArray, created_at: Long, completed_at: Long?, - status_type: OutgoingStatusTypeVersion?, + status_type: LightningOutgoingStatusTypeVersion?, status_blob: ByteArray?, // lightning parts data, may be null lightning_part_id: String?, @@ -234,16 +225,9 @@ class OutgoingQueries(val database: PaymentsDatabase) { lightning_part_route: List?, lightning_part_created_at: Long?, lightning_part_completed_at: Long?, - lightning_part_status_type: OutgoingPartStatusTypeVersion?, + lightning_part_status_type: LightningOutgoingPartStatusTypeVersion?, lightning_part_status_blob: ByteArray?, - // closing tx parts data, may be null - closingtx_part_id: String?, - closingtx_part_tx_id: ByteArray?, - closingtx_part_amount_sat: Long?, - closingtx_part_closing_info_type: OutgoingPartClosingInfoTypeVersion?, - closingtx_part_closing_info_blob: ByteArray?, - closingtx_part_created_at: Long? - ): OutgoingPayment { + ): LightningOutgoingPayment { val parts = if (lightning_part_id != null && lightning_part_amount_msat != null && lightning_part_route != null && lightning_part_created_at != null) { listOf( @@ -281,7 +265,7 @@ class OutgoingQueries(val database: PaymentsDatabase) { route: List, createdAt: Long, completedAt: Long?, - statusType: OutgoingPartStatusTypeVersion?, + statusType: LightningOutgoingPartStatusTypeVersion?, statusBlob: ByteArray? ): LightningOutgoingPayment.Part { return LightningOutgoingPayment.Part( @@ -298,22 +282,22 @@ class OutgoingQueries(val database: PaymentsDatabase) { } private fun mapPaymentStatus( - statusType: OutgoingStatusTypeVersion?, + statusType: LightningOutgoingStatusTypeVersion?, statusBlob: ByteArray?, completedAt: Long?, ): LightningOutgoingPayment.Status = when { completedAt == null && statusType == null && statusBlob == null -> LightningOutgoingPayment.Status.Pending - completedAt != null && statusType != null && statusBlob != null -> OutgoingStatusData.deserialize(statusType, statusBlob, completedAt) + completedAt != null && statusType != null && statusBlob != null -> LightningOutgoingStatusData.deserialize(statusType, statusBlob, completedAt) else -> throw UnhandledOutgoingStatus(completedAt, statusType, statusBlob) } private fun mapLightningPartStatus( - statusType: OutgoingPartStatusTypeVersion?, + statusType: LightningOutgoingPartStatusTypeVersion?, statusBlob: ByteArray?, completedAt: Long?, ): LightningOutgoingPayment.Part.Status = when { completedAt == null && statusType == null && statusBlob == null -> LightningOutgoingPayment.Part.Status.Pending - completedAt != null && statusType != null && statusBlob != null -> OutgoingPartStatusData.deserialize(statusType, statusBlob, completedAt) + completedAt != null && statusType != null && statusBlob != null -> LightningOutgoingPartStatusData.deserialize(statusType, statusBlob, completedAt) else -> throw UnhandledOutgoingPartStatus(statusType, statusBlob, completedAt) } @@ -336,8 +320,8 @@ class OutgoingQueries(val database: PaymentsDatabase) { } } -data class UnhandledOutgoingStatus(val completedAt: Long?, val statusTypeVersion: OutgoingStatusTypeVersion?, val statusData: ByteArray?) : +data class UnhandledOutgoingStatus(val completedAt: Long?, val statusTypeVersion: LightningOutgoingStatusTypeVersion?, val statusData: ByteArray?) : RuntimeException("cannot map outgoing payment status data with completed_at=$completedAt status_type=$statusTypeVersion status=$statusData") -data class UnhandledOutgoingPartStatus(val status_type: OutgoingPartStatusTypeVersion?, val status_blob: ByteArray?, val completedAt: Long?) : +data class UnhandledOutgoingPartStatus(val status_type: LightningOutgoingPartStatusTypeVersion?, val status_blob: ByteArray?, val completedAt: Long?) : RuntimeException("cannot map outgoing part status data [ completed_at=$completedAt status_type=$status_type status_blob=$status_blob]") \ No newline at end of file diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingStatusType.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingStatusType.kt similarity index 62% rename from src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingStatusType.kt rename to src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingStatusType.kt index d44ef4d..70cb523 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/OutgoingStatusType.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LightningOutgoingStatusType.kt @@ -22,7 +22,6 @@ package fr.acinq.lightning.bin.db.payments import fr.acinq.bitcoin.ByteVector32 -import fr.acinq.bitcoin.Satoshi import fr.acinq.lightning.bin.db.payments.DbTypesHelper.decodeBlob import fr.acinq.lightning.bin.db.serializers.v1.ByteVector32Serializer import fr.acinq.lightning.bin.db.serializers.v1.SatoshiSerializer @@ -32,54 +31,35 @@ import io.ktor.utils.io.charsets.* import io.ktor.utils.io.core.* import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers -import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -enum class OutgoingStatusTypeVersion { +enum class LightningOutgoingStatusTypeVersion { SUCCEEDED_OFFCHAIN_V0, FAILED_V0, } -sealed class OutgoingStatusData { +sealed class LightningOutgoingStatusData { - sealed class SucceededOffChain : OutgoingStatusData() { + sealed class SucceededOffChain : LightningOutgoingStatusData() { @Serializable data class V0(@Serializable val preimage: ByteVector32) : SucceededOffChain() } - sealed class SucceededOnChain : OutgoingStatusData() { - @Serializable - data class V0( - val txIds: List<@Serializable ByteVector32>, - @Serializable val claimed: Satoshi, - val closingType: String - ) : SucceededOnChain() - - @Serializable - object V1 : SucceededOnChain() - } - - sealed class Failed : OutgoingStatusData() { + sealed class Failed : LightningOutgoingStatusData() { @Serializable data class V0(val reason: String) : Failed() } companion object { - /** Extract valuable data from old outgoing payments status that represent closing transactions. */ - fun deserializeLegacyClosingStatus(blob: ByteArray): SucceededOnChain.V0 = decodeBlob(blob) { json, format -> - val data = format.decodeFromString(json) - data - } - - fun deserialize(typeVersion: OutgoingStatusTypeVersion, blob: ByteArray, completedAt: Long): LightningOutgoingPayment.Status = decodeBlob(blob) { json, format -> + fun deserialize(typeVersion: LightningOutgoingStatusTypeVersion, blob: ByteArray, completedAt: Long): LightningOutgoingPayment.Status = decodeBlob(blob) { json, format -> @Suppress("DEPRECATION") when (typeVersion) { - OutgoingStatusTypeVersion.SUCCEEDED_OFFCHAIN_V0 -> format.decodeFromString(json).let { + LightningOutgoingStatusTypeVersion.SUCCEEDED_OFFCHAIN_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Status.Completed.Succeeded.OffChain(it.preimage, completedAt) } - OutgoingStatusTypeVersion.FAILED_V0 -> format.decodeFromString(json).let { + LightningOutgoingStatusTypeVersion.FAILED_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Status.Completed.Failed(deserializeFinalFailure(it.reason), completedAt) } } @@ -101,10 +81,9 @@ sealed class OutgoingStatusData { } } -fun LightningOutgoingPayment.Status.Completed.mapToDb(): Pair = when (this) { - is LightningOutgoingPayment.Status.Completed.Succeeded.OffChain -> OutgoingStatusTypeVersion.SUCCEEDED_OFFCHAIN_V0 to - Json.encodeToString(OutgoingStatusData.SucceededOffChain.V0(preimage)).toByteArray(Charsets.UTF_8) - is LightningOutgoingPayment.Status.Completed.Failed -> OutgoingStatusTypeVersion.FAILED_V0 to - Json.encodeToString(OutgoingStatusData.Failed.V0(OutgoingStatusData.serializeFinalFailure(reason))).toByteArray(Charsets.UTF_8) +fun LightningOutgoingPayment.Status.Completed.mapToDb(): Pair = when (this) { + is LightningOutgoingPayment.Status.Completed.Succeeded.OffChain -> LightningOutgoingStatusTypeVersion.SUCCEEDED_OFFCHAIN_V0 to + Json.encodeToString(LightningOutgoingStatusData.SucceededOffChain.V0(preimage)).toByteArray(Charsets.UTF_8) + is LightningOutgoingPayment.Status.Completed.Failed -> LightningOutgoingStatusTypeVersion.FAILED_V0 to + Json.encodeToString(LightningOutgoingStatusData.Failed.V0(LightningOutgoingStatusData.serializeFinalFailure(reason))).toByteArray(Charsets.UTF_8) } - diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LinkTxToPaymentQueries.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LinkTxToPaymentQueries.kt index 43062b2..d288293 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LinkTxToPaymentQueries.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/LinkTxToPaymentQueries.kt @@ -20,12 +20,12 @@ import app.cash.sqldelight.coroutines.asFlow import app.cash.sqldelight.coroutines.mapToList import fr.acinq.bitcoin.TxId import fr.acinq.lightning.bin.db.WalletPaymentId -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import kotlinx.coroutines.flow.* -class LinkTxToPaymentQueries(val database: PaymentsDatabase) { +class LinkTxToPaymentQueries(val database: PhoenixDatabase) { private val linkTxQueries = database.linkTxToPaymentQueries fun listUnconfirmedTxs(): Flow> { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/PaymentsMetadataQueries.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/PaymentsMetadataQueries.kt index 9cd19da..69b7af4 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/PaymentsMetadataQueries.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/PaymentsMetadataQueries.kt @@ -3,9 +3,9 @@ package fr.acinq.lightning.bin.db.payments import fr.acinq.lightning.bin.db.PaymentMetadata import fr.acinq.lightning.bin.db.WalletPaymentId import fr.acinq.lightning.utils.currentTimestampMillis -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase -class PaymentsMetadataQueries(private val database: PaymentsDatabase) { +class PaymentsMetadataQueries(private val database: PhoenixDatabase) { private val queries = database.paymentsMetadataQueries diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/SpliceCpfpOutgoingQueries.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/SpliceCpfpOutgoingQueries.kt index b675991..ca1f5c2 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/SpliceCpfpOutgoingQueries.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/SpliceCpfpOutgoingQueries.kt @@ -21,9 +21,9 @@ import fr.acinq.lightning.db.SpliceCpfpOutgoingPayment import fr.acinq.lightning.utils.UUID import fr.acinq.lightning.utils.sat import fr.acinq.lightning.utils.toByteVector32 -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase -class SpliceCpfpOutgoingQueries(val database: PaymentsDatabase) { +class SpliceCpfpOutgoingQueries(val database: PhoenixDatabase) { private val cpfpQueries = database.spliceCpfpOutgoingPaymentsQueries fun addCpfpPayment(payment: SpliceCpfpOutgoingPayment) { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/SpliceOutgoingQueries.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/SpliceOutgoingQueries.kt index 7d8c632..0d8ae4e 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/SpliceOutgoingQueries.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/db/payments/SpliceOutgoingQueries.kt @@ -21,9 +21,9 @@ import fr.acinq.lightning.db.SpliceOutgoingPayment import fr.acinq.lightning.utils.UUID import fr.acinq.lightning.utils.sat import fr.acinq.lightning.utils.toByteVector32 -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase -class SpliceOutgoingQueries(val database: PaymentsDatabase) { +class SpliceOutgoingQueries(val database: PhoenixDatabase) { private val spliceOutQueries = database.spliceOutgoingPaymentsQueries fun addSpliceOutgoingPayment(payment: SpliceOutgoingPayment) { diff --git a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/ChannelCloseOutgoingPayments.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/ChannelCloseOutgoingPayments.sq similarity index 90% rename from src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/ChannelCloseOutgoingPayments.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/ChannelCloseOutgoingPayments.sq index b495f3e..cf98d7c 100644 --- a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/ChannelCloseOutgoingPayments.sq +++ b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/ChannelCloseOutgoingPayments.sq @@ -1,4 +1,4 @@ -import fr.acinq.lightning.bin.db.payments.OutgoingPartClosingInfoTypeVersion; +import fr.acinq.lightning.bin.db.payments.ClosingInfoTypeVersion; -- Store in a flat row outgoing payments standing for channel-closing. -- There are no complex json columns like in the outgoing_payments table. @@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS channel_close_outgoing_payments ( confirmed_at INTEGER DEFAULT NULL, locked_at INTEGER DEFAULT NULL, channel_id BLOB NOT NULL, - closing_info_type TEXT AS OutgoingPartClosingInfoTypeVersion NOT NULL, + closing_info_type TEXT AS ClosingInfoTypeVersion NOT NULL, closing_info_blob BLOB NOT NULL ); diff --git a/src/commonMain/sqldelight/channelsdb/fr/acinq/phoenix/db/ChannelsDatabase.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/Channels.sq similarity index 100% rename from src/commonMain/sqldelight/channelsdb/fr/acinq/phoenix/db/ChannelsDatabase.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/Channels.sq diff --git a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/InboundLiquidityOutgoing.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/InboundLiquidityOutgoingPayments.sq similarity index 100% rename from src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/InboundLiquidityOutgoing.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/InboundLiquidityOutgoingPayments.sq diff --git a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/IncomingPayments.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/IncomingPayments.sq similarity index 100% rename from src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/IncomingPayments.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/IncomingPayments.sq diff --git a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/OutgoingPayments.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/LightningOutgoingPayments.sq similarity index 53% rename from src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/OutgoingPayments.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/LightningOutgoingPayments.sq index 5221061..f60de40 100644 --- a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/OutgoingPayments.sq +++ b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/LightningOutgoingPayments.sq @@ -1,36 +1,35 @@ import fr.acinq.lightning.db.HopDesc; -import fr.acinq.lightning.bin.db.payments.OutgoingDetailsTypeVersion; -import fr.acinq.lightning.bin.db.payments.OutgoingPartClosingInfoTypeVersion; -import fr.acinq.lightning.bin.db.payments.OutgoingPartStatusTypeVersion; -import fr.acinq.lightning.bin.db.payments.OutgoingStatusTypeVersion; +import fr.acinq.lightning.bin.db.payments.LightningOutgoingDetailsTypeVersion; +import fr.acinq.lightning.bin.db.payments.LightningOutgoingPartStatusTypeVersion; +import fr.acinq.lightning.bin.db.payments.LightningOutgoingStatusTypeVersion; import kotlin.collections.List; PRAGMA foreign_keys = 1; -- outgoing payments -- Stores an outgoing payment in a flat row. Some columns can be null. -CREATE TABLE IF NOT EXISTS outgoing_payments ( +CREATE TABLE IF NOT EXISTS lightning_outgoing_payments ( id TEXT NOT NULL PRIMARY KEY, recipient_amount_msat INTEGER NOT NULL, recipient_node_id TEXT NOT NULL, payment_hash BLOB NOT NULL, created_at INTEGER NOT NULL, -- details - details_type TEXT AS OutgoingDetailsTypeVersion NOT NULL, + details_type TEXT AS LightningOutgoingDetailsTypeVersion NOT NULL, details_blob BLOB NOT NULL, -- status completed_at INTEGER DEFAULT NULL, - status_type TEXT AS OutgoingStatusTypeVersion DEFAULT NULL, + status_type TEXT AS LightningOutgoingStatusTypeVersion DEFAULT NULL, status_blob BLOB DEFAULT NULL ); -- Create indexes to optimize the queries in AggregatedQueries. -- Tip: Use "explain query plan" to ensure they're actually being used. CREATE INDEX IF NOT EXISTS outgoing_payments_filter_idx - ON outgoing_payments(completed_at); + ON lightning_outgoing_payments(completed_at); -- Stores the lightning parts that make up a lightning payment -CREATE TABLE IF NOT EXISTS outgoing_payment_parts ( +CREATE TABLE IF NOT EXISTS lightning_outgoing_payment_parts ( part_id TEXT NOT NULL PRIMARY KEY, part_parent_id TEXT NOT NULL, part_amount_msat INTEGER NOT NULL, @@ -38,24 +37,10 @@ CREATE TABLE IF NOT EXISTS outgoing_payment_parts ( part_created_at INTEGER NOT NULL, -- status part_completed_at INTEGER DEFAULT NULL, - part_status_type TEXT AS OutgoingPartStatusTypeVersion DEFAULT NULL, + part_status_type TEXT AS LightningOutgoingPartStatusTypeVersion DEFAULT NULL, part_status_blob BLOB DEFAULT NULL, - FOREIGN KEY(part_parent_id) REFERENCES outgoing_payments(id) -); - --- !! This table is legacy, and will only contain old payments. See ChannelCloseOutgoingPayment.sq for the new table. --- Stores the transactions that close a channel -CREATE TABLE IF NOT EXISTS outgoing_payment_closing_tx_parts ( - part_id TEXT NOT NULL PRIMARY KEY, - part_parent_id TEXT NOT NULL, - part_tx_id BLOB NOT NULL, - part_amount_sat INTEGER NOT NULL, - part_closing_info_type TEXT AS OutgoingPartClosingInfoTypeVersion NOT NULL, - part_closing_info_blob BLOB NOT NULL, - part_created_at INTEGER NOT NULL, - - FOREIGN KEY(part_parent_id) REFERENCES outgoing_payments(id) + FOREIGN KEY(part_parent_id) REFERENCES lightning_outgoing_payments(id) ); -- A FOREIGN KEY does NOT create an implicit index. @@ -64,17 +49,16 @@ CREATE TABLE IF NOT EXISTS outgoing_payment_closing_tx_parts ( -- > Indices are not required for child key columns but they are almost always beneficial. -- > [...] So, in most real systems, an index should be created on the child key columns -- > of each foreign key constraint. -CREATE INDEX IF NOT EXISTS parent_id_idx ON outgoing_payment_parts(part_parent_id); -CREATE INDEX IF NOT EXISTS parent_id_idx ON outgoing_payment_closing_tx_parts(part_parent_id); +CREATE INDEX IF NOT EXISTS parent_id_idx ON lightning_outgoing_payment_parts(part_parent_id); -- queries for outgoing payments hasPayment: -SELECT COUNT(*) FROM outgoing_payments +SELECT COUNT(*) FROM lightning_outgoing_payments WHERE id = ?; insertPayment: -INSERT INTO outgoing_payments ( +INSERT INTO lightning_outgoing_payments ( id, recipient_amount_msat, recipient_node_id, @@ -85,23 +69,23 @@ INSERT INTO outgoing_payments ( VALUES (?, ?, ?, ?, ?, ?, ?); updatePayment: -UPDATE outgoing_payments SET completed_at=?, status_type=?, status_blob=? WHERE id=?; +UPDATE lightning_outgoing_payments SET completed_at=?, status_type=?, status_blob=? WHERE id=?; scanCompleted: SELECT id, completed_at -FROM outgoing_payments +FROM lightning_outgoing_payments WHERE completed_at IS NOT NULL; deletePayment: -DELETE FROM outgoing_payments WHERE id = ?; +DELETE FROM lightning_outgoing_payments WHERE id = ?; -- queries for lightning parts countLightningPart: -SELECT COUNT(*) FROM outgoing_payment_parts WHERE part_id = ?; +SELECT COUNT(*) FROM lightning_outgoing_payment_parts WHERE part_id = ?; insertLightningPart: -INSERT INTO outgoing_payment_parts ( +INSERT INTO lightning_outgoing_payment_parts ( part_id, part_parent_id, part_amount_msat, @@ -110,33 +94,17 @@ INSERT INTO outgoing_payment_parts ( VALUES (?, ?, ?, ?, ?); updateLightningPart: -UPDATE outgoing_payment_parts +UPDATE lightning_outgoing_payment_parts SET part_status_type=?, part_status_blob=?, part_completed_at=? WHERE part_id=?; getLightningPart: -SELECT * FROM outgoing_payment_parts WHERE part_id=?; +SELECT * FROM lightning_outgoing_payment_parts WHERE part_id=?; deleteLightningPartsForParentId: -DELETE FROM outgoing_payment_parts WHERE part_parent_id = ?; - --- queries for closing tx parts - -countClosingTxPart: -SELECT COUNT(*) FROM outgoing_payment_closing_tx_parts WHERE part_id = ?; - -insertClosingTxPart: -INSERT INTO outgoing_payment_closing_tx_parts ( - part_id, - part_parent_id, - part_tx_id, - part_amount_sat, - part_closing_info_type, - part_closing_info_blob, - part_created_at -) VALUES (:id, :parent_id, :tx_id, :amount_msat, :closing_info_type, :closing_info_blob, :created_at); +DELETE FROM lightning_outgoing_payment_parts WHERE part_parent_id = ?; -- queries mixing outgoing payments and parts @@ -151,12 +119,12 @@ SELECT id, completed_at, status_type, status_blob -FROM outgoing_payments +FROM lightning_outgoing_payments WHERE id=?; getOldestCompletedDate: SELECT completed_at -FROM outgoing_payments AS o +FROM lightning_outgoing_payments AS o WHERE completed_at IS NOT NULL ORDER BY o.completed_at ASC LIMIT 1; @@ -179,17 +147,9 @@ SELECT parent.id, lightning_parts.part_created_at AS lightning_part_created_at, lightning_parts.part_completed_at AS lightning_part_completed_at, lightning_parts.part_status_type AS lightning_part_status_type, - lightning_parts.part_status_blob AS lightning_part_status_blob, - -- closing tx parts - closing_parts.part_id AS closingtx_part_id, - closing_parts.part_tx_id AS closingtx_tx_id, - closing_parts.part_amount_sat AS closingtx_amount_sat, - closing_parts.part_closing_info_type AS closingtx_info_type, - closing_parts.part_closing_info_blob AS closingtx_info_blob, - closing_parts.part_created_at AS closingtx_created_at -FROM outgoing_payments AS parent -LEFT OUTER JOIN outgoing_payment_parts AS lightning_parts ON lightning_parts.part_parent_id = parent.id -LEFT OUTER JOIN outgoing_payment_closing_tx_parts AS closing_parts ON closing_parts.part_parent_id = parent.id + lightning_parts.part_status_blob AS lightning_part_status_blob +FROM lightning_outgoing_payments AS parent +LEFT OUTER JOIN lightning_outgoing_payment_parts AS lightning_parts ON lightning_parts.part_parent_id = parent.id WHERE parent.id=?; listPaymentsForPaymentHash: @@ -210,17 +170,9 @@ SELECT parent.id, lightning_parts.part_created_at AS lightning_part_created_at, lightning_parts.part_completed_at AS lightning_part_completed_at, lightning_parts.part_status_type AS lightning_part_status_type, - lightning_parts.part_status_blob AS lightning_part_status_blob, - -- closing tx parts - closing_parts.part_id AS closingtx_part_id, - closing_parts.part_tx_id AS closingtx_tx_id, - closing_parts.part_amount_sat AS closingtx_amount_sat, - closing_parts.part_closing_info_type AS closingtx_info_type, - closing_parts.part_closing_info_blob AS closingtx_info_blob, - closing_parts.part_created_at AS closingtx_created_at -FROM outgoing_payments AS parent -LEFT OUTER JOIN outgoing_payment_parts AS lightning_parts ON lightning_parts.part_parent_id = parent.id -LEFT OUTER JOIN outgoing_payment_closing_tx_parts AS closing_parts ON closing_parts.part_parent_id = parent.id + lightning_parts.part_status_blob AS lightning_part_status_blob +FROM lightning_outgoing_payments AS parent +LEFT OUTER JOIN lightning_outgoing_payment_parts AS lightning_parts ON lightning_parts.part_parent_id = parent.id WHERE payment_hash=?; -- use this in a `transaction` block to know how many rows were changed after an UPDATE diff --git a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/LinkTxToPayment.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/LinkTxToPayment.sq similarity index 100% rename from src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/LinkTxToPayment.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/LinkTxToPayment.sq diff --git a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/PaymentsMetadata.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/PaymentsMetadata.sq similarity index 100% rename from src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/PaymentsMetadata.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/PaymentsMetadata.sq diff --git a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/SpliceCpfpOutgoingPayments.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/SpliceCpfpOutgoingPayments.sq similarity index 100% rename from src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/SpliceCpfpOutgoingPayments.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/SpliceCpfpOutgoingPayments.sq diff --git a/src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/SpliceOutgoingPayments.sq b/src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/SpliceOutgoingPayments.sq similarity index 100% rename from src/commonMain/sqldelight/paymentsdb/fr/acinq/phoenix/db/SpliceOutgoingPayments.sq rename to src/commonMain/sqldelight/phoenixdb/fr/acinq/phoenix/db/SpliceOutgoingPayments.sq diff --git a/src/jvmMain/kotlin/fr/acinq/lightning/bin/Actuals.kt b/src/jvmMain/kotlin/fr/acinq/lightning/bin/Actuals.kt index 0578e6b..5d6219e 100644 --- a/src/jvmMain/kotlin/fr/acinq/lightning/bin/Actuals.kt +++ b/src/jvmMain/kotlin/fr/acinq/lightning/bin/Actuals.kt @@ -2,8 +2,7 @@ package fr.acinq.lightning.bin import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver -import fr.acinq.phoenix.db.ChannelsDatabase -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase import okio.Path import okio.Path.Companion.toPath @@ -12,13 +11,6 @@ actual val homeDirectory: Path = System.getProperty("user.home").toPath() actual fun createAppDbDriver(dir: Path): SqlDriver { val path = dir / "phoenix.db" val driver = JdbcSqliteDriver("jdbc:sqlite:$path") - ChannelsDatabase.Schema.create(driver) - return driver -} - -actual fun createPaymentsDbDriver(dir: Path): SqlDriver { - val path = dir / "payments.db" - val driver = JdbcSqliteDriver("jdbc:sqlite:$path") - PaymentsDatabase.Schema.create(driver) + PhoenixDatabase.Schema.create(driver) return driver } diff --git a/src/nativeMain/kotlin/fr/acinq/lightning/bin/Actuals.kt b/src/nativeMain/kotlin/fr/acinq/lightning/bin/Actuals.kt index ea24629..19c4929 100644 --- a/src/nativeMain/kotlin/fr/acinq/lightning/bin/Actuals.kt +++ b/src/nativeMain/kotlin/fr/acinq/lightning/bin/Actuals.kt @@ -2,8 +2,7 @@ package fr.acinq.lightning.bin import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.native.NativeSqliteDriver -import fr.acinq.phoenix.db.ChannelsDatabase -import fr.acinq.phoenix.db.PaymentsDatabase +import fr.acinq.phoenix.db.PhoenixDatabase import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.toKString import okio.Path @@ -15,13 +14,7 @@ import platform.posix.setenv actual val homeDirectory: Path = setenv("KTOR_LOG_LEVEL", "WARN", 1).let { getenv("HOME")?.toKString()!!.toPath() } actual fun createAppDbDriver(dir: Path): SqlDriver { - return NativeSqliteDriver(ChannelsDatabase.Schema, "phoenix.db", + return NativeSqliteDriver(PhoenixDatabase.Schema, "phoenix.db", onConfiguration = { it.copy(extendedConfig = it.extendedConfig.copy(basePath = dir.toString())) } ) } - -actual fun createPaymentsDbDriver(dir: Path): SqlDriver { - return NativeSqliteDriver(PaymentsDatabase.Schema, "payments.db", - onConfiguration = { it.copy(extendedConfig = it.extendedConfig.copy(basePath = dir.toString())) } - ) -} \ No newline at end of file