mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 23:47:57 -05:00
Subnet-Based Peer Permissions (#7168)
Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net>
This commit is contained in:
committed by
GitHub
parent
90d2db9736
commit
e3e86c7ef6
@@ -26,6 +26,7 @@
|
||||
- Support for eth_maxPriorityFeePerGas [#5658](https://github.com/hyperledger/besu/issues/5658)
|
||||
- Enable continuous profiling with default setting [#7006](https://github.com/hyperledger/besu/pull/7006)
|
||||
- A full and up to date implementation of EOF for Prague [#7169](https://github.com/hyperledger/besu/pull/7169)
|
||||
- Add Subnet-Based Peer Permissions. [#7168](https://github.com/hyperledger/besu/pull/7168)
|
||||
|
||||
### Bug fixes
|
||||
- Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102)
|
||||
|
||||
@@ -80,6 +80,7 @@ dependencies {
|
||||
implementation 'org.xerial.snappy:snappy-java'
|
||||
implementation 'tech.pegasys:jc-kzg-4844'
|
||||
implementation 'org.rocksdb:rocksdbjni'
|
||||
implementation 'commons-net:commons-net'
|
||||
|
||||
runtimeOnly 'org.apache.logging.log4j:log4j-jul'
|
||||
runtimeOnly 'com.splunk.logging:splunk-library-javalogging'
|
||||
|
||||
@@ -88,6 +88,7 @@ import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
|
||||
import org.hyperledger.besu.ethereum.p2p.network.ProtocolManager;
|
||||
import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer;
|
||||
import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration;
|
||||
import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissionSubnet;
|
||||
import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions;
|
||||
import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissionsDenylist;
|
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration;
|
||||
@@ -146,6 +147,7 @@ import com.google.common.base.Strings;
|
||||
import graphql.GraphQL;
|
||||
import io.vertx.core.Vertx;
|
||||
import io.vertx.core.VertxOptions;
|
||||
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
import org.slf4j.Logger;
|
||||
@@ -192,6 +194,7 @@ public class RunnerBuilder {
|
||||
private JsonRpcIpcConfiguration jsonRpcIpcConfiguration;
|
||||
private boolean legacyForkIdEnabled;
|
||||
private Optional<EnodeDnsConfiguration> enodeDnsConfiguration;
|
||||
private List<SubnetInfo> allowedSubnets = new ArrayList<>();
|
||||
|
||||
/** Instantiates a new Runner builder. */
|
||||
public RunnerBuilder() {}
|
||||
@@ -589,6 +592,17 @@ public class RunnerBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subnet configuration
|
||||
*
|
||||
* @param allowedSubnets the allowedSubnets
|
||||
* @return the runner builder
|
||||
*/
|
||||
public RunnerBuilder allowedSubnets(final List<SubnetInfo> allowedSubnets) {
|
||||
this.allowedSubnets = allowedSubnets;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Runner instance.
|
||||
*
|
||||
@@ -648,6 +662,10 @@ public class RunnerBuilder {
|
||||
final PeerPermissionsDenylist bannedNodes = PeerPermissionsDenylist.create();
|
||||
bannedNodeIds.forEach(bannedNodes::add);
|
||||
|
||||
PeerPermissionSubnet peerPermissionSubnet = new PeerPermissionSubnet(allowedSubnets);
|
||||
final PeerPermissions defaultPeerPermissions =
|
||||
PeerPermissions.combine(peerPermissionSubnet, bannedNodes);
|
||||
|
||||
final List<EnodeURL> bootnodes = discoveryConfiguration.getBootnodes();
|
||||
|
||||
final Synchronizer synchronizer = besuController.getSynchronizer();
|
||||
@@ -667,8 +685,8 @@ public class RunnerBuilder {
|
||||
final PeerPermissions peerPermissions =
|
||||
nodePermissioningController
|
||||
.map(nodePC -> new PeerPermissionsAdapter(nodePC, bootnodes, context.getBlockchain()))
|
||||
.map(nodePerms -> PeerPermissions.combine(nodePerms, bannedNodes))
|
||||
.orElse(bannedNodes);
|
||||
.map(nodePerms -> PeerPermissions.combine(nodePerms, defaultPeerPermissions))
|
||||
.orElse(defaultPeerPermissions);
|
||||
|
||||
LOG.info("Detecting NAT service.");
|
||||
final boolean fallbackEnabled = natMethod == NatMethod.AUTO || natMethodFallbackEnabled;
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.hyperledger.besu.cli.config.NetworkName;
|
||||
import org.hyperledger.besu.cli.config.ProfileName;
|
||||
import org.hyperledger.besu.cli.converter.MetricCategoryConverter;
|
||||
import org.hyperledger.besu.cli.converter.PercentageConverter;
|
||||
import org.hyperledger.besu.cli.converter.SubnetInfoConverter;
|
||||
import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty;
|
||||
import org.hyperledger.besu.cli.error.BesuExecutionExceptionHandler;
|
||||
import org.hyperledger.besu.cli.error.BesuParameterExceptionHandler;
|
||||
@@ -243,6 +244,7 @@ import io.vertx.core.Vertx;
|
||||
import io.vertx.core.VertxOptions;
|
||||
import io.vertx.core.json.DecodeException;
|
||||
import io.vertx.core.metrics.MetricsOptions;
|
||||
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
import org.slf4j.Logger;
|
||||
@@ -527,6 +529,15 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
|
||||
return autoDiscoveredDefaultIP;
|
||||
}
|
||||
|
||||
@Option(
|
||||
names = {"--net-restrict"},
|
||||
arity = "1..*",
|
||||
split = ",",
|
||||
converter = SubnetInfoConverter.class,
|
||||
description =
|
||||
"Comma-separated list of allowed IP subnets (e.g., '192.168.1.0/24,10.0.0.0/8').")
|
||||
private List<SubnetInfo> allowedSubnets;
|
||||
}
|
||||
|
||||
@Option(
|
||||
@@ -2320,6 +2331,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
.storageProvider(keyValueStorageProvider(keyValueStorageName))
|
||||
.rpcEndpointService(rpcEndpointServiceImpl)
|
||||
.enodeDnsConfiguration(getEnodeDnsConfiguration())
|
||||
.allowedSubnets(p2PDiscoveryOptionGroup.allowedSubnets)
|
||||
.build();
|
||||
|
||||
addShutdownHook(runner);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.cli.converter;
|
||||
|
||||
import org.apache.commons.net.util.SubnetUtils;
|
||||
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
||||
import picocli.CommandLine;
|
||||
|
||||
/** The SubnetInfo converter for CLI options. */
|
||||
public class SubnetInfoConverter implements CommandLine.ITypeConverter<SubnetInfo> {
|
||||
/** Default Constructor. */
|
||||
public SubnetInfoConverter() {}
|
||||
|
||||
/**
|
||||
* Converts an IP addresses with CIDR notation into SubnetInfo
|
||||
*
|
||||
* @param value The IP addresses with CIDR notation.
|
||||
* @return the SubnetInfo
|
||||
*/
|
||||
@Override
|
||||
public SubnetInfo convert(final String value) {
|
||||
return new SubnetUtils(value).getInfo();
|
||||
}
|
||||
}
|
||||
@@ -1217,6 +1217,28 @@ public class BesuCommandTest extends CommandTestAbstract {
|
||||
.contains("Invalid value for option '--fast-sync-min-peers': 'ten' is not an int");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void netRestrictParsedCorrectly() {
|
||||
final String subnet1 = "127.0.0.1/24";
|
||||
final String subnet2 = "10.0.0.1/24";
|
||||
parseCommand("--net-restrict", String.join(",", subnet1, subnet2));
|
||||
verify(mockRunnerBuilder).allowedSubnets(allowedSubnetsArgumentCaptor.capture());
|
||||
assertThat(allowedSubnetsArgumentCaptor.getValue().size()).isEqualTo(2);
|
||||
assertThat(allowedSubnetsArgumentCaptor.getValue().get(0).getCidrSignature())
|
||||
.isEqualTo(subnet1);
|
||||
assertThat(allowedSubnetsArgumentCaptor.getValue().get(1).getCidrSignature())
|
||||
.isEqualTo(subnet2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void netRestrictInvalidShouldFail() {
|
||||
final String subnet = "127.0.0.1/abc";
|
||||
parseCommand("--net-restrict", subnet);
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder);
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains("Invalid value for option '--net-restrict'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ethStatsOptionIsParsedCorrectly() {
|
||||
final String url = "besu-node:secret@host:443";
|
||||
|
||||
@@ -117,6 +117,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.vertx.core.Vertx;
|
||||
import io.vertx.core.VertxOptions;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
@@ -261,6 +262,7 @@ public abstract class CommandTestAbstract {
|
||||
@Captor protected ArgumentCaptor<ApiConfiguration> apiConfigurationCaptor;
|
||||
|
||||
@Captor protected ArgumentCaptor<EthstatsOptions> ethstatsOptionsArgumentCaptor;
|
||||
@Captor protected ArgumentCaptor<List<SubnetInfo>> allowedSubnetsArgumentCaptor;
|
||||
|
||||
@BeforeEach
|
||||
public void initMocks() throws Exception {
|
||||
@@ -354,6 +356,7 @@ public abstract class CommandTestAbstract {
|
||||
when(mockRunnerBuilder.legacyForkId(anyBoolean())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.apiConfiguration(any())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.enodeDnsConfiguration(any())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.allowedSubnets(any())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.build()).thenReturn(mockRunner);
|
||||
|
||||
final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.cli.converter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SubnetInfoConverterTest {
|
||||
|
||||
@Test
|
||||
void testCreateIpRestrictionHandlerWithValidSubnets() {
|
||||
String subnet = "192.168.1.0/24";
|
||||
assertThat(parseSubnetRules(subnet).getCidrSignature()).isEqualTo(subnet);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateIpRestrictionHandlerWithInvalidSubnet() {
|
||||
assertThrows(IllegalArgumentException.class, () -> parseSubnetRules("abc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateIpRestrictionHandlerMissingCIDR() {
|
||||
assertThrows(IllegalArgumentException.class, () -> parseSubnetRules("192.168.1.0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateIpRestrictionHandlerBigCIDR() {
|
||||
assertThrows(IllegalArgumentException.class, () -> parseSubnetRules("192.168.1.0:25"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateIpRestrictionHandlerWithInvalidCIDR() {
|
||||
assertThrows(IllegalArgumentException.class, () -> parseSubnetRules("192.168.1.0/abc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateIpRestrictionHandlerWithEmptyString() {
|
||||
assertThrows(IllegalArgumentException.class, () -> parseSubnetRules(""));
|
||||
}
|
||||
|
||||
private SubnetInfo parseSubnetRules(final String subnet) {
|
||||
return new SubnetInfoConverter().convert(subnet);
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@ engine-jwt-disabled=true
|
||||
engine-jwt-secret="/tmp/jwt.hex"
|
||||
required-blocks=["8675309=123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"]
|
||||
discovery-dns-url="enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@nodes.example.org"
|
||||
net-restrict=["none"]
|
||||
|
||||
# chain
|
||||
network="MAINNET"
|
||||
|
||||
@@ -57,6 +57,7 @@ dependencies {
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
|
||||
implementation 'org.owasp.encoder:encoder'
|
||||
implementation 'org.xerial.snappy:snappy-java'
|
||||
implementation 'commons-net:commons-net'
|
||||
|
||||
annotationProcessor "org.immutables:value"
|
||||
implementation "org.immutables:value-annotations"
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.p2p.permissions;
|
||||
|
||||
import org.hyperledger.besu.ethereum.p2p.peers.Peer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Manages peer permissions based on IP subnet restrictions.
|
||||
*
|
||||
* <p>This class extends {@link PeerPermissions} to implement access control based on IP subnets. It
|
||||
* allows for the configuration of permitted subnets and uses these configurations to determine
|
||||
* whether a peer should be allowed or denied access based on its IP address.
|
||||
*
|
||||
* <p>Note: If no subnets are specified, all peers are considered permitted by default.
|
||||
*
|
||||
* @see PeerPermissions
|
||||
*/
|
||||
public class PeerPermissionSubnet extends PeerPermissions {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PeerPermissionSubnet.class);
|
||||
|
||||
private final List<SubnetInfo> allowedSubnets;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PeerPermissionSubnet} instance with specified allowed subnets.
|
||||
*
|
||||
* @param allowedSubnets A list of {@link SubnetInfo} objects representing the subnets that are
|
||||
* allowed to interact with the local node. Cannot be {@code null}.
|
||||
*/
|
||||
public PeerPermissionSubnet(final List<SubnetInfo> allowedSubnets) {
|
||||
this.allowedSubnets = allowedSubnets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a peer is permitted based on the configured subnets.
|
||||
*
|
||||
* <p>This method checks if the remote peer's IP address falls within any of the configured
|
||||
* allowed subnets. If the peer's IP is within any of the allowed subnets, it is permitted.
|
||||
* Otherwise, it is denied.
|
||||
*
|
||||
* @param localNode This parameter is not used in the current implementation.
|
||||
* @param remotePeer The remote peer to check. Its IP address is used to determine permission.
|
||||
* @param action Ignored. If the peer is not allowed in the subnet, all actions are now allowed.
|
||||
* @return {@code true} if the peer is permitted based on its IP address; {@code false} otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPermitted(final Peer localNode, final Peer remotePeer, final Action action) {
|
||||
// If no subnets are specified, all peers are permitted
|
||||
if (allowedSubnets == null || allowedSubnets.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
String remotePeerHostAddress = remotePeer.getEnodeURL().getIpAsString();
|
||||
for (SubnetInfo subnet : allowedSubnets) {
|
||||
if (subnet.isInRange(remotePeerHostAddress)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LOG.trace("Peer {} is not allowed in any of the configured subnets.", remotePeerHostAddress);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.p2p.permissions;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer;
|
||||
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
|
||||
import org.hyperledger.besu.ethereum.p2p.peers.Peer;
|
||||
import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions.Action;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.net.util.SubnetUtils;
|
||||
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class PeerPermissionsSubnetTest {
|
||||
|
||||
private final Peer remoteNode = createPeer();
|
||||
|
||||
@Test
|
||||
public void peerInSubnetRangeShouldBePermitted() {
|
||||
List<SubnetInfo> allowedSubnets = List.of(subnet("127.0.0.0/24"));
|
||||
PeerPermissionSubnet peerPermissionSubnet = new PeerPermissionSubnet(allowedSubnets);
|
||||
checkPermissions(peerPermissionSubnet, remoteNode, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peerInAtLeastOneSubnetRangeShouldBePermitted() {
|
||||
List<SubnetInfo> allowedSubnets = List.of(subnet("127.0.0.0/24"), subnet("10.0.0.1/24"));
|
||||
PeerPermissionSubnet peerPermissionSubnet = new PeerPermissionSubnet(allowedSubnets);
|
||||
checkPermissions(peerPermissionSubnet, remoteNode, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peerOutSubnetRangeShouldNotBePermitted() {
|
||||
List<SubnetInfo> allowedSubnets = List.of(subnet("10.0.0.0/24"));
|
||||
PeerPermissionSubnet peerPermissionSubnet = new PeerPermissionSubnet(allowedSubnets);
|
||||
checkPermissions(peerPermissionSubnet, remoteNode, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peerShouldBePermittedIfNoSubnets() {
|
||||
PeerPermissionSubnet peerPermissionSubnet = new PeerPermissionSubnet(List.of());
|
||||
checkPermissions(peerPermissionSubnet, remoteNode, true);
|
||||
}
|
||||
|
||||
private void checkPermissions(
|
||||
final PeerPermissions peerPermissions, final Peer remotePeer, final boolean expectedResult) {
|
||||
for (Action action : Action.values()) {
|
||||
assertThat(peerPermissions.isPermitted(createPeer(), remotePeer, action))
|
||||
.isEqualTo(expectedResult);
|
||||
}
|
||||
}
|
||||
|
||||
private SubnetInfo subnet(final String subnet) {
|
||||
return new SubnetUtils(subnet).getInfo();
|
||||
}
|
||||
|
||||
private Peer createPeer() {
|
||||
return DefaultPeer.fromEnodeURL(
|
||||
EnodeURLImpl.builder()
|
||||
.nodeId(Peer.randomId())
|
||||
.ipAddress("127.0.0.1")
|
||||
.discoveryAndListeningPorts(EnodeURLImpl.DEFAULT_LISTENING_PORT)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
@@ -1353,6 +1353,14 @@
|
||||
<sha256 value="8defda7ceb4888ffe4d4e63278956a1a3c514b75b8363d6716a1bd66fe962c7f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="commons-net" name="commons-net" version="3.11.0">
|
||||
<artifact name="commons-net-3.11.0.jar">
|
||||
<sha256 value="e78f28726a8565187cd381ed228e917ef39367de2280a4a7e19e85b06fe0c087" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="commons-net-3.11.0.pom">
|
||||
<sha256 value="fc80df2d6dd214df1769c92802f4e051e60410e22a620b1526dc75076a659ad6" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="commons-net" name="commons-net" version="3.9.0">
|
||||
<artifact name="commons-net-3.9.0.jar">
|
||||
<sha256 value="e3c1566f821b84489308cd933f57e8c00dd8714dc96b898bef844386510d3461" origin="Generated by Gradle"/>
|
||||
@@ -3007,6 +3015,11 @@
|
||||
<sha256 value="555d0c9eaa69c042aff924927b9381e8f8174136d355eead445224452e6291cc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.apache" name="apache" version="32">
|
||||
<artifact name="apache-32.pom">
|
||||
<sha256 value="cfd872c0ec27f53ae68f43dbc0fecded8add773079a53afbd390e407b42ce72f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.apache" name="apache" version="4">
|
||||
<artifact name="apache-4.pom">
|
||||
<sha256 value="9e9323a26ba8eb2394efef0c96d31b70df570808630dc147cab1e73541cc5194" origin="Generated by Gradle"/>
|
||||
@@ -3161,6 +3174,11 @@
|
||||
<sha256 value="48fd6dc846e56b1f408660d163e75300f9e384bb63be482a8082a21d72a8db9c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.apache.commons" name="commons-parent" version="70">
|
||||
<artifact name="commons-parent-70.pom">
|
||||
<sha256 value="60335a34e91f49ce50723b007d7c12514fd5766da17dfffb6732e1131e58cd1b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.apache.commons" name="commons-text" version="1.11.0">
|
||||
<artifact name="commons-text-1.11.0.jar">
|
||||
<sha256 value="2acf30a070b19163d5a480eae411a281341e870020e3534c6d5d4c8472739e30" origin="Generated by Gradle"/>
|
||||
@@ -5135,6 +5153,14 @@
|
||||
<sha256 value="21c4b0286f4b20069577ff4b20978a85c100ac8a46b6f1c8672fbaab337bc3f2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.junit" name="junit-bom" version="5.11.0-M1">
|
||||
<artifact name="junit-bom-5.11.0-M1.module">
|
||||
<sha256 value="8f632f8965e9b6f4069e3d58b9ea26b9a5bc76a98e89b43233777ace6dadb237" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="junit-bom-5.11.0-M1.pom">
|
||||
<sha256 value="b50975f5cba86204abda3dcd6f097af919fe22e21ef69478dd6b919f6c740d85" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.junit" name="junit-bom" version="5.7.1">
|
||||
<artifact name="junit-bom-5.7.1.module">
|
||||
<sha256 value="9854e3894d64b2485207e0046bca07b3d42d169e782f4fa8c9ce229a78faee04" origin="Generated by Gradle"/>
|
||||
|
||||
@@ -134,6 +134,7 @@ dependencyManagement {
|
||||
dependency 'org.apache.commons:commons-lang3:3.14.0'
|
||||
dependency 'org.apache.commons:commons-text:1.11.0'
|
||||
dependency 'org.apache.commons:commons-collections4:4.4'
|
||||
dependency 'commons-net:commons-net:3.11.0'
|
||||
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.22.1') {
|
||||
entry 'log4j-api'
|
||||
|
||||
Reference in New Issue
Block a user