This is an automated email from the ASF dual-hosted git repository.

toulmean pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-tuweni.git


The following commit(s) were added to refs/heads/master by this push:
     new de49f47  Add support for list entries in ENRs
     new 30a04f7  Merge pull request #115 from 
atoulme/add_support_for_lists_in_enrs
de49f47 is described below

commit de49f47e57a4a908adc13e56ca447dd4d9396a91
Author: Antoine Toulme <anto...@lunar-ocean.com>
AuthorDate: Sun Jul 5 10:26:44 2020 -0700

    Add support for list entries in ENRs
---
 .../devp2p/v5/DefaultNodeDiscoveryServiceTest.kt   |  1 +
 .../org/apache/tuweni/devp2p/DiscoveryService.kt   |  2 +-
 .../org/apache/tuweni/devp2p/EthereumNodeRecord.kt | 38 +++++++++++++++++-----
 .../tuweni/devp2p/v5/NodeDiscoveryService.kt       |  1 +
 .../tuweni/devp2p/v5/storage/RoutingTable.kt       |  2 +-
 .../apache/tuweni/devp2p/ENRResponsePacketTest.kt  |  7 ++--
 .../apache/tuweni/devp2p/EthereumNodeRecordTest.kt | 29 ++++++++++-------
 .../tuweni/devp2p/v5/storage/RoutingTableTest.kt   | 17 +++++++---
 8 files changed, 69 insertions(+), 28 deletions(-)

diff --git 
a/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/DefaultNodeDiscoveryServiceTest.kt
 
b/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/DefaultNodeDiscoveryServiceTest.kt
index e448415..92e3838 100644
--- 
a/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/DefaultNodeDiscoveryServiceTest.kt
+++ 
b/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/DefaultNodeDiscoveryServiceTest.kt
@@ -52,6 +52,7 @@ class DefaultNodeDiscoveryServiceTest {
     keyPair,
     enrSeq,
     emptyMap(),
+    emptyMap(),
     bindAddress.address,
     null,
     bindAddress.port
diff --git 
a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/DiscoveryService.kt 
b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/DiscoveryService.kt
index 24021b1..f5b9b73 100644
--- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/DiscoveryService.kt
+++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/DiscoveryService.kt
@@ -349,7 +349,7 @@ internal class CoroutineDiscoveryService(
     )
 
     enr = EthereumNodeRecord.toRLP(
-      keyPair, seq, enrData, selfEndpoint.address, selfEndpoint.tcpPort,
+      keyPair, seq, enrData, null, selfEndpoint.address, selfEndpoint.tcpPort,
       selfEndpoint.udpPort
     )
 
diff --git 
a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecord.kt 
b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecord.kt
index cc6f7f7..abeea22 100644
--- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecord.kt
+++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecord.kt
@@ -31,7 +31,12 @@ import java.time.Instant
 /**
  * Ethereum Node Record (ENR) as described in 
[EIP-778](https://eips.ethereum.org/EIPS/eip-778).
  */
-class EthereumNodeRecord(val signature: Bytes, val seq: Long, val data: 
Map<String, Bytes>) {
+class EthereumNodeRecord(
+  val signature: Bytes,
+  val seq: Long,
+  val data: Map<String, Bytes>,
+  val listData: Map<String, List<Bytes>> = emptyMap()
+) {
 
   companion object {
 
@@ -52,19 +57,26 @@ class EthereumNodeRecord(val signature: Bytes, val seq: 
Long, val data: Map<Stri
           val seq = it.readLong()
 
           val data = mutableMapOf<String, Bytes>()
+          val listData = mutableMapOf<String, List<Bytes>>()
           while (!it.isComplete) {
             val key = it.readString()
             if (it.nextIsList()) {
-              it.skipNext()
-              // TODO("not ready yet to read list values")
-              // data[key] = it.readListContents { listreader -> 
listreader.readValue()}
+              listData[key] = it.readListContents { listreader ->
+                if (listreader.nextIsList()) {
+                  // TODO complex structures not supported
+                  listreader.skipNext()
+                  null
+                } else {
+                  listreader.readValue()
+                }
+              }.filterNotNull()
             } else {
               val value = it.readValue()
               data[key] = value
             }
           }
 
-          EthereumNodeRecord(sig, seq, data)
+          EthereumNodeRecord(sig, seq, data, listData)
       }
     }
 
@@ -75,6 +87,7 @@ class EthereumNodeRecord(val signature: Bytes, val seq: Long, 
val data: Map<Stri
       tcp: Int? = null,
       udp: Int? = null,
       data: Map<String, Bytes>? = null,
+      listData: Map<String, List<Bytes>>? = null,
       writer: RLPWriter
     ) {
       writer.writeLong(seq)
@@ -92,11 +105,18 @@ class EthereumNodeRecord(val signature: Bytes, val seq: 
Long, val data: Map<Stri
       udp?.let {
         mutableData["udp"] = Bytes.ofUnsignedShort(it)
       }
-      mutableData.keys.sorted().forEach { key ->
+      val keys = mutableListOf<String>()
+      keys.addAll(mutableData.keys)
+      listData?.let { keys.addAll(it.keys) }
+      keys.sorted().forEach { key ->
           mutableData[key]?.let { value ->
             writer.writeString(key)
             writer.writeValue(value)
           }
+          listData?.get(key)?.let { value ->
+          writer.writeString(key)
+          writer.writeList(value) { writer, v -> writer.writeValue(v) }
+          }
       }
     }
 
@@ -105,6 +125,7 @@ class EthereumNodeRecord(val signature: Bytes, val seq: 
Long, val data: Map<Stri
      * @param signatureKeyPair the key pair to use to sign the ENR
      * @param seq the sequence number for the ENR. It should be higher than 
the previous time the ENR was generated. It defaults to the current time since 
epoch in milliseconds.
      * @param data the key pairs to encode in the ENR
+     * @param listData the key pairs of list values to encode in the ENR
      * @param ip the IP address of the host
      * @param tcp an optional parameter to a TCP port used for the wire 
protocol
      * @param udp an optional parameter to a UDP port used for discovery
@@ -116,12 +137,13 @@ class EthereumNodeRecord(val signature: Bytes, val seq: 
Long, val data: Map<Stri
       signatureKeyPair: SECP256K1.KeyPair,
       seq: Long = Instant.now().toEpochMilli(),
       data: Map<String, Bytes>? = null,
+      listData: Map<String, List<Bytes>>? = null,
       ip: InetAddress,
       tcp: Int? = null,
       udp: Int? = null
     ): Bytes {
       val encoded = RLP.encode { writer ->
-        encode(signatureKeyPair, seq, ip, tcp, udp, data, writer)
+        encode(signatureKeyPair, seq, ip, tcp, udp, data, listData, writer)
       }
       val signature = SECP256K1.sign(Hash.keccak256(encoded), signatureKeyPair)
       val sigBytes = MutableBytes.create(64)
@@ -130,7 +152,7 @@ class EthereumNodeRecord(val signature: Bytes, val seq: 
Long, val data: Map<Stri
 
       val completeEncoding = RLP.encodeList { writer ->
         writer.writeValue(sigBytes)
-        encode(signatureKeyPair, seq, ip, tcp, udp, data, writer)
+        encode(signatureKeyPair, seq, ip, tcp, udp, data, listData, writer)
       }
       return completeEncoding
     }
diff --git 
a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/NodeDiscoveryService.kt 
b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/NodeDiscoveryService.kt
index 2862ac1..653a392 100644
--- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/NodeDiscoveryService.kt
+++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/NodeDiscoveryService.kt
@@ -90,6 +90,7 @@ class DefaultNodeDiscoveryService(
         keyPair,
         enrSeq,
         emptyMap(),
+        emptyMap(),
         bindAddress.address,
         null,
         bindAddress.port
diff --git 
a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/storage/RoutingTable.kt 
b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/storage/RoutingTable.kt
index 6777272..252a382 100644
--- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/storage/RoutingTable.kt
+++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/storage/RoutingTable.kt
@@ -36,7 +36,7 @@ class RoutingTable(
     nodeId = nodeIdCalculation,
     distanceToSelf = {
       val xorResult = key(it) xorDist selfNodeId
-      IntMath.log2(xorResult, RoundingMode.FLOOR)
+      if (xorResult == 0) 0 else IntMath.log2(xorResult, RoundingMode.FLOOR)
     })
 
   val size: Int
diff --git 
a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/ENRResponsePacketTest.kt 
b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/ENRResponsePacketTest.kt
index df0f929..63f2b75 100644
--- a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/ENRResponsePacketTest.kt
+++ b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/ENRResponsePacketTest.kt
@@ -35,8 +35,11 @@ internal class ENRResponsePacketTest {
     val keyPair = SECP256K1.KeyPair.random()
 
     val requestHash = Bytes32.random()
-    val enr = EthereumNodeRecord.toRLP(SECP256K1.KeyPair.random(), 2, 
emptyMap(),
-      InetAddress.getByName("localhost"), 3000, 12000)
+    val enr = EthereumNodeRecord.toRLP(
+      SECP256K1.KeyPair.random(), 2, emptyMap(),
+      emptyMap(),
+      InetAddress.getByName("localhost"), 3000, 12000
+    )
     val now = System.currentTimeMillis()
     val pong = ENRResponsePacket.create(keyPair, now, requestHash, enr)
 
diff --git 
a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecordTest.kt 
b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecordTest.kt
index eeb1552..87cc06b 100644
--- a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecordTest.kt
+++ b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecordTest.kt
@@ -23,7 +23,6 @@ import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.assertThrows
 import org.junit.jupiter.api.extension.ExtendWith
-import java.lang.IllegalArgumentException
 import java.net.InetAddress
 
 @ExtendWith(BouncyCastleExtension::class)
@@ -40,34 +39,42 @@ class EthereumNodeRecordTest {
 
   @Test
   fun readFromRLP() {
-    val enr = EthereumNodeRecord.fromRLP(Bytes.fromHexString(
-      "f884b8407098ad865b00a582051940cb9cf36836572411a4727878307701" +
-      "1599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11" +
-      "df72ecf1145ccb9c01826964827634826970847f00000189736563703235" +
-      "366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1" +
-      "400f3258cd31388375647082765f"))
+    val enr = EthereumNodeRecord.fromRLP(
+      Bytes.fromHexString(
+        "f884b8407098ad865b00a582051940cb9cf36836572411a4727878307701" +
+          "1599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11" +
+          "df72ecf1145ccb9c01826964827634826970847f00000189736563703235" +
+          "366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1" +
+          "400f3258cd31388375647082765f"
+      )
+    )
     assertEquals(1L, enr.seq)
     assertEquals(Bytes.wrap("v4".toByteArray()), enr.data["id"])
     assertEquals(Bytes.fromHexString("7f000001"), enr.data["ip"])
     assertEquals(
       
Bytes.fromHexString("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138"),
-      enr.data["secp256k1"])
+      enr.data["secp256k1"]
+    )
     assertEquals(Bytes.fromHexString("765f"), enr.data["udp"])
     enr.validate()
-    System.out.println(enr.publicKey().bytes())
   }
 
   @Test
   fun toRLP() {
     val keypair = SECP256K1.KeyPair.random()
-    val rlp = EthereumNodeRecord.toRLP(keypair,
+    val rlp = EthereumNodeRecord.toRLP(
+      keypair,
       seq = 1L,
       data = mutableMapOf(Pair("key", Bytes.fromHexString("deadbeef"))),
-      ip = InetAddress.getByName("127.0.0.1"))
+      listData = mutableMapOf(Pair("foo", 
listOf(Bytes.fromHexString("deadbeef")))),
+      ip = InetAddress.getByName("127.0.0.1")
+    )
     val record = EthereumNodeRecord.fromRLP(rlp)
     assertEquals(1L, record.seq)
     assertEquals(Bytes.wrap("v4".toByteArray()), record.data["id"])
     assertEquals(Bytes.fromHexString("7f000001"), record.data["ip"])
     assertEquals(keypair.publicKey(), record.publicKey())
+    assertEquals(Bytes.fromHexString("deadbeef"), record.data["key"])
+    assertEquals(Bytes.fromHexString("deadbeef"), (record.listData["foo"] ?: 
error("None"))[0])
   }
 }
diff --git 
a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/storage/RoutingTableTest.kt
 
b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/storage/RoutingTableTest.kt
index 9792645..7293590 100644
--- 
a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/storage/RoutingTableTest.kt
+++ 
b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/storage/RoutingTableTest.kt
@@ -21,6 +21,9 @@ import org.apache.tuweni.crypto.SECP256K1
 import org.apache.tuweni.devp2p.EthereumNodeRecord
 import org.apache.tuweni.junit.BouncyCastleExtension
 import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertNotEquals
+import org.junit.jupiter.api.Assertions.assertTrue
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.extension.ExtendWith
 import java.net.InetAddress
@@ -38,26 +41,30 @@ class RoutingTableTest {
   @Test
   fun addCreatesRecordInBucket() {
     routingTable.add(newEnr)
-
-    assert(!routingTable.isEmpty())
+    assertTrue(!routingTable.isEmpty())
   }
 
   @Test
   fun evictRemovesRecord() {
     routingTable.add(newEnr)
 
-    assert(!routingTable.isEmpty())
+    assertTrue(!routingTable.isEmpty())
 
     routingTable.evict(newEnr)
 
-    assert(routingTable.isEmpty())
+    assertTrue(routingTable.isEmpty())
   }
 
   @Test
   fun getSelfEnrGivesTableOwnerEnr() {
     val result = routingTable.getSelfEnr()
+    assertEquals(enr, result)
+  }
 
-    assert(result == enr)
+  @Test
+  fun distanceToSelf() {
+    assertEquals(0, routingTable.distanceToSelf(routingTable.getSelfEnr()))
+    assertNotEquals(0, routingTable.distanceToSelf(newEnr))
   }
 
   @AfterEach


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@tuweni.apache.org
For additional commands, e-mail: commits-h...@tuweni.apache.org

Reply via email to