private BlockHeader lookupPreviousHeader( final MutableBlockchain blockchain, final BlockHeader header) { return blockchain .getBlockHeader(header.getParentHash()) .orElseThrow( () -> new IllegalStateException( String.format( "Block %s does not connect to the existing chain. Current chain head %s", header.getNumber(), blockchain.getChainHeadBlockNumber()))); }
private BlockHeader getHeaderForCurrentChainHead() { return blockchain.getBlockHeader(blockchain.getChainHeadHash()).get(); }
private Blockchain createMockedBlockChainWithHeadOf( final long blockNumber, final Address proposer) { when(blockInterface.getProposerOfBlock(any())).thenReturn(proposer); final BlockHeaderTestFixture headerBuilderFixture = new BlockHeaderTestFixture(); headerBuilderFixture.number(blockNumber); final BlockHeader prevBlockHeader = headerBuilderFixture.buildHeader(); // Construct a block chain and world state final MutableBlockchain blockchain = mock(MutableBlockchain.class); when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.of(prevBlockHeader)); return blockchain; }
@Test public void buildVoteTallyByExtractingValidatorsFromEpochBlock() { when(serialiser.validatorsInBlock(any())).thenReturn(asList(subject, validator1)); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeader header = headerBuilder.buildHeader(); when(blockchain.getChainHeadBlockNumber()).thenReturn(EPOCH_LENGTH); when(blockchain.getBlockHeader(EPOCH_LENGTH)).thenReturn(Optional.of(header)); final VoteTally voteTally = updater.buildVoteTallyFromBlockchain(blockchain); assertThat(voteTally.getValidators()).containsExactly(subject, validator1); }
@Test public void buildVoteTallyByExtractingValidatorsFromGenesisBlock() { when(serialiser.validatorsInBlock(any())).thenReturn(asList(subject, validator1)); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); headerBuilder.number(0); final BlockHeader header = headerBuilder.buildHeader(); when(blockchain.getChainHeadBlockNumber()).thenReturn(EPOCH_LENGTH); when(blockchain.getBlockHeader(EPOCH_LENGTH)).thenReturn(Optional.of(header)); final VoteTally voteTally = updater.buildVoteTallyFromBlockchain(blockchain); assertThat(voteTally.getValidators()).containsExactly(subject, validator1); }
@Test public void addVotesFromBlocksAfterMostRecentEpoch() { when(serialiser.validatorsInBlock(any())).thenReturn(asList(validator1)); when(serialiser.extractVoteFromHeader(any())) .thenReturn(Optional.of(new ValidatorVote(ADD, proposerAddress, subject))); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); headerBuilder.number(EPOCH_LENGTH); final BlockHeader epochHeader = headerBuilder.buildHeader(); headerBuilder.number(EPOCH_LENGTH + 1); final BlockHeader voteBlockHeader = headerBuilder.buildHeader(); when(blockchain.getChainHeadBlockNumber()).thenReturn(EPOCH_LENGTH + 1); when(blockchain.getBlockHeader(EPOCH_LENGTH)).thenReturn(Optional.of(epochHeader)); when(blockchain.getBlockHeader(EPOCH_LENGTH + 1)).thenReturn(Optional.of(voteBlockHeader)); final VoteTally voteTally = updater.buildVoteTallyFromBlockchain(blockchain); assertThat(voteTally.getValidators()).containsExactly(subject, validator1); } }
@Test public void validateHeaderChain() { final BlockHeader blockHeader = generator.header(); when(blockchain.getBlockHeader(blockHeader.getParentHash())) .thenReturn(Optional.of(blockHeader)); final BlockHeaderValidator<Void> validator = new BlockHeaderValidator.Builder<Void>().addRule(createPassingAttachedRule()).build(); assertThat(validator.validateHeader(blockHeader, protocolContext, HeaderValidationMode.FULL)) .isTrue(); }
@Test public void validateHeaderChainFailsWhenParentNotAvailable() { final BlockHeader blockHeader = generator.header(); when(blockchain.getBlockHeader(blockHeader.getNumber() - 1)).thenReturn(Optional.empty()); final BlockHeaderValidator<Void> validator = new BlockHeaderValidator.Builder<Void>().addRule(createPassingAttachedRule()).build(); assertThat(validator.validateHeader(blockHeader, protocolContext, HeaderValidationMode.FULL)) .isFalse(); }
@Test public void validateHeaderLightChainFailsWhenParentNotAvailable() { final BlockHeader blockHeader = generator.header(); when(blockchain.getBlockHeader(blockHeader.getParentHash())).thenReturn(Optional.empty()); final BlockHeaderValidator<Void> validator = new BlockHeaderValidator.Builder<Void>().addRule(createPassingAttachedRule()).build(); assertThat(validator.validateHeader(blockHeader, protocolContext, HeaderValidationMode.LIGHT)) .isFalse(); }
@Test public void downloadPivotBlockHeaderShouldRetrievePivotBlockHeader() { final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1001); final CompletableFuture<FastSyncState> result = fastSyncActions.downloadPivotBlockHeader(new FastSyncState(OptionalLong.of(1))); assertThat(result).isNotCompleted(); final Responder responder = RespondingEthPeer.blockchainResponder(blockchain); peer.respond(responder); assertThat(result) .isCompletedWithValue(new FastSyncState(OptionalLong.of(1), blockchain.getBlockHeader(1))); }
@Test public void shouldSkipAdditionalValidationRulesWhenDoingLightValidation() { final BlockHeaderValidator<Void> validator = new BlockHeaderValidator.Builder<Void>() .addRule(createPassingDetachedRule(true)) .addRule(createFailingDetachedRule(false)) .build(); final BlockHeader header = generator.header(); final BlockHeader parentHeader = generator.header(); when(blockchain.getBlockHeader(header.getParentHash())).thenReturn(Optional.of(parentHeader)); assertThat(validator.validateHeader(header, protocolContext, HeaderValidationMode.LIGHT)) .isTrue(); }
@Test public void shouldIgnorePeersThatDoNotHaveThePivotBlock() { final Responder responder = RespondingEthPeer.blockchainResponder(blockchain, protocolContext.getWorldStateArchive()); final RespondingEthPeer respondingPeerA = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1); EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1); final CompletableFuture<FastSyncState> future = pivotBlockRetriever.downloadPivotBlockHeader(); while (!future.isDone()) { respondingPeerA.respondWhile(responder, () -> !future.isDone()); } assertThat(future) .isCompletedWithValue( new FastSyncState( OptionalLong.of(PIVOT_BLOCK_NUMBER), blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER))); }
blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash());
@Test public void shouldSucceedWhenAllPeersAgree() { final Responder responder = RespondingEthPeer.blockchainResponder(blockchain, protocolContext.getWorldStateArchive()); final RespondingEthPeer respondingPeerA = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final RespondingEthPeer respondingPeerB = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final RespondingEthPeer respondingPeerC = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final CompletableFuture<FastSyncState> future = pivotBlockRetriever.downloadPivotBlockHeader(); while (!future.isDone()) { respondingPeerA.respond(responder); respondingPeerB.respond(responder); respondingPeerC.respond(responder); } assertThat(future) .isCompletedWithValue( new FastSyncState( OptionalLong.of(PIVOT_BLOCK_NUMBER), blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER))); }
@Test public void shouldSucceedWhenMajorityOfPeersAgree() { final Responder responder = RespondingEthPeer.blockchainResponder(blockchain, protocolContext.getWorldStateArchive()); final Responder fakeResponder = responderForFakeBlock(); final RespondingEthPeer respondingPeerA = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final RespondingEthPeer respondingPeerB = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final RespondingEthPeer respondingPeerC = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final CompletableFuture<FastSyncState> future = pivotBlockRetriever.downloadPivotBlockHeader(); while (!future.isDone()) { respondingPeerA.respond(responder); respondingPeerB.respond(fakeResponder); respondingPeerC.respond(responder); } assertThat(future) .isCompletedWithValue( new FastSyncState( OptionalLong.of(PIVOT_BLOCK_NUMBER), blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER))); }
when(blockchain.getBlockHeader(any())).thenReturn(optionalHeader);
commonHeader = localBlockchain.getBlockHeader(i).get(); final List<TransactionReceipt> receipts = localBlockchain.getTxReceipts(commonHeader.getHash()).get(); headers.add(remoteBlockchain.getBlockHeader(i).get());
@Test public void logsShouldBeFlaggedAsRemovedWhenBlockIsNotInCanonicalChain() { // create initial blockchain final BlockchainWithData data = setupBlockchain(3); final Block targetBlock = data.blockData.get(data.blockData.size() - 1).block; // check that logs have removed = false List<LogWithMetadata> logs = data.blockchainQueries.matchingLogs(targetBlock.getHash(), new LogsQuery.Builder().build()); assertThat(logs).isNotEmpty(); assertThat(logs).allMatch(l -> !l.isRemoved()); // Create parallel fork of length 1 final int forkBlock = 2; final int commonAncestor = 1; final BlockOptions options = new BlockOptions() .setParentHash(data.blockchain.getBlockHashByNumber(commonAncestor).get()) .setBlockNumber(forkBlock) .setDifficulty( data.blockchain.getBlockHeader(forkBlock).get().getDifficulty().plus(10L)); final Block fork = gen.block(options); final List<TransactionReceipt> forkReceipts = gen.receipts(fork); // Add fork data.blockchain.appendBlock(fork, forkReceipts); // check that logs have removed = true logs = data.blockchainQueries.matchingLogs(targetBlock.getHash(), new LogsQuery.Builder().build()); assertThat(logs).isNotEmpty(); assertThat(logs).allMatch(LogWithMetadata::isRemoved); }
BlockHeader commonHeader = genesisBlock.getHeader(); for (long i = 1; i <= commonAncestorHeight; i++) { commonHeader = localBlockchain.getBlockHeader(i).get(); final List<TransactionReceipt> receipts = localBlockchain.getTxReceipts(commonHeader.getHash()).get();
when(blockchain.getBlockHeader(any())).thenReturn(optionalHeader);