use of org.hyperledger.besu.ethereum.eth.messages.StatusMessage in project besu by hyperledger.
the class EthProtocolManager method handleStatusMessage.
private void handleStatusMessage(final EthPeer peer, final MessageData data) {
final StatusMessage status = StatusMessage.readFrom(data);
try {
if (!status.networkId().equals(networkId)) {
LOG.debug("{} has mismatched network id: {}", peer, status.networkId());
peer.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
} else if (!forkIdManager.peerCheck(status.forkId()) && status.protocolVersion() > 63) {
LOG.debug("{} has matching network id ({}), but non-matching fork id: {}", peer, networkId, status.forkId());
peer.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
} else if (forkIdManager.peerCheck(status.genesisHash())) {
LOG.debug("{} has matching network id ({}), but non-matching genesis hash: {}", peer, networkId, status.genesisHash());
peer.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
} else if (isFinalized()) {
long lockStamp = this.powTerminalDifficultyLock.readLock();
try {
if (this.powTerminalDifficulty.isPresent() && status.totalDifficulty().greaterThan(this.powTerminalDifficulty.get())) {
LOG.debug("Disconnecting peer with difficulty {}, likely still on PoW chain", status.totalDifficulty());
peer.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
}
} finally {
this.powTerminalDifficultyLock.unlockRead(lockStamp);
}
} else {
LOG.debug("Received status message from {}: {}", peer, status);
peer.registerStatusReceived(status.bestHash(), status.totalDifficulty(), status.protocolVersion());
}
} catch (final RLPException e) {
LOG.debug("Unable to parse status message.", e);
// Parsing errors can happen when clients broadcast network ids outside the int range,
// So just disconnect with "subprotocol" error rather than "breach of protocol".
peer.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
}
}
use of org.hyperledger.besu.ethereum.eth.messages.StatusMessage in project besu by hyperledger.
the class EthProtocolManagerTest method disconnectOnWrongGenesisHash.
@Test
public void disconnectOnWrongGenesisHash() {
try (final EthProtocolManager ethManager = EthProtocolManagerTestUtil.create(blockchain, () -> false, protocolContext.getWorldStateArchive(), transactionPool, EthProtocolConfiguration.defaultConfig())) {
final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get()));
final MockPeerConnection peer = setupPeerWithoutStatusExchange(ethManager, (cap, msg, conn) -> {
});
// Send status message with wrong chain
final StatusMessage statusMessage = StatusMessage.create(EthProtocol.EthVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), gen.hash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash());
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, statusMessage));
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData));
assertThat(peer.isDisconnected()).isTrue();
}
}
use of org.hyperledger.besu.ethereum.eth.messages.StatusMessage in project besu by hyperledger.
the class EthProtocolManagerTest method disconnectPoWPeersAfterTransition.
@Test
public void disconnectPoWPeersAfterTransition() {
try (final EthProtocolManager ethManager = EthProtocolManagerTestUtil.create(blockchain, () -> false, protocolContext.getWorldStateArchive(), transactionPool, EthProtocolConfiguration.defaultConfig())) {
final MockPeerConnection workPeer = setupPeer(ethManager, (cap, msg, conn) -> {
});
final MockPeerConnection stakePeer = setupPeer(ethManager, (cap, msg, conn) -> {
});
final StatusMessage workPeerStatus = StatusMessage.create(EthProtocol.EthVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty().add(20), blockchain.getChainHeadHash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash());
final StatusMessage stakePeerStatus = StatusMessage.create(EthProtocol.EthVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash());
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(workPeer, workPeerStatus));
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(stakePeer, stakePeerStatus));
ethManager.onCrossingMergeBoundary(true, Optional.of(blockchain.getChainHead().getTotalDifficulty()));
ethManager.onNewForkchoiceMessage(Hash.EMPTY, Optional.of(Hash.hash(Bytes.of(1))), Hash.EMPTY);
ethManager.onNewForkchoiceMessage(Hash.EMPTY, Optional.of(Hash.hash(Bytes.of(2))), Hash.EMPTY);
assertThat(workPeer.isDisconnected()).isTrue();
assertThat(workPeer.getDisconnectReason()).isPresent();
assertThat(workPeer.getDisconnectReason()).get().isEqualTo(DisconnectReason.SUBPROTOCOL_TRIGGERED);
assertThat(stakePeer.isDisconnected()).isFalse();
}
}
use of org.hyperledger.besu.ethereum.eth.messages.StatusMessage in project besu by hyperledger.
the class EthProtocolManagerTest method shouldSuccessfullyRespondToGetHeadersRequestLessThanZero.
@Test
public void shouldSuccessfullyRespondToGetHeadersRequestLessThanZero() throws ExecutionException, InterruptedException {
final Block genesisBlock = gen.genesisBlock();
final MutableBlockchain blockchain = createInMemoryBlockchain(genesisBlock);
final BlockDataGenerator.BlockOptions options = new BlockDataGenerator.BlockOptions().setBlockNumber(1L).setParentHash(blockchain.getBlockHashByNumber(0L).get());
final Block block = gen.block(options);
final List<TransactionReceipt> receipts = gen.receipts(block);
blockchain.appendBlock(block, receipts);
final CompletableFuture<Void> done = new CompletableFuture<>();
try (final EthProtocolManager ethManager = EthProtocolManagerTestUtil.create(blockchain, () -> false, protocolContext.getWorldStateArchive(), transactionPool, EthProtocolConfiguration.defaultConfig())) {
final long startBlock = 1L;
final int requestedBlockCount = 13;
final int receivedBlockCount = 2;
final MessageData messageData = GetBlockHeadersMessage.create(startBlock, requestedBlockCount, 0, true);
final MockPeerConnection.PeerSendHandler onSend = (cap, message, conn) -> {
if (message.getCode() == EthPV62.STATUS) {
// Ignore status message
return;
}
assertThat(message.getCode()).isEqualTo(EthPV62.BLOCK_HEADERS);
final BlockHeadersMessage headersMsg = BlockHeadersMessage.readFrom(message);
final List<BlockHeader> headers = Lists.newArrayList(headersMsg.getHeaders(protocolSchedule));
assertThat(headers).hasSize(receivedBlockCount);
for (int i = 0; i < receivedBlockCount; i++) {
assertThat(headers.get(i).getNumber()).isEqualTo(receivedBlockCount - 1 - i);
}
done.complete(null);
};
final Set<Capability> caps = new HashSet<>(Collections.singletonList(EthProtocol.ETH63));
final MockPeerConnection peer = new MockPeerConnection(caps, onSend);
ethManager.handleNewConnection(peer);
final StatusMessage statusMessage = StatusMessage.create(EthProtocol.EthVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash());
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, statusMessage));
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData));
done.get();
}
}
use of org.hyperledger.besu.ethereum.eth.messages.StatusMessage in project besu by hyperledger.
the class EthProtocolManagerTest method setupPeer.
private MockPeerConnection setupPeer(final EthProtocolManager ethManager, final PeerSendHandler onSend) {
final MockPeerConnection peer = setupPeerWithoutStatusExchange(ethManager, onSend);
final StatusMessage statusMessage = StatusMessage.create(EthProtocol.EthVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash());
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, statusMessage));
return peer;
}
Aggregations