use of org.hyperledger.besu.ethereum.eth.sync.tasks.RetryingGetHeaderFromPeerByNumberTask in project besu by hyperledger.
the class FastSyncTargetManager method confirmPivotBlockHeader.
private CompletableFuture<Optional<EthPeer>> confirmPivotBlockHeader(final EthPeer bestPeer) {
final BlockHeader pivotBlockHeader = fastSyncState.getPivotBlockHeader().get();
final RetryingGetHeaderFromPeerByNumberTask task = RetryingGetHeaderFromPeerByNumberTask.forSingleNumber(protocolSchedule, ethContext, metricsSystem, pivotBlockHeader.getNumber(), MAX_QUERY_RETRIES_PER_PEER);
task.assignPeer(bestPeer);
return ethContext.getScheduler().timeout(task).thenCompose(result -> {
if (peerHasDifferentPivotBlock(result)) {
if (!hasPivotChanged(pivotBlockHeader)) {
// if the pivot block has not changed, then warn and disconnect this peer
LOG.warn("Best peer has wrong pivot block (#{}) expecting {} but received {}. Disconnect: {}", pivotBlockHeader.getNumber(), pivotBlockHeader.getHash(), result.size() == 1 ? result.get(0).getHash() : "invalid response", bestPeer);
bestPeer.disconnect(DisconnectReason.USELESS_PEER);
return CompletableFuture.completedFuture(Optional.<EthPeer>empty());
}
LOG.debug("Retrying best peer {} with new pivot block {}", bestPeer.getShortNodeId(), pivotBlockHeader.toLogString());
return confirmPivotBlockHeader(bestPeer);
} else {
return CompletableFuture.completedFuture(Optional.of(bestPeer));
}
}).exceptionally(error -> {
LOG.debug("Could not confirm best peer had pivot block", error);
return Optional.empty();
});
}
use of org.hyperledger.besu.ethereum.eth.sync.tasks.RetryingGetHeaderFromPeerByNumberTask in project besu by hyperledger.
the class PivotBlockConfirmer method executePivotQuery.
private CompletableFuture<BlockHeader> executePivotQuery(final long blockNumber) {
if (isCancelled.get() || result.isDone()) {
// Stop loop if this task is done
return CompletableFuture.failedFuture(new CancellationException());
}
final Optional<RetryingGetHeaderFromPeerByNumberTask> query = createPivotQuery(blockNumber);
final CompletableFuture<BlockHeader> pivotHeaderFuture;
if (query.isPresent()) {
final CompletableFuture<BlockHeader> headerQuery = query.get().getHeader();
pivotHeaderFuture = FutureUtils.exceptionallyCompose(headerQuery, (error) -> executePivotQuery(blockNumber));
} else {
// We were unable to find a peer to query, wait and try again
LOG.debug("No peer currently available to query for block {}.", blockNumber);
pivotHeaderFuture = ethContext.getScheduler().timeout(WaitForPeerTask.create(ethContext, metricsSystem), Duration.ofSeconds(5)).handle(// Ignore result
(err, res) -> null).thenCompose(res -> executePivotQuery(blockNumber));
}
return pivotHeaderFuture;
}
use of org.hyperledger.besu.ethereum.eth.sync.tasks.RetryingGetHeaderFromPeerByNumberTask in project besu by hyperledger.
the class PivotBlockConfirmer method createGetHeaderTask.
Optional<RetryingGetHeaderFromPeerByNumberTask> createGetHeaderTask(final EthPeer peer, final long blockNumber) {
final RetryingGetHeaderFromPeerByNumberTask task = RetryingGetHeaderFromPeerByNumberTask.forSingleNumber(protocolSchedule, ethContext, metricsSystem, blockNumber, numberOfRetriesPerPeer);
task.assignPeer(peer);
// Try adding our task
synchronized (runningQueries) {
if (isCancelled.get()) {
// Don't run a new query if this task is already cancelled
return Optional.empty();
}
final RetryingGetHeaderFromPeerByNumberTask preexistingTask = pivotBlockQueriesByPeerId.putIfAbsent(peer.nodeId(), task);
if (preexistingTask != null) {
// We already have a task for this peer, try again later
return Optional.empty();
}
}
LOG.debug("Query peer {}... for block {}.", peer.nodeId().toString().substring(0, 8), blockNumber);
return Optional.of(task);
}
Aggregations