-
Notifications
You must be signed in to change notification settings - Fork 265
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Asynchronously clean up obsolete HTLC info from DB (#2705)
When a channel is closed, we can forget the data from historical HTLCs sent and received through that channel (which is otherwise required to punish cheating attempts by our peer). We previously synchronously removed that data from the DB when the closing transaction confirmed. However, this could create performance issues as the `htlc_infos` table can be very large for busy nodes and many concurrent writes may be happening at the same time. We don't need to get rid of this data immediately: we only want to remove it to avoid degrading the performance of active channels that read and write to the `htlc_infos` table. We now mark channels as closed in a dedicated table, and run a background actor that deletes batches of obsolete htlc data at regular intervals. This ensures that the table is eventually cleaned up, without impacting the performance of active channels. When a splice transaction confirms, all the revoked commitment transactions that only applied to the previous funding transaction cannot be published anymore, because the previous funding output has already been spent. We can thus forget all the historical HTLCs that were included in those commitments, because we will never need to generate the corresponding penalty transactions. This ensures that the growth of our DB is bounded, and will shrink every time a splice transaction is confirmed. Fixes #2610, #2702 and #2740
- Loading branch information
Showing
24 changed files
with
578 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
eclair-core/src/main/scala/fr/acinq/eclair/db/RevokedHtlcInfoCleaner.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright 2023 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.eclair.db | ||
|
||
import akka.actor.typed.Behavior | ||
import akka.actor.typed.eventstream.EventStream | ||
import akka.actor.typed.scaladsl.Behaviors | ||
import fr.acinq.bitcoin.scalacompat.ByteVector32 | ||
|
||
import scala.concurrent.duration.FiniteDuration | ||
|
||
/** | ||
* When a channel is closed or a splice transaction confirms, we can remove the information about old HTLCs that was | ||
* stored in the DB to punish revoked commitments. We potentially have millions of rows to delete per channel, and there | ||
* is no rush to remove them. We don't want this to negatively impact active channels, so this actor deletes that data | ||
* in small batches, at regular intervals. | ||
*/ | ||
object RevokedHtlcInfoCleaner { | ||
|
||
// @formatter:off | ||
sealed trait Command | ||
case class ForgetHtlcInfos(channelId: ByteVector32, beforeCommitIndex: Long) extends Command | ||
private case object DeleteBatch extends Command | ||
// @formatter:on | ||
|
||
case class Config(batchSize: Int, interval: FiniteDuration) | ||
|
||
def apply(db: ChannelsDb, config: Config): Behavior[Command] = { | ||
Behaviors.setup { context => | ||
context.system.eventStream ! EventStream.Subscribe(context.self) | ||
Behaviors.withTimers { timers => | ||
timers.startTimerWithFixedDelay(DeleteBatch, config.interval) | ||
Behaviors.receiveMessage { | ||
case ForgetHtlcInfos(channelId, beforeCommitIndex) => | ||
db.markHtlcInfosForRemoval(channelId, beforeCommitIndex) | ||
Behaviors.same | ||
case DeleteBatch => | ||
db.removeHtlcInfos(config.batchSize) | ||
Behaviors.same | ||
} | ||
} | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.