From 7e373ccc97d87fc23086b7fcd03a7a7f7afb0074 Mon Sep 17 00:00:00 2001 From: tmohay <37158202+rain-on@users.noreply.github.com> Date: Wed, 16 Jan 2019 15:41:34 +1100 Subject: [PATCH] Split Block Validation from Importing (#579) Ibft is required to validate a block upon reception, but not import it until a later time. As such, IBFT will require validation and importing to be separated. The validator has been exposed as part of the ProtocolSpecification. Signed-off-by: Adrian Sutton --- .../clique/CliqueProtocolSchedule.java | 2 + .../consensus/ibft/IbftProtocolSchedule.java | 7 +- .../ibftlegacy/IbftProtocolSchedule.java | 7 +- .../pantheon/ethereum/BlockValidator.java | 47 ++++++++ .../ethereum/MainnetBlockValidator.java | 109 ++++++++++++++++++ .../mainnet/MainnetBlockImporter.java | 79 ++++--------- .../mainnet/MainnetProtocolSpecs.java | 2 + .../ethereum/mainnet/ProtocolSpec.java | 15 +++ .../ethereum/mainnet/ProtocolSpecBuilder.java | 25 +++- .../methods/EthGetTransactionReceiptTest.java | 2 + 10 files changed, 229 insertions(+), 66 deletions(-) create mode 100644 ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/BlockValidator.java create mode 100644 ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/MainnetBlockValidator.java diff --git a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java index b8497f6fdc..e8cd7b4359 100644 --- a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java +++ b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java @@ -18,6 +18,7 @@ import tech.pegasys.pantheon.config.CliqueConfigOptions; import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.consensus.common.EpochManager; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; +import tech.pegasys.pantheon.ethereum.MainnetBlockValidator; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.core.Wei; @@ -63,6 +64,7 @@ public class CliqueProtocolSchedule { difficultyCalculator -> cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager), difficultyCalculator -> cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager), MainnetBlockBodyValidator::new, + MainnetBlockValidator::new, MainnetBlockImporter::new, new CliqueDifficultyCalculator(localNodeAddress)) .blockReward(Wei.ZERO) diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java index 1f741c7fe1..a26b15ce14 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java @@ -18,6 +18,7 @@ import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.config.IbftConfigOptions; import tech.pegasys.pantheon.consensus.common.EpochManager; import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater; +import tech.pegasys.pantheon.ethereum.MainnetBlockValidator; import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockBodyValidator; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockImporter; @@ -57,10 +58,10 @@ public class IbftProtocolSchedule { difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), MainnetBlockBodyValidator::new, - (blockHeaderValidator, blockBodyValidator, blockProcessor) -> + MainnetBlockValidator::new, + (blockValidator) -> new IbftBlockImporter( - new MainnetBlockImporter<>( - blockHeaderValidator, blockBodyValidator, blockProcessor), + new MainnetBlockImporter<>(blockValidator), new VoteTallyUpdater(epochManager, new IbftBlockInterface())), (time, parent, protocolContext) -> BigInteger.ONE) .blockReward(Wei.ZERO) diff --git a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java index dccd76b2eb..e86f4db18c 100644 --- a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java @@ -20,6 +20,7 @@ import tech.pegasys.pantheon.consensus.common.EpochManager; import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater; import tech.pegasys.pantheon.consensus.ibft.IbftBlockImporter; import tech.pegasys.pantheon.consensus.ibft.IbftContext; +import tech.pegasys.pantheon.ethereum.MainnetBlockValidator; import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockBodyValidator; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockImporter; @@ -59,10 +60,10 @@ public class IbftProtocolSchedule { difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), MainnetBlockBodyValidator::new, - (blockHeaderValidator, blockBodyValidator, blockProcessor) -> + MainnetBlockValidator::new, + (blockValidator) -> new IbftBlockImporter( - new MainnetBlockImporter<>( - blockHeaderValidator, blockBodyValidator, blockProcessor), + new MainnetBlockImporter<>(blockValidator), new VoteTallyUpdater(epochManager, new IbftLegacyBlockInterface())), (time, parent, protocolContext) -> BigInteger.ONE) .blockReward(Wei.ZERO) diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/BlockValidator.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/BlockValidator.java new file mode 100644 index 0000000000..45bdcb0f29 --- /dev/null +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/BlockValidator.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package tech.pegasys.pantheon.ethereum; + +import tech.pegasys.pantheon.ethereum.core.Block; +import tech.pegasys.pantheon.ethereum.core.MutableWorldState; +import tech.pegasys.pantheon.ethereum.core.TransactionReceipt; +import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode; + +import java.util.List; +import java.util.Optional; + +public interface BlockValidator { + + class BlockProcessingOutputs { + public final MutableWorldState worldState; + public final List receipts; + + public BlockProcessingOutputs( + final MutableWorldState worldState, final List receipts) { + this.worldState = worldState; + this.receipts = receipts; + } + } + + Optional validateAndProcessBlock( + final ProtocolContext context, + final Block block, + final HeaderValidationMode headerValidationMode, + final HeaderValidationMode ommerValidationMode); + + boolean fastBlockValidation( + final ProtocolContext context, + final Block block, + final List receipts, + final HeaderValidationMode headerValidationMode); +} diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/MainnetBlockValidator.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/MainnetBlockValidator.java new file mode 100644 index 0000000000..0110e7bb18 --- /dev/null +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/MainnetBlockValidator.java @@ -0,0 +1,109 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package tech.pegasys.pantheon.ethereum; + +import static org.apache.logging.log4j.LogManager.getLogger; + +import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; +import tech.pegasys.pantheon.ethereum.core.Block; +import tech.pegasys.pantheon.ethereum.core.BlockHeader; +import tech.pegasys.pantheon.ethereum.core.MutableWorldState; +import tech.pegasys.pantheon.ethereum.core.TransactionReceipt; +import tech.pegasys.pantheon.ethereum.mainnet.BlockBodyValidator; +import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator; +import tech.pegasys.pantheon.ethereum.mainnet.BlockProcessor; +import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode; + +import java.util.List; +import java.util.Optional; + +import org.apache.logging.log4j.Logger; + +public class MainnetBlockValidator implements BlockValidator { + + private static final Logger LOG = getLogger(); + + private final BlockHeaderValidator blockHeaderValidator; + + private final BlockBodyValidator blockBodyValidator; + + private final BlockProcessor blockProcessor; + + public MainnetBlockValidator( + final BlockHeaderValidator blockHeaderValidator, + final BlockBodyValidator blockBodyValidator, + final BlockProcessor blockProcessor) { + this.blockHeaderValidator = blockHeaderValidator; + this.blockBodyValidator = blockBodyValidator; + this.blockProcessor = blockProcessor; + } + + @Override + public Optional validateAndProcessBlock( + final ProtocolContext context, + final Block block, + final HeaderValidationMode headerValidationMode, + final HeaderValidationMode ommerValidationMode) { + final BlockHeader header = block.getHeader(); + + final Optional maybeParentHeader = + context.getBlockchain().getBlockHeader(header.getParentHash()); + if (!maybeParentHeader.isPresent()) { + LOG.error( + "Attempted to import block {} with hash {} but parent block {} was not present", + header.getNumber(), + header.getHash(), + header.getParentHash()); + return Optional.empty(); + } + final BlockHeader parentHeader = maybeParentHeader.get(); + + if (!blockHeaderValidator.validateHeader(header, parentHeader, context, headerValidationMode)) { + return Optional.empty(); + } + + final MutableBlockchain blockchain = context.getBlockchain(); + final MutableWorldState worldState = + context.getWorldStateArchive().getMutable(parentHeader.getStateRoot()); + final BlockProcessor.Result result = blockProcessor.processBlock(blockchain, worldState, block); + if (!result.isSuccessful()) { + return Optional.empty(); + } + + final List receipts = result.getReceipts(); + if (!blockBodyValidator.validateBody( + context, block, receipts, worldState.rootHash(), ommerValidationMode)) { + return Optional.empty(); + } + + return Optional.of(new BlockProcessingOutputs(worldState, receipts)); + } + + @Override + public boolean fastBlockValidation( + final ProtocolContext context, + final Block block, + final List receipts, + final HeaderValidationMode headerValidationMode) { + final BlockHeader header = block.getHeader(); + if (!blockHeaderValidator.validateHeader(header, context, headerValidationMode)) { + return false; + } + + if (!blockBodyValidator.validateBodyLight( + context, block, receipts, HeaderValidationMode.FULL)) { + return false; + } + return true; + } +} diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockImporter.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockImporter.java index bbe231f5dd..f877e6abde 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockImporter.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockImporter.java @@ -14,12 +14,12 @@ package tech.pegasys.pantheon.ethereum.mainnet; import static org.apache.logging.log4j.LogManager.getLogger; +import tech.pegasys.pantheon.ethereum.BlockValidator; +import tech.pegasys.pantheon.ethereum.BlockValidator.BlockProcessingOutputs; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Block; -import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockImporter; -import tech.pegasys.pantheon.ethereum.core.MutableWorldState; import tech.pegasys.pantheon.ethereum.core.TransactionReceipt; import java.util.List; @@ -28,21 +28,13 @@ import java.util.Optional; import org.apache.logging.log4j.Logger; public class MainnetBlockImporter implements BlockImporter { - private static final Logger LOG = getLogger(); - - private final BlockHeaderValidator blockHeaderValidator; - private final BlockBodyValidator blockBodyValidator; + private static final Logger LOG = getLogger(); - private final BlockProcessor blockProcessor; + final BlockValidator blockValidator; - public MainnetBlockImporter( - final BlockHeaderValidator blockHeaderValidator, - final BlockBodyValidator blockBodyValidator, - final BlockProcessor blockProcessor) { - this.blockHeaderValidator = blockHeaderValidator; - this.blockBodyValidator = blockBodyValidator; - this.blockProcessor = blockProcessor; + public MainnetBlockImporter(final BlockValidator blockValidator) { + this.blockValidator = blockValidator; } @Override @@ -51,41 +43,23 @@ public class MainnetBlockImporter implements BlockImporter { final Block block, final HeaderValidationMode headerValidationMode, final HeaderValidationMode ommerValidationMode) { - final BlockHeader header = block.getHeader(); - - final Optional maybeParentHeader = - context.getBlockchain().getBlockHeader(header.getParentHash()); - if (!maybeParentHeader.isPresent()) { - LOG.error( - "Attempted to import block {} with hash {} but parent block {} was not present", - header.getNumber(), - header.getHash(), - header.getParentHash()); - return false; - } - final BlockHeader parentHeader = maybeParentHeader.get(); - if (!blockHeaderValidator.validateHeader(header, parentHeader, context, headerValidationMode)) { - return false; - } + final Optional outputs = + blockValidator.validateAndProcessBlock( + context, block, headerValidationMode, ommerValidationMode); - final MutableBlockchain blockchain = context.getBlockchain(); - final MutableWorldState worldState = - context.getWorldStateArchive().getMutable(parentHeader.getStateRoot()); - final BlockProcessor.Result result = blockProcessor.processBlock(blockchain, worldState, block); - if (!result.isSuccessful()) { - return false; - } + outputs.ifPresent(processingOutputs -> persistState(processingOutputs, block, context)); - final List receipts = result.getReceipts(); - if (!blockBodyValidator.validateBody( - context, block, receipts, worldState.rootHash(), ommerValidationMode)) { - return false; - } - - blockchain.appendBlock(block, receipts); + return outputs.isPresent(); + } - return true; + private void persistState( + final BlockProcessingOutputs processingOutputs, + final Block block, + final ProtocolContext context) { + processingOutputs.worldState.persist(); + final MutableBlockchain blockchain = context.getBlockchain(); + blockchain.appendBlock(block, processingOutputs.receipts); } @Override @@ -94,19 +68,12 @@ public class MainnetBlockImporter implements BlockImporter { final Block block, final List receipts, final HeaderValidationMode headerValidationMode) { - final BlockHeader header = block.getHeader(); - if (!blockHeaderValidator.validateHeader(header, context, headerValidationMode)) { - return false; + if (blockValidator.fastBlockValidation(context, block, receipts, headerValidationMode)) { + context.getBlockchain().appendBlock(block, receipts); + return true; } - if (!blockBodyValidator.validateBodyLight( - context, block, receipts, HeaderValidationMode.FULL)) { - return false; - } - - context.getBlockchain().appendBlock(block, receipts); - - return true; + return false; } } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java index ebd5c29139..6941e02ce6 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java @@ -12,6 +12,7 @@ */ package tech.pegasys.pantheon.ethereum.mainnet; +import tech.pegasys.pantheon.ethereum.MainnetBlockValidator; import tech.pegasys.pantheon.ethereum.chain.Blockchain; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.BlockHeader; @@ -87,6 +88,7 @@ public abstract class MainnetProtocolSpecs { .transactionReceiptFactory(MainnetProtocolSpecs::frontierTransactionReceiptFactory) .blockReward(FRONTIER_BLOCK_REWARD) .blockProcessorBuilder(MainnetBlockProcessor::new) + .blockValidatorBuilder(MainnetBlockValidator::new) .blockImporterBuilder(MainnetBlockImporter::new) .transactionReceiptType(TransactionReceiptType.ROOT) .blockHashFunction(MainnetBlockHashFunction::createHash) diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpec.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpec.java index 49089f911e..499df4425d 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpec.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpec.java @@ -12,6 +12,7 @@ */ package tech.pegasys.pantheon.ethereum.mainnet; +import tech.pegasys.pantheon.ethereum.BlockValidator; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.BlockImporter; import tech.pegasys.pantheon.ethereum.core.Wei; @@ -36,6 +37,8 @@ public class ProtocolSpec { private final BlockImporter blockImporter; + private final BlockValidator blockValidator; + private final BlockProcessor blockProcessor; private final BlockHashFunction blockHashFunction; @@ -60,6 +63,7 @@ public class ProtocolSpec { * @param blockBodyValidator the block body validator to use * @param blockProcessor the block processor to use * @param blockImporter the block importer to use + * @param blockValidator the block validator to use * @param blockHashFunction the block hash function to use * @param transactionReceiptFactory the transactionReceiptFactory to use * @param difficultyCalculator the difficultyCalculator to use @@ -77,6 +81,7 @@ public class ProtocolSpec { final BlockBodyValidator blockBodyValidator, final BlockProcessor blockProcessor, final BlockImporter blockImporter, + final BlockValidator blockValidator, final BlockHashFunction blockHashFunction, final TransactionReceiptFactory transactionReceiptFactory, final DifficultyCalculator difficultyCalculator, @@ -92,6 +97,7 @@ public class ProtocolSpec { this.blockBodyValidator = blockBodyValidator; this.blockProcessor = blockProcessor; this.blockImporter = blockImporter; + this.blockValidator = blockValidator; this.blockHashFunction = blockHashFunction; this.transactionReceiptFactory = transactionReceiptFactory; this.difficultyCalculator = difficultyCalculator; @@ -144,6 +150,15 @@ public class ProtocolSpec { return blockImporter; } + /** + * Returns the block validator used in this specification. + * + * @return the block validator + */ + public BlockValidator getBlockValidator() { + return blockValidator; + } + /** * Returns the block header validator used in this specification. * diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java index a95cd0ad4e..06eebeb789 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java @@ -14,6 +14,7 @@ package tech.pegasys.pantheon.ethereum.mainnet; import static com.google.common.base.Preconditions.checkNotNull; +import tech.pegasys.pantheon.ethereum.BlockValidator; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.BlockImporter; import tech.pegasys.pantheon.ethereum.core.Wei; @@ -43,6 +44,7 @@ public class ProtocolSpecBuilder { messageCallProcessorBuilder; private TransactionProcessorBuilder transactionProcessorBuilder; private BlockProcessorBuilder blockProcessorBuilder; + private BlockValidatorBuilder blockValidatorBuilder; private BlockImporterBuilder blockImporterBuilder; private TransactionReceiptType transactionReceiptType; private String name; @@ -146,6 +148,12 @@ public class ProtocolSpecBuilder { return this; } + public ProtocolSpecBuilder blockValidatorBuilder( + final BlockValidatorBuilder blockValidatorBuilder) { + this.blockValidatorBuilder = blockValidatorBuilder; + return this; + } + public ProtocolSpecBuilder transactionReceiptType( final TransactionReceiptType transactionReceiptType) { this.transactionReceiptType = transactionReceiptType; @@ -172,6 +180,7 @@ public class ProtocolSpecBuilder { final Function, BlockHeaderValidator> blockHeaderValidatorBuilder, final Function, BlockHeaderValidator> ommerHeaderValidatorBuilder, final Function, BlockBodyValidator> blockBodyValidatorBuilder, + final BlockValidatorBuilder blockValidatorBuilder, final BlockImporterBuilder blockImporterBuilder, final DifficultyCalculator difficultyCalculator) { return new ProtocolSpecBuilder() @@ -186,6 +195,7 @@ public class ProtocolSpecBuilder { .ommerHeaderValidatorBuilder(ommerHeaderValidatorBuilder) .blockBodyValidatorBuilder(blockBodyValidatorBuilder) .blockProcessorBuilder(blockProcessorBuilder) + .blockValidatorBuilder(blockValidatorBuilder) .blockImporterBuilder(blockImporterBuilder) .blockHashFunction(blockHashFunction) .blockReward(blockReward) @@ -208,6 +218,7 @@ public class ProtocolSpecBuilder { checkNotNull(blockBodyValidatorBuilder, "Missing block body validator"); checkNotNull(blockProcessorBuilder, "Missing block processor"); checkNotNull(blockImporterBuilder, "Missing block importer"); + checkNotNull(blockValidatorBuilder, "Missing block validator"); checkNotNull(blockHashFunction, "Missing block hash function"); checkNotNull(blockReward, "Missing block reward"); checkNotNull(difficultyCalculator, "Missing difficulty calculator"); @@ -243,8 +254,9 @@ public class ProtocolSpecBuilder { transactionReceiptFactory, blockReward, miningBeneficiaryCalculator); - final BlockImporter blockImporter = - blockImporterBuilder.apply(blockHeaderValidator, blockBodyValidator, blockProcessor); + final BlockValidator blockValidator = + blockValidatorBuilder.apply(blockHeaderValidator, blockBodyValidator, blockProcessor); + final BlockImporter blockImporter = blockImporterBuilder.apply(blockValidator); return new ProtocolSpec<>( name, evm, @@ -255,6 +267,7 @@ public class ProtocolSpecBuilder { blockBodyValidator, blockProcessor, blockImporter, + blockValidator, blockHashFunction, transactionReceiptFactory, difficultyCalculator, @@ -279,10 +292,14 @@ public class ProtocolSpecBuilder { MiningBeneficiaryCalculator miningBeneficiaryCalculator); } - public interface BlockImporterBuilder { - BlockImporter apply( + public interface BlockValidatorBuilder { + BlockValidator apply( BlockHeaderValidator blockHeaderValidator, BlockBodyValidator blockBodyValidator, BlockProcessor blockProcessor); } + + public interface BlockImporterBuilder { + BlockImporter apply(BlockValidator blockValidator); + } } diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java index ae349b3ae9..4dbe7acff2 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java @@ -89,6 +89,7 @@ public class EthGetTransactionReceiptTest { null, null, null, + null, TransactionReceiptType.ROOT, BlockHeader::getCoinbase); private final ProtocolSpec statusTransactionTypeSpec = @@ -106,6 +107,7 @@ public class EthGetTransactionReceiptTest { null, null, null, + null, TransactionReceiptType.STATUS, BlockHeader::getCoinbase);