Skip to content

Commit

Permalink
IPv4/IPv6 additional handling + dependencies updates (#180)
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanBratanov authored Jun 26, 2024
1 parent 09182b6 commit c66f3d7
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 33 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
id 'com.github.ben-manes.versions' version '0.51.0'
id 'com.github.hierynomus.license' version '0.16.1'
id 'io.spring.dependency-management' version '1.1.5'
id 'net.ltgt.errorprone' version '3.1.0'
id 'net.ltgt.errorprone' version '4.0.1'
id 'org.ajoberstar.grgit' version '5.2.2'
}

Expand Down
10 changes: 5 additions & 5 deletions gradle/versions.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
dependencyManagement {
dependencies {
dependencySet(group: 'com.google.errorprone', version: '2.27.1') {
dependencySet(group: 'com.google.errorprone', version: '2.28.0') {
entry 'error_prone_annotation'
entry 'error_prone_check_api'
entry 'error_prone_core'
Expand All @@ -9,10 +9,10 @@ dependencyManagement {

dependency 'tech.pegasys.tools.epchecks:errorprone-checks:1.1.1'

dependency 'com.google.guava:guava:33.2.0-jre'
dependency 'com.google.guava:guava:33.2.1-jre'

dependency "io.netty:netty-all:4.1.110.Final"
dependency 'io.projectreactor:reactor-core:3.6.6'
dependency "io.netty:netty-all:4.1.111.Final"
dependency 'io.projectreactor:reactor-core:3.6.7'

dependencySet(group: 'org.apache.logging.log4j', version: '2.23.1') {
entry 'log4j-api'
Expand All @@ -22,7 +22,7 @@ dependencyManagement {

dependency 'org.bouncycastle:bcprov-jdk18on:1.78.1'

dependency 'org.assertj:assertj-core:3.25.3'
dependency 'org.assertj:assertj-core:3.26.0'
dependency 'org.mockito:mockito-core:5.12.0'

dependencySet(group: 'org.apache.tuweni', version: '2.3.1') {
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
2 changes: 1 addition & 1 deletion gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.netty.channel.socket.InternetProtocolFamily;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.time.Clock;
import java.time.Duration;
Expand Down Expand Up @@ -83,9 +84,6 @@ public DiscoverySystemBuilder listen(final String listenAddress, final int liste
}

public DiscoverySystemBuilder listen(final InetSocketAddress... listenAddresses) {
Preconditions.checkArgument(
listenAddresses.length == 1 || listenAddresses.length == 2,
"Can define only 1 or 2 listen addresses - IPv4/IPv6 or IPv4 and IPv6");
validateListenAddresses(Arrays.stream(listenAddresses).collect(Collectors.toList()));
this.listenAddresses = Optional.of(Arrays.asList(listenAddresses));
return this;
Expand Down Expand Up @@ -161,13 +159,11 @@ public DiscoverySystemBuilder discoveryServer(final NettyDiscoveryServer discove
}

public DiscoverySystemBuilder discoveryServers(final NettyDiscoveryServer... discoveryServers) {
Preconditions.checkArgument(
discoveryServers.length == 1 || discoveryServers.length == 2,
"Can define only 1 or 2 discovery servers - IPv4/IPv6 or IPv4 and IPv6");
validateListenAddresses(
final List<InetSocketAddress> listenAddresses =
Arrays.stream(discoveryServers)
.map(NettyDiscoveryServer::getListenAddress)
.collect(Collectors.toList()));
.collect(Collectors.toList());
validateListenAddresses(listenAddresses);
this.discoveryServers = Arrays.asList(discoveryServers);
return this;
}
Expand All @@ -184,6 +180,9 @@ public DiscoverySystemBuilder addressAccessPolicy(final AddressAccessPolicy addr
}

private void validateListenAddresses(final List<InetSocketAddress> listenAddresses) {
Preconditions.checkArgument(
listenAddresses.size() == 1 || listenAddresses.size() == 2,
"Can define only 1 or 2 listen addresses - IPv4/IPv6 or IPv4 and IPv6");
if (listenAddresses.size() == 2) {
final Set<InternetProtocolFamily> ipFamilies =
listenAddresses.stream()
Expand All @@ -202,12 +201,15 @@ private void createDefaults() {
requireNonNullElseGet(
newAddressHandler,
() ->
(oldRecord, newAddress) ->
Optional.of(
oldRecord.withNewAddress(
newAddress,
oldRecord.getTcpAddress().map(InetSocketAddress::getPort),
secretKey)));
(oldRecord, newAddress) -> {
final Optional<InetSocketAddress> oldTcpAddress =
newAddress.getAddress() instanceof Inet6Address
? oldRecord.getTcp6Address()
: oldRecord.getTcpAddress();
return Optional.of(
oldRecord.withNewAddress(
newAddress, oldTcpAddress.map(InetSocketAddress::getPort), secretKey));
});
schedulers = requireNonNullElseGet(schedulers, Schedulers::createDefault);
final List<InetSocketAddress> serverListenAddresses =
listenAddresses.orElseGet(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static com.google.common.base.Preconditions.checkState;

import com.google.common.annotations.VisibleForTesting;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.time.Instant;
Expand All @@ -16,6 +17,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.ethereum.beacon.discovery.schema.NodeRecord;
import org.ethereum.beacon.discovery.storage.LocalNodeRecordStore;

public class DefaultExternalAddressSelector implements ExternalAddressSelector {
Expand Down Expand Up @@ -58,8 +60,11 @@ public void onExternalAddressReport(
selectExternalAddress()
.ifPresent(
selectedAddress -> {
final NodeRecord homeNodeRecord = localNodeRecordStore.getLocalNodeRecord();
final Optional<InetSocketAddress> currentAddress =
localNodeRecordStore.getLocalNodeRecord().getUdpAddress();
selectedAddress.getAddress() instanceof Inet6Address
? homeNodeRecord.getUdp6Address()
: homeNodeRecord.getUdpAddress();
if (currentAddress.map(current -> !current.equals(selectedAddress)).orElse(true)) {
localNodeRecordStore.onSocketAddressChanged(selectedAddress);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand All @@ -29,15 +31,19 @@
import org.ethereum.beacon.discovery.util.Utils;

public class IdentitySchemaV4Interpreter implements IdentitySchemaInterpreter {

private static final Logger LOG = LogManager.getLogger();

private final LoadingCache<Bytes, Bytes> nodeIdCache =
CacheBuilder.newBuilder()
.maximumSize(4000)
.build(CacheLoader.from(IdentitySchemaV4Interpreter::calculateNodeId));

private static final ImmutableSet<String> ADDRESS_FIELD_NAMES =
ImmutableSet.of(EnrField.IP_V4, EnrField.IP_V6, EnrField.UDP, EnrField.UDP_V6);
private static final ImmutableSet<String> ADDRESS_IP_V4_FIELD_NAMES =
ImmutableSet.of(EnrField.IP_V4, EnrField.UDP);

private static final ImmutableSet<String> ADDRESS_IP_V6_FIELD_NAMES =
ImmutableSet.of(EnrField.IP_V6, EnrField.UDP_V6);

@Override
public boolean isValid(final NodeRecord nodeRecord) {
Expand Down Expand Up @@ -115,8 +121,16 @@ public NodeRecord createWithNewAddress(
final Optional<Integer> newTcpPort,
final SecretKey secretKey) {
final List<EnrField> fields =
getAllFieldsThatMatch(nodeRecord, field -> !ADDRESS_FIELD_NAMES.contains(field.getName()));

getAllFieldsThatMatch(
nodeRecord,
field -> {
// don't match the address fields that we are going to change
final Set<String> addressFieldsToChange =
newAddress.getAddress() instanceof Inet6Address
? ADDRESS_IP_V6_FIELD_NAMES
: ADDRESS_IP_V4_FIELD_NAMES;
return !addressFieldsToChange.contains(field.getName());
});
NodeRecordBuilder.addFieldsForAddress(
fields, newAddress.getAddress(), newAddress.getPort(), newTcpPort);
final NodeRecord newRecord = NodeRecord.fromValues(this, nodeRecord.getSeq().add(1), fields);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public void shouldUpdateIpV6AddressAndPort() throws Exception {
}

@Test
public void shouldSwitchFromIpV4ToIpV6() throws Exception {
public void shouldAddIpV6toAlreadyExistingIpV4() throws Exception {
final NodeRecord initialRecord =
createNodeRecord(
new EnrField(EnrField.IP_V4, Bytes.wrap(new byte[4])),
Expand All @@ -229,28 +229,33 @@ public void shouldSwitchFromIpV4ToIpV6() throws Exception {
interpreter.createWithNewAddress(
initialRecord, newSocketAddress, Optional.of(5667), SECRET_KEY);

assertThat(newRecord.getUdpAddress()).isEmpty();
assertThat(newRecord.getUdpAddress()).isEqualTo(initialRecord.getUdpAddress());
assertThat(newRecord.getUdp6Address()).contains(newSocketAddress);
assertThat(newRecord.getTcpAddress()).isEmpty();
assertThat(newRecord.getTcpAddress()).isEqualTo(initialRecord.getTcpAddress());
assertThat(newRecord.getTcp6Address())
.contains(new InetSocketAddress(newSocketAddress.getAddress(), 5667));
assertThat(newRecord.get(EnrField.IP_V4)).isNull();
assertThat(newRecord.get(EnrField.IP_V4)).isEqualTo(initialRecord.get(EnrField.IP_V4));
assertThat(newRecord.get(EnrField.IP_V6)).isEqualTo(IPV6_LOCALHOST);
}

@Test
public void shouldSwitchFromIpV6ToIpV4() {
public void shouldAddIpV4ToAlreadyExistingIpV6() {
final NodeRecord initialRecord =
createNodeRecord(
new EnrField(EnrField.IP_V6, IPV6_LOCALHOST), new EnrField(EnrField.UDP_V6, 3030));
new EnrField(EnrField.IP_V6, IPV6_LOCALHOST),
new EnrField(EnrField.UDP_V6, 3030),
new EnrField(EnrField.TCP_V6, 5666));
final InetSocketAddress newSocketAddress = new InetSocketAddress("127.0.0.1", 40404);
final NodeRecord newRecord =
interpreter.createWithNewAddress(
initialRecord, newSocketAddress, Optional.of(5667), SECRET_KEY);

assertThat(newRecord.getUdp6Address()).isEqualTo(initialRecord.getUdp6Address());
assertThat(newRecord.getUdpAddress()).contains(newSocketAddress);
assertThat(newRecord.getTcp6Address()).isEqualTo(initialRecord.getTcp6Address());
assertThat(newRecord.getTcpAddress())
.contains(new InetSocketAddress(newSocketAddress.getAddress(), 5667));
assertThat(newRecord.get(EnrField.IP_V6)).isEqualTo(initialRecord.get(EnrField.IP_V6));
assertThat(newRecord.get(EnrField.IP_V4)).isEqualTo(Bytes.wrap(new byte[] {127, 0, 0, 1}));
}

Expand Down

0 comments on commit c66f3d7

Please sign in to comment.