@@ -21,9 +21,9 @@ import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
2121import fr .acinq .bitcoin .scalacompat .{Block , BlockHash , Crypto , Satoshi , SatoshiLong }
2222import fr .acinq .eclair .Setup .Seeds
2323import fr .acinq .eclair .blockchain .fee ._
24- import fr .acinq .eclair .channel .ChannelFlags
2524import fr .acinq .eclair .channel .fsm .Channel
2625import fr .acinq .eclair .channel .fsm .Channel .{BalanceThreshold , ChannelConf , UnhandledExceptionStrategy }
26+ import fr .acinq .eclair .channel .{ChannelFlags , ChannelTypes }
2727import fr .acinq .eclair .crypto .Noise .KeyPair
2828import fr .acinq .eclair .crypto .keymanager .{ChannelKeyManager , NodeKeyManager , OnChainKeyManager }
2929import fr .acinq .eclair .db ._
@@ -36,6 +36,7 @@ import fr.acinq.eclair.router.Graph.{HeuristicsConstants, WeightRatios}
3636import fr .acinq .eclair .router .Router ._
3737import fr .acinq .eclair .router .{Graph , PathFindingExperimentConf }
3838import fr .acinq .eclair .tor .Socks5ProxyParams
39+ import fr .acinq .eclair .transactions .Transactions
3940import fr .acinq .eclair .wire .protocol ._
4041import grizzled .slf4j .Logging
4142import scodec .bits .ByteVector
@@ -57,7 +58,7 @@ case class NodeParams(nodeKeyManager: NodeKeyManager,
5758 onChainKeyManager_opt : Option [OnChainKeyManager ],
5859 instanceId : UUID , // a unique instance ID regenerated after each restart
5960 private val blockHeight : AtomicLong ,
60- private val feerates : AtomicReference [FeeratesPerKw ],
61+ private val bitcoinCoreFeerates : AtomicReference [FeeratesPerKw ],
6162 alias : String ,
6263 color : Color ,
6364 publicAddresses : List [NodeAddress ],
@@ -102,13 +103,34 @@ case class NodeParams(nodeKeyManager: NodeKeyManager,
102103
103104 def currentBlockHeight : BlockHeight = BlockHeight (blockHeight.get)
104105
105- def currentFeerates : FeeratesPerKw = feerates .get()
106+ def currentBitcoinCoreFeerates : FeeratesPerKw = bitcoinCoreFeerates .get()
106107
107108 /** Only to be used in tests. */
108- def setFeerates (value : FeeratesPerKw ): Unit = feerates .set(value)
109+ def setBitcoinCoreFeerates (value : FeeratesPerKw ): Unit = bitcoinCoreFeerates .set(value)
109110
110111 /** Returns the features that should be used in our init message with the given peer. */
111112 def initFeaturesFor (nodeId : PublicKey ): Features [InitFeature ] = overrideInitFeatures.getOrElse(nodeId, features).initFeatures()
113+
114+ /** Returns the feerates we'd like our peer to use when funding channels. */
115+ def recommendedFeerates (remoteNodeId : PublicKey , localFeatures : Features [InitFeature ], remoteFeatures : Features [InitFeature ]): RecommendedFeerates = {
116+ val feerateTolerance = onChainFeeConf.feerateToleranceFor(remoteNodeId)
117+ val fundingFeerate = onChainFeeConf.getFundingFeerate(currentBitcoinCoreFeerates)
118+ val fundingRange = RecommendedFeeratesTlv .FundingFeerateRange (
119+ min = fundingFeerate * feerateTolerance.ratioLow,
120+ max = fundingFeerate * feerateTolerance.ratioHigh,
121+ )
122+ // We use the most likely commitment format, even though there is no guarantee that this is the one that will be used.
123+ val commitmentFormat = ChannelTypes .defaultFromFeatures(localFeatures, remoteFeatures, announceChannel = false ).commitmentFormat
124+ val commitmentFeerate = onChainFeeConf.getCommitmentFeerate(currentBitcoinCoreFeerates, remoteNodeId, commitmentFormat, channelConf.minFundingPrivateSatoshis)
125+ val commitmentRange = RecommendedFeeratesTlv .CommitmentFeerateRange (
126+ min = commitmentFeerate * feerateTolerance.ratioLow,
127+ max = commitmentFormat match {
128+ case Transactions .DefaultCommitmentFormat => commitmentFeerate * feerateTolerance.ratioHigh
129+ case _ : Transactions .AnchorOutputsCommitmentFormat => (commitmentFeerate * feerateTolerance.ratioHigh).max(feerateTolerance.anchorOutputMaxCommitFeerate)
130+ },
131+ )
132+ RecommendedFeerates (chainHash, fundingFeerate, commitmentFeerate, TlvStream (fundingRange, commitmentRange))
133+ }
112134}
113135
114136case class PaymentFinalExpiryConf (min : CltvExpiryDelta , max : CltvExpiryDelta ) {
@@ -219,7 +241,7 @@ object NodeParams extends Logging {
219241
220242 def makeNodeParams (config : Config , instanceId : UUID ,
221243 nodeKeyManager : NodeKeyManager , channelKeyManager : ChannelKeyManager , onChainKeyManager_opt : Option [OnChainKeyManager ],
222- torAddress_opt : Option [NodeAddress ], database : Databases , blockHeight : AtomicLong , feerates : AtomicReference [FeeratesPerKw ],
244+ torAddress_opt : Option [NodeAddress ], database : Databases , blockHeight : AtomicLong , bitcoinCoreFeerates : AtomicReference [FeeratesPerKw ],
223245 pluginParams : Seq [PluginParams ] = Nil ): NodeParams = {
224246 // check configuration for keys that have been renamed
225247 val deprecatedKeyPaths = Map (
@@ -513,7 +535,7 @@ object NodeParams extends Logging {
513535 onChainKeyManager_opt = onChainKeyManager_opt,
514536 instanceId = instanceId,
515537 blockHeight = blockHeight,
516- feerates = feerates ,
538+ bitcoinCoreFeerates = bitcoinCoreFeerates ,
517539 alias = nodeAlias,
518540 color = Color (color(0 ), color(1 ), color(2 )),
519541 publicAddresses = addresses,
0 commit comments