From bd9b98c002db02a8e0edc033effe8e801759090f Mon Sep 17 00:00:00 2001 From: garyschulte Date: Tue, 9 Aug 2022 16:31:48 -0700 Subject: [PATCH] fix for fast sync regression on post-merge networks (#4224) * use attached/detached rule difference to prevent PoW rules from influencing fast sync around TTD Signed-off-by: garyschulte --- .../mainnet/MainnetBlockHeaderValidator.java | 47 ++++++++++++------- .../AttachedProofOfWorkValidationRule.java | 46 ++++++++++++++++++ .../CalculatedDifficultyValidationRule.java | 5 +- .../ProofOfWorkValidationRule.java | 7 --- .../TimestampMoreRecentThanParent.java | 4 -- 5 files changed, 78 insertions(+), 31 deletions(-) create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/AttachedProofOfWorkValidationRule.java diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java index 84b9357d31..04c1e6562a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java @@ -14,9 +14,11 @@ */ package org.hyperledger.besu.ethereum.mainnet; +import org.hyperledger.besu.config.MergeConfigOptions; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AncestryValidationRule; +import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AttachedProofOfWorkValidationRule; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.BaseFeeMarketBlockHeaderGasPriceValidationRule; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.CalculatedDifficultyValidationRule; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantFieldValidationRule; @@ -122,22 +124,35 @@ public final class MainnetBlockHeaderValidator { public static BlockHeaderValidator.Builder createBaseFeeMarketValidator( final BaseFeeMarket baseFeeMarket) { - return new BlockHeaderValidator.Builder() - .addRule(CalculatedDifficultyValidationRule::new) - .addRule(new AncestryValidationRule()) - .addRule(new GasUsageValidationRule()) - .addRule( - new GasLimitRangeAndDeltaValidationRule( - MIN_GAS_LIMIT, Long.MAX_VALUE, Optional.of(baseFeeMarket))) - .addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT)) - .addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S)) - .addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES)) - .addRule( - new ProofOfWorkValidationRule( - new EpochCalculator.DefaultEpochCalculator(), - PoWHasher.ETHASH_LIGHT, - Optional.of(baseFeeMarket))) - .addRule((new BaseFeeMarketBlockHeaderGasPriceValidationRule(baseFeeMarket))); + var builder = + new BlockHeaderValidator.Builder() + .addRule(CalculatedDifficultyValidationRule::new) + .addRule(new AncestryValidationRule()) + .addRule(new GasUsageValidationRule()) + .addRule( + new GasLimitRangeAndDeltaValidationRule( + MIN_GAS_LIMIT, Long.MAX_VALUE, Optional.of(baseFeeMarket))) + .addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT)) + .addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S)) + .addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES)) + .addRule((new BaseFeeMarketBlockHeaderGasPriceValidationRule(baseFeeMarket))); + + // if merge is enabled, use the attached version of the proof of work validation rule + if (MergeConfigOptions.isMergeEnabled()) { + builder.addRule( + new AttachedProofOfWorkValidationRule( + new EpochCalculator.DefaultEpochCalculator(), + PoWHasher.ETHASH_LIGHT, + Optional.of(baseFeeMarket))); + + } else { + builder.addRule( + new ProofOfWorkValidationRule( + new EpochCalculator.DefaultEpochCalculator(), + PoWHasher.ETHASH_LIGHT, + Optional.of(baseFeeMarket))); + } + return builder; } static BlockHeaderValidator.Builder createBaseFeeMarketOmmerValidator( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/AttachedProofOfWorkValidationRule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/AttachedProofOfWorkValidationRule.java new file mode 100644 index 0000000000..59cd5b3b3a --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/AttachedProofOfWorkValidationRule.java @@ -0,0 +1,46 @@ +/* + * Copyright Hyperledger Besu Contributors + * + * 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.headervalidationrules; + +import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.mainnet.AttachedBlockHeaderValidationRule; +import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; +import org.hyperledger.besu.ethereum.mainnet.PoWHasher; +import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; + +import java.util.Optional; + +/** + * An attached proof of work validation rule that wraps the detached version of the same. Suitable + * for use in block validator stacks supporting the merge. + */ +public class AttachedProofOfWorkValidationRule implements AttachedBlockHeaderValidationRule { + + private final ProofOfWorkValidationRule detachedRule; + + public AttachedProofOfWorkValidationRule( + final EpochCalculator epochCalculator, + final PoWHasher hasher, + final Optional feeMarket) { + this.detachedRule = new ProofOfWorkValidationRule(epochCalculator, hasher, feeMarket); + } + + @Override + public boolean validate( + final BlockHeader header, final BlockHeader parent, final ProtocolContext protocolContext) { + return detachedRule.validate(header, parent); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/CalculatedDifficultyValidationRule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/CalculatedDifficultyValidationRule.java index 2bffde67cc..bcc4e21358 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/CalculatedDifficultyValidationRule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/CalculatedDifficultyValidationRule.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.mainnet.headervalidationrules; -import org.hyperledger.besu.config.MergeConfigOptions; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.mainnet.AttachedBlockHeaderValidationRule; @@ -37,9 +36,7 @@ public class CalculatedDifficultyValidationRule implements AttachedBlockHeaderVa @Override public boolean validate( final BlockHeader header, final BlockHeader parent, final ProtocolContext context) { - if (MergeConfigOptions.isMergeEnabled()) { - return true; - } + final BigInteger actualDifficulty = new BigInteger(1, header.getDifficulty().toArray()); final BigInteger expectedDifficulty = difficultyCalculator.nextDifficulty(header.getTimestamp(), parent, context); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRule.java index 2c98f311b2..6f1612f1c8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRule.java @@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.mainnet.headervalidationrules; import static java.lang.Boolean.FALSE; -import org.hyperledger.besu.config.MergeConfigOptions; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule; @@ -70,12 +69,6 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid return false; } - // TODO: remove this rule bypass, use post-merge headervalidation rules - // https://github.com/hyperledger/besu/issues/2898 - if (MergeConfigOptions.isMergeEnabled()) { - return true; - } - final Hash headerHash = hashHeader(header); PoWSolution solution = hasher.hash(header.getNonce(), header.getNumber(), epochCalculator, headerHash); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/TimestampMoreRecentThanParent.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/TimestampMoreRecentThanParent.java index 2af6d23d87..6aa7e5479e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/TimestampMoreRecentThanParent.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/TimestampMoreRecentThanParent.java @@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.mainnet.headervalidationrules; import static com.google.common.base.Preconditions.checkArgument; -import org.hyperledger.besu.config.MergeConfigOptions; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule; @@ -36,9 +35,6 @@ public class TimestampMoreRecentThanParent implements DetachedBlockHeaderValidat @Override public boolean validate(final BlockHeader header, final BlockHeader parent) { - if (MergeConfigOptions.isMergeEnabled()) { - return true; - } return validateTimestamp(header.getTimestamp(), parent.getTimestamp()); }