Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Commit

Permalink
Renaming functions in Votetally and cache to better represent their p…
Browse files Browse the repository at this point in the history
…urpose

VoteTallyCache has been refactored to simplify some logic.
  • Loading branch information
tmohay committed Dec 4, 2018
1 parent 2171267 commit deaa392
Show file tree
Hide file tree
Showing 33 changed files with 114 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public static boolean addressIsAllowedToProduceNextBlock(
final ProtocolContext<CliqueContext> protocolContext,
final BlockHeader parent) {
final VoteTally validatorProvider =
protocolContext.getConsensusState().getVoteTallyCache().getVoteTallyAtBlock(parent);
protocolContext.getConsensusState().getVoteTallyCache().getVoteTallyAfterBlock(parent);

if (!validatorProvider.getCurrentValidators().contains(candidate)) {
if (!validatorProvider.getValidators().contains(candidate)) {
return false;
}

Expand Down Expand Up @@ -72,7 +72,7 @@ public static boolean addressIsAllowedToProduceNextBlock(
}

private static int minimumBlocksSincePreviousSigning(final ValidatorProvider validatorProvider) {
final int validatorCount = validatorProvider.getCurrentValidators().size();
final int validatorCount = validatorProvider.getValidators().size();
// The number of contiguous blocks in which a signer may only sign 1 (as taken from clique spec)
final int signerLimit = (validatorCount / 2) + 1;
return signerLimit - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,18 @@ public VoteTallyCache(
this.epochManager = epochManager;
}

public VoteTally getVoteTallyAtBlock(final BlockHeader header) {
/**
* Determines the VoteTally for a given block header, by back-tracing the blockchain to a
* previously cached value or epoch block. Then appyling votes in each intermediate header such
* that representative state can be provided. This function assumes the vote cast in {@code
* header} is applied, thus the voteTally returned contains the group of validators who are
* permitted to partake in the next block's creation.
*
* @param header the header of the block after which the VoteTally is to be returned
* @return The Vote Tally (and therefore validators) following the application of all votes upto
* and including the requested header.
*/
public VoteTally getVoteTallyAfterBlock(final BlockHeader header) {
try {
return voteTallyCache.get(header.getHash(), () -> populateCacheUptoAndIncluding(header));
} catch (final ExecutionException ex) {
Expand All @@ -64,7 +75,8 @@ private VoteTally populateCacheUptoAndIncluding(final BlockHeader start) {
VoteTally voteTally = null;

while (true) { // Will run into an epoch block (and thus a VoteTally) to break loop.
voteTally = findMostRecentAvailableVoteTally(header, intermediateBlocks);
intermediateBlocks.push(header);
voteTally = getValidatorsAfter(header);
if (voteTally != null) {
break;
}
Expand All @@ -80,24 +92,22 @@ private VoteTally populateCacheUptoAndIncluding(final BlockHeader start) {
return constructMissingCacheEntries(intermediateBlocks, voteTally);
}

private VoteTally findMostRecentAvailableVoteTally(
final BlockHeader header, final Deque<BlockHeader> intermediateBlockHeaders) {
intermediateBlockHeaders.push(header);
VoteTally voteTally = voteTallyCache.getIfPresent(header.getParentHash());
if ((voteTally == null) && (epochManager.isEpochBlock(header.getNumber()))) {
final CliqueExtraData extraData = CliqueExtraData.decode(header.getExtraData());
voteTally = new VoteTally(extraData.getValidators());
private VoteTally getValidatorsAfter(final BlockHeader header) {
if (epochManager.isEpochBlock(header.getNumber())) {
final CliqueBlockInterface blockInterface = new CliqueBlockInterface();
return new VoteTally(blockInterface.validatorsInBlock(header));
}

return voteTally;
return voteTallyCache.getIfPresent(header.getParentHash());
}

private VoteTally constructMissingCacheEntries(
final Deque<BlockHeader> headers, final VoteTally tally) {
final VoteTally mutableVoteTally = tally.copy();
while (!headers.isEmpty()) {
final BlockHeader h = headers.pop();
voteTallyUpdater.updateForBlock(h, tally);
voteTallyCache.put(h.getHash(), tally.copy());
voteTallyUpdater.updateForBlock(h, mutableVoteTally);
voteTallyCache.put(h.getHash(), mutableVoteTally.copy());
}
return tally;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableB
.blockHashFunction(blockHashFunction);

final CliqueContext cliqueContext = protocolContext.getConsensusState();
final VoteTally voteTally = cliqueContext.getVoteTallyCache().getVoteTallyAtBlock(parentHeader);
final VoteTally voteTally =
cliqueContext.getVoteTallyCache().getVoteTallyAfterBlock(parentHeader);

final Optional<ValidatorVote> vote =
cliqueContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ private int calculateTurnBasedDelay(final BlockHeader parentHeader) {
if (nextProposer.equals(localNodeAddress)) {
return 0;
}
return calculatorOutOfTurnDelay(voteTallyCache.getVoteTallyAtBlock(parentHeader));
return calculatorOutOfTurnDelay(voteTallyCache.getVoteTallyAfterBlock(parentHeader));
}

private int calculatorOutOfTurnDelay(final ValidatorProvider validators) {
final int countSigners = validators.getCurrentValidators().size();
final int countSigners = validators.getValidators().size();
final double multiplier = (countSigners / 2d) + 1;
final int maxDelay = (int) (multiplier * OUT_OF_TURN_DELAY_MULTIPLIER_MILLIS);
return r.nextInt(maxDelay) + 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,11 @@ public BytesValue calculateExtraData(final BlockHeader parentHeader) {
// Building ON TOP of canonical head, if the next block is epoch, include validators.
if (epochManager.isEpochBlock(parentHeader.getNumber() + 1)) {
final VoteTally voteTally =
protocolContext.getConsensusState().getVoteTallyCache().getVoteTallyAtBlock(parentHeader);
validators.addAll(voteTally.getCurrentValidators());
protocolContext
.getConsensusState()
.getVoteTallyCache()
.getVoteTallyAfterBlock(parentHeader);
validators.addAll(voteTally.getValidators());
}

final CliqueExtraData extraData = new CliqueExtraData(vanityDataToInsert, null, validators);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public CliqueProposerSelector(final VoteTallyCache voteTallyCache) {
*/
public Address selectProposerForNextBlock(final BlockHeader parentHeader) {

final VoteTally parentVoteTally = voteTallyCache.getVoteTallyAtBlock(parentHeader);
final List<Address> validatorSet = new ArrayList<>(parentVoteTally.getCurrentValidators());
final VoteTally parentVoteTally = voteTallyCache.getVoteTallyAfterBlock(parentHeader);
final List<Address> validatorSet = new ArrayList<>(parentVoteTally.getValidators());

final long nextBlockNumber = parentHeader.getNumber() + 1L;
final int indexIntoValidators = (int) (nextBlockNumber % validatorSet.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ public boolean validate(
final ProtocolContext<CliqueContext> protocolContext) {
try {
final VoteTally validatorProvider =
protocolContext.getConsensusState().getVoteTallyCache().getVoteTallyAtBlock(parent);
protocolContext.getConsensusState().getVoteTallyCache().getVoteTallyAfterBlock(parent);

final Collection<Address> storedValidators = validatorProvider.getCurrentValidators();
final Collection<Address> storedValidators = validatorProvider.getValidators();
return extraDataIsValid(storedValidators, header);

} catch (final RLPException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public String getName() {
public JsonRpcResponse response(final JsonRpcRequest request) {
final Optional<BlockHeader> blockHeader = determineBlockHeader(request);
return blockHeader
.map(bh -> voteTallyCache.getVoteTallyAtBlock(bh).getCurrentValidators())
.map(bh -> voteTallyCache.getVoteTallyAfterBlock(bh).getValidators())
.map(addresses -> addresses.stream().map(Objects::toString).collect(Collectors.toList()))
.<JsonRpcResponse>map(addresses -> new JsonRpcSuccessResponse(request.getId(), addresses))
.orElse(new JsonRpcErrorResponse(request.getId(), JsonRpcError.INTERNAL_ERROR));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public String getName() {
public JsonRpcResponse response(final JsonRpcRequest request) {
final Optional<BlockHeader> blockHeader = determineBlockHeader(request);
return blockHeader
.map(bh -> voteTallyCache.getVoteTallyAtBlock(bh).getCurrentValidators())
.map(bh -> voteTallyCache.getVoteTallyAfterBlock(bh).getValidators())
.map(addresses -> addresses.stream().map(Objects::toString).collect(Collectors.toList()))
.<JsonRpcResponse>map(addresses -> new JsonRpcSuccessResponse(request.getId(), addresses))
.orElse(new JsonRpcErrorResponse(request.getId(), JsonRpcError.INTERNAL_ERROR));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void setup() {
validatorList.add(AddressHelpers.calculateAddressWithRespectTo(localAddr, 1));

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();

final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void networkWithOneValidatorIsAllowedToCreateConsecutiveBlocks() {
blockChain = createInMemoryBlockchain(genesisBlock);

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext);
Expand All @@ -98,7 +98,7 @@ public void networkWithTwoValidatorsIsAllowedToProduceBlockIfNotPreviousBlockPro
blockChain = createInMemoryBlockchain(genesisBlock);

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext);
Expand Down Expand Up @@ -132,7 +132,7 @@ public void networkWithTwoValidatorsIsNotAllowedToProduceBlockIfIsPreviousBlockP
blockChain = createInMemoryBlockchain(genesisBlock);

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext);
Expand Down Expand Up @@ -162,7 +162,7 @@ public void withThreeValidatorsMustHaveOneBlockBetweenSignings() {
blockChain = createInMemoryBlockchain(genesisBlock);

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext);
Expand Down Expand Up @@ -207,7 +207,7 @@ public void signerIsValidIfInsufficientBlocksExistInHistory() {
blockChain = createInMemoryBlockchain(genesisBlock);

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext);
Expand Down Expand Up @@ -236,7 +236,7 @@ public void exceptionIsThrownIfOnAnOrphanedChain() {
blockChain = createInMemoryBlockchain(genesisBlock);

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext);
Expand All @@ -260,7 +260,7 @@ public void nonValidatorIsNotAllowedToCreateABlock() {
blockChain = createInMemoryBlockchain(genesisBlock);

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void parentBlockVoteTallysAreCachedWhenChildVoteTallyRequested() {
// The votetallyUpdater should be invoked for the requested block, and all parents including
// the epoch (genesis) block.
final ArgumentCaptor<BlockHeader> varArgs = ArgumentCaptor.forClass(BlockHeader.class);
cache.getVoteTallyAtBlock(block_2.getHeader());
cache.getVoteTallyAfterBlock(block_2.getHeader());
verify(tallyUpdater, times(3)).updateForBlock(varArgs.capture(), any());
assertThat(varArgs.getAllValues())
.isEqualTo(
Expand All @@ -97,10 +97,10 @@ public void parentBlockVoteTallysAreCachedWhenChildVoteTallyRequested() {

// Requesting the vote tally to the parent block should not invoke the voteTallyUpdater as the
// vote tally was cached from previous operation.
cache.getVoteTallyAtBlock(block_1.getHeader());
cache.getVoteTallyAfterBlock(block_1.getHeader());
verifyZeroInteractions(tallyUpdater);

cache.getVoteTallyAtBlock(block_2.getHeader());
cache.getVoteTallyAfterBlock(block_2.getHeader());
verifyZeroInteractions(tallyUpdater);
}

Expand All @@ -113,7 +113,7 @@ public void exceptionThrownIfNoParentBlockExists() {
final Block orphanBlock = createEmptyBlock(4, Hash.ZERO);

assertThatExceptionOfType(UncheckedExecutionException.class)
.isThrownBy(() -> cache.getVoteTallyAtBlock(orphanBlock.getHeader()))
.isThrownBy(() -> cache.getVoteTallyAfterBlock(orphanBlock.getHeader()))
.withMessageContaining(
"Supplied block was on a orphaned chain, unable to generate " + "VoteTally.");
}
Expand All @@ -125,14 +125,14 @@ public void walkBackStopsWhenACachedVoteTallyIsFound() {
new VoteTallyCache(blockChain, tallyUpdater, new EpochManager(30_000));

// Load the Cache up to block_2
cache.getVoteTallyAtBlock(block_2.getHeader());
cache.getVoteTallyAfterBlock(block_2.getHeader());

reset(tallyUpdater);

// Append new blocks to the chain, and ensure the walkback only goes as far as block_2.
final Block block_3 = createEmptyBlock(4, block_2.getHeader().getHash());
// Load the Cache up to block_2
cache.getVoteTallyAtBlock(block_3.getHeader());
cache.getVoteTallyAfterBlock(block_3.getHeader());

// The votetallyUpdater should be invoked for the requested block, and all parents including
// the epoch (genesis) block.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void setup() {
validatorList.add(otherAddress);

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void setup() {
validatorList.add(AddressHelpers.calculateAddressWithRespectTo(localAddr, 1));

voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));

blockHeaderBuilder = new BlockHeaderTestFixture();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void setup() {
validatorList.add(AddressHelpers.calculateAddressWithRespectTo(localAddress, 3));

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();

final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class CliqueProposerSelectorTest {
@Before
public void setup() {
voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(voteTally);
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(voteTally);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void setup() {
validatorList.add(AddressHelpers.calculateAddressWithRespectTo(localAddress, 1));

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));
final VoteProposer voteProposer = new VoteProposer();

final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void setup() {
validatorList.add(AddressHelpers.calculateAddressWithRespectTo(localAddr, 1));

final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class);
when(voteTallyCache.getVoteTallyAtBlock(any())).thenReturn(new VoteTally(validatorList));
when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList));

final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, null, null);
cliqueProtocolContext = new ProtocolContext<>(null, null, cliqueContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ public void returnsValidatorsForBlockHash() {
when(blockchainQueries.blockByHash(Hash.fromHexString(BLOCK_HASH)))
.thenReturn(Optional.of(blockWithMetadata));
when(blockWithMetadata.getHeader()).thenReturn(blockHeader);
when(voteTallyCache.getVoteTallyAtBlock(blockHeader)).thenReturn(voteTally);
when(voteTally.getCurrentValidators()).thenReturn(validators);
when(voteTallyCache.getVoteTallyAfterBlock(blockHeader)).thenReturn(voteTally);
when(voteTally.getValidators()).thenReturn(validators);

final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
assertEquals(validatorsAsStrings, response.getResult());
Expand Down
Loading

0 comments on commit deaa392

Please sign in to comment.