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

Activate extended channel range queries #1165

Merged
merged 2 commits into from
Oct 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion eclair-core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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 + option_channel_range_queries_ex
override-features = [ // optional per-node features
# {
# nodeid = "02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
Expand Down
3 changes: 3 additions & 0 deletions eclair-core/src/main/scala/fr/acinq/eclair/Features.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
44 changes: 21 additions & 23 deletions eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down