diff --git a/besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java b/besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java index c76b3ad6860..23e38fc1641 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java +++ b/besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.evm.worldstate.WorldState; @@ -146,9 +147,9 @@ private void importBlock(final Block block) { .getByBlockNumber(block.getHeader().getNumber()) .getBlockImporter(); - final boolean imported = + final BlockImportResult importResult = importer.importBlock(controller.getProtocolContext(), block, HeaderValidationMode.NONE); - if (imported) { + if (importResult.isImported()) { LOG.info( "Successfully created and imported block at height {} ({})", block.getHeader().getNumber(), @@ -220,7 +221,7 @@ private BlockHeader getParentHeader(final BlockData blockData, final List if (importedBlocks.size() > 0 && blockData.getNumber().isPresent()) { final long targetParentBlockNumber = blockData.getNumber().get() - 1L; - Optional maybeHeader = + final Optional maybeHeader = importedBlocks.stream() .map(Block::getHeader) .filter(h -> h.getNumber() == targetParentBlockNumber) @@ -230,7 +231,7 @@ private BlockHeader getParentHeader(final BlockData blockData, final List } } - long blockNumber; + final long blockNumber; if (blockData.getNumber().isPresent()) { blockNumber = blockData.getNumber().get() - 1L; } else if (importedBlocks.size() > 0) { diff --git a/besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java b/besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java index bf08121f4a5..80c7dae50be 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java +++ b/besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -208,7 +209,7 @@ private void evaluateBlock( cumulativeTimer.start(); segmentTimer.start(); final BlockImporter blockImporter = protocolSpec.getBlockImporter(); - final boolean blockImported = + final BlockImportResult blockImported = blockImporter.importBlock( context, block, @@ -216,7 +217,7 @@ private void evaluateBlock( ? HeaderValidationMode.LIGHT_SKIP_DETACHED : HeaderValidationMode.SKIP_DETACHED, skipPowValidation ? HeaderValidationMode.LIGHT : HeaderValidationMode.FULL); - if (!blockImported) { + if (!blockImported.isImported()) { throw new IllegalStateException( "Invalid block at block number " + header.getNumber() + "."); } diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java index 0ca8913409e..adcfb070051 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java @@ -48,6 +48,7 @@ import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -465,9 +466,9 @@ private static void setupState( final ProtocolSpec protocolSpec = protocolSchedule.getByBlockNumber(block.getHeader().getNumber()); final BlockImporter blockImporter = protocolSpec.getBlockImporter(); - final boolean result = + final BlockImportResult result = blockImporter.importBlock(protocolContext, block, HeaderValidationMode.FULL); - if (!result) { + if (!result.isImported()) { throw new IllegalStateException("Unable to import block " + block.getHeader().getNumber()); } } diff --git a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java index 9900dbeadf4..3324e90c5b0 100644 --- a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java +++ b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java @@ -47,6 +47,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException; import org.hyperledger.besu.util.Subscribers; @@ -103,7 +104,7 @@ public void setup() { throwingMessageFactory = new MessageFactory(nodeKey); transmitter = new IbftMessageTransmitter(throwingMessageFactory, multicaster); - BftExtraData proposedExtraData = + final BftExtraData proposedExtraData = new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), empty(), 0, emptyList()); final BlockHeaderTestFixture headerTestFixture = new BlockHeaderTestFixture(); headerTestFixture.extraData(bftExtraDataEncoder.encode(proposedExtraData)); @@ -111,7 +112,7 @@ public void setup() { final BlockHeader header = headerTestFixture.buildHeader(); proposedBlock = new Block(header, new BlockBody(emptyList(), emptyList())); - when(blockImporter.importBlock(any(), any(), any())).thenReturn(true); + when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true)); protocolContext = new ProtocolContext( diff --git a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java index d767ea0fc4f..66795e15734 100644 --- a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java +++ b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java @@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException; import org.hyperledger.besu.util.Subscribers; @@ -103,7 +104,7 @@ public void startRoundWith( final RoundChangeCertificate roundChangeCertificate = roundChangeArtifacts.getRoundChangeCertificate(); - Block blockToPublish; + final Block blockToPublish; if (!bestBlockFromRoundChange.isPresent()) { LOG.debug("Sending proposal with new block. round={}", roundState.getRoundIdentifier()); blockToPublish = blockCreator.createBlock(headerTimestamp); @@ -260,9 +261,9 @@ private void importBlockToChain() { blockToImport.getHash()); } LOG.trace("Importing block with extraData={}", extraData); - final boolean result = + final BlockImportResult result = blockImporter.importBlock(protocolContext, blockToImport, HeaderValidationMode.FULL); - if (!result) { + if (!result.isImported()) { LOG.error( "Failed to import block to chain. block={} extraData={} blockHeader={}", blockNumber, diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java index 8ea4681abf9..643bba58eba 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java @@ -52,6 +52,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException; import org.hyperledger.besu.util.Subscribers; @@ -120,7 +121,7 @@ public void setup() { when(blockCreator.createBlock(anyLong())).thenReturn(proposedBlock); - when(blockImporter.importBlock(any(), any(), any())).thenReturn(true); + when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true)); subscribers.subscribe(minedBlockObserver); } diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java index d6e56d93f8a..cd75bb0418f 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java +++ b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java @@ -49,6 +49,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException; import org.hyperledger.besu.util.Subscribers; @@ -113,7 +114,7 @@ public void setup() { final BlockHeader header = headerTestFixture.buildHeader(); proposedBlock = new Block(header, new BlockBody(emptyList(), emptyList())); - when(blockImporter.importBlock(any(), any(), any())).thenReturn(true); + when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true)); protocolContext = new ProtocolContext( diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java index eb739845a20..51c4517da7f 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java @@ -42,6 +42,7 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException; import org.hyperledger.besu.util.Subscribers; @@ -107,7 +108,7 @@ public void startRoundWith( final Optional bestPreparedCertificate = roundChangeArtifacts.getBestPreparedPeer(); - Block blockToPublish; + final Block blockToPublish; if (bestPreparedCertificate.isEmpty()) { LOG.debug("Sending proposal with new block. round={}", roundState.getRoundIdentifier()); blockToPublish = blockCreator.createBlock(headerTimestamp); @@ -278,9 +279,9 @@ private void importBlockToChain() { blockToImport.getHash()); } LOG.trace("Importing proposed block with extraData={}", extraData); - final boolean result = + final BlockImportResult result = blockImporter.importBlock(protocolContext, blockToImport, HeaderValidationMode.FULL); - if (!result) { + if (!result.isImported()) { LOG.error( "Failed to import proposed block to chain. block={} extraData={} blockHeader={}", blockNumber, diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java index dae9998205c..a3730258ec4 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java @@ -64,6 +64,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.Util; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; import org.hyperledger.besu.util.Subscribers; @@ -146,6 +147,7 @@ public void setup() { when(messageValidatorFactory.createFutureRoundProposalMessageValidator(anyLong(), any())) .thenReturn(futureRoundProposalMessageValidator); when(messageValidatorFactory.createMessageValidator(any(), any())).thenReturn(messageValidator); + when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(false)); protocolContext = new ProtocolContext( diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java index 21d1229a9e2..f63a5711c09 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java @@ -56,6 +56,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException; import org.hyperledger.besu.util.Subscribers; @@ -128,7 +129,7 @@ public void setup() { when(blockCreator.createBlock(anyLong())).thenReturn(proposedBlock); - when(blockImporter.importBlock(any(), any(), any())).thenReturn(true); + when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true)); subscribers.subscribe(minedBlockObserver); } diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java index 95b0fee846e..be4fb35541c 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.util.Subscribers; @@ -140,9 +141,9 @@ protected boolean mineBlock() throws InterruptedException { final BlockImporter importer = protocolSchedule.getByBlockNumber(block.getHeader().getNumber()).getBlockImporter(); - final boolean blockImported = + final BlockImportResult blockImportResult = importer.importBlock(protocolContext, block, HeaderValidationMode.FULL); - if (blockImported) { + if (blockImportResult.isImported()) { notifyNewBlockListeners(block); final double taskTimeInSec = stopwatch.elapsed(TimeUnit.MILLISECONDS) / 1000.0; LOG.info( @@ -159,7 +160,7 @@ protected boolean mineBlock() throws InterruptedException { LOG.error("Illegal block mined, could not be imported to local chain."); } - return blockImported; + return blockImportResult.isImported(); } public void cancel() { diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java index c9480eb80d3..fab404038be 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.MutableProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -64,7 +65,7 @@ public void blockCreatedIsAddedToBlockChain() throws InterruptedException { final ProtocolSchedule protocolSchedule = singleSpecSchedule(protocolSpec); when(protocolSpec.getBlockImporter()).thenReturn(blockImporter); - when(blockImporter.importBlock(any(), any(), any())).thenReturn(true); + when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true)); final MinedBlockObserver observer = mock(MinedBlockObserver.class); final DefaultBlockScheduler scheduler = mock(DefaultBlockScheduler.class); @@ -103,7 +104,11 @@ public void failureToImportDoesNotTriggerObservers() throws InterruptedException final ProtocolSchedule protocolSchedule = singleSpecSchedule(protocolSpec); when(protocolSpec.getBlockImporter()).thenReturn(blockImporter); - when(blockImporter.importBlock(any(), any(), any())).thenReturn(false, false, true); + when(blockImporter.importBlock(any(), any(), any())) + .thenReturn( + new BlockImportResult(false), + new BlockImportResult(false), + new BlockImportResult(true)); final MinedBlockObserver observer = mock(MinedBlockObserver.class); final DefaultBlockScheduler scheduler = mock(DefaultBlockScheduler.class); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockImporter.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockImporter.java index ed3e5b962b2..ce5c849e3a2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockImporter.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockImporter.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.core; import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import java.util.List; @@ -34,10 +35,10 @@ public interface BlockImporter { * @param context The context to attempt to update * @param block The block * @param headerValidationMode Determines the validation to perform on this header. - * @return {@code true} if the block was added somewhere in the blockchain; otherwise {@code - * false} + * @return {@code BlockImportResult} + * @see BlockImportResult */ - default boolean importBlock( + default BlockImportResult importBlock( final ProtocolContext context, final Block block, final HeaderValidationMode headerValidationMode) { @@ -51,10 +52,10 @@ default boolean importBlock( * @param block The block * @param headerValidationMode Determines the validation to perform on this header. * @param ommerValidationMode Determines the validation to perform on ommer headers. - * @return {@code true} if the block was added somewhere in the blockchain; otherwise {@code - * false} + * @return {@code BlockImportResult} + * @see BlockImportResult */ - boolean importBlock( + BlockImportResult importBlock( ProtocolContext context, Block block, HeaderValidationMode headerValidationMode, @@ -69,10 +70,10 @@ boolean importBlock( * @param receipts The receipts associated with this block. * @param headerValidationMode Determines the validation to perform on this header. * @param ommerValidationMode Determines the validation to perform on ommer headers. - * @return {@code true} if the block was added somewhere in the blockchain; otherwise {@code - * false} + * @return {@code BlockImportResult} + * @see BlockImportResult */ - boolean fastImportBlock( + BlockImportResult fastImportBlock( ProtocolContext context, Block block, List receipts, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockImportResult.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockImportResult.java new file mode 100644 index 00000000000..920b343059a --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockImportResult.java @@ -0,0 +1,48 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.mainnet; + +/** The result of a block import. */ +public class BlockImportResult { + private final BlockImportStatus status; + + public enum BlockImportStatus { + IMPORTED, + NOT_IMPORTED, + ALREADY_IMPORTED + } + + public BlockImportResult(final boolean status) { + this.status = status ? BlockImportStatus.IMPORTED : BlockImportStatus.NOT_IMPORTED; + } + + public BlockImportResult(final BlockImportStatus status) { + this.status = status; + } + + /** + * The result of the block import call + * + * @return {@code true} if the block was added somewhere in the blockchain; otherwise {@code + * false} + */ + public boolean isImported() { + return status == BlockImportStatus.IMPORTED || status == BlockImportStatus.ALREADY_IMPORTED; + } + + public BlockImportStatus getStatus() { + return status; + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporter.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporter.java index add02b1391b..33ca5e3ef6d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporter.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporter.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.TransactionReceipt; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult.BlockImportStatus; import java.util.List; @@ -31,13 +32,13 @@ public MainnetBlockImporter(final BlockValidator blockValidator) { } @Override - public synchronized boolean importBlock( + public synchronized BlockImportResult importBlock( final ProtocolContext context, final Block block, final HeaderValidationMode headerValidationMode, final HeaderValidationMode ommerValidationMode) { if (context.getBlockchain().contains(block.getHash())) { - return true; + return new BlockImportResult(BlockImportStatus.ALREADY_IMPORTED); } final var result = @@ -48,11 +49,14 @@ public synchronized boolean importBlock( processingOutputs -> context.getBlockchain().appendBlock(block, processingOutputs.receipts)); - return result.blockProcessingOutputs.isPresent(); + return result + .blockProcessingOutputs + .map(blockProcessingOutputs -> new BlockImportResult(true)) + .orElseGet(() -> new BlockImportResult(false)); } @Override - public boolean fastImportBlock( + public BlockImportResult fastImportBlock( final ProtocolContext context, final Block block, final List receipts, @@ -62,9 +66,9 @@ public boolean fastImportBlock( if (blockValidator.fastBlockValidation( context, block, receipts, headerValidationMode, ommerValidationMode)) { context.getBlockchain().appendBlock(block, receipts); - return true; + return new BlockImportResult(true); } - return false; + return new BlockImportResult(false); } } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java index 66f9914256d..be2643af5e7 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -245,9 +246,9 @@ private void importBlocks(final List blocks) { final ProtocolSpec protocolSpec = protocolSchedule.getByBlockNumber(block.getHeader().getNumber()); final BlockImporter blockImporter = protocolSpec.getBlockImporter(); - final boolean result = + final BlockImportResult result = blockImporter.importBlock(protocolContext, block, HeaderValidationMode.FULL); - if (!result) { + if (!result.isImported()) { throw new IllegalStateException("Unable to import block " + block.getHeader().getNumber()); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporterTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporterTest.java index 6f7bf077c69..28221791224 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporterTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporterTest.java @@ -53,10 +53,12 @@ public void setup() { public void doNotImportBlockIfBlockchainAlreadyHasBlock() { when(blockchain.contains(hash)).thenReturn(true); - assertThat( - blockImporter.importBlock( - context, block, HeaderValidationMode.FULL, HeaderValidationMode.FULL)) - .isTrue(); + final BlockImportResult result = + blockImporter.importBlock( + context, block, HeaderValidationMode.FULL, HeaderValidationMode.FULL); + + assertThat(result.isImported()).isTrue(); + verify(blockValidator, never()) .validateAndProcessBlock( context, block, HeaderValidationMode.FULL, HeaderValidationMode.FULL); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastImportBlocksStep.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastImportBlocksStep.java index 9ba3118049f..323f1a04581 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastImportBlocksStep.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastImportBlocksStep.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.sync.ValidationPolicy; import org.hyperledger.besu.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import java.util.List; @@ -96,11 +97,13 @@ public void accept(final List blocksWithReceipts) { protected boolean importBlock(final BlockWithReceipts blockWithReceipts) { final BlockImporter importer = protocolSchedule.getByBlockNumber(blockWithReceipts.getNumber()).getBlockImporter(); - return importer.fastImportBlock( - protocolContext, - blockWithReceipts.getBlock(), - blockWithReceipts.getReceipts(), - headerValidationPolicy.getValidationModeForNextBlock(), - ommerValidationPolicy.getValidationModeForNextBlock()); + final BlockImportResult blockImportResult = + importer.fastImportBlock( + protocolContext, + blockWithReceipts.getBlock(), + blockWithReceipts.getReceipts(), + headerValidationPolicy.getValidationModeForNextBlock(), + ommerValidationPolicy.getValidationModeForNextBlock()); + return blockImportResult.isImported(); } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullImportBlockStep.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullImportBlockStep.java index fc37ecaac78..87d04530db5 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullImportBlockStep.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullImportBlockStep.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -58,7 +59,9 @@ public void accept(final Block block) { final String blockHash = block.getHash().toHexString(); final BlockImporter importer = protocolSchedule.getByBlockNumber(blockNumber).getBlockImporter(); - if (!importer.importBlock(protocolContext, block, HeaderValidationMode.SKIP_DETACHED)) { + final BlockImportResult blockImportResult = + importer.importBlock(protocolContext, block, HeaderValidationMode.SKIP_DETACHED); + if (!blockImportResult.isImported()) { throw new InvalidBlockException("Failed to import block", blockNumber, block.getHash()); } gasAccumulator += block.getHeader().getGasUsed(); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/PersistBlockTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/PersistBlockTask.java index a8a2969b724..7fbd4922b74 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/PersistBlockTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/PersistBlockTask.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractEthTask; import org.hyperledger.besu.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -46,7 +47,7 @@ public class PersistBlockTask extends AbstractEthTask { private final EthContext ethContext; private final Block block; private final HeaderValidationMode validateHeaders; - private boolean blockImported; + private BlockImportResult blockImportResult; private PersistBlockTask( final ProtocolSchedule protocolSchedule, @@ -61,7 +62,7 @@ private PersistBlockTask( this.ethContext = ethContext; this.block = block; this.validateHeaders = headerValidationMode; - blockImported = false; + blockImportResult = new BlockImportResult(false); } public static PersistBlockTask create( @@ -198,8 +199,8 @@ protected void executeTask() { protocolSchedule.getByBlockNumber(block.getHeader().getNumber()); final BlockImporter blockImporter = protocolSpec.getBlockImporter(); debugLambda(LOG, "Running import task for block {}", block::toLogString); - blockImported = blockImporter.importBlock(protocolContext, block, validateHeaders); - if (!blockImported) { + blockImportResult = blockImporter.importBlock(protocolContext, block, validateHeaders); + if (!blockImportResult.isImported()) { result.completeExceptionally( new InvalidBlockException( "Failed to import block", block.getHeader().getNumber(), block.getHash())); @@ -213,19 +214,26 @@ protected void executeTask() { @Override protected void cleanup() { - if (blockImported) { - final double timeInS = getTaskTimeInSec(); - LOG.info( - String.format( - "Imported #%,d / %d tx / %d om / %,d (%01.1f%%) gas / (%s) in %01.3fs. Peers: %d", - block.getHeader().getNumber(), - block.getBody().getTransactions().size(), - block.getBody().getOmmers().size(), - block.getHeader().getGasUsed(), - (block.getHeader().getGasUsed() * 100.0) / block.getHeader().getGasLimit(), - block.getHash().toHexString(), - timeInS, - ethContext.getEthPeers().peerCount())); + final double timeInS = getTaskTimeInSec(); + switch (blockImportResult.getStatus()) { + case IMPORTED: + LOG.info( + String.format( + "Imported #%,d / %d tx / %d om / %,d (%01.1f%%) gas / (%s) in %01.3fs. Peers: %d", + block.getHeader().getNumber(), + block.getBody().getTransactions().size(), + block.getBody().getOmmers().size(), + block.getHeader().getGasUsed(), + (block.getHeader().getGasUsed() * 100.0) / block.getHeader().getGasLimit(), + block.getHash().toHexString(), + timeInS, + ethContext.getEthPeers().peerCount())); + break; + case ALREADY_IMPORTED: + LOG.info("Block {} is already imported", block.toLogString()); + break; + default: + break; } } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastImportBlocksStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastImportBlocksStepTest.java index ddaedbab38a..1ed35e76a48 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastImportBlocksStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastImportBlocksStepTest.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.eth.sync.ValidationPolicy; import org.hyperledger.besu.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -82,7 +83,7 @@ public void shouldImportBlocks() { blockWithReceipts.getReceipts(), FULL, LIGHT)) - .thenReturn(true); + .thenReturn(new BlockImportResult(true)); } importBlocksStep.accept(blocksWithReceipts); @@ -99,7 +100,7 @@ public void shouldThrowExceptionWhenValidationFails() { when(blockImporter.fastImportBlock( protocolContext, block, blockWithReceipts.getReceipts(), FULL, LIGHT)) - .thenReturn(false); + .thenReturn(new BlockImportResult(false)); assertThatThrownBy(() -> importBlocksStep.accept(singletonList(blockWithReceipts))) .isInstanceOf(InvalidBlockException.class); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullImportBlockStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullImportBlockStepTest.java index eac021d0dff..c22822af78d 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullImportBlockStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullImportBlockStepTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -59,7 +60,8 @@ public void setUp() { public void shouldImportBlock() { final Block block = gen.block(); - when(blockImporter.importBlock(protocolContext, block, SKIP_DETACHED)).thenReturn(true); + when(blockImporter.importBlock(protocolContext, block, SKIP_DETACHED)) + .thenReturn(new BlockImportResult(true)); importBlocksStep.accept(block); verify(protocolSchedule).getByBlockNumber(block.getHeader().getNumber()); @@ -70,7 +72,8 @@ public void shouldImportBlock() { public void shouldThrowExceptionWhenValidationFails() { final Block block = gen.block(); - when(blockImporter.importBlock(protocolContext, block, SKIP_DETACHED)).thenReturn(false); + when(blockImporter.importBlock(protocolContext, block, SKIP_DETACHED)) + .thenReturn(new BlockImportResult(false)); assertThatThrownBy(() -> importBlocksStep.accept(block)) .isInstanceOf(InvalidBlockException.class); } diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java index df95fd3d590..9329a143c25 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.MutableWorldState; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -113,10 +114,10 @@ public static void executeTest(final BlockchainReferenceTestCaseSpec spec) { "NoProof".equalsIgnoreCase(spec.getSealEngine()) ? HeaderValidationMode.LIGHT : HeaderValidationMode.FULL; - final boolean imported = + final BlockImportResult importResult = blockImporter.importBlock(context, block, validationMode, validationMode); - assertThat(imported).isEqualTo(candidateBlock.isValid()); + assertThat(importResult.isImported()).isEqualTo(candidateBlock.isValid()); } catch (final RLPException e) { assertThat(candidateBlock.isValid()).isFalse(); } diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlock.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlock.java index 6289b76c958..7c4c77da863 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlock.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlock.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.retesteth.RetestethContext; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPException; @@ -79,11 +80,13 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { // otherwise attempt to import the block final BlockImporter blockImporter = context.getProtocolSpec(block.getHeader().getNumber()).getBlockImporter(); - if (!blockImporter.importBlock( - protocolContext, - block, - context.getHeaderValidationMode(), - context.getHeaderValidationMode())) { + final BlockImportResult result = + blockImporter.importBlock( + protocolContext, + block, + context.getHeaderValidationMode(), + context.getHeaderValidationMode()); + if (!result.isImported()) { LOG.debug("Failed to import block."); return new JsonRpcErrorResponse( requestContext.getRequest().getId(), JsonRpcError.BLOCK_IMPORT_ERROR); diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java index 047d6225ef7..fa60603dadd 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.retesteth.RetestethClock; @@ -80,7 +81,9 @@ private boolean mineNewBlock() { final BlockImporter blockImporter = protocolSchedule.getByBlockNumber(blockchain.getChainHeadBlockNumber()).getBlockImporter(); - return blockImporter.importBlock( - protocolContext, block, headerValidationMode, headerValidationMode); + final BlockImportResult result = + blockImporter.importBlock( + protocolContext, block, headerValidationMode, headerValidationMode); + return result.isImported(); } }