You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuweni.apache.org by to...@apache.org on 2020/02/27 22:20:44 UTC

[incubator-tuweni] branch master updated: Fix discv5 package-visible issues. Make a Java test to showcase access to the service

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 e02b17f  Fix discv5 package-visible issues. Make a Java test to showcase access to the service
e02b17f is described below

commit e02b17fe669f23de30d2a0ecaf24bc4b3fb2134d
Author: Antoine Toulme <an...@lunar-ocean.com>
AuthorDate: Thu Feb 27 14:20:25 2020 -0800

    Fix discv5 package-visible issues. Make a Java test to showcase access to the service
---
 .../org/apache/tuweni/devp2p/v5/ENRStorage.kt      | 19 +++--
 .../tuweni/devp2p/v5/NodeDiscoveryService.kt       | 95 ++++++++++++++++------
 .../devp2p/v5/internal/DefaultUdpConnector.kt      |  2 +-
 .../tuweni/devp2p/v5/storage/DefaultENRStorage.kt  | 13 ++-
 .../tuweni/devp2p/v5/NodeDiscoveryServiceTest.java | 30 +++++++
 .../tuweni/devp2p/v5/AbstractIntegrationTest.kt    |  4 +-
 .../devp2p/v5/DefaultNodeDiscoveryServiceTest.kt   |  7 +-
 .../kotlin/org/apache/tuweni/relayer/RelayerApp.kt |  2 -
 8 files changed, 125 insertions(+), 47 deletions(-)

diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/ENRStorage.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/ENRStorage.kt
index 3388444..79aa0b8 100644
--- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/ENRStorage.kt
+++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/ENRStorage.kt
@@ -17,25 +17,34 @@
 package org.apache.tuweni.devp2p.v5
 
 import org.apache.tuweni.bytes.Bytes
+import org.apache.tuweni.crypto.Hash
 
 /**
- * In-memory storage of node records
+ * Storage of node records
  */
 interface ENRStorage {
 
   /**
-   * Persist node record into storage
+   * Add an ENR record to the store
    *
    * @param enr node record
    */
-  fun set(enr: Bytes)
+  fun set(enr: Bytes) {
+    val nodeId = Hash.sha2_256(enr)
+    put(nodeId, enr)
+  }
 
   /**
-   * Find node record into storage
+   * Store an ENR record associated with a nodeId in the store.
+   */
+  fun put(nodeId: Bytes, enr: Bytes)
+
+  /**
+   * Find a stored node record
    *
    * @param nodeId node identifier
    *
-   * @return node record
+   * @return node record, if present.
    */
   fun find(nodeId: Bytes): Bytes?
 }
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 66899cd..30fa338 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
@@ -18,8 +18,7 @@ package org.apache.tuweni.devp2p.v5
 
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import org.apache.tuweni.bytes.Bytes
+import org.apache.tuweni.concurrent.coroutines.asyncCompletion
 import org.apache.tuweni.crypto.Hash
 import org.apache.tuweni.crypto.SECP256K1
 import org.apache.tuweni.devp2p.EthereumNodeRecord
@@ -35,41 +34,91 @@ import kotlin.coroutines.CoroutineContext
  * Service executes network discovery, according to discv5 specification
  * (https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md)
  */
-interface NodeDiscoveryService {
+interface NodeDiscoveryService : CoroutineScope {
 
   /**
-   * Initializes node discovery
+   * Starts the node discovery service.
    */
   suspend fun start()
 
   /**
-   * Executes service shut down
+   * Stops the node discovery service.
    */
   suspend fun terminate()
+
+  /**
+   * Starts the discovery service, providing a handle to the completion of the start operation.
+   */
+  fun startAsync() = asyncCompletion { start() }
+
+  /**
+   * Stops the node discovery service, providing a handle to the completion of the shutdown operation.
+   */
+  fun terminateAsync() = asyncCompletion { terminate() }
 }
 
-internal class DefaultNodeDiscoveryService(
-  private val keyPair: SECP256K1.KeyPair,
-  private val localPort: Int,
-  private val bindAddress: InetSocketAddress = InetSocketAddress(localPort),
-  private val bootstrapENRList: List<String> = emptyList(),
-  private val enrSeq: Long = Instant.now().toEpochMilli(),
-  private val selfENR: Bytes = EthereumNodeRecord.toRLP(
-    keyPair,
-    enrSeq,
-    emptyMap(),
-    bindAddress.address,
-    null,
-    bindAddress.port
-  ),
-  private val enrStorage: ENRStorage = DefaultENRStorage(),
-  private val connector: UdpConnector = DefaultUdpConnector(bindAddress, keyPair, selfENR, enrStorage),
+class DefaultNodeDiscoveryService(
+  private val bootstrapENRList: List<String>,
+  private val enrStorage: ENRStorage,
+  private val connector: UdpConnector,
   override val coroutineContext: CoroutineContext = Dispatchers.Default
-) : NodeDiscoveryService, CoroutineScope {
+) : NodeDiscoveryService {
+
+  companion object {
+    /**
+     * Creates a new discovery service, generating the node ENR and configuring the UDP connector.
+     * @param keyPair the key pair identifying the node running the service.
+     * @param bindAddress the address to bind the node to.
+     * @param enrSeq the sequence of the ENR of the node
+     * @param bootstrapENRList the list of other nodes to connect to on bootstrap.
+     * @param enrStorage the permanent storage of ENRs. Defaults to an in-memory store.
+     * @param coroutineContext the coroutine context associated with the store.
+     */
+    @JvmStatic
+    @JvmOverloads
+    fun open(
+      keyPair: SECP256K1.KeyPair,
+      localPort: Int,
+      bindAddress: InetSocketAddress = InetSocketAddress(localPort),
+      enrSeq: Long = Instant.now().toEpochMilli(),
+      bootstrapENRList: List<String> = emptyList(),
+      enrStorage: ENRStorage = DefaultENRStorage(),
+      coroutineContext: CoroutineContext = Dispatchers.Default
+    ): NodeDiscoveryService {
+      val selfENR = EthereumNodeRecord.toRLP(
+        keyPair,
+        enrSeq,
+        emptyMap(),
+        bindAddress.address,
+        null,
+        bindAddress.port
+      )
+      val connector = DefaultUdpConnector(bindAddress, keyPair, selfENR, enrStorage)
+      return open(bootstrapENRList, enrStorage, connector, coroutineContext)
+    }
+
+    /**
+     * Creates a new discovery service with the UDP service provided.
+     * @param bootstrapENRList the list of other nodes to connect to on bootstrap.
+     * @param enrStorage the permanent storage of ENRs. Defaults to an in-memory store.
+     * @param connector the UDP service providing network access.
+     * @param coroutineContext the coroutine context associated with the store.
+     */
+    @JvmStatic
+    @JvmOverloads
+    fun open(
+      bootstrapENRList: List<String> = emptyList(),
+      enrStorage: ENRStorage = DefaultENRStorage(),
+      connector: UdpConnector,
+      coroutineContext: CoroutineContext = Dispatchers.Default
+    ): NodeDiscoveryService {
+      return DefaultNodeDiscoveryService(bootstrapENRList, enrStorage, connector, coroutineContext)
+    }
+  }
 
   override suspend fun start() {
     connector.start()
-    launch { bootstrap() }
+    bootstrap()
   }
 
   override suspend fun terminate() {
diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/internal/DefaultUdpConnector.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/internal/DefaultUdpConnector.kt
index b3afb2c..8e072f8 100644
--- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/internal/DefaultUdpConnector.kt
+++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/internal/DefaultUdpConnector.kt
@@ -71,7 +71,7 @@ import java.time.Duration
 import java.util.concurrent.atomic.AtomicBoolean
 import kotlin.coroutines.CoroutineContext
 
-class DefaultUdpConnector(
+public class DefaultUdpConnector(
   private val bindAddress: InetSocketAddress,
   private val keyPair: SECP256K1.KeyPair,
   private val selfEnr: Bytes,
diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/storage/DefaultENRStorage.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/storage/DefaultENRStorage.kt
index 26ff813..91598a2 100644
--- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/storage/DefaultENRStorage.kt
+++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/storage/DefaultENRStorage.kt
@@ -17,18 +17,17 @@
 package org.apache.tuweni.devp2p.v5.storage
 
 import org.apache.tuweni.bytes.Bytes
-import org.apache.tuweni.crypto.Hash
 import org.apache.tuweni.devp2p.v5.ENRStorage
 import java.util.concurrent.ConcurrentHashMap
 
+/**
+ * Default storage for Ethereum Node Records, backed by an in-memory hash map.
+ */
 class DefaultENRStorage : ENRStorage {
 
-  private val storage: MutableMap<String, Bytes> = ConcurrentHashMap()
+  private val storage: MutableMap<Bytes, Bytes> = ConcurrentHashMap()
 
-  override fun find(nodeId: Bytes): Bytes? = storage[nodeId.toHexString()]
+  override fun find(nodeId: Bytes): Bytes? = storage[nodeId]
 
-  override fun set(enr: Bytes) {
-    val nodeId = Hash.sha2_256(enr)
-    storage[nodeId.toHexString()] = enr
-  }
+  override fun put(nodeId: Bytes, enr: Bytes) { storage.put(nodeId, enr) }
 }
diff --git a/devp2p/src/test/java/org/apache/tuweni/devp2p/v5/NodeDiscoveryServiceTest.java b/devp2p/src/test/java/org/apache/tuweni/devp2p/v5/NodeDiscoveryServiceTest.java
new file mode 100644
index 0000000..87ce231
--- /dev/null
+++ b/devp2p/src/test/java/org/apache/tuweni/devp2p/v5/NodeDiscoveryServiceTest.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
+ * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
+ * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.tuweni.devp2p.v5;
+
+import org.apache.tuweni.crypto.SECP256K1;
+import org.apache.tuweni.junit.BouncyCastleExtension;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(BouncyCastleExtension.class)
+public class NodeDiscoveryServiceTest {
+
+  @Test
+  void testStartAndStop() throws InterruptedException {
+    NodeDiscoveryService service = DefaultNodeDiscoveryService.open(SECP256K1.KeyPair.random(), 1000);
+    service.startAsync().join();
+    service.terminateAsync().join();
+  }
+}
diff --git a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/AbstractIntegrationTest.kt b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/AbstractIntegrationTest.kt
index a762751..621534b 100644
--- a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/AbstractIntegrationTest.kt
+++ b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/AbstractIntegrationTest.kt
@@ -71,9 +71,7 @@ abstract class AbstractIntegrationTest {
       ticketHolder = ticketHolder
     ),
     service: NodeDiscoveryService =
-      DefaultNodeDiscoveryService(
-        keyPair,
-        port,
+      DefaultNodeDiscoveryService.open(
         enrStorage = enrStorage,
         bootstrapENRList = bootList,
         connector = connector,
diff --git a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/DefaultNodeDiscoveryServiceTest.kt b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/DefaultNodeDiscoveryServiceTest.kt
index ee714c1..adb3556 100644
--- a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/DefaultNodeDiscoveryServiceTest.kt
+++ b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/DefaultNodeDiscoveryServiceTest.kt
@@ -58,13 +58,8 @@ class DefaultNodeDiscoveryServiceTest {
     DefaultUdpConnector(bindAddress, keyPair, selfENR)
 
   private val nodeDiscoveryService: NodeDiscoveryService =
-    DefaultNodeDiscoveryService(
-      keyPair,
-      localPort,
-      bindAddress,
+    DefaultNodeDiscoveryService.open(
       bootstrapENRList,
-      enrSeq,
-      selfENR,
       connector = connector
     )
 
diff --git a/hobbits-relayer/src/main/kotlin/org/apache/tuweni/relayer/RelayerApp.kt b/hobbits-relayer/src/main/kotlin/org/apache/tuweni/relayer/RelayerApp.kt
index 5b8c5c4..d94f868 100644
--- a/hobbits-relayer/src/main/kotlin/org/apache/tuweni/relayer/RelayerApp.kt
+++ b/hobbits-relayer/src/main/kotlin/org/apache/tuweni/relayer/RelayerApp.kt
@@ -46,10 +46,8 @@ class RelayerApp {
         System.out.println(it)
       })
       Runtime.getRuntime().addShutdownHook(Thread {
-        println("Relayer stopping")
         relayer.stop()
         vertx.close()
-        println("Relayer stopped")
       })
       runBlocking {
         relayer.start()


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