mirror of
https://github.com/ACINQ/eclair.git
synced 2025-03-13 19:37:35 +01:00
Better explanations
This commit is contained in:
parent
83a56271f5
commit
54f40419b0
8 changed files with 35 additions and 29 deletions
|
@ -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 {
|
||||
|
|
|
@ -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"),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue