Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for zero-conf and scid-alias #2224

Merged
merged 55 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
bbd0b34
rename funding_locked -> channel_ready
pm47 Mar 29, 2022
244d6dd
add new options, reassign trampoline bit
pm47 Mar 30, 2022
838559e
add variations to channel type with alias/zeroconf
pm47 Mar 30, 2022
1e88cb6
set min_depth to 0 in zeroconf
pm47 Mar 29, 2022
54b91ea
add an alias tlv to channel_ready
pm47 Mar 29, 2022
7ae4b1a
store local/remote aliases in channel data
pm47 May 3, 2022
2be5699
fix race condition
pm47 May 17, 2022
dd23c14
bypass blockchain validation for local channels
pm47 May 17, 2022
93bbb8c
address review comments
pm47 Jun 1, 2022
c965f97
fix codec bug and add non-reg test
pm47 Jun 1, 2022
a8940d3
add test proving bug in scid selection for channel_update
pm47 Jun 2, 2022
cac1d22
simplify scid selection for channel_update
pm47 Jun 2, 2022
aab4f76
add test proving bug in rebroadcast
pm47 Jun 2, 2022
32a0d5a
fix rebroadcast bug
pm47 Jun 2, 2022
3aa0560
handle local node announcement synchronously
pm47 Jun 2, 2022
774432e
always re-send channel_update at reconnection for unannounced channels
pm47 Jun 2, 2022
93a3d7e
add channel relay tests
pm47 Jun 3, 2022
2cf1338
remove remaining triple equals
pm47 Jun 3, 2022
7a5a3df
fix rebase
pm47 Jun 3, 2022
a9e572f
fix bug with graph update when channel graduates from private to public
pm47 Jun 3, 2022
ecbcb58
factor channel-router integration test
pm47 Jun 3, 2022
c1fabe7
add integration tests for zero-conf
pm47 Jun 3, 2022
4d25535
fix bug created by de2dee374: need to populate meta for graduating ch…
pm47 Jun 5, 2022
58de78c
fix bug created by de2dee374: need to do watcher/db calls for local p…
pm47 Jun 5, 2022
ca67ffc
nit: comment formatting
pm47 Jun 5, 2022
19d2943
fix race condition in PaymentIntegrationTest
pm47 Jun 6, 2022
9743113
update scala plugins
pm47 Jun 6, 2022
391c8a2
factor ZeroConfAliasIntegrationSpec
pm47 Jun 6, 2022
e26420b
add unit test on scid_alias activation
pm47 Jun 6, 2022
a4c3ab4
added channel_type encoding tests with zeroconf/alias
pm47 Jun 6, 2022
14837e3
added roundtrip serialization test on channel_ready with alias
pm47 Jun 6, 2022
18a3e28
streamline channel_type handling in open api
pm47 Jun 6, 2022
7e41af2
(hopefully) fix race condition in ZeroConfAliasIntegrationSpec
pm47 Jun 6, 2022
1523c41
fix comment
pm47 Jun 6, 2022
0a5a239
force-close zero-conf channels if no remote_alias
pm47 Jun 8, 2022
9be02bf
support early channel_ready as funder
pm47 Jun 8, 2022
572136d
tentative race condition fix in MessageIntegrationSpec
pm47 Jun 8, 2022
a426e1b
emit TransactionConfirmed when funding txis deeply confirmed for zero…
pm47 Jun 8, 2022
34cc748
clean up the router scid map
pm47 Jun 8, 2022
896c4e5
increase timeout to encrypt bitcoin wallet in tests
pm47 Jun 9, 2022
31799b7
group all short ids in a class
pm47 Jun 9, 2022
0db76d4
fix scaladoc warnings
pm47 Jun 9, 2022
957f014
fix error: knownDirectSubclasses of RealShortChannelId observed befor…
pm47 Jun 9, 2022
db232e1
convert scid traits to case classes
pm47 Jun 10, 2022
c20f672
leverage 31799b7ae to simplify generation of routing hints
pm47 Jun 10, 2022
305124f
simplify scid.equals()
pm47 Jun 13, 2022
79ef2c3
Remove watch-confirmed with depth 0 in zero-conf (#2310)
t-bast Jun 13, 2022
189d101
Improve tests in #2224 (#2314)
t-bast Jun 14, 2022
b5f137f
implement waitFor with Thread.sleep
pm47 Jun 14, 2022
dcc5236
first draft of release notes
pm47 Jun 14, 2022
02bfd0f
test activation of zeroconf feature
pm47 Jun 14, 2022
a1ebd76
also remove real scid from the map on channel down
pm47 Jun 15, 2022
ac60f87
address review comments
pm47 Jun 15, 2022
4f6385b
fixup! test activation of zeroconf feature
pm47 Jun 15, 2022
04fc0e6
simplify and fix tests
pm47 Jun 15, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion docs/release-notes/eclair-vnext.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,64 @@

## Major changes

Dropped support for version 2 of Tor protocol. That means
### Add support for channel aliases and zeroconf channels

:information_source: Those features are only supported for channels of type `AnchorOutputsZeroFeeHtlcTx`, which is the
newest channel type and the one enabled by default. If you are opening a channel with a node that doesn't run Eclair,
make sure they support `option_anchors_zero_fee_htlc_tx`.

#### Channel aliases

Channel aliases offer a way to use arbitrary channel identifiers for routing. This feature improves privacy by not
leaking the funding transaction of the channel during payments.

This feature is enabled by default, but your peer has to support it too.

#### Zeroconf channels

Zeroconf channels make it possible to use a newly created channel before the funding tx is confirmed on the blockchain.

:warning: Zeroconf requires the fundee to trust the funder. For this reason it is disabled by default, and you should
only enable it on a peer-by-peer basis.

##### Enabling through features

Below is how to enable zeroconf with a given peer in `eclair.conf`. With this config, your node will _accept_ zeroconf channels from node `03864e...`.

```eclair.conf
override-init-features = [
{
nodeid = "03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f",
features = {
// these features need to be enabled
var_onion_optin = mandatory
payment_secret = mandatory
option_channel_type = optional
// dependencies of zeroconf
option_static_remotekey = optional
option_anchors_zero_fee_htlc_tx = optional
option_scid_alias = optional
// enable zeroconf
option_zeroconf = optional
}
}
]
```

Note that, as funder, Eclair will happily use an unconfirmed channel if the peer sends an early `channel_ready`, even if the `option_zeroconf` feature isn't enabled, as long as the peer provides a channel alias.

##### Enabling through channel type

You can enable `option_scid_alias` and `option_zeroconf` features by requesting them in the channel type, even if those options aren't enabled in your features.

Below is how you would request a zeroconf channel thhrough the command-line interface:
t-bast marked this conversation as resolved.
Show resolved Hide resolved
```shell
$ ./eclair-cli open --nodeId=03864e... --fundingSatoshis=100000 --channelType=anchor_outputs_zero_fee_htlc_tx+zeroconf
t-bast marked this conversation as resolved.
Show resolved Hide resolved
```

### Remove support for Tor v2

Dropped support for version 2 of Tor protocol. That means:

- Eclair can't open control connection to Tor daemon version 0.3.3.5 and earlier anymore
- Eclair can't create hidden services for Tor protocol v2 with newer versions of Tor daemon
Expand Down
6 changes: 5 additions & 1 deletion eclair-core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,13 @@ eclair {
option_dual_fund = disabled
option_onion_messages = optional
option_channel_type = optional
option_scid_alias = optional
option_payment_metadata = optional
trampoline_payment_prototype = disabled
// By enabling option_zeroconf, you will be trusting your peers as fundee. You will lose funds if they double spend
// their funding tx.
option_zeroconf = disabled
t-bast marked this conversation as resolved.
Show resolved Hide resolved
keysend = disabled
trampoline_payment_prototype = disabled
}
override-init-features = [ // optional per-node features
# {
Expand Down
2 changes: 2 additions & 0 deletions eclair-core/src/main/scala/fr/acinq/eclair/BlockHeight.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ case class BlockHeight(private val underlying: Long) extends Ordered[BlockHeight
def toInt: Int = underlying.toInt
def toLong: Long = underlying
def toDouble: Double = underlying.toDouble

override def toString() = underlying.toString
// @formatter:on
}

Expand Down
20 changes: 12 additions & 8 deletions eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,18 @@ class EclairImpl(appKit: Kit) extends Eclair with Logging {
override def open(nodeId: PublicKey, fundingAmount: Satoshi, pushAmount_opt: Option[MilliSatoshi], channelType_opt: Option[SupportedChannelType], fundingFeeratePerByte_opt: Option[FeeratePerByte], announceChannel_opt: Option[Boolean], openTimeout_opt: Option[Timeout])(implicit timeout: Timeout): Future[ChannelOpenResponse] = {
// we want the open timeout to expire *before* the default ask timeout, otherwise user will get a generic response
val openTimeout = openTimeout_opt.getOrElse(Timeout(20 seconds))
(appKit.switchboard ? Peer.OpenChannel(
remoteNodeId = nodeId,
fundingSatoshis = fundingAmount,
pushMsat = pushAmount_opt.getOrElse(0 msat),
channelType_opt = channelType_opt,
fundingTxFeeratePerKw_opt = fundingFeeratePerByte_opt.map(FeeratePerKw(_)),
channelFlags = announceChannel_opt.map(announceChannel => ChannelFlags(announceChannel = announceChannel)),
timeout_opt = Some(openTimeout))).mapTo[ChannelOpenResponse]
for {
_ <- Future.successful(0)
open = Peer.OpenChannel(
remoteNodeId = nodeId,
fundingSatoshis = fundingAmount,
pushMsat = pushAmount_opt.getOrElse(0 msat),
channelType_opt = channelType_opt,
fundingTxFeeratePerKw_opt = fundingFeeratePerByte_opt.map(FeeratePerKw(_)),
channelFlags = announceChannel_opt.map(announceChannel => ChannelFlags(announceChannel = announceChannel)),
timeout_opt = Some(openTimeout))
res <- (appKit.switchboard ? open).mapTo[ChannelOpenResponse]
} yield res
t-bast marked this conversation as resolved.
Show resolved Hide resolved
}

override def close(channels: List[ApiTypes.ChannelIdentifier], scriptPubKey_opt: Option[ByteVector], closingFeerates_opt: Option[ClosingFeerates])(implicit timeout: Timeout): Future[Map[ApiTypes.ChannelIdentifier, Either[Throwable, CommandResponse[CMD_CLOSE]]]] = {
Expand Down
16 changes: 14 additions & 2 deletions eclair-core/src/main/scala/fr/acinq/eclair/Features.scala
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,21 @@ object Features {
val mandatory = 44
}

case object ScidAlias extends Feature with InitFeature with NodeFeature with ChannelTypeFeature {
val rfcName = "option_scid_alias"
val mandatory = 46
}

case object PaymentMetadata extends Feature with InvoiceFeature {
val rfcName = "option_payment_metadata"
val mandatory = 48
}

case object ZeroConf extends Feature with InitFeature with NodeFeature with ChannelTypeFeature {
val rfcName = "option_zeroconf"
val mandatory = 50
}

case object KeySend extends Feature with NodeFeature {
val rfcName = "keysend"
val mandatory = 54
Expand Down Expand Up @@ -278,9 +288,11 @@ object Features {
DualFunding,
OnionMessages,
ChannelType,
ScidAlias,
PaymentMetadata,
TrampolinePaymentPrototype,
KeySend
ZeroConf,
KeySend,
TrampolinePaymentPrototype
)

// Features may depend on other features, as specified in Bolt 9.
Expand Down
63 changes: 44 additions & 19 deletions eclair-core/src/main/scala/fr/acinq/eclair/ShortChannelId.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,71 @@

package fr.acinq.eclair

/**
* A short channel id uniquely identifies a channel by the coordinates of its funding tx output in the blockchain.
* See BOLT 7: https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#requirements
*/
case class ShortChannelId(private val id: Long) extends Ordered[ShortChannelId] {

def toLong: Long = id

def blockHeight = ShortChannelId.blockHeight(this)
import fr.acinq.eclair.ShortChannelId.toShortId

override def toString: String = {
// @formatter:off
sealed trait ShortChannelId extends Ordered[ShortChannelId] {
def toLong: Long
// we use an unsigned long comparison here
override def compare(that: ShortChannelId): Int = (this.toLong + Long.MinValue).compareTo(that.toLong + Long.MinValue)
override def hashCode(): Int = toLong.hashCode()
override def equals(obj: Any): Boolean = obj match {
case scid: ShortChannelId => this.toLong.equals(scid.toLong)
case _ => false
}
def toCoordinatesString: String = {
val TxCoordinates(blockHeight, txIndex, outputIndex) = ShortChannelId.coordinates(this)
s"${blockHeight.toLong}x${txIndex}x$outputIndex"
}

// we use an unsigned long comparison here
override def compare(that: ShortChannelId): Int = (this.id + Long.MinValue).compareTo(that.id + Long.MinValue)
def toHex: String = s"0x${toLong.toHexString}"
}
/** Sometimes we don't know what a scid really is */
case class UnspecifiedShortChannelId(private val id: Long) extends ShortChannelId {
override def toLong: Long = id
override def toString: String = toCoordinatesString // for backwards compatibility, because ChannelUpdate have an unspecified scid
}
case class RealShortChannelId private(private val id: Long) extends ShortChannelId {
override def toLong: Long = id
override def toString: String = toCoordinatesString
def blockHeight: BlockHeight = ShortChannelId.blockHeight(this)
def outputIndex: Int = ShortChannelId.outputIndex(this)
}
case class Alias(private val id: Long) extends ShortChannelId {
override def toLong: Long = id
override def toString: String = toHex
}
// @formatter:on

object ShortChannelId {

def apply(s: String): ShortChannelId = s.split("x").toList match {
case blockHeight :: txIndex :: outputIndex :: Nil => ShortChannelId(toShortId(blockHeight.toInt, txIndex.toInt, outputIndex.toInt))
case blockHeight :: txIndex :: outputIndex :: Nil => UnspecifiedShortChannelId(toShortId(blockHeight.toInt, txIndex.toInt, outputIndex.toInt))
case _ => throw new IllegalArgumentException(s"Invalid short channel id: $s")
}

def apply(blockHeight: BlockHeight, txIndex: Int, outputIndex: Int): ShortChannelId = ShortChannelId(toShortId(blockHeight.toInt, txIndex, outputIndex))
def apply(l: Long): ShortChannelId = UnspecifiedShortChannelId(l)

def toShortId(blockHeight: Int, txIndex: Int, outputIndex: Int): Long = ((blockHeight & 0xFFFFFFL) << 40) | ((txIndex & 0xFFFFFFL) << 16) | (outputIndex & 0xFFFFL)

def generateLocalAlias(): Alias = Alias(System.nanoTime()) // TODO: fixme (duplicate, etc.)

@inline
def blockHeight(shortChannelId: ShortChannelId): BlockHeight = BlockHeight((shortChannelId.id >> 40) & 0xFFFFFF)
def blockHeight(shortChannelId: ShortChannelId): BlockHeight = BlockHeight((shortChannelId.toLong >> 40) & 0xFFFFFF)

@inline
def txIndex(shortChannelId: ShortChannelId): Int = ((shortChannelId.id >> 16) & 0xFFFFFF).toInt
def txIndex(shortChannelId: ShortChannelId): Int = ((shortChannelId.toLong >> 16) & 0xFFFFFF).toInt

@inline
def outputIndex(shortChannelId: ShortChannelId): Int = (shortChannelId.id & 0xFFFF).toInt
def outputIndex(shortChannelId: ShortChannelId): Int = (shortChannelId.toLong & 0xFFFF).toInt

def coordinates(shortChannelId: ShortChannelId): TxCoordinates = TxCoordinates(blockHeight(shortChannelId), txIndex(shortChannelId), outputIndex(shortChannelId))
}

/**
* A real short channel id uniquely identifies a channel by the coordinates of its funding tx output in the blockchain.
* See BOLT 7: https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#requirements
*/
object RealShortChannelId {
def apply(blockHeight: BlockHeight, txIndex: Int, outputIndex: Int): RealShortChannelId = RealShortChannelId(toShortId(blockHeight.toInt, txIndex, outputIndex))
}

case class TxCoordinates(blockHeight: BlockHeight, txIndex: Int, outputIndex: Int)
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private class BalanceActor(context: ActorContext[Command],
Metrics.GlobalBalanceDetailed.withTag(Tags.BalanceType, Tags.BalanceTypes.OnchainConfirmed).update(result.onChain.confirmed.toMilliBtc.toDouble)
Metrics.GlobalBalanceDetailed.withTag(Tags.BalanceType, Tags.BalanceTypes.OnchainUnconfirmed).update(result.onChain.unconfirmed.toMilliBtc.toDouble)
Metrics.GlobalBalanceDetailed.withTag(Tags.BalanceType, Tags.BalanceTypes.Offchain).withTag(Tags.OffchainState, Tags.OffchainStates.waitForFundingConfirmed).update(result.offChain.waitForFundingConfirmed.toMilliBtc.toDouble)
Metrics.GlobalBalanceDetailed.withTag(Tags.BalanceType, Tags.BalanceTypes.Offchain).withTag(Tags.OffchainState, Tags.OffchainStates.waitForFundingLocked).update(result.offChain.waitForFundingLocked.toMilliBtc.toDouble)
Metrics.GlobalBalanceDetailed.withTag(Tags.BalanceType, Tags.BalanceTypes.Offchain).withTag(Tags.OffchainState, Tags.OffchainStates.waitForChannelReady).update(result.offChain.waitForChannelReady.toMilliBtc.toDouble)
Metrics.GlobalBalanceDetailed.withTag(Tags.BalanceType, Tags.BalanceTypes.Offchain).withTag(Tags.OffchainState, Tags.OffchainStates.normal).update(result.offChain.normal.total.toMilliBtc.toDouble)
Metrics.GlobalBalanceDetailed.withTag(Tags.BalanceType, Tags.BalanceTypes.Offchain).withTag(Tags.OffchainState, Tags.OffchainStates.shutdown).update(result.offChain.shutdown.total.toMilliBtc.toDouble)
Metrics.GlobalBalanceDetailed.withTag(Tags.BalanceType, Tags.BalanceTypes.Offchain).withTag(Tags.OffchainState, Tags.OffchainStates.closingLocal).update(result.offChain.closing.localCloseBalance.total.toMilliBtc.toDouble)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ object CheckBalance {
* The overall balance among all channels in all states.
*/
case class OffChainBalance(waitForFundingConfirmed: Btc = 0.sat,
waitForFundingLocked: Btc = 0.sat,
waitForChannelReady: Btc = 0.sat,
normal: MainAndHtlcBalance = MainAndHtlcBalance(),
shutdown: MainAndHtlcBalance = MainAndHtlcBalance(),
negotiating: Btc = 0.sat,
closing: ClosingBalance = ClosingBalance(),
waitForPublishFutureCommitment: Btc = 0.sat) {
val total: Btc = waitForFundingConfirmed + waitForFundingLocked + normal.total + shutdown.total + negotiating + closing.total + waitForPublishFutureCommitment
val total: Btc = waitForFundingConfirmed + waitForChannelReady + normal.total + shutdown.total + negotiating + closing.total + waitForPublishFutureCommitment
}

def updateMainBalance(localCommit: LocalCommit): Btc => Btc = { v: Btc =>
Expand Down Expand Up @@ -201,7 +201,7 @@ object CheckBalance {
channels
.foldLeft(OffChainBalance()) {
case (r, d: DATA_WAIT_FOR_FUNDING_CONFIRMED) => r.modify(_.waitForFundingConfirmed).using(updateMainBalance(d.commitments.localCommit))
case (r, d: DATA_WAIT_FOR_FUNDING_LOCKED) => r.modify(_.waitForFundingLocked).using(updateMainBalance(d.commitments.localCommit))
case (r, d: DATA_WAIT_FOR_CHANNEL_READY) => r.modify(_.waitForChannelReady).using(updateMainBalance(d.commitments.localCommit))
case (r, d: DATA_NORMAL) => r.modify(_.normal).using(updateMainAndHtlcBalance(d.commitments, knownPreimages))
case (r, d: DATA_SHUTDOWN) => r.modify(_.shutdown).using(updateMainAndHtlcBalance(d.commitments, knownPreimages))
case (r, d: DATA_NEGOTIATING) => r.modify(_.negotiating).using(updateMainBalance(d.commitments.localCommit))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ object Monitoring {

object OffchainStates {
val waitForFundingConfirmed = "waitForFundingConfirmed"
val waitForFundingLocked = "waitForFundingLocked"
val waitForChannelReady = "waitForChannelReady"
val normal = "normal"
val shutdown = "shutdown"
val negotiating = "negotiating"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.blockchain.bitcoind.rpc.BitcoinCoreClient
import fr.acinq.eclair.blockchain.watchdogs.BlockchainWatchdog
import fr.acinq.eclair.wire.protocol.ChannelAnnouncement
import fr.acinq.eclair.{BlockHeight, KamonExt, NodeParams, ShortChannelId, TimestampSecond}
import fr.acinq.eclair.{BlockHeight, KamonExt, NodeParams, RealShortChannelId, TimestampSecond}

import java.util.concurrent.atomic.AtomicLong
import scala.concurrent.duration._
Expand Down Expand Up @@ -136,8 +136,8 @@ object ZmqWatcher {
/** This event is sent when a [[WatchSpentBasic]] condition is met. */
sealed trait WatchSpentBasicTriggered extends WatchTriggered

case class WatchExternalChannelSpent(replyTo: ActorRef[WatchExternalChannelSpentTriggered], txId: ByteVector32, outputIndex: Int, shortChannelId: ShortChannelId) extends WatchSpentBasic[WatchExternalChannelSpentTriggered]
case class WatchExternalChannelSpentTriggered(shortChannelId: ShortChannelId) extends WatchSpentBasicTriggered
case class WatchExternalChannelSpent(replyTo: ActorRef[WatchExternalChannelSpentTriggered], txId: ByteVector32, outputIndex: Int, shortChannelId: RealShortChannelId) extends WatchSpentBasic[WatchExternalChannelSpentTriggered]
case class WatchExternalChannelSpentTriggered(shortChannelId: RealShortChannelId) extends WatchSpentBasicTriggered

case class WatchFundingSpent(replyTo: ActorRef[WatchFundingSpentTriggered], txId: ByteVector32, outputIndex: Int, hints: Set[ByteVector32]) extends WatchSpent[WatchFundingSpentTriggered]
case class WatchFundingSpentTriggered(spendingTx: Transaction) extends WatchSpentTriggered
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ case class FeerateTolerance(ratioLow: Double, ratioHigh: Double, anchorOutputMax
channelType match {
case ChannelTypes.Standard | ChannelTypes.StaticRemoteKey =>
proposedFeerate < networkFeerate * ratioLow || networkFeerate * ratioHigh < proposedFeerate
case ChannelTypes.AnchorOutputs | ChannelTypes.AnchorOutputsZeroFeeHtlcTx =>
case ChannelTypes.AnchorOutputs | _: ChannelTypes.AnchorOutputsZeroFeeHtlcTx =>
// when using anchor outputs, we allow any feerate: fees will be set with CPFP and RBF at broadcast time
false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ object BlockchainWatchdog {
case CheckLatestHeaders(blockHeight) =>
val id = UUID.randomUUID()
if (headersOverDnsEnabled) {
context.spawn(HeadersOverDns(nodeParams.chainHash, blockHeight), s"${HeadersOverDns.Source}-${blockHeight.toLong}-$id") ! HeadersOverDns.CheckLatestHeaders(context.self)
context.spawn(HeadersOverDns(nodeParams.chainHash, blockHeight), s"${HeadersOverDns.Source}-${blockHeight}-$id") ! HeadersOverDns.CheckLatestHeaders(context.self)
}
explorers.foreach { explorer =>
context.spawn(ExplorerApi(nodeParams.chainHash, blockHeight, explorer), s"${explorer.name}-${blockHeight.toLong}-$id") ! ExplorerApi.CheckLatestHeaders(context.self)
context.spawn(ExplorerApi(nodeParams.chainHash, blockHeight, explorer), s"${explorer.name}-${blockHeight}-$id") ! ExplorerApi.CheckLatestHeaders(context.self)
}
Behaviors.same
case headers@LatestHeaders(blockHeight, blockHeaders, source) =>
Expand Down
Loading