|
|
|
@ -2,7 +2,7 @@ package net.consensys.pantheon.consensus.clique.blockcreation; |
|
|
|
|
|
|
|
|
|
import net.consensys.pantheon.consensus.clique.VoteTallyCache; |
|
|
|
|
import net.consensys.pantheon.consensus.common.ValidatorProvider; |
|
|
|
|
import net.consensys.pantheon.ethereum.blockcreation.BaseBlockScheduler; |
|
|
|
|
import net.consensys.pantheon.ethereum.blockcreation.DefaultBlockScheduler; |
|
|
|
|
import net.consensys.pantheon.ethereum.core.Address; |
|
|
|
|
import net.consensys.pantheon.ethereum.core.BlockHeader; |
|
|
|
|
import net.consensys.pantheon.util.time.Clock; |
|
|
|
@ -11,7 +11,7 @@ import java.util.Random; |
|
|
|
|
|
|
|
|
|
import com.google.common.annotations.VisibleForTesting; |
|
|
|
|
|
|
|
|
|
public class CliqueBlockScheduler extends BaseBlockScheduler { |
|
|
|
|
public class CliqueBlockScheduler extends DefaultBlockScheduler { |
|
|
|
|
|
|
|
|
|
private final int OUT_OF_TURN_DELAY_MULTIPLIER_MILLIS = 500; |
|
|
|
|
|
|
|
|
@ -24,7 +24,7 @@ public class CliqueBlockScheduler extends BaseBlockScheduler { |
|
|
|
|
final VoteTallyCache voteTallyCache, |
|
|
|
|
final Address localNodeAddress, |
|
|
|
|
final long secondsBetweenBlocks) { |
|
|
|
|
super(clock); |
|
|
|
|
super(secondsBetweenBlocks, 0L, clock); |
|
|
|
|
this.voteTallyCache = voteTallyCache; |
|
|
|
|
this.localNodeAddress = localNodeAddress; |
|
|
|
|
this.secondsBetweenBlocks = secondsBetweenBlocks; |
|
|
|
@ -33,24 +33,29 @@ public class CliqueBlockScheduler extends BaseBlockScheduler { |
|
|
|
|
@Override |
|
|
|
|
@VisibleForTesting |
|
|
|
|
public BlockCreationTimeResult getNextTimestamp(final BlockHeader parentHeader) { |
|
|
|
|
final long nextHeaderTimestamp = parentHeader.getTimestamp() + secondsBetweenBlocks; |
|
|
|
|
long milliSecondsUntilNextBlock = (nextHeaderTimestamp * 1000) - clock.millisecondsSinceEpoch(); |
|
|
|
|
final BlockCreationTimeResult result = super.getNextTimestamp(parentHeader); |
|
|
|
|
|
|
|
|
|
final CliqueProposerSelector proposerSelector = new CliqueProposerSelector(voteTallyCache); |
|
|
|
|
final Address nextSelector = proposerSelector.selectProposerForNextBlock(parentHeader); |
|
|
|
|
if (!nextSelector.equals(localNodeAddress)) { |
|
|
|
|
milliSecondsUntilNextBlock += |
|
|
|
|
calculatorOutOfTurnDelay(voteTallyCache.getVoteTallyAtBlock(parentHeader)); |
|
|
|
|
} |
|
|
|
|
final long milliSecondsUntilNextBlock = |
|
|
|
|
result.getMillisecondsUntilValid() + calculateTurnBasedDelay(parentHeader); |
|
|
|
|
|
|
|
|
|
return new BlockCreationTimeResult( |
|
|
|
|
nextHeaderTimestamp, Math.max(0, milliSecondsUntilNextBlock)); |
|
|
|
|
result.getTimestampForHeader(), Math.max(0, milliSecondsUntilNextBlock)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private int calculateTurnBasedDelay(final BlockHeader parentHeader) { |
|
|
|
|
final CliqueProposerSelector proposerSelector = new CliqueProposerSelector(voteTallyCache); |
|
|
|
|
final Address nextProposer = proposerSelector.selectProposerForNextBlock(parentHeader); |
|
|
|
|
|
|
|
|
|
if (nextProposer.equals(localNodeAddress)) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
return calculatorOutOfTurnDelay(voteTallyCache.getVoteTallyAtBlock(parentHeader)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private int calculatorOutOfTurnDelay(final ValidatorProvider validators) { |
|
|
|
|
int countSigners = validators.getCurrentValidators().size(); |
|
|
|
|
int maxDelay = ((countSigners / 2) + 1) * OUT_OF_TURN_DELAY_MULTIPLIER_MILLIS; |
|
|
|
|
Random r = new Random(); |
|
|
|
|
return r.nextInt((maxDelay) + 1); |
|
|
|
|
return r.nextInt(maxDelay + 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|