From f66d58f1f76b4903366622d4beeae722b68ad1d7 Mon Sep 17 00:00:00 2001 From: sstone Date: Mon, 7 Oct 2019 15:32:47 +0200 Subject: [PATCH 1/2] Activate extended channnel range queries By default we now set the `gossip_queries_ex` feature bit. We also change how we compare feature bits, and will use channel queries (or extended queries) only if the corresponding feature bit is set in both local and remote init messages. --- eclair-core/src/main/resources/reference.conf | 2 +- .../main/scala/fr/acinq/eclair/Features.scala | 3 ++ .../main/scala/fr/acinq/eclair/io/Peer.scala | 44 +++++++++---------- .../scala/fr/acinq/eclair/TestConstants.scala | 2 +- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/eclair-core/src/main/resources/reference.conf b/eclair-core/src/main/resources/reference.conf index 8f441fe41b..f27a672130 100644 --- a/eclair-core/src/main/resources/reference.conf +++ b/eclair-core/src/main/resources/reference.conf @@ -36,7 +36,7 @@ eclair { node-color = "49daaa" global-features = "0200" // variable_length_onion - local-features = "8a" // initial_routing_sync + option_data_loss_protect + option_channel_range_queries + local-features = "088a" // initial_routing_sync + option_data_loss_protect + option_channel_range_queries override-features = [ // optional per-node features # { # nodeid = "02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala b/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala index 145961614c..8fc1b27901 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala @@ -32,6 +32,9 @@ object Features { val CHANNEL_RANGE_QUERIES_BIT_MANDATORY = 6 val CHANNEL_RANGE_QUERIES_BIT_OPTIONAL = 7 + val CHANNEL_RANGE_QUERIES_EX_BIT_MANDATORY = 10 + val CHANNEL_RANGE_QUERIES_EX_BIT_OPTIONAL = 11 + val VARIABLE_LENGTH_ONION_MANDATORY = 8 val VARIABLE_LENGTH_ONION_OPTIONAL = 9 diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala index bad45c0681..0aee107c95 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala @@ -23,7 +23,7 @@ import akka.event.Logging.MDC import akka.util.Timeout import com.google.common.net.HostAndPort import fr.acinq.bitcoin.Crypto.PublicKey -import fr.acinq.bitcoin.{Block, ByteVector32, DeterministicWallet, Satoshi} +import fr.acinq.bitcoin.{ByteVector32, DeterministicWallet, Satoshi} import fr.acinq.eclair.blockchain.EclairWallet import fr.acinq.eclair.channel._ import fr.acinq.eclair.crypto.TransportHandler @@ -132,38 +132,36 @@ class Peer(val nodeParams: NodeParams, remoteNodeId: PublicKey, authenticator: A when(INITIALIZING) { case Event(remoteInit: wire.Init, d: InitializingData) => d.transport ! TransportHandler.ReadAck(remoteInit) - val remoteHasInitialRoutingSync = Features.hasFeature(remoteInit.localFeatures, Features.INITIAL_ROUTING_SYNC_BIT_OPTIONAL) - val remoteHasChannelRangeQueriesOptional = Features.hasFeature(remoteInit.localFeatures, Features.CHANNEL_RANGE_QUERIES_BIT_OPTIONAL) - val remoteHasChannelRangeQueriesMandatory = Features.hasFeature(remoteInit.localFeatures, Features.CHANNEL_RANGE_QUERIES_BIT_MANDATORY) + log.info(s"peer is using globalFeatures=${remoteInit.globalFeatures.toBin} and localFeatures=${remoteInit.localFeatures.toBin}") - log.info(s"$remoteNodeId has features: initialRoutingSync=$remoteHasInitialRoutingSync channelRangeQueriesOptional=$remoteHasChannelRangeQueriesOptional channelRangeQueriesMandatory=$remoteHasChannelRangeQueriesMandatory") + if (Features.areSupported(remoteInit.localFeatures)) { d.origin_opt.foreach(origin => origin ! "connected") - if (remoteHasInitialRoutingSync) { - if (remoteHasChannelRangeQueriesOptional || remoteHasChannelRangeQueriesMandatory) { - // if they support channel queries we do nothing, they will send us their filters - log.info("peer has set initial routing sync and supports channel range queries, we do nothing (they will send us a query)") - } else { - // "old" nodes, do as before - log.info("peer requested a full routing table dump") - router ! GetRoutingState - } - } - if (remoteHasChannelRangeQueriesOptional || remoteHasChannelRangeQueriesMandatory) { - // if they support channel queries, always ask for their filter - // TODO: for now we do not activate extended queries on mainnet - val flags_opt = nodeParams.chainHash match { - case Block.RegtestGenesisBlock.hash | Block.TestnetGenesisBlock.hash => - Some(QueryChannelRangeTlv.QueryFlags(QueryChannelRangeTlv.QueryFlags.WANT_ALL)) - case _ => None - } + import Features._ + + def hasLocalFeature(bit: Int) = Features.hasFeature(d.localInit.localFeatures, bit) + + def hasRemoteFeature(bit: Int) = Features.hasFeature(remoteInit.localFeatures, bit) + + val canUseChannelRangeQueries = (hasLocalFeature(CHANNEL_RANGE_QUERIES_BIT_OPTIONAL) || hasLocalFeature(CHANNEL_RANGE_QUERIES_BIT_MANDATORY)) && (hasRemoteFeature(CHANNEL_RANGE_QUERIES_BIT_OPTIONAL) || hasRemoteFeature(CHANNEL_RANGE_QUERIES_BIT_MANDATORY)) + + val canUseChannelRangeQueriesEx = (hasLocalFeature(CHANNEL_RANGE_QUERIES_EX_BIT_OPTIONAL) || hasLocalFeature(CHANNEL_RANGE_QUERIES_EX_BIT_MANDATORY)) && (hasRemoteFeature(CHANNEL_RANGE_QUERIES_EX_BIT_OPTIONAL) || hasRemoteFeature(CHANNEL_RANGE_QUERIES_EX_BIT_MANDATORY)) + + if (canUseChannelRangeQueries || canUseChannelRangeQueriesEx) { + // if they support channel queries we don't send routing info yet, if they want it they will query us + // we will query them, using extended queries if supported + val flags_opt = if (canUseChannelRangeQueriesEx) Some(QueryChannelRangeTlv.QueryFlags(QueryChannelRangeTlv.QueryFlags.WANT_ALL)) else None if (nodeParams.syncWhitelist.isEmpty || nodeParams.syncWhitelist.contains(remoteNodeId)) { log.info(s"sending sync channel range query with flags_opt=$flags_opt") router ! SendChannelQuery(remoteNodeId, d.transport, flags_opt = flags_opt) } else { log.info("not syncing with this peer") } + } else if (hasRemoteFeature(INITIAL_ROUTING_SYNC_BIT_OPTIONAL)) { + // "old" nodes, do as before + log.info("peer requested a full routing table dump") + router ! GetRoutingState } // let's bring existing/requested channels online diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala b/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala index 757f37f368..f68d3575e8 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala @@ -71,7 +71,7 @@ object TestConstants { color = Color(1, 2, 3), publicAddresses = NodeAddress.fromParts("localhost", 9731).get :: Nil, globalFeatures = globalFeatures, - localFeatures = ByteVector(0), + localFeatures = ByteVector.fromValidHex("088a"), overrideFeatures = Map.empty, syncWhitelist = Set.empty, dustLimit = 1100 sat, From adca8435b729bdd646f0f0b24ae5d72a7d98570c Mon Sep 17 00:00:00 2001 From: sstone Date: Mon, 7 Oct 2019 16:23:46 +0200 Subject: [PATCH 2/2] Reference.conf: update comment --- eclair-core/src/main/resources/reference.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eclair-core/src/main/resources/reference.conf b/eclair-core/src/main/resources/reference.conf index f27a672130..0d31877937 100644 --- a/eclair-core/src/main/resources/reference.conf +++ b/eclair-core/src/main/resources/reference.conf @@ -36,7 +36,7 @@ eclair { node-color = "49daaa" global-features = "0200" // variable_length_onion - local-features = "088a" // initial_routing_sync + option_data_loss_protect + option_channel_range_queries + local-features = "088a" // initial_routing_sync + option_data_loss_protect + option_channel_range_queries + option_channel_range_queries_ex override-features = [ // optional per-node features # { # nodeid = "02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",