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

[PAN-2954] Support for NoReward and NoProof seal engines #1813

Merged
merged 6 commits into from
Aug 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ private static ProtocolSpecBuilder<CliqueContext> applyCliqueSpecificModificatio
MainnetBlockImporter::new,
new CliqueDifficultyCalculator(localNodeAddress))
.blockReward(Wei.ZERO)
.skipZeroBlockRewards(true)
.miningBeneficiaryCalculator(CliqueHelpers::getProposerOfBlock)
.blockHeaderFunctions(new CliqueBlockHeaderFunctions());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public void parametersAlignWithMainnetWithAdjustments() {

assertThat(homestead.getName()).isEqualTo("Frontier");
assertThat(homestead.getBlockReward()).isEqualTo(Wei.ZERO);
assertThat(homestead.isSkipZeroBlockRewards()).isEqualTo(true);
assertThat(homestead.getDifficultyCalculator()).isInstanceOf(CliqueDifficultyCalculator.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ private static ProtocolSpecBuilder<IbftContext> applyIbftChanges(
MainnetBlockImporter::new,
(time, parent, protocolContext) -> BigInteger.ONE)
.blockReward(Wei.ZERO)
.skipZeroBlockRewards(true)
.blockHeaderFunctions(IbftBlockHeaderFunctions.forOnChainBlock());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ private static ProtocolSpecBuilder<IbftContext> applyIbftChanges(
MainnetBlockImporter::new,
(time, parent, protocolContext) -> BigInteger.ONE)
.blockReward(Wei.ZERO)
.skipZeroBlockRewards(true)
.blockHeaderFunctions(new LegacyIbftBlockHeaderFunctions());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import tech.pegasys.pantheon.ethereum.mainnet.DifficultyCalculator;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockProcessor.TransactionReceiptFactory;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import tech.pegasys.pantheon.ethereum.mainnet.TransactionProcessor;
import tech.pegasys.pantheon.util.bytes.BytesValue;
Expand Down Expand Up @@ -129,10 +130,15 @@ public Block createBlock(final long timestamp) {

throwIfStopped();

final Wei blockReward =
protocolSchedule.getByBlockNumber(processableBlockHeader.getNumber()).getBlockReward();
final ProtocolSpec<C> protocolSpec =
protocolSchedule.getByBlockNumber(processableBlockHeader.getNumber());

if (!rewardBeneficiary(disposableWorldState, processableBlockHeader, ommers, blockReward)) {
if (!rewardBeneficiary(
disposableWorldState,
processableBlockHeader,
ommers,
protocolSpec.getBlockReward(),
protocolSpec.isSkipZeroBlockRewards())) {
LOG.trace("Failed to apply mining reward, exiting.");
throw new RuntimeException("Failed to apply mining reward.");
}
Expand Down Expand Up @@ -245,22 +251,23 @@ public boolean isCancelled() {
return isCancelled.get();
}

protected void throwIfStopped() throws CancellationException {
private void throwIfStopped() throws CancellationException {
if (isCancelled.get()) {
throw new CancellationException();
}
}

/* Copied from BlockProcessor (with modifications). */
private boolean rewardBeneficiary(
boolean rewardBeneficiary(
final MutableWorldState worldState,
final ProcessableBlockHeader header,
final List<BlockHeader> ommers,
final Wei blockReward) {
final Wei blockReward,
boolean skipZeroBlockRewards) {

// TODO(tmm): Added to make this work, should come from blockProcessor.
final int MAX_GENERATION = 6;
if (blockReward.isZero()) {
if (skipZeroBlockRewards && blockReward.isZero()) {
return true;
}
final Wei coinbaseReward = blockReward.plus(blockReward.times(ommers.size()).dividedBy(32));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@
*/
package tech.pegasys.pantheon.ethereum.blockcreation;

import static org.assertj.core.api.Assertions.assertThat;

import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderBuilder;
import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.MutableWorldState;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.core.ProcessableBlockHeader;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.eth.transactions.PendingTransactions;
import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolConfiguration;
Expand All @@ -28,13 +34,14 @@
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256;

import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
import java.util.function.Function;

import com.google.common.collect.Lists;
import org.assertj.core.api.Assertions;
import org.junit.Test;

public class EthHashBlockCreatorTest {
Expand Down Expand Up @@ -86,17 +93,17 @@ public void createMainnetBlock1() throws IOException {
executionContextTestFixture.getBlockchain().getChainHeadHeader());

// A Hashrate should not exist in the block creator prior to creating a block
Assertions.assertThat(blockCreator.getHashesPerSecond().isPresent()).isFalse();
assertThat(blockCreator.getHashesPerSecond().isPresent()).isFalse();

final Block actualBlock = blockCreator.createBlock(BLOCK_1_TIMESTAMP);
final Block expectedBlock = ValidationTestUtils.readBlock(1);

Assertions.assertThat(actualBlock).isEqualTo(expectedBlock);
Assertions.assertThat(blockCreator.getHashesPerSecond().isPresent()).isTrue();
assertThat(actualBlock).isEqualTo(expectedBlock);
assertThat(blockCreator.getHashesPerSecond().isPresent()).isTrue();
}

@Test
public void createMainnetBlock1_fixedDifficulty1() throws IOException {
public void createMainnetBlock1_fixedDifficulty1() {
final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(
Expand Down Expand Up @@ -136,4 +143,119 @@ public void createMainnetBlock1_fixedDifficulty1() throws IOException {
// If we weren't setting difficulty to 2^256-1 a difficulty of 1 would have caused a
// IllegalArgumentException at the previous line, as 2^256 is 33 bytes.
}

@Test
public void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() {
final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(
new ProtocolScheduleBuilder<>(
GenesisConfigFile.fromConfig(
"{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions(),
BigInteger.valueOf(42),
Function.identity(),
PrivacyParameters.DEFAULT,
false)
.createProtocolSchedule())
.build();

final EthHashSolver solver = new EthHashSolver(Lists.newArrayList(BLOCK_1_NONCE), new Light());

final PendingTransactions pendingTransactions =
new PendingTransactions(
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS,
1,
TestClock.fixed(),
metricsSystem);

final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(
BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions,
executionContextTestFixture.getProtocolContext(),
executionContextTestFixture.getProtocolSchedule(),
gasLimit -> gasLimit,
solver,
Wei.ZERO,
executionContextTestFixture.getBlockchain().getChainHeadHeader());

final MutableWorldState mutableWorldState =
executionContextTestFixture.getStateArchive().getMutable();
assertThat(mutableWorldState.get(BLOCK_1_COINBASE)).isNull();

final ProcessableBlockHeader header =
BlockHeaderBuilder.create()
.parentHash(Hash.ZERO)
.coinbase(BLOCK_1_COINBASE)
.difficulty(UInt256.ONE)
.number(1)
.gasLimit(1)
.timestamp(1)
.buildProcessableBlockHeader();

blockCreator.rewardBeneficiary(
mutableWorldState, header, Collections.emptyList(), Wei.ZERO, false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably worth creating another version of this test where skipZeroBlockRewards is true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


assertThat(mutableWorldState.get(BLOCK_1_COINBASE)).isNotNull();
assertThat(mutableWorldState.get(BLOCK_1_COINBASE).getBalance()).isEqualTo(Wei.ZERO);
}

@Test
public void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() {
final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(
new ProtocolScheduleBuilder<>(
GenesisConfigFile.fromConfig(
"{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions(),
BigInteger.valueOf(42),
Function.identity(),
PrivacyParameters.DEFAULT,
false)
.createProtocolSchedule())
.build();

final EthHashSolver solver = new EthHashSolver(Lists.newArrayList(BLOCK_1_NONCE), new Light());

final PendingTransactions pendingTransactions =
new PendingTransactions(
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS,
1,
TestClock.fixed(),
metricsSystem);

final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(
BLOCK_1_COINBASE,
parent -> BLOCK_1_EXTRA_DATA,
pendingTransactions,
executionContextTestFixture.getProtocolContext(),
executionContextTestFixture.getProtocolSchedule(),
gasLimit -> gasLimit,
solver,
Wei.ZERO,
executionContextTestFixture.getBlockchain().getChainHeadHeader());

final MutableWorldState mutableWorldState =
executionContextTestFixture.getStateArchive().getMutable();
assertThat(mutableWorldState.get(BLOCK_1_COINBASE)).isNull();

final ProcessableBlockHeader header =
BlockHeaderBuilder.create()
.parentHash(Hash.ZERO)
.coinbase(BLOCK_1_COINBASE)
.difficulty(UInt256.ONE)
.number(1)
.gasLimit(1)
.timestamp(1)
.buildProcessableBlockHeader();

blockCreator.rewardBeneficiary(
mutableWorldState, header, Collections.emptyList(), Wei.ZERO, true);

assertThat(mutableWorldState.get(BLOCK_1_COINBASE)).isNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static class EthHashSolverJob {
private final EthHashSolverInputs inputs;
private final CompletableFuture<EthHashSolution> nonceFuture;

public EthHashSolverJob(
EthHashSolverJob(
final EthHashSolverInputs inputs, final CompletableFuture<EthHashSolution> nonceFuture) {
this.inputs = inputs;
this.nonceFuture = nonceFuture;
Expand All @@ -42,15 +42,15 @@ public static EthHashSolverJob createFromInputs(final EthHashSolverInputs inputs
return new EthHashSolverJob(inputs, new CompletableFuture<>());
}

public EthHashSolverInputs getInputs() {
EthHashSolverInputs getInputs() {
return inputs;
}

public boolean isDone() {
return nonceFuture.isDone();
}

public void solvedWith(final EthHashSolution solution) {
void solvedWith(final EthHashSolution solution) {
nonceFuture.complete(solution);
}

Expand All @@ -62,7 +62,7 @@ public void failed(final Throwable ex) {
nonceFuture.completeExceptionally(ex);
}

public EthHashSolution getSolution() throws InterruptedException, ExecutionException {
EthHashSolution getSolution() throws InterruptedException, ExecutionException {
return nonceFuture.get();
}
}
Expand Down Expand Up @@ -121,7 +121,7 @@ private Optional<EthHashSolution> testNonce(
}

public void cancel() {
currentJob.ifPresent(job -> job.cancel());
currentJob.ifPresent(EthHashSolverJob::cancel);
}

public Optional<EthHashSolverInputs> getWorkDefinition() {
Expand All @@ -137,7 +137,7 @@ public Optional<Long> hashesPerSecond() {

public boolean submitSolution(final EthHashSolution solution) {
final Optional<EthHashSolverJob> jobSnapshot = currentJob;
if (!jobSnapshot.isPresent()) {
if (jobSnapshot.isEmpty()) {
return false;
}

Expand All @@ -156,4 +156,8 @@ public boolean submitSolution(final EthHashSolution solution) {
}
return false;
}

public Iterable<Long> getNonceGenerator() {
return nonceGenerator;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,21 @@ public boolean isSuccessful() {

private final Wei blockReward;

private final boolean skipZeroBlockRewards;

private final MiningBeneficiaryCalculator miningBeneficiaryCalculator;

public MainnetBlockProcessor(
final TransactionProcessor transactionProcessor,
final TransactionReceiptFactory transactionReceiptFactory,
final Wei blockReward,
final MiningBeneficiaryCalculator miningBeneficiaryCalculator) {
final MiningBeneficiaryCalculator miningBeneficiaryCalculator,
final boolean skipZeroBlockRewards) {
this.transactionProcessor = transactionProcessor;
this.transactionReceiptFactory = transactionReceiptFactory;
this.blockReward = blockReward;
this.miningBeneficiaryCalculator = miningBeneficiaryCalculator;
this.skipZeroBlockRewards = skipZeroBlockRewards;
}

@Override
Expand Down Expand Up @@ -143,7 +147,7 @@ public Result processBlock(
receipts.add(transactionReceipt);
}

if (!rewardCoinbase(worldState, blockHeader, ommers)) {
if (!rewardCoinbase(worldState, blockHeader, ommers, skipZeroBlockRewards)) {
return Result.failed();
}

Expand All @@ -154,8 +158,9 @@ public Result processBlock(
private boolean rewardCoinbase(
final MutableWorldState worldState,
final ProcessableBlockHeader header,
final List<BlockHeader> ommers) {
if (blockReward.isZero()) {
final List<BlockHeader> ommers,
final boolean skipZeroBlockRewards) {
if (skipZeroBlockRewards && blockReward.isZero()) {
return true;
}
final Wei coinbaseReward = blockReward.plus(blockReward.times(ommers.size()).dividedBy(32));
Expand Down
Loading