Search in sources :

Example 1 with Eth2Peer

use of tech.pegasys.teku.networking.eth2.peers.Eth2Peer in project teku by ConsenSys.

the class FetchBlockTask method run.

public SafeFuture<FetchBlockResult> run() {
    if (cancelled.get()) {
        return SafeFuture.completedFuture(FetchBlockResult.createFailed(Status.CANCELLED));
    }
    final Optional<Eth2Peer> maybePeer = eth2Network.streamPeers().filter(p -> !queriedPeers.contains(p.getId())).min(Comparator.comparing(Eth2Peer::getOutstandingRequests).thenComparing(SHUFFLING_COMPARATOR));
    if (maybePeer.isEmpty()) {
        return SafeFuture.completedFuture(FetchBlockResult.createFailed(Status.NO_AVAILABLE_PEERS));
    }
    final Eth2Peer peer = maybePeer.get();
    numberOfRuns.incrementAndGet();
    queriedPeers.add(peer.getId());
    return peer.requestBlockByRoot(blockRoot).thenApply(maybeBlock -> maybeBlock.map(FetchBlockResult::createSuccessful).orElseGet(() -> FetchBlockResult.createFailed(Status.FETCH_FAILED))).exceptionally(err -> {
        LOG.debug("Failed to fetch block " + blockRoot, err);
        return FetchBlockResult.createFailed(Status.FETCH_FAILED);
    });
}
Also used : Status(tech.pegasys.teku.beacon.sync.gossip.FetchBlockTask.FetchBlockResult.Status) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SafeFuture(tech.pegasys.teku.infrastructure.async.SafeFuture) Logger(org.apache.logging.log4j.Logger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) P2PNetwork(tech.pegasys.teku.networking.p2p.network.P2PNetwork) Eth2Peer(tech.pegasys.teku.networking.eth2.peers.Eth2Peer) Optional(java.util.Optional) Comparator(java.util.Comparator) NoSuchElementException(java.util.NoSuchElementException) SignedBeaconBlock(tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock) Collections(java.util.Collections) LogManager(org.apache.logging.log4j.LogManager) Bytes32(org.apache.tuweni.bytes.Bytes32) NodeId(tech.pegasys.teku.networking.p2p.peer.NodeId) Eth2Peer(tech.pegasys.teku.networking.eth2.peers.Eth2Peer)

Example 2 with Eth2Peer

use of tech.pegasys.teku.networking.eth2.peers.Eth2Peer in project teku by ConsenSys.

the class SyncManagerTest method sync_retrySyncIfNotSuccessful.

@Test
void sync_retrySyncIfNotSuccessful() {
    when(network.streamPeers()).thenReturn(Stream.of(peer));
    final SafeFuture<PeerSyncResult> syncFuture = new SafeFuture<>();
    when(peerSync.sync(peer)).thenReturn(syncFuture);
    assertThat(syncManager.start()).isCompleted();
    assertThat(syncManager.isSyncActive()).isTrue();
    assertThat(syncManager.isSyncQueued()).isFalse();
    verify(peerSync).sync(peer);
    // The sync didn't complete correctly so we should start a new one with a new peer
    final Eth2Peer peer2 = mock(Eth2Peer.class);
    when(peer2.getStatus()).thenReturn(peerStatus);
    when(network.streamPeers()).thenReturn(Stream.of(peer2));
    when(peerSync.sync(peer2)).thenReturn(new SafeFuture<>());
    syncFuture.complete(PeerSyncResult.FAULTY_ADVERTISEMENT);
    asyncRunner.executeQueuedActions();
    verify(peerSync).sync(peer2);
    assertThat(syncManager.isSyncActive()).isTrue();
    assertThat(syncManager.isSyncQueued()).isFalse();
}
Also used : SafeFuture(tech.pegasys.teku.infrastructure.async.SafeFuture) Eth2Peer(tech.pegasys.teku.networking.eth2.peers.Eth2Peer) Test(org.junit.jupiter.api.Test)

Example 3 with Eth2Peer

use of tech.pegasys.teku.networking.eth2.peers.Eth2Peer in project teku by ConsenSys.

the class PeerSync method executeSync.

@SuppressWarnings("FutureReturnValueIgnored")
private SafeFuture<PeerSyncResult> executeSync(final Eth2Peer peer, final UInt64 startSlot, final SafeFuture<Void> readyForRequest, final boolean findCommonAncestor) {
    if (stopped.get()) {
        return SafeFuture.completedFuture(PeerSyncResult.CANCELLED);
    }
    final PeerStatus status = peer.getStatus();
    final UInt64 count = calculateNumberOfBlocksToRequest(startSlot, status);
    if (count.longValue() == 0) {
        return completeSyncWithPeer(peer, status);
    }
    return readyForRequest.thenCompose(__ -> {
        if (!findCommonAncestor) {
            return SafeFuture.completedFuture(startSlot);
        }
        CommonAncestor ancestor = new CommonAncestor(storageClient);
        return ancestor.getCommonAncestor(peer, startSlot, status.getHeadSlot());
    }).thenCompose((ancestorStartSlot) -> {
        if (findCommonAncestor) {
            LOG.trace("Start sync from slot {}, instead of {}", ancestorStartSlot, startSlot);
        }
        LOG.debug("Request {} blocks starting at {} from peer {}", count, ancestorStartSlot, peer.getId());
        final SafeFuture<Void> readyForNextRequest = asyncRunner.getDelayedFuture(NEXT_REQUEST_TIMEOUT);
        final PeerSyncBlockRequest request = new PeerSyncBlockRequest(readyForNextRequest, ancestorStartSlot.plus(count), this::blockResponseListener);
        return peer.requestBlocksByRange(ancestorStartSlot, count, STEP, request).thenApply((res) -> request);
    }).thenCompose((blockRequest) -> {
        final UInt64 nextSlot = blockRequest.getActualEndSlot().plus(UInt64.ONE);
        LOG.trace("Completed request for {} slots from peer {}. Next request starts from {}", count, peer.getId(), nextSlot);
        if (count.compareTo(MIN_SLOTS_TO_PROGRESS_PER_REQUEST) > 0 && startSlot.plus(MIN_SLOTS_TO_PROGRESS_PER_REQUEST).compareTo(nextSlot) > 0) {
            final int throttledRequests = throttledRequestCount.incrementAndGet();
            LOG.debug("Received {} consecutive excessively throttled response from {}", throttledRequests, peer.getId());
            if (throttledRequests > MAX_THROTTLED_REQUESTS) {
                LOG.debug("Rejecting peer {} as sync target because it excessively throttled returned blocks", peer.getId());
                return SafeFuture.completedFuture(PeerSyncResult.EXCESSIVE_THROTTLING);
            }
        } else {
            throttledRequestCount.set(0);
        }
        return executeSync(peer, nextSlot, blockRequest.getReadyForNextRequest(), false);
    }).exceptionally(err -> handleFailedRequestToPeer(peer, status, err));
}
Also used : MAX_BLOCK_BY_RANGE_REQUEST_SIZE(tech.pegasys.teku.spec.config.Constants.MAX_BLOCK_BY_RANGE_REQUEST_SIZE) FailureReason(tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult.FailureReason) RpcException(tech.pegasys.teku.networking.eth2.rpc.core.RpcException) PeerStatus(tech.pegasys.teku.networking.eth2.peers.PeerStatus) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SafeFuture(tech.pegasys.teku.infrastructure.async.SafeFuture) DisconnectReason(tech.pegasys.teku.networking.p2p.peer.DisconnectReason) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Duration(java.time.Duration) Eth2Peer(tech.pegasys.teku.networking.eth2.peers.Eth2Peer) BlocksByRangeResponseInvalidResponseException(tech.pegasys.teku.networking.eth2.rpc.beaconchain.methods.BlocksByRangeResponseInvalidResponseException) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) BlockImporter(tech.pegasys.teku.statetransition.block.BlockImporter) Spec(tech.pegasys.teku.spec.Spec) SignedBeaconBlock(tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock) AsyncRunner(tech.pegasys.teku.infrastructure.async.AsyncRunner) CancellationException(java.util.concurrent.CancellationException) Throwables(com.google.common.base.Throwables) LabelledMetric(org.hyperledger.besu.plugin.services.metrics.LabelledMetric) List(java.util.List) Logger(org.apache.logging.log4j.Logger) TekuMetricCategory(tech.pegasys.teku.infrastructure.metrics.TekuMetricCategory) RecentChainData(tech.pegasys.teku.storage.client.RecentChainData) MetricsSystem(org.hyperledger.besu.plugin.services.MetricsSystem) LogManager(org.apache.logging.log4j.LogManager) Counter(org.hyperledger.besu.plugin.services.metrics.Counter) PeerStatus(tech.pegasys.teku.networking.eth2.peers.PeerStatus) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64)

Example 4 with Eth2Peer

use of tech.pegasys.teku.networking.eth2.peers.Eth2Peer in project teku by ConsenSys.

the class PeerSync method handleFailedRequestToPeer.

private PeerSyncResult handleFailedRequestToPeer(Eth2Peer peer, final PeerStatus peerStatus, Throwable err) {
    Throwable rootException = Throwables.getRootCause(err);
    if (rootException instanceof FailedBlockImportException) {
        final FailedBlockImportException importException = (FailedBlockImportException) rootException;
        final FailureReason reason = importException.getResult().getFailureReason();
        final SignedBeaconBlock block = importException.getBlock();
        if (reason.equals(FailureReason.UNKNOWN_PARENT) && !hasPeerFinalizedBlock(block, peerStatus)) {
            // We received a block that doesn't connect to our chain.
            // This can happen if our peer is sending us blocks from the non-final portion of their
            // chain. They may be sending us blocks from a stale fork that we have already pruned out of
            // our Store.
            LOG.debug("Failed to import non-final block from peer (err: {}) {}: {}", reason, block, peer);
            return PeerSyncResult.IMPORT_FAILED;
        } else if (BAD_BLOCK_FAILURE_REASONS.contains(reason)) {
            LOG.warn("Failed to import block from peer (err: {}) {}: {}", reason, block, peer);
            LOG.debug("Disconnecting from peer ({}) who sent invalid block ({}): {}", peer, reason.name(), block);
            disconnectFromPeer(peer);
            return PeerSyncResult.BAD_BLOCK;
        } else {
            LOG.warn("Failed to import block from peer (err: {}) {}: {}", reason, block, peer);
            return PeerSyncResult.IMPORT_FAILED;
        }
    }
    if (rootException instanceof CancellationException) {
        return PeerSyncResult.CANCELLED;
    }
    if (rootException instanceof BlocksByRangeResponseInvalidResponseException || rootException instanceof RpcException) {
        disconnectFromPeer(peer);
        return PeerSyncResult.INVALID_RESPONSE;
    }
    if (err instanceof RuntimeException) {
        throw (RuntimeException) err;
    } else {
        throw new RuntimeException("Unhandled error while syncing", err);
    }
}
Also used : CancellationException(java.util.concurrent.CancellationException) FailureReason(tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult.FailureReason) RpcException(tech.pegasys.teku.networking.eth2.rpc.core.RpcException) BlocksByRangeResponseInvalidResponseException(tech.pegasys.teku.networking.eth2.rpc.beaconchain.methods.BlocksByRangeResponseInvalidResponseException) SignedBeaconBlock(tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock)

Example 5 with Eth2Peer

use of tech.pegasys.teku.networking.eth2.peers.Eth2Peer in project teku by ConsenSys.

the class SyncManager method isPeerSyncSuitable.

private boolean isPeerSyncSuitable(Eth2Peer peer) {
    UInt64 ourFinalizedEpoch = storageClient.getFinalizedEpoch();
    LOG.trace("Looking for suitable peer (out of {}) with finalized epoch > {}.", network.getPeerCount(), ourFinalizedEpoch);
    final PeerStatus peerStatus = peer.getStatus();
    return !peersWithSyncErrors.contains(peer.getId()) && peerStatusIsConsistentWithOurNode(peerStatus) && peerIsAheadOfOurNode(peerStatus, ourFinalizedEpoch);
}
Also used : PeerStatus(tech.pegasys.teku.networking.eth2.peers.PeerStatus) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64)

Aggregations

Eth2Peer (tech.pegasys.teku.networking.eth2.peers.Eth2Peer)47 Test (org.junit.jupiter.api.Test)37 SignedBeaconBlock (tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock)29 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)26 Bytes32 (org.apache.tuweni.bytes.Bytes32)14 SignedBlockAndState (tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState)10 ArrayList (java.util.ArrayList)7 Optional (java.util.Optional)7 SafeFuture (tech.pegasys.teku.infrastructure.async.SafeFuture)7 RpcException (tech.pegasys.teku.networking.eth2.rpc.core.RpcException)7 MethodSource (org.junit.jupiter.params.provider.MethodSource)6 RecentChainData (tech.pegasys.teku.storage.client.RecentChainData)6 FetchBlockResult (tech.pegasys.teku.beacon.sync.gossip.FetchBlockTask.FetchBlockResult)5 StorageSystem (tech.pegasys.teku.storage.storageSystem.StorageSystem)5 MetadataMessage (tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.metadata.MetadataMessage)4 LogManager (org.apache.logging.log4j.LogManager)3 PeerStatus (tech.pegasys.teku.networking.eth2.peers.PeerStatus)3 Spec (tech.pegasys.teku.spec.Spec)3 Throwables (com.google.common.base.Throwables)2 ClosedChannelException (java.nio.channels.ClosedChannelException)2