use of org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage in project besu by hyperledger.
the class Istanbul99ProtocolManagerTest method respondToEth65GetHeadersUsingIstanbul99.
@Test
public void respondToEth65GetHeadersUsingIstanbul99() throws ExecutionException, InterruptedException, TimeoutException {
final CompletableFuture<Void> done = new CompletableFuture<>();
final EthScheduler ethScheduler = new DeterministicEthScheduler(() -> false);
EthPeers peers = new EthPeers(Istanbul99Protocol.NAME, TestClock.fixed(), new NoOpMetricsSystem(), 25);
EthMessages messages = new EthMessages();
final BigInteger networkId = BigInteger.ONE;
try (final EthProtocolManager ethManager = new Istanbul99ProtocolManager(blockchain, networkId, protocolContext.getWorldStateArchive(), transactionPool, EthProtocolConfiguration.defaultConfig(), peers, messages, new EthContext(peers, messages, ethScheduler), Collections.emptyList(), false, ethScheduler)) {
final long startBlock = blockchain.getChainHeadBlockNumber() + 1;
final int blockCount = 5;
final MessageData messageData = GetBlockHeadersMessage.create(startBlock, blockCount, 0, false);
final 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.size()).isEqualTo(0);
done.complete(null);
};
final PeerConnection peer = setupPeer(ethManager, onSend);
ethManager.processMessage(Istanbul99Protocol.ISTANBUL99, new DefaultMessage(peer, messageData));
done.get(10, TimeUnit.SECONDS);
}
}
use of org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage in project besu by hyperledger.
the class DownloadHeaderSequenceTaskTest method failsWhenPeerReturnsOnlySubsetOfHeaders.
@Test
public void failsWhenPeerReturnsOnlySubsetOfHeaders() {
final RespondingEthPeer respondingPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager);
// Execute task and wait for response
final BlockHeader referenceHeader = blockchain.getChainHeadHeader();
final EthTask<List<BlockHeader>> task = DownloadHeaderSequenceTask.endingAtHeader(protocolSchedule, protocolContext, ethContext, referenceHeader, 10, maxRetries, validationPolicy, metricsSystem);
final CompletableFuture<List<BlockHeader>> future = task.run();
// Filter response to include only reference header and previous header
final RespondingEthPeer.Responder fullResponder = RespondingEthPeer.blockchainResponder(blockchain);
final RespondingEthPeer.Responder responder = (cap, message) -> {
final Optional<MessageData> fullResponse = fullResponder.respond(cap, message);
if (!fullResponse.isPresent() || message.getCode() != EthPV62.GET_BLOCK_HEADERS) {
return fullResponse;
}
final BlockHeadersMessage headersMessage = BlockHeadersMessage.readFrom(fullResponse.get());
// Filter for a subset of headers
final List<BlockHeader> headerSubset = headersMessage.getHeaders(protocolSchedule).stream().filter(h -> h.getNumber() >= referenceHeader.getNumber() - 1L).collect(Collectors.toList());
return Optional.of(BlockHeadersMessage.create(headerSubset));
};
respondingPeer.respondTimes(responder, 100);
assertThat(future.isDone()).isTrue();
assertThat(future.isCompletedExceptionally()).isTrue();
assertThatThrownBy(future::get).hasCauseInstanceOf(MaxRetriesReachedException.class);
}
use of org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage in project besu by hyperledger.
the class AbstractGetHeadersFromPeerTask method processResponse.
@Override
protected Optional<List<BlockHeader>> processResponse(final boolean streamClosed, final MessageData message, final EthPeer peer) {
if (streamClosed) {
// All outstanding requests have been responded to and we still haven't found the response
// we wanted. It must have been empty or contain data that didn't match.
peer.recordUselessResponse("headers");
return Optional.of(Collections.emptyList());
}
final BlockHeadersMessage headersMessage = BlockHeadersMessage.readFrom(message);
final List<BlockHeader> headers = headersMessage.getHeaders(protocolSchedule);
if (headers.isEmpty()) {
// Message contains no data - nothing to do
LOG.debug("headers.isEmpty. Peer: {}", peer);
return Optional.empty();
}
if (headers.size() > count) {
// Too many headers - this isn't our response
LOG.debug("headers.size()>count. Peer: {}", peer);
return Optional.empty();
}
final BlockHeader firstHeader = headers.get(0);
if (!matchesFirstHeader(firstHeader)) {
// This isn't our message - nothing to do
LOG.debug("!matchesFirstHeader. Peer: {}", peer);
return Optional.empty();
}
final List<BlockHeader> headersList = new ArrayList<>();
headersList.add(firstHeader);
BlockHeader prevBlockHeader = firstHeader;
final int expectedDelta = reverse ? -(skip + 1) : (skip + 1);
for (int i = 1; i < headers.size(); i++) {
final BlockHeader header = headers.get(i);
if (header.getNumber() != prevBlockHeader.getNumber() + expectedDelta) {
// Skip doesn't match, this isn't our data
LOG.debug("header not matching the expected number. Peer: {}", peer);
return Optional.empty();
}
// if headers are supposed to be sequential check if a chain is formed
if (Math.abs(expectedDelta) == 1) {
final BlockHeader parent = reverse ? header : prevBlockHeader;
final BlockHeader child = reverse ? prevBlockHeader : header;
if (!parent.getHash().equals(child.getParentHash())) {
LOG.debug("Sequential headers must form a chain through hashes, disconnecting peer: {}", peer);
peer.disconnect(DisconnectMessage.DisconnectReason.BREACH_OF_PROTOCOL);
return Optional.empty();
}
}
prevBlockHeader = header;
headersList.add(header);
}
LOG.debug("Received {} of {} headers requested from peer {}", headersList.size(), count, peer);
return Optional.of(headersList);
}
use of org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage in project besu by hyperledger.
the class EthProtocolManagerTest method respondToGetHeaders.
@Test
public void respondToGetHeaders() throws ExecutionException, InterruptedException {
final CompletableFuture<Void> done = new CompletableFuture<>();
try (final EthProtocolManager ethManager = EthProtocolManagerTestUtil.create(blockchain, () -> false, protocolContext.getWorldStateArchive(), transactionPool, EthProtocolConfiguration.defaultConfig())) {
final long startBlock = 5L;
final int blockCount = 5;
final MessageData messageData = GetBlockHeadersMessage.create(startBlock, blockCount, 0, false);
final 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(blockCount);
for (int i = 0; i < blockCount; i++) {
assertThat(headers.get(i).getNumber()).isEqualTo(startBlock + i);
}
done.complete(null);
};
final PeerConnection peer = setupPeer(ethManager, onSend);
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData));
done.get();
}
}
use of org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage in project besu by hyperledger.
the class EthProtocolManagerTest method respondToGetHeadersWithinLimits.
@Test
public void respondToGetHeadersWithinLimits() throws ExecutionException, InterruptedException {
final CompletableFuture<Void> done = new CompletableFuture<>();
final int limit = 5;
try (final EthProtocolManager ethManager = EthProtocolManagerTestUtil.create(blockchain, () -> false, protocolContext.getWorldStateArchive(), transactionPool, new EthProtocolConfiguration(limit, limit, limit, limit, limit, false))) {
final long startBlock = 5L;
final int blockCount = 10;
final MessageData messageData = GetBlockHeadersMessage.create(startBlock, blockCount, 0, false);
final 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(limit);
for (int i = 0; i < limit; i++) {
assertThat(headers.get(i).getNumber()).isEqualTo(startBlock + i);
}
done.complete(null);
};
final PeerConnection peer = setupPeer(ethManager, onSend);
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData));
done.get();
}
}
Aggregations