Remove support for zlib encoding for channel queries (#3263)
What changed, and why it matters
This commit removes the ability of the Eclair Lightning node to receive zlib-compressed channel-query data from peers. The Lightning protocol spec dropped zlib compression for these messages some time ago, and this change catches up by rejecting or ignoring compressed encodings. It is a hardening/cleanup change rather than a fix for an active vulnerability, though keeping a deprecated decompression path could in theory expose a node to memory or CPU issues if a peer sent malicious compressed data.
Treat as a routine spec-compliance cleanup. Operators should upgrade to avoid interoperability edge cases with peers that might still send compressed channel queries, and to remove the zlib parsing surface. No urgent mitigation is indicated by the commit itself. If an organization wants extra assurance, it could audit the removed zlib path for any latent parser weakness, but the commit provides no evidence of one.
Security signals we found
removal of deprecated zlib decompression path in network message parsing
spec-compliance hardening for Lightning routing protocol (gossip queries)
potential reduction of attack surface against compressed-payload parsing (e.g., memory/CPU amplification, though no specific bug is cited)
no CVE, advisory, or vendor security framing in commit message
Evidence from the diff
The patch deletes the COMPRESSED_ZLIB branch from EncodingType and from the scodec discriminators that decode EncodedShortChannelIds, EncodedTimestamps, and EncodedQueryFlags. It also updates tests and serialization codecs to use only UNCOMPRESSED. The previous code would still accept and zlib-decode incoming routing-query payloads; after the patch, any message using encoding type 1 will fail to decode. The commit message frames this as a follow-up to spec change lightning/bolts#981 and to PR #2244, not as a security fix.
Changed components
eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecs.scalaeclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scalaeclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/RoutingTlv.scalaeclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scalaInspect captured patch +24 / −104
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scala b/eclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scala
index 305b141..16fdea1 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scala
@@ -96,9 +96,7 @@ object EclairInternalsSerializer {
val syncConfCodec: Codec[Router.SyncConf] = (
("requestNodeAnnouncements" | bool(8)) ::
- ("encodingType" | discriminated[EncodingType].by(uint8)
- .typecase(0, provide(EncodingType.UNCOMPRESSED))
- .typecase(1, provide(EncodingType.COMPRESSED_ZLIB))) ::
+ ("encodingType" | discriminated[EncodingType].by(uint8).typecase(0, provide(EncodingType.UNCOMPRESSED))) ::
("channelRangeChunkSize" | int32) ::
("channelQueryChunkSize" | int32) ::
("peerLimit" | int32) ::
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecs.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecs.scala
index d8d5a32..181268e 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecs.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecs.scala
@@ -365,15 +365,8 @@ object LightningMessageCodecs {
("signature" | bytes64) ::
channelUpdateWitnessCodec).as[ChannelUpdate]
- val encodedShortChannelIdsCodec: Codec[EncodedShortChannelIds] =
- discriminated[EncodedShortChannelIds].by(byte)
- .\(0) {
- case a@EncodedShortChannelIds(_, Nil) => a // empty list is always encoded with encoding type 'uncompressed' for compatibility with other implementations
- case a@EncodedShortChannelIds(EncodingType.UNCOMPRESSED, _) => a
- }((provide[EncodingType](EncodingType.UNCOMPRESSED) :: list(realshortchannelid)).as[EncodedShortChannelIds])
- .\(1) {
- case a@EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, _) => a
- }((provide[EncodingType](EncodingType.COMPRESSED_ZLIB) :: zlib(list(realshortchannelid))).as[EncodedShortChannelIds])
+ val encodedShortChannelIdsCodec: Codec[EncodedShortChannelIds] = discriminated[EncodedShortChannelIds].by(byte)
+ .typecase(0, (provide[EncodingType](EncodingType.UNCOMPRESSED) :: list(realshortchannelid)).as[EncodedShortChannelIds])
val queryShortChannelIdsCodec: Codec[QueryShortChannelIds] = (
("chainHash" | blockHash) ::
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala
index 099ebaf..f4b60cc 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala
@@ -723,10 +723,10 @@ object ChannelUpdate {
}
// @formatter:off
+// NB: we use a trait here because we used to support zlib compression, which was removed from the spec in https://github.com/lightning/bolts/pull/981.
sealed trait EncodingType
object EncodingType {
case object UNCOMPRESSED extends EncodingType
- case object COMPRESSED_ZLIB extends EncodingType
}
// @formatter:on
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/RoutingTlv.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/RoutingTlv.scala
index d157a38..e130607 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/RoutingTlv.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/RoutingTlv.scala
@@ -136,7 +136,6 @@ object ReplyChannelRangeTlv {
val encodedTimestampsCodec: Codec[EncodedTimestamps] = tlvField(discriminated[EncodedTimestamps].by(byte)
.\(0) { case a@EncodedTimestamps(EncodingType.UNCOMPRESSED, _) => a }((provide[EncodingType](EncodingType.UNCOMPRESSED) :: list(timestampsCodec)).as[EncodedTimestamps])
- .\(1) { case a@EncodedTimestamps(EncodingType.COMPRESSED_ZLIB, _) => a }((provide[EncodingType](EncodingType.COMPRESSED_ZLIB) :: zlib(list(timestampsCodec))).as[EncodedTimestamps])
)
val checksumsCodec: Codec[Checksums] = (
@@ -189,8 +188,6 @@ object QueryShortChannelIdsTlv {
val encodedQueryFlagsCodec: Codec[EncodedQueryFlags] =
discriminated[EncodedQueryFlags].by(byte)
.\(0) { case a@EncodedQueryFlags(EncodingType.UNCOMPRESSED, _) => a }((provide[EncodingType](EncodingType.UNCOMPRESSED) :: list(varintoverflow)).as[EncodedQueryFlags])
- .\(1) { case a@EncodedQueryFlags(EncodingType.COMPRESSED_ZLIB, _) => a }((provide[EncodingType](EncodingType.COMPRESSED_ZLIB) :: zlib(list(varintoverflow))).as[EncodedQueryFlags])
-
val codec: Codec[TlvStream[QueryShortChannelIdsTlv]] = TlvCodecs.tlvStream(discriminated.by(varint)
.typecase(UInt64(1), tlvField[EncodedQueryFlags, EncodedQueryFlags](encodedQueryFlagsCodec))
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 0a8f0a0..3f6febd 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala
@@ -212,7 +212,7 @@ object TestConstants {
routerBroadcastInterval = 1 day, // "disables" rebroadcast
syncConf = Router.SyncConf(
requestNodeAnnouncements = true,
- encodingType = EncodingType.COMPRESSED_ZLIB,
+ encodingType = EncodingType.UNCOMPRESSED,
channelRangeChunkSize = 20,
channelQueryChunkSize = 5,
peerLimit = 10,
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/ChannelRangeQueriesSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/ChannelRangeQueriesSpec.scala
index 5917e75..e5799fa 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/router/ChannelRangeQueriesSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/ChannelRangeQueriesSpec.scala
@@ -17,14 +17,12 @@
package fr.acinq.eclair.router
import fr.acinq.bitcoin.scalacompat.{Block, ByteVector32, SatoshiLong, TxId}
-import fr.acinq.eclair.RealShortChannelId
import fr.acinq.eclair.router.Router.{ChannelMeta, PublicChannel}
import fr.acinq.eclair.router.Sync._
-import fr.acinq.eclair.wire.protocol.QueryChannelRangeTlv.QueryFlags
import fr.acinq.eclair.wire.protocol.QueryShortChannelIdsTlv.QueryFlagType._
import fr.acinq.eclair.wire.protocol.ReplyChannelRangeTlv._
import fr.acinq.eclair.wire.protocol.{EncodedShortChannelIds, EncodingType, LightningMessageCodecs, ReplyChannelRange}
-import fr.acinq.eclair.{BlockHeight, MilliSatoshiLong, ShortChannelId, TimestampSecond, TimestampSecondLong, randomKey}
+import fr.acinq.eclair.{BlockHeight, MilliSatoshiLong, RealShortChannelId, ShortChannelId, TimestampSecond, TimestampSecondLong, randomKey}
import org.scalatest.funsuite.AnyFunSuite
import scodec.bits.ByteVector
@@ -367,23 +365,4 @@ class ChannelRangeQueriesSpec extends AnyFunSuite {
assert(encoded.require.bytes.length <= 0xffff)
}
- test("do not encode empty lists as COMPRESSED_ZLIB") {
- {
- val reply = buildReplyChannelRange(ShortChannelIdsChunk(BlockHeight(0), 42, Nil), syncComplete = true, Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_ALL)), SortedMap())
- assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(0), 42L, 1, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, Nil)), Some(EncodedChecksums(Nil))))
- }
- {
- val reply = buildReplyChannelRange(ShortChannelIdsChunk(BlockHeight(0), 42, Nil), syncComplete = false, Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_TIMESTAMPS)), SortedMap())
- assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(0), 42L, 0, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, Nil)), None))
- }
- {
- val reply = buildReplyChannelRange(ShortChannelIdsChunk(BlockHeight(0), 42, Nil), syncComplete = false, Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, Some(QueryFlags(QueryFlags.WANT_CHECKSUMS)), SortedMap())
- assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(0), 42L, 0, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), None, Some(EncodedChecksums(Nil))))
- }
- {
- val reply = buildReplyChannelRange(ShortChannelIdsChunk(BlockHeight(0), 42, Nil), syncComplete = true, Block.RegtestGenesisBlock.hash, EncodingType.COMPRESSED_ZLIB, None, SortedMap())
- assert(reply == ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(0), 42L, 1, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, Nil), None, None))
- }
- }
-
}
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/ExtendedQueriesCodecsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/ExtendedQueriesCodecsSpec.scala
index d9e07d9..45bc861 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/ExtendedQueriesCodecsSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/ExtendedQueriesCodecsSpec.scala
@@ -35,15 +35,6 @@ class ExtendedQueriesCodecsSpec extends AnyFunSuite {
val decoded = encodedShortChannelIdsCodec.decode(encoded).require.value
assert(decoded == ids)
}
-
- {
- // encode/decode with encoding 'zlib'
- val ids = EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676)))
- val encoded = encodedShortChannelIdsCodec.encode(ids).require
- val decoded = encodedShortChannelIdsCodec.decode(encoded).require.value
- assert(decoded == ids)
- }
-
{
// encode/decode empty list with encoding 'uncompressed'
val ids = EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List.empty)
@@ -52,15 +43,6 @@ class ExtendedQueriesCodecsSpec extends AnyFunSuite {
val decoded = encodedShortChannelIdsCodec.decode(encoded).require.value
assert(decoded == ids)
}
-
- {
- // encode/decode empty list with encoding 'zlib'
- val ids = EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, List.empty)
- val encoded = encodedShortChannelIdsCodec.encode(ids).require
- assert(encoded.bytes == hex"00") // NB: empty list is always encoded with encoding type 'uncompressed'
- val decoded = encodedShortChannelIdsCodec.decode(encoded).require.value
- assert(decoded == EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List.empty))
- }
}
test("encode query_short_channel_ids (no optional data)") {
@@ -119,7 +101,7 @@ class ExtendedQueriesCodecsSpec extends AnyFunSuite {
BlockHeight(1), 100,
1.toByte,
EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))),
- Some(EncodedTimestamps(EncodingType.COMPRESSED_ZLIB, List(Timestamps(1 unixsec, 1 unixsec), Timestamps(2 unixsec, 2 unixsec), Timestamps(3 unixsec, 3 unixsec)))),
+ Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, List(Timestamps(1 unixsec, 1 unixsec), Timestamps(2 unixsec, 2 unixsec), Timestamps(3 unixsec, 3 unixsec)))),
None)
val encoded = replyChannelRangeCodec.encode(replyChannelRange).require
@@ -135,7 +117,7 @@ class ExtendedQueriesCodecsSpec extends AnyFunSuite {
EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))),
TlvStream(
Set[ReplyChannelRangeTlv](
- EncodedTimestamps(EncodingType.COMPRESSED_ZLIB, List(Timestamps(1 unixsec, 1 unixsec), Timestamps(2 unixsec, 2 unixsec), Timestamps(3 unixsec, 3 unixsec))),
+ EncodedTimestamps(EncodingType.UNCOMPRESSED, List(Timestamps(1 unixsec, 1 unixsec), Timestamps(2 unixsec, 2 unixsec), Timestamps(3 unixsec, 3 unixsec))),
EncodedChecksums(List(Checksums(1, 1), Checksums(2, 2), Checksums(3, 3)))
),
Set(GenericTlv(UInt64(7), ByteVector.fromValidHex("deadbeef")))
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecsSpec.scala
index 2d6cf5d..970f5d2 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecsSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/protocol/LightningMessageCodecsSpec.scala
@@ -720,59 +720,30 @@ class LightningMessageCodecsSpec extends AnyFunSuite {
test("non-reg encoding type") {
val refs = Map(
- hex"01050f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206001900000000000000008e0000000000003c69000000000045a6c4"
- -> QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), TlvStream.empty),
- hex"01050f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206001601789c636000833e08659309a65c971d0100126e02e3"
- -> QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), TlvStream.empty),
- hex"01050f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206001900000000000000008e0000000000003c69000000000045a6c4010400010204"
- -> QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), TlvStream(QueryShortChannelIdsTlv.EncodedQueryFlags(EncodingType.UNCOMPRESSED, List(1, 2, 4)))),
- hex"01050f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206001601789c636000833e08659309a65c971d0100126e02e3010c01789c6364620100000e0008"
- -> QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), TlvStream(QueryShortChannelIdsTlv.EncodedQueryFlags(EncodingType.COMPRESSED_ZLIB, List(1, 2, 4))))
+ // @formatter:off
+ hex"010506226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f001900000000000000008e0000000000003c69000000000045a6c4" -> QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), TlvStream.empty),
+ hex"010506226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f001900000000000000008e0000000000003c69000000000045a6c4010400010204" -> QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), TlvStream(QueryShortChannelIdsTlv.EncodedQueryFlags(EncodingType.UNCOMPRESSED, List(1, 2, 4)))),
+ // @formatter:on
)
-
- refs.forall {
- case (bin, obj) =>
- lightningMessageCodec.decode(bin.toBitVector).require.value == obj && lightningMessageCodec.encode(obj).require == bin.toBitVector
+ refs.foreach { case (bin, obj) =>
+ assert(lightningMessageCodec.decode(bin.toBitVector).require.value == obj)
+ assert(lightningMessageCodec.encode(obj).require == bin.toBitVector)
}
}
test("test vectors for extended channel queries ") {
val refs = Map(
- QueryChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(100000), 1500, TlvStream.empty) ->
- hex"010706226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000186a0000005dc",
- QueryChannelRange(Block.RegtestGenesisBlock.hash,
- BlockHeight(35000),
- 100,
- TlvStream(QueryChannelRangeTlv.QueryFlags(QueryChannelRangeTlv.QueryFlags.WANT_ALL))) ->
- hex"010706226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000088b800000064010103",
- ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(756230), 1500, 1,
- EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), None, None) ->
- hex"010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000b8a06000005dc01001900000000000000008e0000000000003c69000000000045a6c4",
- ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(1600), 110, 1,
- EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(265462))), None, None) ->
- hex"010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000006400000006e01001601789c636000833e08659309a65878be010010a9023a",
- ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(122334), 1500, 1,
- EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(12355), RealShortChannelId(489686), RealShortChannelId(4645313))),
- Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, List(Timestamps(164545 unixsec, 948165 unixsec), Timestamps(489645 unixsec, 4786864 unixsec), Timestamps(46456 unixsec, 9788415 unixsec)))),
- Some(EncodedChecksums(List(Checksums(1111, 2222), Checksums(3333, 4444), Checksums(5555, 6666))))) ->
- hex"010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f0001ddde000005dc01001900000000000000304300000000000778d6000000000046e1c1011900000282c1000e77c5000778ad00490ab00000b57800955bff031800000457000008ae00000d050000115c000015b300001a0a",
- ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(122334), 1500, 1,
- EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, List(RealShortChannelId(12355), RealShortChannelId(489686), RealShortChannelId(4645313))),
- Some(EncodedTimestamps(EncodingType.COMPRESSED_ZLIB, List(Timestamps(164545 unixsec, 948165 unixsec), Timestamps(489645 unixsec, 4786864 unixsec), Timestamps(46456 unixsec, 9788415 unixsec)))),
- Some(EncodedChecksums(List(Checksums(1111, 2222), Checksums(3333, 4444), Checksums(5555, 6666))))) ->
- hex"010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f0001ddde000005dc01001801789c63600001036730c55e710d4cbb3d3c080017c303b1012201789c63606a3ac8c0577e9481bd622d8327d7060686ad150c53a3ff0300554707db031800000457000008ae00000d050000115c000015b300001a0a",
- QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), TlvStream.empty) ->
- hex"010506226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f001900000000000000008e0000000000003c69000000000045a6c4",
- QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, List(RealShortChannelId(4564), RealShortChannelId(178622), RealShortChannelId(4564676))), TlvStream.empty) ->
- hex"010506226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f001801789c63600001c12b608a69e73e30edbaec0800203b040e",
- QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(12232), RealShortChannelId(15556), RealShortChannelId(4564676))), TlvStream(QueryShortChannelIdsTlv.EncodedQueryFlags(EncodingType.COMPRESSED_ZLIB, List(1, 2, 4)))) ->
- hex"010506226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f0019000000000000002fc80000000000003cc4000000000045a6c4010c01789c6364620100000e0008",
- QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.COMPRESSED_ZLIB, List(RealShortChannelId(14200), RealShortChannelId(46645), RealShortChannelId(4564676))), TlvStream(QueryShortChannelIdsTlv.EncodedQueryFlags(EncodingType.COMPRESSED_ZLIB, List(1, 2, 4)))) ->
- hex"010506226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f001801789c63600001f30a30c5b0cd144cb92e3b020017c6034a010c01789c6364620100000e0008"
+ // @formatter:off
+ QueryChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(100000), 1500, TlvStream.empty) -> hex"010706226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000186a0000005dc",
+ QueryChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(35000), 100, TlvStream(QueryChannelRangeTlv.QueryFlags(QueryChannelRangeTlv.QueryFlags.WANT_ALL))) -> hex"010706226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000088b800000064010103",
+ ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(756230), 1500, 1, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), None, None) -> hex"010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000b8a06000005dc01001900000000000000008e0000000000003c69000000000045a6c4",
+ ReplyChannelRange(Block.RegtestGenesisBlock.hash, BlockHeight(122334), 1500, 1, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(12355), RealShortChannelId(489686), RealShortChannelId(4645313))), Some(EncodedTimestamps(EncodingType.UNCOMPRESSED, List(Timestamps(164545 unixsec, 948165 unixsec), Timestamps(489645 unixsec, 4786864 unixsec), Timestamps(46456 unixsec, 9788415 unixsec)))), Some(EncodedChecksums(List(Checksums(1111, 2222), Checksums(3333, 4444), Checksums(5555, 6666))))) -> hex"010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f0001ddde000005dc01001900000000000000304300000000000778d6000000000046e1c1011900000282c1000e77c5000778ad00490ab00000b57800955bff031800000457000008ae00000d050000115c000015b300001a0a",
+ QueryShortChannelIds(Block.RegtestGenesisBlock.hash, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(142), RealShortChannelId(15465), RealShortChannelId(4564676))), TlvStream.empty) -> hex"010506226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f001900000000000000008e0000000000003c69000000000045a6c4",
+ // @formatter:on
)
refs.map { case (obj, refbin) =>
- val bin = lightningMessageCodec.encode(obj).require
- assert(refbin.bits == bin)
+ assert(lightningMessageCodec.decode(refbin.bits).require.value == obj)
+ assert(refbin.bits == lightningMessageCodec.encode(obj).require)
}
}
Why this scored 28/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.