Search in sources :

Example 1 with GetBlockHeadersMessage

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());
}
Also used : GetBlockHeadersMessage(org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage) BlockchainSetupUtil(org.hyperledger.besu.ethereum.core.BlockchainSetupUtil) RespondingEthPeer(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer) MutableBlockchain(org.hyperledger.besu.ethereum.chain.MutableBlockchain) SynchronizerConfiguration(org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration) ChainDownloader(org.hyperledger.besu.ethereum.eth.sync.ChainDownloader) Test(org.junit.Test)

Example 2 with GetBlockHeadersMessage

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);
}
Also used : GetBlockHeadersMessage(org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage)

Example 3 with GetBlockHeadersMessage

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);
}
Also used : GetBlockHeadersMessage(org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage) Hash(org.hyperledger.besu.datatypes.Hash) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader)

Example 4 with GetBlockHeadersMessage

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;
}
Also used : GetBlockHeadersMessage(org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) RespondingEthPeer(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer)

Example 5 with GetBlockHeadersMessage

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);
}
Also used : GetBlockHeadersMessage(org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage) MessageData(org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData) RespondingEthPeer(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer) InMemoryKeyValueStorageProvider.createInMemoryBlockchain(org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain) Blockchain(org.hyperledger.besu.ethereum.chain.Blockchain) MutableBlockchain(org.hyperledger.besu.ethereum.chain.MutableBlockchain) SynchronizerConfiguration(org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration) ChainDownloader(org.hyperledger.besu.ethereum.eth.sync.ChainDownloader) Test(org.junit.Test)

Aggregations

GetBlockHeadersMessage (org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage)6 RespondingEthPeer (org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer)4 MutableBlockchain (org.hyperledger.besu.ethereum.chain.MutableBlockchain)3 ChainDownloader (org.hyperledger.besu.ethereum.eth.sync.ChainDownloader)3 SynchronizerConfiguration (org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration)3 Test (org.junit.Test)3 Blockchain (org.hyperledger.besu.ethereum.chain.Blockchain)2 BlockHeader (org.hyperledger.besu.ethereum.core.BlockHeader)2 BlockchainSetupUtil (org.hyperledger.besu.ethereum.core.BlockchainSetupUtil)2 InMemoryKeyValueStorageProvider.createInMemoryBlockchain (org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain)2 MessageData (org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData)2 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 List (java.util.List)1 Optional (java.util.Optional)1 TimeUnit (java.util.concurrent.TimeUnit)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Function (java.util.function.Function)1 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)1