Add protocols section to admin_peers (#1580) (#1582)

Add the protocols section to admin_peers.  This involved plumbing
EthPeers through where we were previously using the P2PNetwork to get
our data.  Hence most of the PR is DI refactoring.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
pull/1592/head
Danno Ferrin 4 years ago committed by GitHub
parent a5df0fde2d
commit 42bf5767d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      CHANGELOG.md
  2. 3
      besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java
  3. 5
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java
  4. 17
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminPeers.java
  5. 71
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/PeerResult.java
  6. 47
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/ProtocolsResult.java
  7. 8
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java
  8. 7
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java
  9. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java
  10. 41
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AdminJsonRpcHttpServiceTest.java
  11. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java
  12. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java
  13. 7
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java
  14. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTest.java
  15. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java
  16. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java
  17. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java
  18. 23
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminPeersTest.java
  19. 23
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeer.java
  20. 6
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java
  21. 3
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java
  22. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/RespondingEthPeer.java

@ -4,11 +4,12 @@
### Additions and Improvements
* Added support for batched requests in WebSockets. [#1583](https://github.com/hyperledger/besu/pull/1583)
* Add a protocols section to `admin_peers` to provide info about peer health. [\#1582](https://github.com/hyperledger/besu/pull/1582)
### Bug Fixes
* Ibft2 will discard any received messages targetting a chain height <= current head - this resolves some corner cases in system correctness directly following block import. [#1575](https://github.com/hyperledger/besu/pull/1575)
## 20.10.1
### Additions and Improvements

@ -771,7 +771,8 @@ public class RunnerBuilder {
metricsConfiguration,
natService,
namedPlugins,
dataDir);
dataDir,
besuController.getProtocolManager().ethContext().getEthPeers());
methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis));
return methods;
}

@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
@ -87,6 +88,7 @@ public class JsonRpcTestMethodsFactory {
final Synchronizer synchronizer = mock(Synchronizer.class);
final P2PNetwork peerDiscovery = mock(P2PNetwork.class);
final EthPeers ethPeers = mock(EthPeers.class);
final TransactionPool transactionPool = mock(TransactionPool.class);
final EthHashMiningCoordinator miningCoordinator = mock(EthHashMiningCoordinator.class);
final ObservableMetricsSystem metricsSystem = new NoOpMetricsSystem();
@ -140,6 +142,7 @@ public class JsonRpcTestMethodsFactory {
metricsConfiguration,
natService,
new HashMap<>(),
dataDir);
dataDir,
ethPeers);
}
}

@ -21,17 +21,16 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorR
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.PeerResult;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.p2p.network.exceptions.P2PDisabledException;
import java.util.List;
import java.util.stream.Collectors;
public class AdminPeers implements JsonRpcMethod {
private final P2PNetwork peerDiscoveryAgent;
private final EthPeers ethPeers;
public AdminPeers(final P2PNetwork peerDiscoveryAgent) {
this.peerDiscoveryAgent = peerDiscoveryAgent;
public AdminPeers(final EthPeers ethPeers) {
this.ethPeers = ethPeers;
}
@Override
@ -43,11 +42,9 @@ public class AdminPeers implements JsonRpcMethod {
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
try {
final List<PeerResult> peers =
peerDiscoveryAgent.getPeers().stream().map(PeerResult::new).collect(Collectors.toList());
final JsonRpcResponse result =
new JsonRpcSuccessResponse(requestContext.getRequest().getId(), peers);
return result;
return new JsonRpcSuccessResponse(
requestContext.getRequest().getId(),
ethPeers.streamAllPeers().map(PeerResult::fromEthPeer).collect(Collectors.toList()));
} catch (P2PDisabledException e) {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(), JsonRpcError.P2P_DISABLED);

@ -14,67 +14,62 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.PeerInfo;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.TextNode;
import org.immutables.value.Value;
@JsonPropertyOrder({"version", "name", "caps", "network", "port", "id"})
public class PeerResult {
@JsonPropertyOrder({"version", "name", "caps", "network", "port", "id", "protocols"})
@Value.Immutable
@Value.Style(allParameters = true)
public interface PeerResult {
private final String version;
private final String name;
private final List<JsonNode> caps;
private final NetworkResult network;
private final String port;
private final String id;
public PeerResult(final PeerConnection peer) {
this.version = Quantity.create(peer.getPeerInfo().getVersion());
this.name = peer.getPeerInfo().getClientId();
this.caps =
peer.getPeerInfo().getCapabilities().stream()
.map(Capability::toString)
.map(TextNode::new)
.collect(Collectors.toList());
this.network = new NetworkResult(peer.getLocalAddress(), peer.getRemoteAddress());
this.port = Quantity.create(peer.getPeerInfo().getPort());
this.id = peer.getPeerInfo().getNodeId().toString();
static PeerResult fromEthPeer(final EthPeer peer) {
final PeerConnection connection = peer.getConnection();
final PeerInfo peerInfo = connection.getPeerInfo();
return ImmutablePeerResult.builder()
.version(Quantity.create(peerInfo.getVersion()))
.name(peerInfo.getClientId())
.caps(
peerInfo.getCapabilities().stream()
.map(Capability::toString)
.map(TextNode::new)
.collect(Collectors.toList()))
.network(new NetworkResult(connection.getLocalAddress(), connection.getRemoteAddress()))
.port(Quantity.create(peerInfo.getPort()))
.id(peerInfo.getNodeId().toString())
.protocols(Map.of(peer.getProtocolName(), ProtocolsResult.fromEthPeer(peer)))
.build();
}
@JsonGetter(value = "version")
public String getVersion() {
return version;
}
String getVersion();
@JsonGetter(value = "name")
public String getName() {
return name;
}
String getName();
@JsonGetter(value = "caps")
public List<JsonNode> getCaps() {
return caps;
}
List<JsonNode> getCaps();
@JsonGetter(value = "network")
public NetworkResult getNetwork() {
return network;
}
NetworkResult getNetwork();
@JsonGetter(value = "port")
public String getPort() {
return port;
}
String getPort();
@JsonGetter(value = "id")
public String getId() {
return id;
}
String getId();
@JsonGetter(value = "protocols")
Map<String, ProtocolsResult> getProtocols();
}

@ -0,0 +1,47 @@
/*
* Copyright ConsenSys AG.
*
* 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.api.jsonrpc.internal.results;
import org.hyperledger.besu.ethereum.eth.manager.ChainState.BestBlock;
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.tuweni.bytes.Bytes;
import org.immutables.value.Value;
@JsonPropertyOrder({"difficulty", "head", "version"})
@Value.Immutable
@Value.Style(allParameters = true)
public interface ProtocolsResult {
static ProtocolsResult fromEthPeer(final EthPeer ethPeer) {
final BestBlock bestBlock = ethPeer.chainState().getBestBlock();
return ImmutableProtocolsResult.builder()
.difficulty(Quantity.create(bestBlock.getTotalDifficulty()))
.head(Objects.requireNonNullElse(bestBlock.getHash(), Bytes.EMPTY).toHexString())
.version(ethPeer.getLastProtocolVersion())
.build();
}
String getDifficulty();
String getHead();
int getVersion();
}

@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.AdminRemovePee
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.PluginsReloadConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.plugin.BesuPlugin;
@ -44,6 +45,7 @@ public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final BlockchainQueries blockchainQueries;
private final NatService natService;
private final Map<String, BesuPlugin> namedPlugins;
private final EthPeers ethPeers;
public AdminJsonRpcMethods(
final String clientVersion,
@ -52,7 +54,8 @@ public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods {
final P2PNetwork p2pNetwork,
final BlockchainQueries blockchainQueries,
final Map<String, BesuPlugin> namedPlugins,
final NatService natService) {
final NatService natService,
final EthPeers ethPeers) {
this.clientVersion = clientVersion;
this.networkId = networkId;
this.genesisConfigOptions = genesisConfigOptions;
@ -60,6 +63,7 @@ public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods {
this.blockchainQueries = blockchainQueries;
this.namedPlugins = namedPlugins;
this.natService = natService;
this.ethPeers = ethPeers;
}
@Override
@ -79,7 +83,7 @@ public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods {
p2pNetwork,
blockchainQueries,
natService),
new AdminPeers(p2pNetwork),
new AdminPeers(ethPeers),
new AdminChangeLogLevel(),
new AdminGenerateLogBloomCache(blockchainQueries),
new AdminLogsRepairCache(blockchainQueries),

@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@ -69,7 +70,8 @@ public class JsonRpcMethodsFactory {
final MetricsConfiguration metricsConfiguration,
final NatService natService,
final Map<String, BesuPlugin> namedPlugins,
final Path dataDir) {
final Path dataDir,
final EthPeers ethPeers) {
final Map<String, JsonRpcMethod> enabled = new HashMap<>();
if (!rpcApis.isEmpty()) {
@ -85,7 +87,8 @@ public class JsonRpcMethodsFactory {
p2pNetwork,
blockchainQueries,
namedPlugins,
natService),
natService,
ethPeers),
new DebugJsonRpcMethods(
blockchainQueries, protocolSchedule, metricsSystem, transactionPool, dataDir),
new EeaJsonRpcMethods(

@ -36,6 +36,7 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
@ -169,7 +170,8 @@ public abstract class AbstractJsonRpcHttpServiceTest {
mock(MetricsConfiguration.class),
natService,
new HashMap<>(),
folder.getRoot().toPath());
folder.getRoot().toPath(),
mock(EthPeers.class));
}
protected void startService() throws Exception {

@ -17,9 +17,10 @@ package org.hyperledger.besu.ethereum.api.jsonrpc;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection;
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.PeerInfo;
import org.hyperledger.besu.testutil.TestClock;
import java.net.InetSocketAddress;
import java.util.ArrayList;
@ -46,7 +47,7 @@ public class AdminJsonRpcHttpServiceTest extends JsonRpcHttpServiceTest {
final List<Capability> caps = new ArrayList<>();
caps.add(Capability.create("eth", 61));
caps.add(Capability.create("eth", 62));
final List<PeerConnection> peerList = new ArrayList<>();
final List<EthPeer> peerList = new ArrayList<>();
final PeerInfo info1 =
new PeerInfo(4, CLIENT_VERSION, caps, 30302, Bytes.fromHexString("0001"));
final PeerInfo info2 =
@ -59,11 +60,29 @@ public class AdminJsonRpcHttpServiceTest extends JsonRpcHttpServiceTest {
final InetSocketAddress addr60302 = new InetSocketAddress("localhost", 60302);
final InetSocketAddress addr60303 = new InetSocketAddress("localhost", 60303);
peerList.add(MockPeerConnection.create(info1, addr60301, addr30302));
peerList.add(MockPeerConnection.create(info2, addr30301, addr60302));
peerList.add(MockPeerConnection.create(info3, addr30301, addr60303));
peerList.add(
new EthPeer(
MockPeerConnection.create(info1, addr60301, addr30302),
"eth",
c -> {},
List.of(),
TestClock.fixed()));
peerList.add(
new EthPeer(
MockPeerConnection.create(info2, addr30301, addr60302),
"eth",
c -> {},
List.of(),
TestClock.fixed()));
peerList.add(
new EthPeer(
MockPeerConnection.create(info3, addr30301, addr60303),
"eth",
c -> {},
List.of(),
TestClock.fixed()));
when(peerDiscoveryMock.getPeers()).thenReturn(peerList);
when(ethPeersMock.streamAllPeers()).thenReturn(peerList.stream());
when(peerDiscoveryMock.getPeerCount()).thenReturn(peerList.size());
final String id = "123";
@ -88,10 +107,10 @@ public class AdminJsonRpcHttpServiceTest extends JsonRpcHttpServiceTest {
}
}
protected void assertPeerResultMatchesPeer(
final JsonArray result, final Collection<PeerConnection> peerList) {
private void assertPeerResultMatchesPeer(
final JsonArray result, final Collection<EthPeer> peerList) {
int i = -1;
for (final PeerConnection peerConn : peerList) {
for (final EthPeer ethPeer : peerList) {
final JsonObject peerJson = result.getJsonObject(++i);
final int jsonVersion = Integer.decode(peerJson.getString("version"));
final String jsonClient = peerJson.getString("name");
@ -100,7 +119,7 @@ public class AdminJsonRpcHttpServiceTest extends JsonRpcHttpServiceTest {
final Bytes jsonNodeId = Bytes.fromHexString(peerJson.getString("id"));
final PeerInfo jsonPeer = new PeerInfo(jsonVersion, jsonClient, caps, jsonPort, jsonNodeId);
assertThat(peerConn.getPeerInfo()).isEqualTo(jsonPeer);
assertThat(ethPeer.getConnection().getPeerInfo()).isEqualTo(jsonPeer);
}
}
@ -108,7 +127,7 @@ public class AdminJsonRpcHttpServiceTest extends JsonRpcHttpServiceTest {
final List<Capability> caps = new ArrayList<>();
for (final Object jsonCap : jsonCaps) {
final StringTokenizer st = new StringTokenizer(jsonCap.toString(), "/");
caps.add(Capability.create(st.nextToken(), Integer.valueOf(st.nextToken())));
caps.add(Capability.create(st.nextToken(), Integer.parseInt(st.nextToken())));
}
return caps;
}

@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@ -119,7 +120,8 @@ public class JsonRpcHttpServiceHostWhitelistTest {
mock(MetricsConfiguration.class),
natService,
new HashMap<>(),
folder.getRoot().toPath()));
folder.getRoot().toPath(),
mock(EthPeers.class)));
service = createJsonRpcHttpService();
service.start().join();

@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@ -145,7 +146,8 @@ public class JsonRpcHttpServiceLoginTest {
mock(MetricsConfiguration.class),
natService,
new HashMap<>(),
folder.getRoot().toPath()));
folder.getRoot().toPath(),
mock(EthPeers.class)));
service = createJsonRpcHttpService();
jwtAuth = service.authenticationService.get().getJwtAuthProvider();
service.start().join();

@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration;
@ -213,7 +214,8 @@ public class JsonRpcHttpServiceRpcApisTest {
mock(MetricsConfiguration.class),
natService,
new HashMap<>(),
folder.getRoot().toPath()));
folder.getRoot().toPath(),
mock(EthPeers.class)));
final JsonRpcHttpService jsonRpcHttpService =
new JsonRpcHttpService(
vertx,
@ -307,7 +309,8 @@ public class JsonRpcHttpServiceRpcApisTest {
metricsConfiguration,
natService,
new HashMap<>(),
folder.getRoot().toPath()));
folder.getRoot().toPath(),
mock(EthPeers.class)));
final JsonRpcHttpService jsonRpcHttpService =
new JsonRpcHttpService(
vertx,

@ -47,6 +47,7 @@ import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@ -104,6 +105,7 @@ public class JsonRpcHttpServiceTest {
protected static final String CLIENT_VERSION = "TestClientVersion/0.1.0";
protected static final BigInteger CHAIN_ID = BigInteger.valueOf(123);
protected static P2PNetwork peerDiscoveryMock;
protected static EthPeers ethPeersMock;
protected static BlockchainQueries blockchainQueries;
protected static Synchronizer synchronizer;
protected static final Collection<RpcApi> JSON_RPC_APIS =
@ -114,6 +116,7 @@ public class JsonRpcHttpServiceTest {
@BeforeClass
public static void initServerAndClient() throws Exception {
peerDiscoveryMock = mock(P2PNetwork.class);
ethPeersMock = mock(EthPeers.class);
blockchainQueries = mock(BlockchainQueries.class);
synchronizer = mock(Synchronizer.class);
@ -147,7 +150,8 @@ public class JsonRpcHttpServiceTest {
mock(MetricsConfiguration.class),
natService,
new HashMap<>(),
folder.getRoot().toPath()));
folder.getRoot().toPath(),
ethPeersMock));
service = createJsonRpcHttpService();
service.start().join();

@ -39,6 +39,7 @@ import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@ -137,7 +138,8 @@ public class JsonRpcHttpServiceTlsClientAuthTest {
mock(MetricsConfiguration.class),
natService,
Collections.emptyMap(),
folder.getRoot().toPath()));
folder.getRoot().toPath(),
mock(EthPeers.class)));
System.setProperty("javax.net.ssl.trustStore", CLIENT_AS_CA_CERT.getKeyStoreFile().toString());
System.setProperty(

@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@ -125,7 +126,8 @@ public class JsonRpcHttpServiceTlsMisconfigurationTest {
mock(MetricsConfiguration.class),
natService,
Collections.emptyMap(),
folder.getRoot().toPath()));
folder.getRoot().toPath(),
mock(EthPeers.class)));
}
@After

@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.blockcreation.EthHashMiningCoordinator;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@ -128,7 +129,8 @@ public class JsonRpcHttpServiceTlsTest {
mock(MetricsConfiguration.class),
natService,
Collections.emptyMap(),
folder.getRoot().toPath()));
folder.getRoot().toPath(),
mock(EthPeers.class)));
service = createJsonRpcHttpService(createJsonRpcConfig());
service.start().join();
baseUrl = service.url();

@ -25,10 +25,13 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorR
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.PeerResult;
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.p2p.network.exceptions.P2PDisabledException;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.PeerInfo;
import org.hyperledger.besu.testutil.TestClock;
import java.net.InetSocketAddress;
import java.util.Collection;
@ -37,6 +40,7 @@ import java.util.List;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import io.vertx.core.json.Json;
import org.apache.tuweni.bytes.Bytes;
import org.assertj.core.api.Assertions;
import org.junit.Before;
@ -51,10 +55,11 @@ public class AdminPeersTest {
private AdminPeers adminPeers;
@Mock private P2PNetwork p2pNetwork;
@Mock private EthPeers ethPeers;
@Before
public void before() {
adminPeers = new AdminPeers(p2pNetwork);
adminPeers = new AdminPeers(ethPeers);
}
@Test
@ -67,7 +72,6 @@ public class AdminPeersTest {
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(null, Collections.emptyList());
final JsonRpcRequestContext request = adminPeers();
when(p2pNetwork.getPeers()).thenReturn(Collections.emptyList());
final JsonRpcResponse response = adminPeers.response(request);
@ -76,23 +80,23 @@ public class AdminPeersTest {
@Test
public void shouldReturnExpectedPeerListWhenP2PNetworkHavePeers() {
final Collection<PeerConnection> peerList = peerList();
final Collection<EthPeer> peerList = peerList();
final List<PeerResult> expectedPeerResults =
peerList.stream().map(PeerResult::new).collect(Collectors.toList());
peerList.stream().map(PeerResult::fromEthPeer).collect(Collectors.toList());
final JsonRpcRequestContext request = adminPeers();
final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, expectedPeerResults);
when(p2pNetwork.getPeers()).thenReturn(peerList);
when(ethPeers.streamAllPeers()).thenReturn(peerList.stream());
final JsonRpcResponse response = adminPeers.response(request);
assertThat(response).isEqualToComparingFieldByFieldRecursively(expectedResponse);
assertThat(Json.encode(response)).isEqualTo(Json.encode(expectedResponse));
}
@Test
public void shouldFailIfP2pDisabled() {
when(p2pNetwork.getPeers()).thenThrow(new P2PDisabledException("P2P disabled."));
when(ethPeers.streamAllPeers()).thenThrow(new P2PDisabledException("P2P disabled."));
final JsonRpcRequestContext request = adminPeers();
final JsonRpcResponse expectedResponse =
@ -102,14 +106,15 @@ public class AdminPeersTest {
.isEqualToComparingFieldByField(expectedResponse);
}
private Collection<PeerConnection> peerList() {
private Collection<EthPeer> peerList() {
final PeerInfo peerInfo = new PeerInfo(5, "0x0", Collections.emptyList(), 30303, Bytes.EMPTY);
final PeerConnection p =
MockPeerConnection.create(
peerInfo,
InetSocketAddress.createUnresolved("1.2.3.4", 9876),
InetSocketAddress.createUnresolved("4.3.2.1", 6789));
return Lists.newArrayList(p);
final EthPeer ethPeer = new EthPeer(p, "eth", c -> {}, List.of(), TestClock.fixed());
return Lists.newArrayList(ethPeer);
}
private JsonRpcRequestContext adminPeers() {

@ -65,6 +65,7 @@ public class EthPeer {
private final ChainState chainHeadState;
private final AtomicBoolean statusHasBeenSentToPeer = new AtomicBoolean(false);
private final AtomicBoolean statusHasBeenReceivedFromPeer = new AtomicBoolean(false);
private final AtomicInteger lastProtocolVersion = new AtomicInteger(0);
private volatile long lastRequestTimestamp = 0;
private final RequestManager headersRequestManager = new RequestManager(this);
@ -77,7 +78,8 @@ public class EthPeer {
private final PeerReputation reputation = new PeerReputation();
private final Map<PeerValidator, Boolean> validationStatus = new HashMap<>();
EthPeer(
@VisibleForTesting
public EthPeer(
final PeerConnection connection,
final String protocolName,
final Consumer<EthPeer> onStatusesExchanged,
@ -97,7 +99,7 @@ public class EthPeer {
}));
this.chainHeadState = new ChainState();
this.onStatusesExchanged.set(onStatusesExchanged);
for (PeerValidator peerValidator : peerValidators) {
for (final PeerValidator peerValidator : peerValidators) {
validationStatus.put(peerValidator, false);
}
}
@ -115,7 +117,7 @@ public class EthPeer {
* @return {@code true} if all peer validation logic has run and successfully validated this peer
*/
public boolean isFullyValidated() {
for (Boolean isValid : validationStatus.values()) {
for (final Boolean isValid : validationStatus.values()) {
if (!isValid) {
return false;
}
@ -307,8 +309,10 @@ public class EthPeer {
maybeExecuteStatusesExchangedCallback();
}
public void registerStatusReceived(final Hash hash, final Difficulty td) {
public void registerStatusReceived(
final Hash hash, final Difficulty td, final int protocolVersion) {
chainHeadState.statusReceived(hash, td);
lastProtocolVersion.set(protocolVersion);
statusHasBeenReceivedFromPeer.set(true);
maybeExecuteStatusesExchangedCallback();
}
@ -363,6 +367,14 @@ public class EthPeer {
return chainHeadState;
}
public int getLastProtocolVersion() {
return lastProtocolVersion.get();
}
public String getProtocolName() {
return protocolName;
}
/**
* Return A read-only snapshot of this peer's current {@code chainState} }
*
@ -396,8 +408,7 @@ public class EthPeer {
return connection.getAgreedCapabilities();
}
@VisibleForTesting
PeerConnection getConnection() {
public PeerConnection getConnection() {
return connection;
}

@ -136,8 +136,12 @@ public class EthPeers {
return connections.size();
}
public Stream<EthPeer> streamAllPeers() {
return connections.values().stream();
}
public Stream<EthPeer> streamAvailablePeers() {
return connections.values().stream().filter(EthPeer::readyForRequests);
return streamAllPeers().filter(EthPeer::readyForRequests);
}
public Stream<EthPeer> streamBestPeers() {

@ -335,7 +335,8 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
peer.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
} else {
LOG.debug("Received status message from {}: {}", peer, status);
peer.registerStatusReceived(status.bestHash(), status.totalDifficulty());
peer.registerStatusReceived(
status.bestHash(), status.totalDifficulty(), status.protocolVersion());
}
} catch (final RLPException e) {
LOG.debug("Unable to parse status message, disconnecting from peer.", e);

@ -125,7 +125,7 @@ public class RespondingEthPeer {
caps, (cap, msg, conn) -> outgoingMessages.add(new OutgoingMessage(cap, msg)));
ethPeers.registerConnection(peerConnection, peerValidators);
final EthPeer peer = ethPeers.peer(peerConnection);
peer.registerStatusReceived(chainHeadHash, totalDifficulty);
peer.registerStatusReceived(chainHeadHash, totalDifficulty, 63);
estimatedHeight.ifPresent(height -> peer.chainState().update(chainHeadHash, height));
peer.registerStatusSent();

Loading…
Cancel
Save