1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-03-13 19:37:35 +01:00

Better explanations

This commit is contained in:
Thomas HUET 2024-08-01 16:47:30 +02:00
parent 83a56271f5
commit 54f40419b0
8 changed files with 35 additions and 29 deletions

View file

@ -237,6 +237,18 @@ eclair {
// Number of blocks before the incoming HTLC expires that an async payment must be triggered by the receiver
cancel-safety-before-timeout-blocks = 144
}
// We assign reputations to our peers to prioritize HTLCs during congestion.
// The reputation is computed as fees paid divided by what should have been paid if all HTLCs were successful.
peer-reputation {
// Reputation decays with the following half life to emphasize recent behavior.
half-life = 7 days
// HTLCs that stay pending for longer than this get penalized
max-htlc-relay-duration = 12 seconds
// Pending HTLCs are counted as failed, and because they could potentially stay pending for a very long time, the
// following multiplier is applied.
pending-multiplier = 1000 // A pending HTLCs counts as a thousand failed ones.
}
}
on-chain-fees {
@ -547,15 +559,6 @@ eclair {
enabled = true // enable automatic purges of expired invoices from the database
interval = 24 hours // interval between expired invoice purges
}
local-reputation {
# Reputation decays with the following half life to emphasize recent behavior.
half-life = 7 days
# HTLCs that stay pending for longer than this get penalized
good-htlc-duration = 12 seconds # 95% of successful payments settle in less than 12 seconds, only the slowest 5% will be penalized.
# How much to penalize pending HLTCs. A pending HTLC is considered equivalent to this many fast-failing HTLCs.
pending-multiplier = 1000
}
}
akka {

View file

@ -88,8 +88,7 @@ case class NodeParams(nodeKeyManager: NodeKeyManager,
blockchainWatchdogSources: Seq[String],
onionMessageConfig: OnionMessageConfig,
purgeInvoicesInterval: Option[FiniteDuration],
revokedHtlcInfoCleanerConfig: RevokedHtlcInfoCleaner.Config,
localReputationConfig: ReputationConfig) {
revokedHtlcInfoCleanerConfig: RevokedHtlcInfoCleaner.Config) {
val privateKey: Crypto.PrivateKey = nodeKeyManager.nodeKey.privateKey
val nodeId: PublicKey = nodeKeyManager.nodeId
@ -563,7 +562,12 @@ object NodeParams extends Logging {
privateChannelFees = getRelayFees(config.getConfig("relay.fees.private-channels")),
minTrampolineFees = getRelayFees(config.getConfig("relay.fees.min-trampoline")),
enforcementDelay = FiniteDuration(config.getDuration("relay.fees.enforcement-delay").getSeconds, TimeUnit.SECONDS),
asyncPaymentsParams = AsyncPaymentsParams(asyncPaymentHoldTimeoutBlocks, asyncPaymentCancelSafetyBeforeTimeoutBlocks)
asyncPaymentsParams = AsyncPaymentsParams(asyncPaymentHoldTimeoutBlocks, asyncPaymentCancelSafetyBeforeTimeoutBlocks),
peerReputationConfig = ReputationConfig(
FiniteDuration(config.getDuration("relay.peer-reputation.half-life").getSeconds, TimeUnit.SECONDS),
FiniteDuration(config.getDuration("relay.peer-reputation.max-htlc-relay-duration").getSeconds, TimeUnit.SECONDS),
config.getDouble("relay.peer-reputation.pending-multiplier"),
),
),
db = database,
autoReconnect = config.getBoolean("auto-reconnect"),
@ -613,12 +617,7 @@ object NodeParams extends Logging {
revokedHtlcInfoCleanerConfig = RevokedHtlcInfoCleaner.Config(
batchSize = config.getInt("db.revoked-htlc-info-cleaner.batch-size"),
interval = FiniteDuration(config.getDuration("db.revoked-htlc-info-cleaner.interval").getSeconds, TimeUnit.SECONDS)
),
localReputationConfig = ReputationConfig(
FiniteDuration(config.getDuration("local-reputation.half-life").getSeconds, TimeUnit.SECONDS),
FiniteDuration(config.getDuration("local-reputation.good-htlc-duration").getSeconds, TimeUnit.SECONDS),
config.getDouble("local-reputation.pending-multiplier"),
),
)
)
}
}

View file

@ -361,7 +361,7 @@ class Setup(val datadir: File,
offerManager = system.spawn(Behaviors.supervise(OfferManager(nodeParams, router, paymentTimeout = 1 minute)).onFailure(typed.SupervisorStrategy.resume), name = "offer-manager")
paymentHandler = system.actorOf(SimpleSupervisor.props(PaymentHandler.props(nodeParams, register, offerManager), "payment-handler", SupervisorStrategy.Resume))
triggerer = system.spawn(Behaviors.supervise(AsyncPaymentTriggerer()).onFailure(typed.SupervisorStrategy.resume), name = "async-payment-triggerer")
reputationRecorder = system.spawn(Behaviors.supervise(ReputationRecorder(nodeParams.localReputationConfig, Map.empty)).onFailure(typed.SupervisorStrategy.resume), name = "reputation-recorder")
reputationRecorder = system.spawn(Behaviors.supervise(ReputationRecorder(nodeParams.relayParams.peerReputationConfig, Map.empty)).onFailure(typed.SupervisorStrategy.resume), name = "reputation-recorder")
relayer = system.actorOf(SimpleSupervisor.props(Relayer.props(nodeParams, router, register, paymentHandler, triggerer, reputationRecorder, Some(postRestartCleanUpInitialized)), "relayer", SupervisorStrategy.Resume))
_ = relayer ! PostRestartHtlcCleaner.Init(channels)
// Before initializing the switchboard (which re-connects us to the network) and the user-facing parts of the system,

View file

@ -28,6 +28,7 @@ import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.PendingCommandsDb
import fr.acinq.eclair.payment._
import fr.acinq.eclair.reputation.Reputation.ReputationConfig
import fr.acinq.eclair.reputation.ReputationRecorder
import fr.acinq.eclair.wire.protocol._
import fr.acinq.eclair.{CltvExpiryDelta, Logs, MilliSatoshi, NodeParams}
@ -136,7 +137,8 @@ object Relayer extends Logging {
privateChannelFees: RelayFees,
minTrampolineFees: RelayFees,
enforcementDelay: FiniteDuration,
asyncPaymentsParams: AsyncPaymentsParams) {
asyncPaymentsParams: AsyncPaymentsParams,
peerReputationConfig: ReputationConfig) {
def defaultFees(announceChannel: Boolean): RelayFees = {
if (announceChannel) {
publicChannelFees

View file

@ -76,7 +76,7 @@ object Reputation {
}
}
case class ReputationConfig(halfLife: FiniteDuration, goodDuration: FiniteDuration, pendingMultiplier: Double)
case class ReputationConfig(halfLife: FiniteDuration, maxHtlcRelayDuration: FiniteDuration, pendingMultiplier: Double)
def init(config: ReputationConfig): Reputation = Reputation(0.0, 0.0, TimestampMilli.min, Map.empty, config.halfLife, config.goodDuration, config.pendingMultiplier)
def init(config: ReputationConfig): Reputation = Reputation(0.0, 0.0, TimestampMilli.min, Map.empty, config.halfLife, config.maxHtlcRelayDuration, config.pendingMultiplier)
}

View file

@ -166,7 +166,9 @@ object TestConstants {
feeBase = 548000 msat,
feeProportionalMillionths = 30),
enforcementDelay = 10 minutes,
asyncPaymentsParams = AsyncPaymentsParams(1008, CltvExpiryDelta(144))),
asyncPaymentsParams = AsyncPaymentsParams(1008, CltvExpiryDelta(144)),
peerReputationConfig = ReputationConfig(1 day, 10 seconds, 100),
),
db = TestDatabases.inMemoryDb(),
autoReconnect = false,
initialRandomReconnectDelay = 5 seconds,
@ -233,7 +235,6 @@ object TestConstants {
),
purgeInvoicesInterval = None,
revokedHtlcInfoCleanerConfig = RevokedHtlcInfoCleaner.Config(10, 100 millis),
localReputationConfig = ReputationConfig(1 day, 10 seconds, 100),
)
def channelParams: LocalParams = OpenChannelInterceptor.makeChannelParams(
@ -337,7 +338,9 @@ object TestConstants {
feeBase = 548000 msat,
feeProportionalMillionths = 30),
enforcementDelay = 10 minutes,
asyncPaymentsParams = AsyncPaymentsParams(1008, CltvExpiryDelta(144))),
asyncPaymentsParams = AsyncPaymentsParams(1008, CltvExpiryDelta(144)),
peerReputationConfig = ReputationConfig(2 day, 20 seconds, 200),
),
db = TestDatabases.inMemoryDb(),
autoReconnect = false,
initialRandomReconnectDelay = 5 seconds,
@ -404,7 +407,6 @@ object TestConstants {
),
purgeInvoicesInterval = None,
revokedHtlcInfoCleanerConfig = RevokedHtlcInfoCleaner.Config(10, 100 millis),
localReputationConfig = ReputationConfig(2 days, 20 seconds, 200),
)
def channelParams: LocalParams = OpenChannelInterceptor.makeChannelParams(

View file

@ -67,8 +67,8 @@ class FuzzySpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Channe
val bobRegister = system.actorOf(Props(new TestRegister()))
val alicePaymentHandler = system.actorOf(Props(new PaymentHandler(aliceParams, aliceRegister, TestProbe().ref)))
val bobPaymentHandler = system.actorOf(Props(new PaymentHandler(bobParams, bobRegister, TestProbe().ref)))
val aliceReputationRecorder = system.spawnAnonymous(ReputationRecorder(aliceParams.localReputationConfig, Map.empty))
val bobReputationRecorder = system.spawnAnonymous(ReputationRecorder(bobParams.localReputationConfig, Map.empty))
val aliceReputationRecorder = system.spawnAnonymous(ReputationRecorder(aliceParams.relayParams.peerReputationConfig, Map.empty))
val bobReputationRecorder = system.spawnAnonymous(ReputationRecorder(bobParams.relayParams.peerReputationConfig, Map.empty))
val aliceRelayer = system.actorOf(Relayer.props(aliceParams, TestProbe().ref, aliceRegister, alicePaymentHandler, TestProbe().ref, aliceReputationRecorder))
val bobRelayer = system.actorOf(Relayer.props(bobParams, TestProbe().ref, bobRegister, bobPaymentHandler, TestProbe().ref, bobReputationRecorder))
val wallet = new DummyOnChainWallet()

View file

@ -97,7 +97,7 @@ object MinimalNodeFixture extends Assertions with Eventually with IntegrationPat
val router = system.actorOf(Router.props(nodeParams, watcherTyped), "router")
val offerManager = system.spawn(OfferManager(nodeParams, router, 1 minute), "offer-manager")
val paymentHandler = system.actorOf(PaymentHandler.props(nodeParams, register, offerManager), "payment-handler")
val reputationRecorder = system.spawn(ReputationRecorder(nodeParams.localReputationConfig, Map.empty), "reputation-recorder")
val reputationRecorder = system.spawn(ReputationRecorder(nodeParams.relayParams.peerReputationConfig, Map.empty), "reputation-recorder")
val relayer = system.actorOf(Relayer.props(nodeParams, router, register, paymentHandler, triggerer.ref.toTyped, reputationRecorder), "relayer")
val txPublisherFactory = Channel.SimpleTxPublisherFactory(nodeParams, watcherTyped, bitcoinClient)
val channelFactory = Peer.SimpleChannelFactory(nodeParams, watcherTyped, relayer, wallet, txPublisherFactory)