diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Aborted.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Aborted.kt index 322841751..8a079eacb 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Aborted.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Aborted.kt @@ -7,7 +7,7 @@ import fr.acinq.lightning.channel.ChannelCommand * Channel has been aborted before it was funded (because we did not receive a FundingCreated or FundingSigned message for example) */ data object Aborted : ChannelState() { - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return Pair(this@Aborted, listOf()) } } diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Channel.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Channel.kt index 50217a5f1..517cfe459 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Channel.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Channel.kt @@ -49,9 +49,9 @@ sealed class ChannelState { * @param cmd input event (for example, a message was received, a command was sent by the GUI/API, etc) * @return a (new state, list of actions) pair */ - abstract fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> + abstract suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> - fun ChannelContext.process(cmd: ChannelCommand): Pair> { + suspend fun ChannelContext.process(cmd: ChannelCommand): Pair> { return try { processInternal(cmd) .let { (newState, actions) -> Pair(newState, newState.run { maybeAddBackupToMessages(actions) }) } diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Closed.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Closed.kt index 1dce1e156..1bf83e3e1 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Closed.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Closed.kt @@ -14,7 +14,7 @@ data class Closed(val state: Closing) : ChannelStateWithCommitments() { return this.copy(state = state.updateCommitments(input) as Closing) } - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return Pair(this@Closed, listOf()) } } diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Closing.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Closing.kt index baee55dcd..f6b323504 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Closing.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Closing.kt @@ -71,7 +71,7 @@ data class Closing( override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.WatchReceived -> { val watch = cmd.watch diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/LegacyWaitForFundingConfirmed.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/LegacyWaitForFundingConfirmed.kt index 1761a11d3..d98cbe403 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/LegacyWaitForFundingConfirmed.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/LegacyWaitForFundingConfirmed.kt @@ -28,7 +28,7 @@ data class LegacyWaitForFundingConfirmed( ) : ChannelStateWithCommitments() { override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is ChannelReady -> Pair(this@LegacyWaitForFundingConfirmed.copy(deferred = cmd.message), listOf()) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/LegacyWaitForFundingLocked.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/LegacyWaitForFundingLocked.kt index f5ed95d94..338300031 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/LegacyWaitForFundingLocked.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/LegacyWaitForFundingLocked.kt @@ -22,7 +22,7 @@ data class LegacyWaitForFundingLocked( ) : ChannelStateWithCommitments() { override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is ChannelReady -> { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Negotiating.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Negotiating.kt index b50299edb..0961c8edc 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Negotiating.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Negotiating.kt @@ -28,7 +28,7 @@ data class Negotiating( override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is ClosingSigned -> { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt index be6fb9ec9..8ac44045f 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt @@ -31,7 +31,7 @@ data class Normal( override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { val forbiddenPreSplice = cmd is ChannelCommand.ForbiddenDuringQuiescence && spliceStatus is QuiescenceNegotiation val forbiddenDuringSplice = cmd is ChannelCommand.ForbiddenDuringSplice && spliceStatus is QuiescentSpliceStatus if (forbiddenPreSplice || forbiddenDuringSplice) { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Offline.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Offline.kt index 978e12a4f..10264fb9e 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Offline.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Offline.kt @@ -14,7 +14,7 @@ data class Offline(val state: PersistedChannelState) : ChannelState() { val channelId = state.channelId - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.Connected -> { when (state) { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/ShuttingDown.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/ShuttingDown.kt index b9bb26da7..f1ba3f63e 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/ShuttingDown.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/ShuttingDown.kt @@ -15,7 +15,7 @@ data class ShuttingDown( ) : ChannelStateWithCommitments() { override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> { when (cmd.message) { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Syncing.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Syncing.kt index 2b51aab4f..f6c2d7b60 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Syncing.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Syncing.kt @@ -18,7 +18,7 @@ data class Syncing(val state: PersistedChannelState, val channelReestablishSent: is ChannelStateWithCommitments -> state.commitments.params.localParams.channelKeys(keyManager) } - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is ChannelReestablish -> { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForAcceptChannel.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForAcceptChannel.kt index 06f4383b1..c00720b28 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForAcceptChannel.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForAcceptChannel.kt @@ -25,7 +25,7 @@ data class WaitForAcceptChannel( ) : ChannelState() { val temporaryChannelId: ByteVector32 get() = lastSent.temporaryChannelId - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is AcceptDualFundedChannel -> { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForChannelReady.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForChannelReady.kt index 8135ed4f7..c5f5aba61 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForChannelReady.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForChannelReady.kt @@ -18,7 +18,7 @@ data class WaitForChannelReady( ) : ChannelStateWithCommitments() { override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is TxSignatures -> when (commitments.latest.localFundingStatus) { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingConfirmed.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingConfirmed.kt index 22876b53d..02e092358 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingConfirmed.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingConfirmed.kt @@ -29,7 +29,7 @@ data class WaitForFundingConfirmed( override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is TxSignatures -> when (latestFundingTx.sharedTx) { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingCreated.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingCreated.kt index 45f093b15..304ba5f8f 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingCreated.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingCreated.kt @@ -45,7 +45,7 @@ data class WaitForFundingCreated( ) : ChannelState() { val channelId: ByteVector32 = interactiveTxSession.fundingParams.channelId - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is InteractiveTxConstructionMessage -> { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingSigned.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingSigned.kt index 2ed3c3ed7..e1fba47e5 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingSigned.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingSigned.kt @@ -47,7 +47,7 @@ data class WaitForFundingSigned( ) : PersistedChannelState() { override val channelId: ByteVector32 = channelParams.channelId - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is CommitSig -> { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForInit.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForInit.kt index d45f4328a..c97ce807a 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForInit.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForInit.kt @@ -11,7 +11,7 @@ import fr.acinq.lightning.wire.OpenDualFundedChannel import fr.acinq.lightning.wire.TlvStream data object WaitForInit : ChannelState() { - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.Init.NonInitiator -> { val nextState = WaitForOpenChannel( diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForOpenChannel.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForOpenChannel.kt index adc88ce7d..18dcdba66 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForOpenChannel.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForOpenChannel.kt @@ -29,7 +29,7 @@ data class WaitForOpenChannel( val channelConfig: ChannelConfig, val remoteInit: Init ) : ChannelState() { - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when (cmd) { is ChannelCommand.MessageReceived -> when (cmd.message) { is OpenDualFundedChannel -> { diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForRemotePublishFutureCommitment.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForRemotePublishFutureCommitment.kt index aa51c7d17..2b56922ce 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForRemotePublishFutureCommitment.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForRemotePublishFutureCommitment.kt @@ -14,7 +14,7 @@ data class WaitForRemotePublishFutureCommitment( ) : ChannelStateWithCommitments() { override fun updateCommitments(input: Commitments): ChannelStateWithCommitments = this.copy(commitments = input) - override fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { + override suspend fun ChannelContext.processInternal(cmd: ChannelCommand): Pair> { return when { cmd is ChannelCommand.WatchReceived && cmd.watch is WatchEventSpent && cmd.watch.event is BITCOIN_FUNDING_SPENT -> handlePotentialForceClose(cmd.watch) cmd is ChannelCommand.Disconnected -> Pair(Offline(this@WaitForRemotePublishFutureCommitment), listOf()) diff --git a/src/commonTest/kotlin/fr/acinq/lightning/channel/TestsHelper.kt b/src/commonTest/kotlin/fr/acinq/lightning/channel/TestsHelper.kt index 48bb99e4c..93d83d0fa 100644 --- a/src/commonTest/kotlin/fr/acinq/lightning/channel/TestsHelper.kt +++ b/src/commonTest/kotlin/fr/acinq/lightning/channel/TestsHelper.kt @@ -11,7 +11,8 @@ import fr.acinq.lightning.channel.states.* import fr.acinq.lightning.crypto.KeyManager import fr.acinq.lightning.db.ChannelClosingType import fr.acinq.lightning.json.JsonSerializers -import fr.acinq.lightning.logging.* +import fr.acinq.lightning.logging.MDCLogger +import fr.acinq.lightning.logging.mdc import fr.acinq.lightning.payment.OutgoingPaymentPacket import fr.acinq.lightning.router.ChannelHop import fr.acinq.lightning.serialization.Serialization @@ -20,6 +21,7 @@ import fr.acinq.lightning.tests.utils.testLoggerFactory import fr.acinq.lightning.transactions.Transactions import fr.acinq.lightning.utils.* import fr.acinq.lightning.wire.* +import kotlinx.coroutines.runBlocking import kotlinx.serialization.encodeToString import kotlin.test.* @@ -89,7 +91,7 @@ data class LNChannel( } } - fun process(cmd: ChannelCommand): Pair, List> = + fun process(cmd: ChannelCommand): Pair, List> = runBlocking { state .run { ctx.copy(logger = ctx.logger.copy(staticMdc = state.mdc())).process(cmd) } .let { (newState, actions) -> @@ -97,6 +99,7 @@ data class LNChannel( JsonSerializers.json.encodeToString(newState) LNChannel(ctx, newState) to actions } + } /** same as [process] but with the added assumption that we stay in the same state */ fun processSameState(event: ChannelCommand): Pair, List> { diff --git a/src/commonTest/kotlin/fr/acinq/lightning/tests/utils/runTest.kt b/src/commonTest/kotlin/fr/acinq/lightning/tests/utils/runTest.kt index 988a416bc..4cb18aceb 100644 --- a/src/commonTest/kotlin/fr/acinq/lightning/tests/utils/runTest.kt +++ b/src/commonTest/kotlin/fr/acinq/lightning/tests/utils/runTest.kt @@ -7,6 +7,9 @@ import kotlinx.coroutines.withTimeout import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds +/** + * This defers to kotlin's [kotlinx.coroutines.runBlocking] on all platforms except iOS which needs custom code. + */ expect fun runSuspendBlocking(block: suspend CoroutineScope.() -> Unit) fun runSuspendTest(timeout: Duration = 30.seconds, test: suspend CoroutineScope.() -> Unit) {