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