From 82e5b5968da8bc41c0e0a44303e65883ce4c9aa2 Mon Sep 17 00:00:00 2001 From: Bastien Teinturier <31281497+t-bast@users.noreply.github.com> Date: Wed, 17 Feb 2021 15:12:39 +0100 Subject: [PATCH] Sort addresses in node announcement (#1693) Addresses in node announcement should be sorted. We accept node announcements that don't do this, but we should do it for our own announcements. See /~https://github.com/lightningnetwork/lightning-rfc/pull/842 --- .../fr/acinq/eclair/router/Announcements.scala | 10 ++++++++-- .../eclair/router/AnnouncementsSpec.scala | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/router/Announcements.scala b/eclair-core/src/main/scala/fr/acinq/eclair/router/Announcements.scala index ea718e71ea..a158a0a585 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/router/Announcements.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/router/Announcements.scala @@ -72,7 +72,13 @@ object Announcements { def makeNodeAnnouncement(nodeSecret: PrivateKey, alias: String, color: Color, nodeAddresses: List[NodeAddress], features: Features, timestamp: Long = System.currentTimeMillis.milliseconds.toSeconds): NodeAnnouncement = { require(alias.length <= 32) - val witness = nodeAnnouncementWitnessEncode(timestamp, nodeSecret.publicKey, color, alias, features, nodeAddresses, unknownFields = ByteVector.empty) + val sortedAddresses = nodeAddresses.map { + case address@(_: IPv4) => (1, address) + case address@(_: IPv6) => (2, address) + case address@(_: Tor2) => (3, address) + case address@(_: Tor3) => (4, address) + }.sortBy(_._1).map(_._2) + val witness = nodeAnnouncementWitnessEncode(timestamp, nodeSecret.publicKey, color, alias, features, sortedAddresses, unknownFields = ByteVector.empty) val sig = Crypto.sign(witness, nodeSecret) NodeAnnouncement( signature = sig, @@ -81,7 +87,7 @@ object Announcements { rgbColor = color, alias = alias, features = features, - addresses = nodeAddresses + addresses = sortedAddresses ) } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsSpec.scala index 383c146755..7c6faa9e0a 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsSpec.scala @@ -21,6 +21,7 @@ import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey} import fr.acinq.eclair.TestConstants.Alice import fr.acinq.eclair._ import fr.acinq.eclair.router.Announcements._ +import fr.acinq.eclair.wire.NodeAddress import org.scalatest.funsuite.AnyFunSuite import scodec.bits._ @@ -57,6 +58,23 @@ class AnnouncementsSpec extends AnyFunSuite { assert(checkSig(ann.copy(timestamp = 153)) === false) } + test("sort node announcement addresses") { + val addresses = List( + NodeAddress.fromParts("iq7zhmhck54vcax2vlrdcavq2m32wao7ekh6jyeglmnuuvv3js57r4id.onion", 9735).get, + NodeAddress.fromParts("2620:1ec:c11:0:0:0:0:200", 9735).get, + NodeAddress.fromParts("140.82.121.4", 9735).get, + NodeAddress.fromParts("hsmithsxurybd7uh.onion", 9735).get, + ) + val ann = makeNodeAnnouncement(Alice.nodeParams.privateKey, Alice.nodeParams.alias, Alice.nodeParams.color, addresses, Alice.nodeParams.features) + assert(checkSig(ann)) + assert(ann.addresses === List( + NodeAddress.fromParts("140.82.121.4", 9735).get, + NodeAddress.fromParts("2620:1ec:c11:0:0:0:0:200", 9735).get, + NodeAddress.fromParts("hsmithsxurybd7uh.onion", 9735).get, + NodeAddress.fromParts("iq7zhmhck54vcax2vlrdcavq2m32wao7ekh6jyeglmnuuvv3js57r4id.onion", 9735).get, + )) + } + test("nodeParams.nodeId equals nodeParams.privateKey.publicKey") { assert(Alice.nodeParams.nodeId === Alice.nodeParams.privateKey.publicKey) }