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();
}
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();
}
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());
}
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();
}
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);
}
}
Aggregations