@Test public void onBlockImported_withPendingFutureBlocks() throws Exception { final int blockCount = 3; final List<SignedBeaconBlock> blocks = new ArrayList<>(blockCount); incrementSlot(); for (int i = 0; i < blockCount; i++) { final UInt64 nextSlot = genesisSlot.plus(i + 1); blocks.add(remoteChain.createAndImportBlockAtSlot(nextSlot)); } blocks.subList(1, blockCount).stream() .map(GossipedBlockEvent::new) .forEach(localEventBus::post); assertThat(importedBlocks.get()).isEmpty(); assertThat(pendingBlocks.size()).isEqualTo(blockCount - 1); final SignedBeaconBlock firstBlock = blocks.get(0); assertThat(blockImporter.importBlock(firstBlock).get().isSuccessful()).isTrue(); assertThat(importedBlocks.get()).containsExactly(firstBlock); assertThat(pendingBlocks.size()).isEqualTo(1); assertThat(futureBlocks.size()).isEqualTo(1); incrementSlot(); assertThat(importedBlocks.get()).containsExactly(firstBlock, blocks.get(1)); assertThat(pendingBlocks.size()).isEqualTo(0); assertThat(futureBlocks.size()).isEqualTo(1); incrementSlot(); assertThat(importedBlocks.get()).containsExactlyElementsOf(blocks); assertThat(pendingBlocks.size()).isEqualTo(0); assertThat(futureBlocks.size()).isEqualTo(0); }
private void importBlock(final SignedBeaconBlock block) { recentBlockFetcher.cancelRecentBlockRequest(block.getRoot()); if (!shouldImportBlock(block)) { return; } blockImporter .importBlock(block) .thenAccept( result -> { if (result.isSuccessful()) { LOG.trace("Imported block: {}", block); } else if (result.getFailureReason() == FailureReason.UNKNOWN_PARENT) { pendingBlocks.add(block); if (recentChainData.containsBlock(block.getParent_root())) { pendingBlocks.remove(block); importBlock(block); } } else if (result.getFailureReason() == FailureReason.BLOCK_IS_FROM_FUTURE) { futureBlocks.add(block); } else { LOG.trace( "Unable to import block for reason {}: {}", result.getFailureReason(), block); dropInvalidBlock(block); } }) .reportExceptions(); }
BlockManager extends Service implements SlotEventsChannel { private void importBlock(final SignedBeaconBlock block) { recentBlockFetcher.cancelRecentBlockRequest(block.getRoot()); if (!shouldImportBlock(block)) { return; } blockImporter .importBlock(block) .thenAccept( result -> { if (result.isSuccessful()) { LOG.trace("Imported block: {}", block); } else if (result.getFailureReason() == FailureReason.UNKNOWN_PARENT) { pendingBlocks.add(block); if (recentChainData.containsBlock(block.getParent_root())) { pendingBlocks.remove(block); importBlock(block); } } else if (result.getFailureReason() == FailureReason.BLOCK_IS_FROM_FUTURE) { futureBlocks.add(block); } else { LOG.trace( "Unable to import block for reason {}: {}", result.getFailureReason(), block); dropInvalidBlock(block); } }) .reportExceptions(); } }
BlockManager extends Service implements SlotEventsChannel { private void importBlock(final SignedBeaconBlock block) { recentBlockFetcher.cancelRecentBlockRequest(block.getRoot()); if (!shouldImportBlock(block)) { return; } blockImporter .importBlock(block) .thenAccept( result -> { if (result.isSuccessful()) { LOG.trace("Imported block: {}", block); } else if (result.getFailureReason() == FailureReason.UNKNOWN_PARENT) { pendingBlocks.add(block); if (recentChainData.containsBlock(block.getParent_root())) { pendingBlocks.remove(block); importBlock(block); } } else if (result.getFailureReason() == FailureReason.BLOCK_IS_FROM_FUTURE) { futureBlocks.add(block); } else { LOG.trace( "Unable to import block for reason {}: {}", result.getFailureReason(), block); dropInvalidBlock(block); } }) .reportExceptions(); } BlockManager(
      final EventBus eventBus,
      final RecentChainData recentChainData,
      final BlockImporter blockImporter,
      final PendingPool<SignedBeaconBlock> pendingBlocks,
      final FutureItems<SignedBeaconBlock> futureBlocks,
      final FetchRecentBlocksService recentBlockFetcher); }
BlockManager extends Service implements SlotEventsChannel { private void importBlock(final SignedBeaconBlock block) { recentBlockFetcher.cancelRecentBlockRequest(block.getRoot()); if (!shouldImportBlock(block)) { return; } blockImporter .importBlock(block) .thenAccept( result -> { if (result.isSuccessful()) { LOG.trace("Imported block: {}", block); } else if (result.getFailureReason() == FailureReason.UNKNOWN_PARENT) { pendingBlocks.add(block); if (recentChainData.containsBlock(block.getParent_root())) { pendingBlocks.remove(block); importBlock(block); } } else if (result.getFailureReason() == FailureReason.BLOCK_IS_FROM_FUTURE) { futureBlocks.add(block); } else { LOG.trace( "Unable to import block for reason {}: {}", result.getFailureReason(), block); dropInvalidBlock(block); } }) .reportExceptions(); } BlockManager(
      final EventBus eventBus,
      final RecentChainData recentChainData,
      final BlockImporter blockImporter,
      final PendingPool<SignedBeaconBlock> pendingBlocks,
      final FutureItems<SignedBeaconBlock> futureBlocks,
      final FetchRecentBlocksService recentBlockFetcher); static BlockManager create(
      final EventBus eventBus,
      final PendingPool<SignedBeaconBlock> pendingBlocks,
      final FutureItems<SignedBeaconBlock> futureBlocks,
      final FetchRecentBlocksService recentBlockFetcher,
      final RecentChainData recentChainData,
      final BlockImporter blockImporter); @Override SafeFuture<?> doStart(); @Override void onSlot(final UInt64 slot); }
BlockManager extends Service implements SlotEventsChannel { private void importBlock(final SignedBeaconBlock block) { recentBlockFetcher.cancelRecentBlockRequest(block.getRoot()); if (!shouldImportBlock(block)) { return; } blockImporter .importBlock(block) .thenAccept( result -> { if (result.isSuccessful()) { LOG.trace("Imported block: {}", block); } else if (result.getFailureReason() == FailureReason.UNKNOWN_PARENT) { pendingBlocks.add(block); if (recentChainData.containsBlock(block.getParent_root())) { pendingBlocks.remove(block); importBlock(block); } } else if (result.getFailureReason() == FailureReason.BLOCK_IS_FROM_FUTURE) { futureBlocks.add(block); } else { LOG.trace( "Unable to import block for reason {}: {}", result.getFailureReason(), block); dropInvalidBlock(block); } }) .reportExceptions(); } BlockManager(
      final EventBus eventBus,
      final RecentChainData recentChainData,
      final BlockImporter blockImporter,
      final PendingPool<SignedBeaconBlock> pendingBlocks,
      final FutureItems<SignedBeaconBlock> futureBlocks,
      final FetchRecentBlocksService recentBlockFetcher); static BlockManager create(
      final EventBus eventBus,
      final PendingPool<SignedBeaconBlock> pendingBlocks,
      final FutureItems<SignedBeaconBlock> futureBlocks,
      final FetchRecentBlocksService recentBlockFetcher,
      final RecentChainData recentChainData,
      final BlockImporter blockImporter); @Override SafeFuture<?> doStart(); @Override void onSlot(final UInt64 slot);  }