Configurable transaction confirmation target#1083
Conversation
…emove unused 'smartfeeNBlocks'
sstone
left a comment
There was a problem hiding this comment.
Nice to get rid of all these calls to Globals !
eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala
Outdated
Show resolved
Hide resolved
…ets` to fr.acinq.blockchain.fee.FeeEstimator.
eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FeeEstimator.scala
Show resolved
Hide resolved
Do you think we should hard-code this for 1079? I think it's better to keep it configurable, because this is linked to the amount of time you can expect to be safely offline, so if you are on a not-so-reliable node (raspberry pi for example) you might want to use a value higher than 2 here. |
Not necessarily, it's just that now we have a rationale for the default value. OTOH changing the default commitment target is definitely risky. |
There was a problem hiding this comment.
Nice change. As a side effect, with the removal of global access to feerates we are one step closer to being able to run tests in parallel.
I think we should probably get rid of the global Alice and Bob parameters. They are not needed since we can always retrieve the actual parameters from TestActorRef.underlyingActor.nodeParams. Maybe we could replace them with methods like makeAliceParams to discourage using them directly. NB: that would be a different PR.
eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FeeProvider.scala
Show resolved
Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala
Outdated
Show resolved
Hide resolved
|
|
||
| def firstClosingFee(commitments: Commitments, localScriptPubkey: ByteVector, remoteScriptPubkey: ByteVector, feeEstimator: FeeEstimator, feeTargets: FeeTargets)(implicit log: LoggingAdapter): Satoshi = { | ||
| // we "MUST set fee_satoshis less than or equal to the base fee of the final commitment transaction" | ||
| val blockTarget = Math.max(feeTargets.mutualCloseBlockTarget, feeTargets.commitmentBlockTarget) |
There was a problem hiding this comment.
We need to compare feerates, not block targets.
There was a problem hiding this comment.
We are comparing feerates, this code is the result of adapting:
// no need to use a very high fee here, so we target 6 blocks; also, we "MUST set fee_satoshis less than or equal to the base fee of the final commitment transaction"
val feeratePerKw = Math.min(Globals.feeratesPerKw.get.blocks_6, commitments.localCommit.spec.feeratePerKw)
into
// we "MUST set fee_satoshis less than or equal to the base fee of the final commitment transaction"
val blockTarget = Math.max(feeTargets.mutualCloseBlockTarget, feeTargets.commitmentBlockTarget)
val feeratePerKw = feeEstimator.getFeeratePerKw(blockTarget)
It's just a different way to extract the feerate, note that the Math.min of the 2 feerates has become Math.max of the confirmation target because the higher the target the lower the feerate.
There was a problem hiding this comment.
I understand what you did, but it doesn't work: there is no guarantee that the resulting fee will be lesser than the one used in the last commitment, because fees may vary widely. We must compare to commitments.localCommit.spec.feeratePerKw.
There was a problem hiding this comment.
That's correct the resulting feerate must be compared with the one used in the commitment transaction and it's not the case currently.
There was a problem hiding this comment.
In 419bf60 i used Math.min(feeEstimator.getFeeratePerKw(blockTarget), commitments.localCommit.spec.feeratePerKw) to do the proper check.
There was a problem hiding this comment.
Right, but the line above with the max on block targets is misleading. This conveys the intent better:
val requestedFeerate = feeEstimator.getFeeratePerKw(feeTargets.mutualCloseBlockTarget)
// we "MUST set fee_satoshis less than or equal to the base fee of the final commitment transaction"
val feeratePerKw = Math.min(requestedFeerate, commitments.localCommit.spec.feeratePerKw)There was a problem hiding this comment.
Sounds good to me, but note that with this change if mutualCloseBlockTarget < commitmentBlockTarget we are (likely) to make a spec violation, I propose to have a check done in the NodeParam to avoid that.
There was a problem hiding this comment.
@pm47 Nevermind my comment above, the suggested change is correct.
eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala
Outdated
Show resolved
Hide resolved
Add a warning to commitment confirmation target configuration key Co-Authored-By: Pierre-Marie Padiou <pm47@users.noreply.github.com>
Codecov Report
@@ Coverage Diff @@
## master #1083 +/- ##
==========================================
+ Coverage 82.7% 82.76% +0.05%
==========================================
Files 101 101
Lines 7621 7652 +31
Branches 293 309 +16
==========================================
+ Hits 6303 6333 +30
- Misses 1318 1319 +1
|
# Conflicts: # eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala # eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala
|
Latest commit 1c21959 makes use of the |
8856051 to
1c21959
Compare
|
Summary of latest changes:
|
eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala
Outdated
Show resolved
Hide resolved
eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala
Outdated
Show resolved
Hide resolved
# Conflicts: # eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala
…he commitment fee and the configured fee target
…, move comment closer to relevant line.
| pingDisconnect: Boolean, | ||
| maxFeerateMismatch: Double, | ||
| updateFeeMinDiffRatio: Double, | ||
| onChainFeeConf: OnChainFeeConf, |
There was a problem hiding this comment.
Last nit: onChainFeeConf is lost in between peer-specific params, can you move it somewhere where it makes more sense?
36a8d5e to
8f1bcc0
Compare
Summary of changes
Rationale
Fee computation is a sensitive topic and directly affects the profitability of node operators, thus saving as much as possible is a priority and a nice-to-have feature. Currently eclair uses a very conservative estimation for most of the transactions, resulting in unnecessary high fees under certain scenarios; this PR aims at making this behavior configurable and give the node operators the opportunity to fine tune on chain transaction costs.
High level overview
There is a new configuration block that can be used to define default values for the block target used in the fee calculation for various transactions, currently supported are types: "funding", "commitment", "mutual-close" and "claim-main". Eclair will target the block number defined there when computing the fees, this means that according to the current feerate (still taken from the usual fee providers) we calculate the absolute transaction fee trying to target the confirmation on the N-th block where N is user defined default.
fundingis the block target for the funding transaction (you can override this when opening a channel)commitmentis the block target using when computing the commitment transaction, this is used when force closing the channel.mutual-closeblock target used when negotiating the closing transaction fee with the remote peer.claim-mainblock target is used to compute fee for the claim-main transaction, this used to spend our main channel output to our on-chain walletImplementation details
The
claim-mainblock target is applied to both the claim-main-delayed and claim-main transaction, those are logically equal and none of them is competing with the counterparty for confirmation.We still don't provide configurable block target for htlc-2nd stage transactions and main penalty transaction, this is due to the fact that in these scenarios we're competing with the counterparty and we
must act swiftly.
Transactions and block target
fundingcommitmentmutual-close( must be >=commitment)claim-mainclaim-mainclaim-mainFixes #1028