Skip to content

Commit

Permalink
Correctly set gossip sync_complete (#1668)
Browse files Browse the repository at this point in the history
We are restoring the previous behavior of using the `sync_complete` field
to signal the end of a `channel_range_query` sync.

The first step is to correctly set that field, before we can read it and
interpret it to mark the end of sync.

See lightning/bolts#826
  • Loading branch information
t-bast committed Feb 15, 2021
1 parent 72179de commit fdeb3ce
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 54 deletions.
16 changes: 9 additions & 7 deletions eclair-core/src/main/scala/fr/acinq/eclair/router/Sync.scala
Expand Up @@ -80,8 +80,9 @@ object Sync {
log.info("replying with {} items for range=({}, {})", shortChannelIds.size, q.firstBlockNum, q.numberOfBlocks)
val chunks = split(shortChannelIds, q.firstBlockNum, q.numberOfBlocks, routerConf.channelRangeChunkSize)
Metrics.QueryChannelRange.Replies.withoutTags().record(chunks.size)
chunks.foreach { chunk =>
val reply = buildReplyChannelRange(chunk, q.chainHash, routerConf.encodingType, q.queryFlags_opt, channels)
chunks.zipWithIndex.foreach { case (chunk, i) =>
val syncComplete = i == chunks.size - 1
val reply = buildReplyChannelRange(chunk, syncComplete, q.chainHash, routerConf.encodingType, q.queryFlags_opt, channels)
origin.peerConnection ! reply
Metrics.ReplyChannelRange.Blocks.withTag(Tags.Direction, Tags.Directions.Outgoing).record(reply.numberOfBlocks)
Metrics.ReplyChannelRange.ShortChannelIds.withTag(Tags.Direction, Tags.Directions.Outgoing).record(reply.shortChannelIds.array.size)
Expand Down Expand Up @@ -392,12 +393,13 @@ object Sync {

case class ShortChannelIdsChunk(firstBlock: Long, numBlocks: Long, shortChannelIds: List[ShortChannelId]) {
/**
*
* @param maximumSize maximum size of the short channel ids list
* @return a chunk with at most `maximumSize` ids
*/
def enforceMaximumSize(maximumSize: Int) = {
if (shortChannelIds.size <= maximumSize) this else {
def enforceMaximumSize(maximumSize: Int): ShortChannelIdsChunk = {
if (shortChannelIds.size <= maximumSize) {
this
} else {
// we use a random offset here, so even if shortChannelIds.size is much bigger than maximumSize (which should
// not happen) peers will eventually receive info about all channels in this chunk
val offset = Random.nextInt(shortChannelIds.size - maximumSize + 1)
Expand Down Expand Up @@ -480,7 +482,7 @@ object Sync {
* @param channels channels map
* @return a ReplyChannelRange object
*/
def buildReplyChannelRange(chunk: ShortChannelIdsChunk, chainHash: ByteVector32, defaultEncoding: EncodingType, queryFlags_opt: Option[QueryChannelRangeTlv.QueryFlags], channels: SortedMap[ShortChannelId, PublicChannel]): ReplyChannelRange = {
def buildReplyChannelRange(chunk: ShortChannelIdsChunk, syncComplete: Boolean, chainHash: ByteVector32, defaultEncoding: EncodingType, queryFlags_opt: Option[QueryChannelRangeTlv.QueryFlags], channels: SortedMap[ShortChannelId, PublicChannel]): ReplyChannelRange = {
val encoding = if (chunk.shortChannelIds.isEmpty) EncodingType.UNCOMPRESSED else defaultEncoding
val (timestamps, checksums) = queryFlags_opt match {
case Some(extension) if extension.wantChecksums | extension.wantTimestamps =>
Expand All @@ -492,7 +494,7 @@ object Sync {
case _ => (None, None)
}
ReplyChannelRange(chainHash, chunk.firstBlock, chunk.numBlocks,
complete = 1,
syncComplete = if (syncComplete) 1 else 0,
shortChannelIds = EncodedShortChannelIds(encoding, chunk.shortChannelIds),
timestamps = timestamps,
checksums = checksums)
Expand Down
Expand Up @@ -16,9 +16,6 @@

package fr.acinq.eclair.wire

import java.net.{Inet4Address, Inet6Address, InetAddress, InetSocketAddress}
import java.nio.charset.StandardCharsets

import com.google.common.base.Charsets
import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey}
import fr.acinq.bitcoin.{ByteVector32, ByteVector64, Satoshi}
Expand All @@ -27,6 +24,8 @@ import fr.acinq.eclair.router.Announcements
import fr.acinq.eclair.{CltvExpiry, CltvExpiryDelta, Features, MilliSatoshi, ShortChannelId, UInt64}
import scodec.bits.ByteVector

import java.net.{Inet4Address, Inet6Address, InetAddress, InetSocketAddress}
import java.nio.charset.StandardCharsets
import scala.util.Try

/**
Expand Down Expand Up @@ -246,27 +245,17 @@ case class EncodedShortChannelIds(encoding: EncodingType, array: List[ShortChann
override def toString: String = s"EncodedShortChannelIds($encoding,${array.headOption.getOrElse("")}->${array.lastOption.getOrElse("")} size=${array.size})"
}

case class QueryShortChannelIds(chainHash: ByteVector32,
shortChannelIds: EncodedShortChannelIds,
tlvStream: TlvStream[QueryShortChannelIdsTlv] = TlvStream.empty) extends RoutingMessage with HasChainHash {
case class QueryShortChannelIds(chainHash: ByteVector32, shortChannelIds: EncodedShortChannelIds, tlvStream: TlvStream[QueryShortChannelIdsTlv] = TlvStream.empty) extends RoutingMessage with HasChainHash {
val queryFlags_opt: Option[QueryShortChannelIdsTlv.EncodedQueryFlags] = tlvStream.get[QueryShortChannelIdsTlv.EncodedQueryFlags]
}

case class ReplyShortChannelIdsEnd(chainHash: ByteVector32, complete: Byte) extends RoutingMessage with HasChainHash

case class QueryChannelRange(chainHash: ByteVector32,
firstBlockNum: Long,
numberOfBlocks: Long,
tlvStream: TlvStream[QueryChannelRangeTlv] = TlvStream.empty) extends RoutingMessage {
case class QueryChannelRange(chainHash: ByteVector32, firstBlockNum: Long, numberOfBlocks: Long, tlvStream: TlvStream[QueryChannelRangeTlv] = TlvStream.empty) extends RoutingMessage {
val queryFlags_opt: Option[QueryChannelRangeTlv.QueryFlags] = tlvStream.get[QueryChannelRangeTlv.QueryFlags]
}

case class ReplyChannelRange(chainHash: ByteVector32,
firstBlockNum: Long,
numberOfBlocks: Long,
complete: Byte,
shortChannelIds: EncodedShortChannelIds,
tlvStream: TlvStream[ReplyChannelRangeTlv] = TlvStream.empty) extends RoutingMessage {
case class ReplyChannelRange(chainHash: ByteVector32, firstBlockNum: Long, numberOfBlocks: Long, syncComplete: Byte, shortChannelIds: EncodedShortChannelIds, tlvStream: TlvStream[ReplyChannelRangeTlv] = TlvStream.empty) extends RoutingMessage {
val timestamps_opt: Option[ReplyChannelRangeTlv.EncodedTimestamps] = tlvStream.get[ReplyChannelRangeTlv.EncodedTimestamps]
val checksums_opt: Option[ReplyChannelRangeTlv.EncodedChecksums] = tlvStream.get[ReplyChannelRangeTlv.EncodedChecksums]
}
Expand All @@ -275,13 +264,13 @@ object ReplyChannelRange {
def apply(chainHash: ByteVector32,
firstBlockNum: Long,
numberOfBlocks: Long,
complete: Byte,
syncComplete: Byte,
shortChannelIds: EncodedShortChannelIds,
timestamps: Option[ReplyChannelRangeTlv.EncodedTimestamps],
checksums: Option[ReplyChannelRangeTlv.EncodedChecksums]): ReplyChannelRange = {
timestamps.foreach(ts => require(ts.timestamps.length == shortChannelIds.array.length))
checksums.foreach(cs => require(cs.checksums.length == shortChannelIds.array.length))
new ReplyChannelRange(chainHash, firstBlockNum, numberOfBlocks, complete, shortChannelIds, TlvStream(timestamps.toList ::: checksums.toList))
new ReplyChannelRange(chainHash, firstBlockNum, numberOfBlocks, syncComplete, shortChannelIds, TlvStream(timestamps.toList ::: checksums.toList))
}
}

Expand Down
Expand Up @@ -20,6 +20,7 @@ import fr.acinq.bitcoin.{Block, ByteVector32, SatoshiLong}
import fr.acinq.eclair.router.Router.{ChannelMeta, PublicChannel}
import fr.acinq.eclair.router.Sync._
import fr.acinq.eclair.wire.QueryChannelRangeTlv.QueryFlags
import fr.acinq.eclair.wire.QueryShortChannelIdsTlv.QueryFlagType._
import fr.acinq.eclair.wire.ReplyChannelRangeTlv._
import fr.acinq.eclair.wire.{EncodedShortChannelIds, EncodingType, ReplyChannelRange}
import fr.acinq.eclair.{MilliSatoshiLong, ShortChannelId, randomKey}
Expand Down Expand Up @@ -83,7 +84,6 @@ class ChannelRangeQueriesSpec extends AnyFunSuite {
}

test("compute flag tests") {

val now = System.currentTimeMillis / 1000

val a = randomKey.publicKey
Expand All @@ -96,7 +96,6 @@ class ChannelRangeQueriesSpec extends AnyFunSuite {
val d = randomKey.publicKey
val cd = RouteCalculationSpec.makeChannel(451312L, c, d)
val ucd1 = RouteCalculationSpec.makeUpdateShort(cd.shortChannelId, cd.nodeId1, cd.nodeId2, 0 msat, 0, timestamp = now)
val ucd2 = RouteCalculationSpec.makeUpdateShort(cd.shortChannelId, cd.nodeId2, cd.nodeId1, 0 msat, 0, timestamp = now)

val e = randomKey.publicKey
val f = randomKey.publicKey
Expand All @@ -107,30 +106,28 @@ class ChannelRangeQueriesSpec extends AnyFunSuite {
cd.shortChannelId -> PublicChannel(cd, ByteVector32.Zeroes, 0 sat, Some(ucd1), None, None)
)

import fr.acinq.eclair.wire.QueryShortChannelIdsTlv.QueryFlagType._

assert(getChannelDigestInfo(channels)(ab.shortChannelId) == (Timestamps(now, now), Checksums(1697591108L, 3692323747L)))

// no extended info but we know the channel: we ask for the updates
assert(computeFlag(channels)(ab.shortChannelId, None, None, false) === (INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2))
assert(computeFlag(channels)(ab.shortChannelId, None, None, true) === (INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
assert(computeFlag(channels)(ab.shortChannelId, None, None, includeNodeAnnouncements = false) === (INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2))
assert(computeFlag(channels)(ab.shortChannelId, None, None, includeNodeAnnouncements = true) === (INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
// same checksums, newer timestamps: we don't ask anything
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now + 1, now + 1)), Some(Checksums(1697591108L, 3692323747L)), true) === 0)
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now + 1, now + 1)), Some(Checksums(1697591108L, 3692323747L)), includeNodeAnnouncements = true) === 0)
// different checksums, newer timestamps: we ask for the updates
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now + 1, now)), Some(Checksums(154654604, 3692323747L)), true) === (INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now, now + 1)), Some(Checksums(1697591108L, 45664546)), true) === (INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now + 1, now + 1)), Some(Checksums(154654604, 45664546 + 6)), true) === (INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now + 1, now)), Some(Checksums(154654604, 3692323747L)), includeNodeAnnouncements = true) === (INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now, now + 1)), Some(Checksums(1697591108L, 45664546)), includeNodeAnnouncements = true) === (INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now + 1, now + 1)), Some(Checksums(154654604, 45664546 + 6)), includeNodeAnnouncements = true) === (INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
// different checksums, older timestamps: we don't ask anything
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now - 1, now)), Some(Checksums(154654604, 3692323747L)), true) === 0)
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now, now - 1)), Some(Checksums(1697591108L, 45664546)), true) === 0)
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now - 1, now - 1)), Some(Checksums(154654604, 45664546)), true) === 0)
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now - 1, now)), Some(Checksums(154654604, 3692323747L)), includeNodeAnnouncements = true) === 0)
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now, now - 1)), Some(Checksums(1697591108L, 45664546)), includeNodeAnnouncements = true) === 0)
assert(computeFlag(channels)(ab.shortChannelId, Some(Timestamps(now - 1, now - 1)), Some(Checksums(154654604, 45664546)), includeNodeAnnouncements = true) === 0)

// missing channel update: we ask for it
assert(computeFlag(channels)(cd.shortChannelId, Some(Timestamps(now, now)), Some(Checksums(3297511804L, 3297511804L)), true) === (INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
assert(computeFlag(channels)(cd.shortChannelId, Some(Timestamps(now, now)), Some(Checksums(3297511804L, 3297511804L)), includeNodeAnnouncements = true) === (INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))

// unknown channel: we ask everything
assert(computeFlag(channels)(ef.shortChannelId, None, None, false) === (INCLUDE_CHANNEL_ANNOUNCEMENT | INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2))
assert(computeFlag(channels)(ef.shortChannelId, None, None, true) === (INCLUDE_CHANNEL_ANNOUNCEMENT | INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
assert(computeFlag(channels)(ef.shortChannelId, None, None, includeNodeAnnouncements = false) === (INCLUDE_CHANNEL_ANNOUNCEMENT | INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2))
assert(computeFlag(channels)(ef.shortChannelId, None, None, includeNodeAnnouncements = true) === (INCLUDE_CHANNEL_ANNOUNCEMENT | INCLUDE_CHANNEL_UPDATE_1 | INCLUDE_CHANNEL_UPDATE_2 | INCLUDE_NODE_ANNOUNCEMENT_1 | INCLUDE_NODE_ANNOUNCEMENT_2))
}

def makeShortChannelIds(height: Int, count: Int): List[ShortChannelId] = {
Expand All @@ -149,7 +146,7 @@ class ChannelRangeQueriesSpec extends AnyFunSuite {
output.toList
}

def validate(chunk: ShortChannelIdsChunk) = {
def validate(chunk: ShortChannelIdsChunk): Unit = {
require(chunk.shortChannelIds.forall(keep(chunk.firstBlock, chunk.numBlocks, _)))
}

Expand Down Expand Up @@ -326,9 +323,9 @@ class ChannelRangeQueriesSpec extends AnyFunSuite {

test("enforce maximum size of short channel lists") {

def makeChunk(startBlock: Int, count: Int) = ShortChannelIdsChunk(startBlock, count, makeShortChannelIds(startBlock, count))
def makeChunk(startBlock: Int, count: Int): ShortChannelIdsChunk = ShortChannelIdsChunk(startBlock, count, makeShortChannelIds(startBlock, count))

def validate(before: ShortChannelIdsChunk, after: ShortChannelIdsChunk) = {
def validate(before: ShortChannelIdsChunk, after: ShortChannelIdsChunk): Unit = {
require(before.shortChannelIds.containsSlice(after.shortChannelIds))
require(after.shortChannelIds.size <= Sync.MAXIMUM_CHUNK_SIZE)
}
Expand All @@ -353,28 +350,28 @@ class ChannelRangeQueriesSpec extends AnyFunSuite {
{
val chunks = collection.mutable.ArrayBuffer.empty[ShortChannelIdsChunk]
// we select parameters to make sure that some chunks will have too many ids
for (i <- 0 until 100) chunks += makeChunk(0, Sync.MAXIMUM_CHUNK_SIZE - 500 + Random.nextInt(1000))
for (_ <- 0 until 100) chunks += makeChunk(0, Sync.MAXIMUM_CHUNK_SIZE - 500 + Random.nextInt(1000))
val pruned = enforceMaximumSize(chunks.toList)
validateChunks(chunks.toList, pruned)
}
}

test("do not encode empty lists as COMPRESSED_ZLIB") {
{
val reply = buildReplyChannelRange(ShortChannelIdsChunk(0, 42, Nil), Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_ALL)), SortedMap())
assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, 0L, 42L, 1.toByte, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, Nil)), Some(EncodedChecksums(Nil))))
val reply = buildReplyChannelRange(ShortChannelIdsChunk(0, 42, Nil), syncComplete = true, Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_ALL)), SortedMap())
assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, 0, 42L, 1, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, Nil)), Some(EncodedChecksums(Nil))))
}
{
val reply = buildReplyChannelRange(ShortChannelIdsChunk(0, 42, Nil), Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_TIMESTAMPS)), SortedMap())
assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, 0L, 42L, 1.toByte, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, Nil)), None))
val reply = buildReplyChannelRange(ShortChannelIdsChunk(0, 42, Nil), syncComplete = false, Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_TIMESTAMPS)), SortedMap())
assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, 0, 42L, 0, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, Nil)), None))
}
{
val reply = buildReplyChannelRange(ShortChannelIdsChunk(0, 42, Nil), Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_CHECKSUMS)), SortedMap())
assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, 0L, 42L, 1.toByte, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), None, Some(EncodedChecksums(Nil))))
val reply = buildReplyChannelRange(ShortChannelIdsChunk(0, 42, Nil), syncComplete = false, Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_CHECKSUMS)), SortedMap())
assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, 0, 42L, 0, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), None, Some(EncodedChecksums(Nil))))
}
{
val reply = buildReplyChannelRange(ShortChannelIdsChunk(0, 42, Nil), Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, None, SortedMap())
assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, 0L, 42L, 1.toByte, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), None, None))
val reply = buildReplyChannelRange(ShortChannelIdsChunk(0, 42, Nil), syncComplete = true, Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, None, SortedMap())
assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, 0, 42L, 1, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), None, None))
}
}
}
Expand Up @@ -92,6 +92,8 @@ class RoutingSyncSpec extends TestKitBaseClass with AnyFunSuiteLike with Paralle
val rcrs = pipe.receiveWhile() {
case rcr: ReplyChannelRange => rcr
}
rcrs.dropRight(1).foreach(rcr => assert(rcr.syncComplete == 0))
assert(rcrs.last.syncComplete == 1)
pipe.expectMsgType[Data]
rcrs.foreach(rcr => pipe.send(src, PeerRoutingMessage(pipe.ref, tgtId, rcr)))
// then src will now query announcements
Expand Down Expand Up @@ -297,7 +299,7 @@ class RoutingSyncSpec extends TestKitBaseClass with AnyFunSuiteLike with Paralle
assert(!router.stateData.sync.contains(remoteNodeId))

// we didn't send a corresponding query_channel_range, but peer sends us a reply_channel_range
val unsolicitedBlocks = ReplyChannelRange(params.chainHash, 10, 5, 1, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, fakeRoutingInfo.take(5).keys.toList), None, None)
val unsolicitedBlocks = ReplyChannelRange(params.chainHash, 10, 5, 0, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, fakeRoutingInfo.take(5).keys.toList), None, None)
peerConnection.send(router, PeerRoutingMessage(peerConnection.ref, remoteNodeId, unsolicitedBlocks))

// it will be simply ignored
Expand Down

0 comments on commit fdeb3ce

Please sign in to comment.