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

Commit

Permalink
Clique should use beneficiary of zero on epoch blocks (#833)
Browse files Browse the repository at this point in the history
  • Loading branch information
jframe authored Feb 12, 2019
1 parent 7f41923 commit a6c0587
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,18 @@ public Optional<ValidatorVote> extractVoteFromHeader(final BlockHeader header) {
return Optional.empty();
}

public static BlockHeaderBuilder insertVoteToHeaderBuilder(
public static BlockHeaderBuilder createHeaderBuilderWithVoteHeaders(
final BlockHeaderBuilder builder, final Optional<ValidatorVote> vote) {
final BlockHeaderBuilder voteHeaderBuilder = BlockHeaderBuilder.fromBuilder(builder);
if (vote.isPresent()) {
final ValidatorVote voteToCast = vote.get();
builder.nonce(voteToValue.get(voteToCast.getVotePolarity()));
builder.coinbase(voteToCast.getRecipient());
voteHeaderBuilder.nonce(voteToValue.get(voteToCast.getVotePolarity()));
voteHeaderBuilder.coinbase(voteToCast.getRecipient());
} else {
builder.nonce(voteToValue.get(VoteType.DROP));
builder.coinbase(NO_VOTE_SUBJECT);
voteHeaderBuilder.nonce(voteToValue.get(VoteType.DROP));
voteHeaderBuilder.coinbase(NO_VOTE_SUBJECT);
}
return builder;
return voteHeaderBuilder;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface;
import tech.pegasys.pantheon.consensus.clique.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueExtraData;
import tech.pegasys.pantheon.consensus.common.EpochManager;
import tech.pegasys.pantheon.consensus.common.ValidatorVote;
import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.crypto.SECP256K1;
Expand All @@ -40,6 +41,7 @@
public class CliqueBlockCreator extends AbstractBlockCreator<CliqueContext> {

private final KeyPair nodeKeys;
private final EpochManager epochManager;

public CliqueBlockCreator(
final Address coinbase,
Expand All @@ -50,7 +52,8 @@ public CliqueBlockCreator(
final Function<Long, Long> gasLimitCalculator,
final KeyPair nodeKeys,
final Wei minTransactionGasPrice,
final BlockHeader parentHeader) {
final BlockHeader parentHeader,
final EpochManager epochManager) {
super(
coinbase,
extraDataCalculator,
Expand All @@ -62,6 +65,7 @@ public CliqueBlockCreator(
Util.publicKeyToAddress(nodeKeys.getPublicKey()),
parentHeader);
this.nodeKeys = nodeKeys;
this.epochManager = epochManager;
}

/**
Expand All @@ -74,7 +78,6 @@ public CliqueBlockCreator(
*/
@Override
protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableBlockHeader) {

final BlockHashFunction blockHashFunction =
ScheduleBasedBlockHashFunction.create(protocolSchedule);

Expand All @@ -84,22 +87,28 @@ protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableB
.mixHash(Hash.ZERO)
.blockHashFunction(blockHashFunction);

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

final Optional<ValidatorVote> vote =
cliqueContext
.getVoteProposer()
.getVote(Util.publicKeyToAddress(nodeKeys.getPublicKey()), voteTally);
final Optional<ValidatorVote> vote = determineCliqueVote(sealableBlockHeader);
final BlockHeaderBuilder builderIncludingProposedVotes =
CliqueBlockInterface.insertVoteToHeaderBuilder(builder, vote);

CliqueBlockInterface.createHeaderBuilderWithVoteHeaders(builder, vote);
final CliqueExtraData sealedExtraData =
constructSignedExtraData(builderIncludingProposedVotes.buildBlockHeader());

// Replace the extraData in the BlockHeaderBuilder, and return header.
return builder.extraData(sealedExtraData.encode()).buildBlockHeader();
return builderIncludingProposedVotes.extraData(sealedExtraData.encode()).buildBlockHeader();
}

private Optional<ValidatorVote> determineCliqueVote(
final SealableBlockHeader sealableBlockHeader) {
if (epochManager.isEpochBlock(sealableBlockHeader.getNumber())) {
return Optional.empty();
} else {
final CliqueContext cliqueContext = protocolContext.getConsensusState();
final VoteTally voteTally =
cliqueContext.getVoteTallyCache().getVoteTallyAfterBlock(parentHeader);
return cliqueContext
.getVoteProposer()
.getVote(Util.publicKeyToAddress(nodeKeys.getPublicKey()), voteTally);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ public CliqueBlockMiner startAsyncMining(
(gasLimit) -> gasLimit,
nodeKeys,
minTransactionGasPrice,
parentHeader);
parentHeader,
epochManager);

final CliqueBlockMiner currentRunningMiner =
new CliqueBlockMiner(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void blendingAddVoteToHeaderResultsInHeaderWithNonceOfMaxLong() {
final ValidatorVote vote =
new ValidatorVote(ADD, AddressHelpers.ofValue(1), AddressHelpers.ofValue(2));
final BlockHeaderBuilder builderWithVote =
CliqueBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
CliqueBlockInterface.createHeaderBuilderWithVoteHeaders(builder, Optional.of(vote));

final BlockHeader header = builderWithVote.buildBlockHeader();

Expand All @@ -101,7 +101,7 @@ public void blendingDropVoteToHeaderResultsInHeaderWithNonceOfZero() {
final ValidatorVote vote =
new ValidatorVote(DROP, AddressHelpers.ofValue(1), AddressHelpers.ofValue(2));
final BlockHeaderBuilder builderWithVote =
CliqueBlockInterface.insertVoteToHeaderBuilder(builder, Optional.of(vote));
CliqueBlockInterface.createHeaderBuilderWithVoteHeaders(builder, Optional.of(vote));

final BlockHeader header = builderWithVote.buildBlockHeader();

Expand All @@ -112,7 +112,7 @@ public void blendingDropVoteToHeaderResultsInHeaderWithNonceOfZero() {
@Test
public void nonVoteBlendedIntoHeaderResultsInACoinbaseOfZero() {
final BlockHeaderBuilder builderWithVote =
CliqueBlockInterface.insertVoteToHeaderBuilder(builder, Optional.empty());
CliqueBlockInterface.createHeaderBuilderWithVoteHeaders(builder, Optional.empty());

final BlockHeader header = builderWithVote.buildBlockHeader();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule;
import tech.pegasys.pantheon.consensus.clique.TestHelpers;
import tech.pegasys.pantheon.consensus.clique.VoteTallyCache;
import tech.pegasys.pantheon.consensus.common.EpochManager;
import tech.pegasys.pantheon.consensus.common.VoteProposer;
import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
Expand Down Expand Up @@ -64,6 +65,7 @@ public class CliqueBlockCreatorTest {
private MutableBlockchain blockchain;
private ProtocolContext<CliqueContext> protocolContext;
private VoteProposer voteProposer;
private EpochManager epochManager;

@Before
public void setup() {
Expand All @@ -83,6 +85,7 @@ public void setup() {
GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule).getBlock();
blockchain = createInMemoryBlockchain(genesis);
protocolContext = new ProtocolContext<>(blockchain, stateArchive, cliqueContext);
epochManager = new EpochManager(10);

// Add a block above the genesis
final BlockHeaderTestFixture headerTestFixture = new BlockHeaderTestFixture();
Expand Down Expand Up @@ -112,7 +115,8 @@ public void proposerAddressCanBeExtractFromAConstructedBlock() {
gasLimit -> gasLimit,
proposerKeyPair,
Wei.ZERO,
blockchain.getChainHeadHeader());
blockchain.getChainHeadHeader(),
epochManager);

final Block createdBlock = blockCreator.createBlock(5L);

Expand All @@ -138,7 +142,8 @@ public void insertsValidVoteIntoConstructedBlock() {
gasLimit -> gasLimit,
proposerKeyPair,
Wei.ZERO,
blockchain.getChainHeadHeader());
blockchain.getChainHeadHeader(),
epochManager);

final Block createdBlock = blockCreator.createBlock(0L);
assertThat(createdBlock.getHeader().getNonce()).isEqualTo(CliqueBlockInterface.ADD_NONCE);
Expand All @@ -163,7 +168,37 @@ public void insertsNoVoteWhenAuthInValidators() {
gasLimit -> gasLimit,
proposerKeyPair,
Wei.ZERO,
blockchain.getChainHeadHeader());
blockchain.getChainHeadHeader(),
epochManager);

final Block createdBlock = blockCreator.createBlock(0L);
assertThat(createdBlock.getHeader().getNonce()).isEqualTo(CliqueBlockInterface.DROP_NONCE);
assertThat(createdBlock.getHeader().getCoinbase()).isEqualTo(Address.fromHexString("0"));
}

@Test
public void insertsNoVoteWhenAtEpoch() {
// ensure that the next block is epoch
epochManager = new EpochManager(1);

final CliqueExtraData extraData =
new CliqueExtraData(BytesValue.wrap(new byte[32]), null, validatorList);
final Address a1 = Address.fromHexString("5");
voteProposer.auth(a1);
final Address coinbase = AddressHelpers.ofValue(1);

final CliqueBlockCreator blockCreator =
new CliqueBlockCreator(
coinbase,
parent -> extraData.encode(),
new PendingTransactions(5),
protocolContext,
protocolSchedule,
gasLimit -> gasLimit,
proposerKeyPair,
Wei.ZERO,
blockchain.getChainHeadHeader(),
epochManager);

final Block createdBlock = blockCreator.createBlock(0L);
assertThat(createdBlock.getHeader().getNonce()).isEqualTo(CliqueBlockInterface.DROP_NONCE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ public static BlockHeaderBuilder fromHeader(final BlockHeader header) {
.nonce(header.getNonce());
}

public static BlockHeaderBuilder fromBuilder(final BlockHeaderBuilder fromBuilder) {
BlockHeaderBuilder toBuilder =
create()
.parentHash(fromBuilder.parentHash)
.ommersHash(fromBuilder.ommersHash)
.coinbase(fromBuilder.coinbase)
.stateRoot(fromBuilder.stateRoot)
.transactionsRoot(fromBuilder.transactionsRoot)
.receiptsRoot(fromBuilder.receiptsRoot)
.logsBloom(fromBuilder.logsBloom)
.difficulty(fromBuilder.difficulty)
.number(fromBuilder.number)
.gasLimit(fromBuilder.gasLimit)
.gasUsed(fromBuilder.gasUsed)
.timestamp(fromBuilder.timestamp)
.extraData(fromBuilder.extraData)
.mixHash(fromBuilder.mixHash)
.blockHashFunction(fromBuilder.blockHashFunction);
toBuilder.nonce = fromBuilder.nonce;
return toBuilder;
}

public BlockHeader buildBlockHeader() {
validateBlockHeader();

Expand Down

0 comments on commit a6c0587

Please sign in to comment.