use of org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage in project besu by hyperledger.
the class FastSyncChainDownloaderTest method recoversFromSyncTargetDisconnect.
@Test
public void recoversFromSyncTargetDisconnect() {
final BlockchainSetupUtil shorterChainUtil = BlockchainSetupUtil.forTesting(storageFormat);
final MutableBlockchain shorterChain = shorterChainUtil.getBlockchain();
otherBlockchainSetup.importFirstBlocks(30);
shorterChainUtil.importFirstBlocks(28);
final RespondingEthPeer bestPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, otherBlockchain);
final RespondingEthPeer secondBestPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, shorterChain);
final RespondingEthPeer.Responder shorterResponder = RespondingEthPeer.blockchainResponder(shorterChain);
// Doesn't respond to requests for checkpoints unless it's starting from genesis
// So the import can only make it as far as block 15 (3 checkpoints 5 blocks apart)
final RespondingEthPeer.Responder shorterLimitedRangeResponder = RespondingEthPeer.targetedResponder((cap, msg) -> {
if (msg.getCode() == EthPV62.GET_BLOCK_HEADERS) {
final GetBlockHeadersMessage request = GetBlockHeadersMessage.readFrom(msg);
return request.skip() == 0 || (request.hash().equals(localBlockchain.getBlockHashByNumber(0)));
} else {
return true;
}
}, (cap, msg) -> shorterResponder.respond(cap, msg).get());
final SynchronizerConfiguration syncConfig = SynchronizerConfiguration.builder().downloaderChainSegmentSize(5).downloaderHeadersRequestSize(3).downloaderParallelism(1).build();
final long pivotBlockNumber = 25;
final ChainDownloader downloader = downloader(syncConfig, pivotBlockNumber);
final CompletableFuture<Void> result = downloader.start();
while (localBlockchain.getChainHeadBlockNumber() < 15) {
bestPeer.respond(shorterLimitedRangeResponder);
secondBestPeer.respond(shorterLimitedRangeResponder);
LockSupport.parkNanos(200);
}
assertThat(localBlockchain.getChainHeadBlockNumber()).isEqualTo(15);
assertThat(result).isNotCompleted();
ethProtocolManager.handleDisconnect(bestPeer.getPeerConnection(), TOO_MANY_PEERS, true);
secondBestPeer.respondWhileOtherThreadsWork(shorterResponder, () -> !result.isDone());
assertThat(result).isCompleted();
assertThat(localBlockchain.getChainHeadBlockNumber()).isEqualTo(pivotBlockNumber);
assertThat(localBlockchain.getChainHeadHeader()).isEqualTo(otherBlockchain.getBlockHeader(pivotBlockNumber).get());
}
use of org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage in project besu by hyperledger.
the class EthPeer method getHeadersByHash.
public RequestManager.ResponseStream getHeadersByHash(final Hash hash, final int maxHeaders, final int skip, final boolean reverse) throws PeerNotConnected {
final GetBlockHeadersMessage message = GetBlockHeadersMessage.create(hash, maxHeaders, skip, reverse);
final RequestManager requestManager = requestManagers.get(protocolName).get(EthPV62.GET_BLOCK_HEADERS);
return sendRequest(requestManager, message);
}
use of org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage in project besu by hyperledger.
the class EthServer method constructGetHeadersResponse.
static MessageData constructGetHeadersResponse(final Blockchain blockchain, final MessageData message, final int requestLimit) {
final GetBlockHeadersMessage getHeaders = GetBlockHeadersMessage.readFrom(message);
final Optional<Hash> hash = getHeaders.hash();
final int skip = getHeaders.skip();
final int maxHeaders = Math.min(requestLimit, getHeaders.maxHeaders());
final boolean reversed = getHeaders.reverse();
final BlockHeader firstHeader;
if (hash.isPresent()) {
final Hash startHash = hash.get();
firstHeader = blockchain.getBlockHeader(startHash).orElse(null);
} else {
final long firstNumber = getHeaders.blockNumber().getAsLong();
firstHeader = blockchain.getBlockHeader(firstNumber).orElse(null);
}
final Collection<BlockHeader> resp;
if (firstHeader == null) {
resp = Collections.emptyList();
} else {
resp = Lists.newArrayList(firstHeader);
final long numberDelta = reversed ? -(skip + 1) : (skip + 1);
for (int i = 1; i < maxHeaders; i++) {
final long blockNumber = firstHeader.getNumber() + i * numberDelta;
if (blockNumber < BlockHeader.GENESIS_BLOCK_NUMBER) {
break;
}
final Optional<BlockHeader> maybeHeader = blockchain.getBlockHeader(blockNumber);
if (maybeHeader.isPresent()) {
resp.add(maybeHeader.get());
} else {
break;
}
}
}
return BlockHeadersMessage.create(resp);
}
use of org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage in project besu by hyperledger.
the class AbstractPeerBlockValidatorTest method respondToBlockRequest.
AtomicBoolean respondToBlockRequest(final RespondingEthPeer peer, final Block block) {
final AtomicBoolean blockRequested = new AtomicBoolean(false);
final RespondingEthPeer.Responder responder = RespondingEthPeer.targetedResponder((cap, msg) -> {
if (msg.getCode() != EthPV62.GET_BLOCK_HEADERS) {
return false;
}
final GetBlockHeadersMessage headersRequest = GetBlockHeadersMessage.readFrom(msg);
final boolean isTargetedBlockRequest = headersRequest.blockNumber().isPresent() && headersRequest.blockNumber().getAsLong() == block.getHeader().getNumber();
if (isTargetedBlockRequest) {
blockRequested.set(true);
}
return isTargetedBlockRequest;
}, (cap, msg) -> BlockHeadersMessage.create(block.getHeader()));
// Respond
peer.respond(responder);
return blockRequested;
}
use of org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage in project besu by hyperledger.
the class FullSyncChainDownloaderTest method recoversFromSyncTargetDisconnect.
@Test
public void recoversFromSyncTargetDisconnect() {
localBlockchainSetup.importFirstBlocks(2);
final long localChainHeadAtStart = localBlockchain.getChainHeadBlockNumber();
otherBlockchainSetup.importAllBlocks();
final long targetBlock = otherBlockchain.getChainHeadBlockNumber();
// Sanity check
assertThat(targetBlock).isGreaterThan(localBlockchain.getChainHeadBlockNumber());
final SynchronizerConfiguration syncConfig = syncConfigBuilder().downloaderChainSegmentSize(5).downloaderHeadersRequestSize(3).build();
final ChainDownloader downloader = downloader(syncConfig);
final long bestPeerChainHead = otherBlockchain.getChainHeadBlockNumber();
final RespondingEthPeer bestPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, otherBlockchain);
final long secondBestPeerChainHead = bestPeerChainHead - 3;
final Blockchain shorterChain = createShortChain(otherBlockchain, secondBestPeerChainHead);
final RespondingEthPeer secondBestPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, shorterChain);
final RespondingEthPeer.Responder bestResponder = RespondingEthPeer.blockchainResponder(otherBlockchain);
final RespondingEthPeer.Responder secondBestResponder = RespondingEthPeer.blockchainResponder(shorterChain);
downloader.start();
// Process through sync target selection
bestPeer.respondWhileOtherThreadsWork(bestResponder, () -> !syncState.syncTarget().isPresent());
assertThat(syncState.syncTarget()).isPresent();
assertThat(syncState.syncTarget().get().peer()).isEqualTo(bestPeer.getEthPeer());
// The next message should be for checkpoint headers from the sync target
Awaitility.waitAtMost(10, TimeUnit.SECONDS).until(() -> bestPeer.peekNextOutgoingRequest().isPresent());
final Optional<MessageData> maybeNextMessage = bestPeer.peekNextOutgoingRequest();
assertThat(maybeNextMessage).isPresent();
final MessageData nextMessage = maybeNextMessage.get();
assertThat(nextMessage.getCode()).isEqualTo(EthPV62.GET_BLOCK_HEADERS);
final GetBlockHeadersMessage headersMessage = GetBlockHeadersMessage.readFrom(nextMessage);
assertThat(headersMessage.skip()).isGreaterThan(0);
// Process through the first import
await().atMost(10, TimeUnit.SECONDS).pollInterval(100, TimeUnit.MILLISECONDS).untilAsserted(() -> {
if (!bestPeer.respond(bestResponder)) {
secondBestPeer.respond(secondBestResponder);
}
assertThat(localBlockchain.getChainHeadBlockNumber()).isNotEqualTo(localChainHeadAtStart);
});
// Sanity check that we haven't already passed the second best peer
assertThat(localBlockchain.getChainHeadBlockNumber()).isLessThan(secondBestPeerChainHead);
// Disconnect peer
ethProtocolManager.handleDisconnect(bestPeer.getPeerConnection(), DisconnectReason.TOO_MANY_PEERS, true);
// Downloader should recover and sync to next best peer, but it may stall
// for 10 seconds first (by design).
secondBestPeer.respondWhileOtherThreadsWork(secondBestResponder, () -> localBlockchain.getChainHeadBlockNumber() != secondBestPeerChainHead);
assertThat(localBlockchain.getChainHeadBlockNumber()).isEqualTo(secondBestPeerChainHead);
}
Aggregations