Search in sources :

Example 1 with NewBlockHashesMessage

use of org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage in project besu by hyperledger.

the class AbstractBlockPropagationManagerTest method ignoresOldNewBlockHashAnnouncement.

@Test
public void ignoresOldNewBlockHashAnnouncement() {
    final BlockDataGenerator gen = new BlockDataGenerator();
    blockchainUtil.importFirstBlocks(10);
    final Block blockOne = blockchainUtil.getBlock(1);
    final Block oldBlock = gen.nextBlock(blockOne);
    // Sanity check
    assertThat(blockchain.contains(oldBlock.getHash())).isFalse();
    final BlockPropagationManager propManager = spy(blockPropagationManager);
    propManager.start();
    // Setup peer and messages
    final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 0);
    final NewBlockHashesMessage oldAnnouncement = NewBlockHashesMessage.create(Collections.singletonList(new NewBlockHashesMessage.NewBlockHash(oldBlock.getHash(), oldBlock.getHeader().getNumber())));
    // Broadcast
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, oldAnnouncement);
    final Responder responder = RespondingEthPeer.blockchainResponder(getFullBlockchain());
    peer.respondWhile(responder, peer::hasOutstandingRequests);
    verify(propManager, times(0)).importOrSavePendingBlock(any(), any(Bytes.class));
    assertThat(blockchain.contains(oldBlock.getHash())).isFalse();
}
Also used : Bytes(org.apache.tuweni.bytes.Bytes) RespondingEthPeer(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer) Block(org.hyperledger.besu.ethereum.core.Block) BlockDataGenerator(org.hyperledger.besu.ethereum.core.BlockDataGenerator) NewBlockHashesMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage) Responder(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer.Responder) Test(org.junit.Test)

Example 2 with NewBlockHashesMessage

use of org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage in project besu by hyperledger.

the class AbstractBlockPropagationManagerTest method shouldTryWithAnotherPeerWhenFailedDownloadingBlock.

@Test
public void shouldTryWithAnotherPeerWhenFailedDownloadingBlock() {
    blockchainUtil.importFirstBlocks(2);
    final Block nextBlock = blockchainUtil.getBlock(2);
    // Sanity check
    assertThat(blockchain.contains(nextBlock.getHash())).isFalse();
    blockPropagationManager.start();
    // Setup peer and messages
    final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 0);
    final RespondingEthPeer secondPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 2);
    // Pretend the second peer is busier, so the first is selected a first
    when(spy(secondPeer.getEthPeer()).outstandingRequests()).thenReturn(1);
    final NewBlockHashesMessage nextAnnouncement = NewBlockHashesMessage.create(Collections.singletonList(new NewBlockHashesMessage.NewBlockHash(nextBlock.getHash(), nextBlock.getHeader().getNumber())));
    // Broadcast first message
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, nextAnnouncement);
    peer.respondWhile(RespondingEthPeer.emptyResponder(), peer::hasOutstandingRequests);
    secondPeer.respondWhile(RespondingEthPeer.blockchainResponder(getFullBlockchain()), secondPeer::hasOutstandingRequests);
    assertThat(blockchain.contains(nextBlock.getHash())).isTrue();
}
Also used : RespondingEthPeer(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer) Block(org.hyperledger.besu.ethereum.core.Block) NewBlockHashesMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage) Test(org.junit.Test)

Example 3 with NewBlockHashesMessage

use of org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage in project besu by hyperledger.

the class AbstractBlockPropagationManagerTest method handlesDuplicateAnnouncements.

@Test
public void handlesDuplicateAnnouncements() {
    final ProtocolSchedule stubProtocolSchedule = spy(protocolSchedule);
    final ProtocolSpec stubProtocolSpec = spy(protocolSchedule.getByBlockNumber(2));
    final BlockImporter stubBlockImporter = spy(stubProtocolSpec.getBlockImporter());
    doReturn(stubProtocolSpec).when(stubProtocolSchedule).getByBlockNumber(anyLong());
    doReturn(stubBlockImporter).when(stubProtocolSpec).getBlockImporter();
    final BlockPropagationManager blockPropagationManager = new BlockPropagationManager(syncConfig, stubProtocolSchedule, protocolContext, ethProtocolManager.ethContext(), syncState, pendingBlocksManager, metricsSystem, blockBroadcaster);
    blockchainUtil.importFirstBlocks(2);
    final Block nextBlock = blockchainUtil.getBlock(2);
    // Sanity check
    assertThat(blockchain.contains(nextBlock.getHash())).isFalse();
    blockPropagationManager.start();
    // Setup peer and messages
    final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 0);
    final NewBlockHashesMessage newBlockHash = NewBlockHashesMessage.create(Collections.singletonList(new NewBlockHashesMessage.NewBlockHash(nextBlock.getHash(), nextBlock.getHeader().getNumber())));
    final NewBlockMessage newBlock = NewBlockMessage.create(nextBlock, getFullBlockchain().getTotalDifficultyByHash(nextBlock.getHash()).get());
    final Responder responder = RespondingEthPeer.blockchainResponder(getFullBlockchain());
    // Broadcast first message
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, newBlock);
    peer.respondWhile(responder, peer::hasOutstandingRequests);
    // Broadcast duplicate
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, newBlockHash);
    peer.respondWhile(responder, peer::hasOutstandingRequests);
    // Broadcast duplicate
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, newBlock);
    peer.respondWhile(responder, peer::hasOutstandingRequests);
    assertThat(blockchain.contains(nextBlock.getHash())).isTrue();
    verify(stubBlockImporter, times(1)).importBlock(eq(protocolContext), eq(nextBlock), any());
}
Also used : NewBlockMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockMessage) ProtocolSpec(org.hyperledger.besu.ethereum.mainnet.ProtocolSpec) RespondingEthPeer(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer) Block(org.hyperledger.besu.ethereum.core.Block) ProtocolSchedule(org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule) BlockImporter(org.hyperledger.besu.ethereum.core.BlockImporter) NewBlockHashesMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage) Responder(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer.Responder) Test(org.junit.Test)

Example 4 with NewBlockHashesMessage

use of org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage in project besu by hyperledger.

the class AbstractBlockPropagationManagerTest method importsMixedOutOfOrderMessages.

@Test
public void importsMixedOutOfOrderMessages() {
    blockchainUtil.importFirstBlocks(2);
    final Block block1 = blockchainUtil.getBlock(2);
    final Block block2 = blockchainUtil.getBlock(3);
    final Block block3 = blockchainUtil.getBlock(4);
    final Block block4 = blockchainUtil.getBlock(5);
    // Sanity check
    assertThat(blockchain.contains(block1.getHash())).isFalse();
    assertThat(blockchain.contains(block2.getHash())).isFalse();
    assertThat(blockchain.contains(block3.getHash())).isFalse();
    assertThat(blockchain.contains(block4.getHash())).isFalse();
    blockPropagationManager.start();
    // Setup peer and messages
    final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 0);
    final NewBlockHashesMessage block1Msg = NewBlockHashesMessage.create(Collections.singletonList(new NewBlockHashesMessage.NewBlockHash(block1.getHash(), block1.getHeader().getNumber())));
    final NewBlockMessage block2Msg = NewBlockMessage.create(block2, getFullBlockchain().getTotalDifficultyByHash(block2.getHash()).get());
    final NewBlockHashesMessage block3Msg = NewBlockHashesMessage.create(Collections.singletonList(new NewBlockHashesMessage.NewBlockHash(block3.getHash(), block3.getHeader().getNumber())));
    final NewBlockMessage block4Msg = NewBlockMessage.create(block4, getFullBlockchain().getTotalDifficultyByHash(block4.getHash()).get());
    final Responder responder = RespondingEthPeer.blockchainResponder(getFullBlockchain());
    // Broadcast older blocks
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, block3Msg);
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, block4Msg);
    peer.respondWhile(responder, peer::hasOutstandingRequests);
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, block2Msg);
    peer.respondWhile(responder, peer::hasOutstandingRequests);
    // Broadcast first block
    EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, block1Msg);
    peer.respondWhile(responder, peer::hasOutstandingRequests);
    assertThat(blockchain.contains(block1.getHash())).isTrue();
    assertThat(blockchain.contains(block2.getHash())).isTrue();
    assertThat(blockchain.contains(block3.getHash())).isTrue();
    assertThat(blockchain.contains(block4.getHash())).isTrue();
}
Also used : NewBlockMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockMessage) RespondingEthPeer(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer) Block(org.hyperledger.besu.ethereum.core.Block) NewBlockHashesMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage) Responder(org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer.Responder) Test(org.junit.Test)

Example 5 with NewBlockHashesMessage

use of org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage in project besu by hyperledger.

the class BlockPropagationManager method handleNewBlockHashesFromNetwork.

private void handleNewBlockHashesFromNetwork(final EthMessage message) {
    final Blockchain blockchain = protocolContext.getBlockchain();
    final NewBlockHashesMessage newBlockHashesMessage = NewBlockHashesMessage.readFrom(message.getData());
    try {
        // Register announced blocks
        final List<NewBlockHash> announcedBlocks = Lists.newArrayList(newBlockHashesMessage.getNewHashes());
        traceLambda(LOG, "New block hashes from network {} from peer {}. Current status {}", () -> toLogString(announcedBlocks), message::getPeer, () -> this);
        for (final NewBlockHash announcedBlock : announcedBlocks) {
            message.getPeer().registerKnownBlock(announcedBlock.hash());
            message.getPeer().registerHeight(announcedBlock.hash(), announcedBlock.number());
        }
        // Filter announced blocks for blocks we care to import
        final long localChainHeight = protocolContext.getBlockchain().getChainHeadBlockNumber();
        final long bestChainHeight = syncState.bestChainHeight(localChainHeight);
        final List<NewBlockHash> relevantAnnouncements = announcedBlocks.stream().filter(a -> shouldImportBlockAtHeight(a.number(), localChainHeight, bestChainHeight)).collect(Collectors.toList());
        // Filter for blocks we don't yet know about
        final List<NewBlockHash> newBlocks = new ArrayList<>();
        for (final NewBlockHash announcedBlock : relevantAnnouncements) {
            if (pendingBlocksManager.contains(announcedBlock.hash())) {
                LOG.trace("New block hash from network {} is already pending", announcedBlock);
                continue;
            }
            if (importingBlocks.contains(announcedBlock.hash())) {
                LOG.trace("New block hash from network {} is already importing", announcedBlock);
                continue;
            }
            if (blockchain.contains(announcedBlock.hash())) {
                LOG.trace("New block hash from network {} was already imported", announcedBlock);
                continue;
            }
            if (requestedBlocks.add(announcedBlock.hash())) {
                newBlocks.add(announcedBlock);
            } else {
                LOG.trace("New block hash from network {} was already requested", announcedBlock);
            }
        }
        // Process known blocks we care about
        for (final NewBlockHash newBlock : newBlocks) {
            processAnnouncedBlock(message.getPeer(), newBlock);
        }
    } catch (final RLPException e) {
        LOG.debug("Malformed NEW_BLOCK_HASHES message received from peer, disconnecting: {}", message.getPeer(), e);
        message.getPeer().disconnect(DisconnectReason.BREACH_OF_PROTOCOL);
    }
}
Also used : NewBlockHash(org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage.NewBlockHash) RLPException(org.hyperledger.besu.ethereum.rlp.RLPException) EthPV62(org.hyperledger.besu.ethereum.eth.messages.EthPV62) SyncState(org.hyperledger.besu.ethereum.eth.sync.state.SyncState) EthPeer(org.hyperledger.besu.ethereum.eth.manager.EthPeer) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) RetryingGetBlockFromPeersTask(org.hyperledger.besu.ethereum.eth.manager.task.RetryingGetBlockFromPeersTask) CompletableFuture(java.util.concurrent.CompletableFuture) Bytes(org.apache.tuweni.bytes.Bytes) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) PendingBlocksManager(org.hyperledger.besu.ethereum.eth.sync.state.PendingBlocksManager) ProtocolSchedule(org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule) Lists(com.google.common.collect.Lists) BlockHeaderValidator(org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator) BlockAddedEvent(org.hyperledger.besu.ethereum.chain.BlockAddedEvent) Block(org.hyperledger.besu.ethereum.core.Block) EventType(org.hyperledger.besu.ethereum.chain.BlockAddedEvent.EventType) EthMessage(org.hyperledger.besu.ethereum.eth.manager.EthMessage) Slf4jLambdaHelper.traceLambda(org.hyperledger.besu.util.Slf4jLambdaHelper.traceLambda) ProcessableBlockHeader(org.hyperledger.besu.ethereum.core.ProcessableBlockHeader) DisconnectReason(org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason) PersistBlockTask(org.hyperledger.besu.ethereum.eth.sync.tasks.PersistBlockTask) NewBlockHash(org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage.NewBlockHash) Difficulty(org.hyperledger.besu.ethereum.core.Difficulty) Logger(org.slf4j.Logger) BadBlockManager(org.hyperledger.besu.ethereum.chain.BadBlockManager) NewBlockHashesMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) Collection(java.util.Collection) Blockchain(org.hyperledger.besu.ethereum.chain.Blockchain) NewBlockMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockMessage) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Range(com.google.common.collect.Range) EthContext(org.hyperledger.besu.ethereum.eth.manager.EthContext) Set(java.util.Set) Collectors(java.util.stream.Collectors) List(java.util.List) ProtocolContext(org.hyperledger.besu.ethereum.ProtocolContext) Optional(java.util.Optional) HeaderValidationMode(org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode) MetricsSystem(org.hyperledger.besu.plugin.services.MetricsSystem) VisibleForTesting(com.google.common.annotations.VisibleForTesting) ProtocolSpec(org.hyperledger.besu.ethereum.mainnet.ProtocolSpec) Collections(java.util.Collections) Hash(org.hyperledger.besu.datatypes.Hash) Blockchain(org.hyperledger.besu.ethereum.chain.Blockchain) ArrayList(java.util.ArrayList) RLPException(org.hyperledger.besu.ethereum.rlp.RLPException) NewBlockHashesMessage(org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage)

Aggregations

Block (org.hyperledger.besu.ethereum.core.Block)11 NewBlockHashesMessage (org.hyperledger.besu.ethereum.eth.messages.NewBlockHashesMessage)11 RespondingEthPeer (org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer)10 Test (org.junit.Test)10 Responder (org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer.Responder)8 NewBlockMessage (org.hyperledger.besu.ethereum.eth.messages.NewBlockMessage)4 ProtocolSchedule (org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule)3 ProtocolSpec (org.hyperledger.besu.ethereum.mainnet.ProtocolSpec)3 Bytes (org.apache.tuweni.bytes.Bytes)2 BlockImporter (org.hyperledger.besu.ethereum.core.BlockImporter)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Lists (com.google.common.collect.Lists)1 Range (com.google.common.collect.Range)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 List (java.util.List)1 Optional (java.util.Optional)1 Set (java.util.Set)1 CompletableFuture (java.util.concurrent.CompletableFuture)1