From e1f44897411eaa8a11a87c23c381090bb6ed18b1 Mon Sep 17 00:00:00 2001 From: Jason Frame Date: Fri, 20 Sep 2024 16:07:27 +1000 Subject: [PATCH] Disable body validation for POS networks during sync (#7646) Signed-off-by: Jason Frame Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> --- .../besu/ethereum/BlockValidator.java | 11 +- .../besu/ethereum/MainnetBlockValidator.java | 8 +- .../besu/ethereum/core/BlockImporter.java | 6 +- .../mainnet/BaseFeeBlockBodyValidator.java | 6 +- .../ethereum/mainnet/BlockBodyValidator.java | 3 +- .../ethereum/mainnet/BodyValidationMode.java | 26 ++++ .../mainnet/MainnetBlockBodyValidator.java | 34 +++-- .../mainnet/MainnetBlockImporter.java | 10 +- .../ethereum/MainnetBlockValidatorTest.java | 44 ++++--- .../MainnetBlockBodyValidatorTest.java | 123 +++++++++++++++++- .../mainnet/PragueRequestsValidatorTest.java | 3 +- .../FastSyncDownloadPipelineFactory.java | 8 +- .../eth/sync/fastsync/ImportBlocksStep.java | 14 +- .../sync/fastsync/ImportBlocksStepTest.java | 18 ++- 14 files changed, 255 insertions(+), 59 deletions(-) create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidationMode.java diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/BlockValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/BlockValidator.java index e8136062bbd..8cfafee730b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/BlockValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/BlockValidator.java @@ -17,6 +17,7 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.TransactionReceipt; +import org.hyperledger.besu.ethereum.mainnet.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import java.util.List; @@ -83,8 +84,8 @@ BlockProcessingResult validateAndProcessBlock( final boolean shouldRecordBadBlock); /** - * Performs fast block validation with the given context, block, transaction receipts, requests, - * header validation mode, and ommer validation mode. + * Performs fast block validation appropriate for use during syncing skipping transaction receipt + * roots and receipts roots as these are done during the download of the blocks. * * @param context the protocol context * @param block the block to validate @@ -92,13 +93,15 @@ BlockProcessingResult validateAndProcessBlock( * @param requests the requests * @param headerValidationMode the header validation mode * @param ommerValidationMode the ommer validation mode + * @param bodyValidationMode the body validation mode * @return true if the block is valid, false otherwise */ - boolean fastBlockValidation( + boolean validateBlockForSyncing( final ProtocolContext context, final Block block, final List receipts, final Optional> requests, final HeaderValidationMode headerValidationMode, - final HeaderValidationMode ommerValidationMode); + final HeaderValidationMode ommerValidationMode, + final BodyValidationMode bodyValidationMode); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java index 5d80a951505..0c56a419e35 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.mainnet.BlockBodyValidator; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; import org.hyperledger.besu.ethereum.mainnet.BlockProcessor; +import org.hyperledger.besu.ethereum.mainnet.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.plugin.services.exception.StorageException; @@ -247,13 +248,14 @@ protected BlockProcessingResult processBlock( } @Override - public boolean fastBlockValidation( + public boolean validateBlockForSyncing( final ProtocolContext context, final Block block, final List receipts, final Optional> requests, final HeaderValidationMode headerValidationMode, - final HeaderValidationMode ommerValidationMode) { + final HeaderValidationMode ommerValidationMode, + final BodyValidationMode bodyValidationMode) { final BlockHeader header = block.getHeader(); if (!blockHeaderValidator.validateHeader(header, context, headerValidationMode)) { String description = String.format("Failed header validation (%s)", headerValidationMode); @@ -262,7 +264,7 @@ public boolean fastBlockValidation( } if (!blockBodyValidator.validateBodyLight( - context, block, receipts, requests, ommerValidationMode)) { + context, block, receipts, requests, ommerValidationMode, bodyValidationMode)) { badBlockManager.addBadBlock( block, BadBlockCause.fromValidationFailure("Failed body validation (light)")); return false; 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 ce5c849e3a2..468485b9fde 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 @@ -16,6 +16,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; +import org.hyperledger.besu.ethereum.mainnet.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import java.util.List; @@ -73,10 +74,11 @@ BlockImportResult importBlock( * @return {@code BlockImportResult} * @see BlockImportResult */ - BlockImportResult fastImportBlock( + BlockImportResult importBlockForSyncing( ProtocolContext context, Block block, List receipts, HeaderValidationMode headerValidationMode, - HeaderValidationMode ommerValidationMode); + HeaderValidationMode ommerValidationMode, + BodyValidationMode bodyValidationMode); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BaseFeeBlockBodyValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BaseFeeBlockBodyValidator.java index 0e288185cfc..aabc4ee5d09 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BaseFeeBlockBodyValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BaseFeeBlockBodyValidator.java @@ -43,9 +43,11 @@ public boolean validateBodyLight( final Block block, final List receipts, final Optional> requests, - final HeaderValidationMode ommerValidationMode) { + final HeaderValidationMode ommerValidationMode, + final BodyValidationMode bodyValidationMode) { - return super.validateBodyLight(context, block, receipts, requests, ommerValidationMode) + return super.validateBodyLight( + context, block, receipts, requests, ommerValidationMode, bodyValidationMode) && validateTransactionGasPrice(block); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockBodyValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockBodyValidator.java index 62b4985f5ca..c84be3771b9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockBodyValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockBodyValidator.java @@ -59,5 +59,6 @@ boolean validateBodyLight( Block block, List receipts, final Optional> requests, - final HeaderValidationMode ommerValidationMode); + final HeaderValidationMode ommerValidationMode, + final BodyValidationMode bodyValidationMode); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidationMode.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidationMode.java new file mode 100644 index 00000000000..344a950e365 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidationMode.java @@ -0,0 +1,26 @@ +/* + * 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; + +public enum BodyValidationMode { + /** No Validation. data must be pre-validated */ + NONE, + + /** Skip receipts and transactions root validation */ + LIGHT, + + /** Fully validate the body */ + FULL; +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java index 3202440dd89..68951f9f2a3 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java @@ -29,6 +29,7 @@ import java.util.Optional; import java.util.Set; +import com.google.common.annotations.VisibleForTesting; import org.apache.tuweni.bytes.Bytes32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,7 +56,8 @@ public boolean validateBody( final Hash worldStateRootHash, final HeaderValidationMode ommerValidationMode) { - if (!validateBodyLight(context, block, receipts, requests, ommerValidationMode)) { + if (!validateBodyLight( + context, block, receipts, requests, ommerValidationMode, BodyValidationMode.FULL)) { return false; } @@ -77,18 +79,26 @@ public boolean validateBodyLight( final Block block, final List receipts, final Optional> requests, - final HeaderValidationMode ommerValidationMode) { + final HeaderValidationMode ommerValidationMode, + final BodyValidationMode bodyValidationMode) { + if (bodyValidationMode == BodyValidationMode.NONE) { + return true; + } + final BlockHeader header = block.getHeader(); final BlockBody body = block.getBody(); - final Bytes32 transactionsRoot = BodyValidation.transactionsRoot(body.getTransactions()); - if (!validateTransactionsRoot(header, header.getTransactionsRoot(), transactionsRoot)) { - return false; - } + // these checks are only needed for full validation and can be skipped for light validation + if (bodyValidationMode == BodyValidationMode.FULL) { + final Bytes32 transactionsRoot = BodyValidation.transactionsRoot(body.getTransactions()); + if (!validateTransactionsRoot(header, header.getTransactionsRoot(), transactionsRoot)) { + return false; + } - final Bytes32 receiptsRoot = BodyValidation.receiptsRoot(receipts); - if (!validateReceiptsRoot(header, header.getReceiptsRoot(), receiptsRoot)) { - return false; + final Bytes32 receiptsRoot = BodyValidation.receiptsRoot(receipts); + if (!validateReceiptsRoot(header, header.getReceiptsRoot(), receiptsRoot)) { + return false; + } } final long gasUsed = @@ -115,7 +125,8 @@ public boolean validateBodyLight( return true; } - private static boolean validateTransactionsRoot( + @VisibleForTesting + protected boolean validateTransactionsRoot( final BlockHeader header, final Bytes32 expected, final Bytes32 actual) { if (!expected.equals(actual)) { LOG.info( @@ -157,7 +168,8 @@ private static boolean validateGasUsed( return true; } - private static boolean validateReceiptsRoot( + @VisibleForTesting + protected boolean validateReceiptsRoot( final BlockHeader header, final Bytes32 expected, final Bytes32 actual) { if (!expected.equals(actual)) { LOG.warn( 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 62b708d33e6..8646467a282 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 @@ -57,20 +57,22 @@ public synchronized BlockImportResult importBlock( } @Override - public BlockImportResult fastImportBlock( + public BlockImportResult importBlockForSyncing( final ProtocolContext context, final Block block, final List receipts, final HeaderValidationMode headerValidationMode, - final HeaderValidationMode ommerValidationMode) { + final HeaderValidationMode ommerValidationMode, + final BodyValidationMode bodyValidationMode) { - if (blockValidator.fastBlockValidation( + if (blockValidator.validateBlockForSyncing( context, block, receipts, block.getBody().getRequests(), headerValidationMode, - ommerValidationMode)) { + ommerValidationMode, + bodyValidationMode)) { context.getBlockchain().appendBlock(block, receipts); return new BlockImportResult(true); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/MainnetBlockValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/MainnetBlockValidatorTest.java index 361353ee2b2..40573ee8d6e 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/MainnetBlockValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/MainnetBlockValidatorTest.java @@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.mainnet.BlockBodyValidator; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; import org.hyperledger.besu.ethereum.mainnet.BlockProcessor; +import org.hyperledger.besu.ethereum.mainnet.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; @@ -98,7 +99,8 @@ public void setup() { when(blockHeaderValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(blockBodyValidator.validateBody(any(), any(), any(), any(), any(), any())) .thenReturn(true); - when(blockBodyValidator.validateBodyLight(any(), any(), any(), any(), any())).thenReturn(true); + when(blockBodyValidator.validateBodyLight(any(), any(), any(), any(), any(), any())) + .thenReturn(true); when(blockProcessor.processBlock(any(), any(), any())).thenReturn(successfulProcessingResult); when(blockProcessor.processBlock(any(), any(), any(), any())) .thenReturn(successfulProcessingResult); @@ -343,55 +345,65 @@ public void validateAndProcessBlock_withShouldRecordBadBlockNotSet() { } @Test - public void fastBlockValidation_onSuccess() { + public void validateBlockForSyncing_onSuccess() { final boolean isValid = - mainnetBlockValidator.fastBlockValidation( + mainnetBlockValidator.validateBlockForSyncing( protocolContext, block, Collections.emptyList(), block.getBody().getRequests(), HeaderValidationMode.FULL, - HeaderValidationMode.FULL); + HeaderValidationMode.FULL, + BodyValidationMode.FULL); assertThat(isValid).isTrue(); assertNoBadBlocks(); } @Test - public void fastBlockValidation_onFailedHeaderValidation() { - final HeaderValidationMode validationMode = HeaderValidationMode.FULL; + public void validateBlockValidation_onFailedHeaderForSyncing() { + final HeaderValidationMode headerValidationMode = HeaderValidationMode.FULL; when(blockHeaderValidator.validateHeader( - any(BlockHeader.class), eq(protocolContext), eq(validationMode))) + any(BlockHeader.class), eq(protocolContext), eq(headerValidationMode))) .thenReturn(false); + final BodyValidationMode bodyValidationMode = BodyValidationMode.FULL; final boolean isValid = - mainnetBlockValidator.fastBlockValidation( + mainnetBlockValidator.validateBlockForSyncing( protocolContext, block, Collections.emptyList(), block.getBody().getRequests(), - validationMode, - validationMode); + headerValidationMode, + headerValidationMode, + bodyValidationMode); assertThat(isValid).isFalse(); assertBadBlockIsTracked(block); } @Test - public void fastBlockValidation_onFailedBodyValidation() { - final HeaderValidationMode validationMode = HeaderValidationMode.FULL; + public void validateBlockValidation_onFailedBodyForSyncing() { + final HeaderValidationMode headerValidationMode = HeaderValidationMode.FULL; + final BodyValidationMode bodyValidationMode = BodyValidationMode.FULL; when(blockBodyValidator.validateBodyLight( - eq(protocolContext), eq(block), any(), any(), eq(validationMode))) + eq(protocolContext), + eq(block), + any(), + any(), + eq(headerValidationMode), + eq(bodyValidationMode))) .thenReturn(false); final boolean isValid = - mainnetBlockValidator.fastBlockValidation( + mainnetBlockValidator.validateBlockForSyncing( protocolContext, block, Collections.emptyList(), block.getBody().getRequests(), - validationMode, - validationMode); + headerValidationMode, + headerValidationMode, + bodyValidationMode); assertThat(isValid).isFalse(); assertBadBlockIsTracked(block); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java index c116d545d80..c412a30756b 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java @@ -19,14 +19,22 @@ import static org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode.NONE; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.GWei; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; +import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.mainnet.requests.DepositRequestValidator; import org.hyperledger.besu.ethereum.mainnet.requests.RequestsValidatorCoordinator; @@ -93,7 +101,12 @@ void validatesWithdrawals() { assertThat( new MainnetBlockBodyValidator(protocolSchedule) .validateBodyLight( - blockchainSetupUtil.getProtocolContext(), block, emptyList(), any(), NONE)) + blockchainSetupUtil.getProtocolContext(), + block, + emptyList(), + any(), + NONE, + BodyValidationMode.FULL)) .isTrue(); } @@ -117,7 +130,12 @@ void validationFailsIfWithdrawalsValidationFails() { assertThat( new MainnetBlockBodyValidator(protocolSchedule) .validateBodyLight( - blockchainSetupUtil.getProtocolContext(), block, emptyList(), any(), NONE)) + blockchainSetupUtil.getProtocolContext(), + block, + emptyList(), + any(), + NONE, + BodyValidationMode.FULL)) .isFalse(); } @@ -141,7 +159,12 @@ void validationFailsIfWithdrawalsRootValidationFails() { assertThat( new MainnetBlockBodyValidator(protocolSchedule) .validateBodyLight( - blockchainSetupUtil.getProtocolContext(), block, emptyList(), any(), NONE)) + blockchainSetupUtil.getProtocolContext(), + block, + emptyList(), + any(), + NONE, + BodyValidationMode.FULL)) .isFalse(); } @@ -165,7 +188,99 @@ public void validationFailsIfWithdrawalRequestsValidationFails() { assertThat( new MainnetBlockBodyValidator(protocolSchedule) .validateBodyLight( - blockchainSetupUtil.getProtocolContext(), block, emptyList(), any(), NONE)) + blockchainSetupUtil.getProtocolContext(), + block, + emptyList(), + any(), + NONE, + BodyValidationMode.FULL)) .isFalse(); } + + @Test + @SuppressWarnings("unchecked") + public void noneValidationModeDoesNothing() { + final Block block = mock(Block.class); + final List receipts = mock(List.class); + + final MainnetBlockBodyValidator bodyValidator = new MainnetBlockBodyValidator(protocolSchedule); + + assertThat( + bodyValidator.validateBodyLight( + blockchainSetupUtil.getProtocolContext(), + block, + receipts, + Optional.empty(), + NONE, + BodyValidationMode.NONE)) + .isTrue(); + verifyNoInteractions(block); + verifyNoInteractions(receipts); + } + + @Test + public void lightValidationDoesNotCheckTransactionRootOrReceiptRoot() { + final Block block = + blockDataGenerator.block( + new BlockOptions() + .setBlockNumber(1) + .setGasUsed(0) + .hasTransactions(false) + .hasOmmers(false) + .setReceiptsRoot(BodyValidation.receiptsRoot(emptyList())) + .setLogsBloom(LogsBloomFilter.empty()) + .setParentHash(blockchainSetupUtil.getBlockchain().getChainHeadHash()) + .setWithdrawals(Optional.of(withdrawals))); + blockchainSetupUtil.getBlockchain().appendBlock(block, Collections.emptyList()); + + final MainnetBlockBodyValidator bodyValidator = new MainnetBlockBodyValidator(protocolSchedule); + final MainnetBlockBodyValidator bodyValidatorSpy = spy(bodyValidator); + + assertThat( + bodyValidatorSpy.validateBodyLight( + blockchainSetupUtil.getProtocolContext(), + block, + emptyList(), + Optional.empty(), + NONE, + BodyValidationMode.LIGHT)) + .isTrue(); + verify(bodyValidatorSpy, never()).validateReceiptsRoot(any(), any(), any()); + verify(bodyValidatorSpy, never()).validateTransactionsRoot(any(), any(), any()); + } + + @Test + public void fullValidationChecksTransactionRootAndReceiptRoot() { + final Block block = + blockDataGenerator.block( + new BlockOptions() + .setBlockNumber(1) + .setGasUsed(0) + .hasTransactions(false) + .hasOmmers(false) + .setReceiptsRoot(BodyValidation.receiptsRoot(emptyList())) + .setLogsBloom(LogsBloomFilter.empty()) + .setParentHash(blockchainSetupUtil.getBlockchain().getChainHeadHash()) + .setWithdrawals(Optional.of(withdrawals))); + blockchainSetupUtil.getBlockchain().appendBlock(block, Collections.emptyList()); + + final MainnetBlockBodyValidator bodyValidator = new MainnetBlockBodyValidator(protocolSchedule); + final MainnetBlockBodyValidator bodyValidatorSpy = spy(bodyValidator); + + assertThat( + bodyValidatorSpy.validateBodyLight( + blockchainSetupUtil.getProtocolContext(), + block, + emptyList(), + Optional.empty(), + NONE, + BodyValidationMode.FULL)) + .isTrue(); + final Hash receiptsRoot = BodyValidation.receiptsRoot(emptyList()); + final Hash transactionsRoot = BodyValidation.transactionsRoot(emptyList()); + verify(bodyValidatorSpy, times(1)) + .validateReceiptsRoot(block.getHeader(), receiptsRoot, receiptsRoot); + verify(bodyValidatorSpy, times(1)) + .validateTransactionsRoot(block.getHeader(), transactionsRoot, transactionsRoot); + } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PragueRequestsValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PragueRequestsValidatorTest.java index 833e692d7f4..6c325b70a86 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PragueRequestsValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PragueRequestsValidatorTest.java @@ -106,7 +106,8 @@ void shouldValidateRequestsTest() { block, emptyList(), expectedRequests, - NONE)) + NONE, + BodyValidationMode.FULL)) .isFalse(); } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java index 07e964426cc..87032b76e57 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java @@ -37,6 +37,7 @@ import org.hyperledger.besu.ethereum.eth.sync.range.SyncTargetRangeSource; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.eth.sync.state.SyncTarget; +import org.hyperledger.besu.ethereum.mainnet.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.metrics.BesuMetricCategory; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -117,6 +118,10 @@ public Pipeline createDownloadPipelineForSyncTarget(final SyncT final int downloaderParallelism = syncConfig.getDownloaderParallelism(); final int headerRequestSize = syncConfig.getDownloaderHeaderRequestSize(); final int singleHeaderBufferSize = headerRequestSize * downloaderParallelism; + final BodyValidationMode bodyValidationMode = + protocolSchedule.anyMatch(scheduledProtocolSpec -> scheduledProtocolSpec.spec().isPoS()) + ? BodyValidationMode.NONE + : BodyValidationMode.LIGHT; final SyncTargetRangeSource checkpointRangeSource = new SyncTargetRangeSource( new RangeHeadersFetcher( @@ -148,7 +153,8 @@ public Pipeline createDownloadPipelineForSyncTarget(final SyncT attachedValidationPolicy, ommerValidationPolicy, ethContext, - fastSyncState.getPivotBlockHeader().get()); + fastSyncState.getPivotBlockHeader().get(), + bodyValidationMode); return PipelineBuilder.createPipelineFrom( "fetchCheckpoints", diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/ImportBlocksStep.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/ImportBlocksStep.java index c6945964cf0..20b9d84916a 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/ImportBlocksStep.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/ImportBlocksStep.java @@ -22,6 +22,7 @@ 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.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import java.util.List; @@ -45,6 +46,7 @@ public class ImportBlocksStep implements Consumer> { private long accumulatedTime = 0L; private OptionalLong logStartBlock = OptionalLong.empty(); private final BlockHeader pivotHeader; + private final BodyValidationMode bodyValidationMode; public ImportBlocksStep( final ProtocolSchedule protocolSchedule, @@ -52,13 +54,15 @@ public ImportBlocksStep( final ValidationPolicy headerValidationPolicy, final ValidationPolicy ommerValidationPolicy, final EthContext ethContext, - final BlockHeader pivotHeader) { + final BlockHeader pivotHeader, + final BodyValidationMode bodyValidationMode) { this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; this.headerValidationPolicy = headerValidationPolicy; this.ommerValidationPolicy = ommerValidationPolicy; this.ethContext = ethContext; this.pivotHeader = pivotHeader; + this.bodyValidationMode = bodyValidationMode; } @Override @@ -106,20 +110,20 @@ protected static long getBlocksPercent(final long lastBlock, final long totalBlo if (totalBlocks == 0) { return 0; } - final long blocksPercent = (100 * lastBlock / totalBlocks); - return blocksPercent; + return (100 * lastBlock / totalBlocks); } protected boolean importBlock(final BlockWithReceipts blockWithReceipts) { final BlockImporter importer = protocolSchedule.getByBlockHeader(blockWithReceipts.getHeader()).getBlockImporter(); final BlockImportResult blockImportResult = - importer.fastImportBlock( + importer.importBlockForSyncing( protocolContext, blockWithReceipts.getBlock(), blockWithReceipts.getReceipts(), headerValidationPolicy.getValidationModeForNextBlock(), - ommerValidationPolicy.getValidationModeForNextBlock()); + ommerValidationPolicy.getValidationModeForNextBlock(), + bodyValidationMode); return blockImportResult.isImported(); } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/ImportBlocksStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/ImportBlocksStepTest.java index 70c9e10eba6..af4f45f6901 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/ImportBlocksStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/ImportBlocksStepTest.java @@ -33,6 +33,7 @@ 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.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -72,7 +73,8 @@ public void setUp() { validationPolicy, ommerValidationPolicy, null, - pivotHeader); + pivotHeader, + BodyValidationMode.FULL); } @Test @@ -84,12 +86,13 @@ public void shouldImportBlocks() { .collect(toList()); for (final BlockWithReceipts blockWithReceipts : blocksWithReceipts) { - when(blockImporter.fastImportBlock( + when(blockImporter.importBlockForSyncing( protocolContext, blockWithReceipts.getBlock(), blockWithReceipts.getReceipts(), FULL, - LIGHT)) + LIGHT, + BodyValidationMode.FULL)) .thenReturn(new BlockImportResult(true)); } importBlocksStep.accept(blocksWithReceipts); @@ -105,8 +108,13 @@ public void shouldThrowExceptionWhenValidationFails() { final Block block = gen.block(); final BlockWithReceipts blockWithReceipts = new BlockWithReceipts(block, gen.receipts(block)); - when(blockImporter.fastImportBlock( - protocolContext, block, blockWithReceipts.getReceipts(), FULL, LIGHT)) + when(blockImporter.importBlockForSyncing( + protocolContext, + block, + blockWithReceipts.getReceipts(), + FULL, + LIGHT, + BodyValidationMode.FULL)) .thenReturn(new BlockImportResult(false)); assertThatThrownBy(() -> importBlocksStep.accept(singletonList(blockWithReceipts))) .isInstanceOf(InvalidBlockException.class);