Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/clique post merge fast sync #4276

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Fixes off-by-one error for mainnet TTD fallback [#4223](https://github.com/hyperledger/besu/pull/4223)
- Fix off-by-one error in AbstractRetryingPeerTask [#4254](https://github.com/hyperledger/besu/pull/4254)
- Fix encoding of key (short hex) in eth_getProof [#4261](https://github.com/hyperledger/besu/pull/4261)
- Fix for post-merge networks fast-sync [#4224](https://github.com/hyperledger/besu/pull/4224), [#4276](https://github.com/hyperledger/besu/pull/4276)

## 22.7.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import org.hyperledger.besu.consensus.clique.BlockHeaderValidationRulesetFactory;
import org.hyperledger.besu.consensus.clique.CliqueContext;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.merge.MergeContext;
import org.hyperledger.besu.consensus.merge.PostMergeContext;
import org.hyperledger.besu.consensus.merge.TransitionProtocolSchedule;
import org.hyperledger.besu.consensus.merge.blockcreation.TransitionCoordinator;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
Expand All @@ -36,8 +39,12 @@
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderValidator;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.storage.StorageProvider;

import java.util.Optional;
Expand Down Expand Up @@ -178,6 +185,56 @@ public void assertPostMergeScheduleForPostMergeExactlyAtTerminalDifficultyIfNotF
.isEqualTo(postMergeProtocolSpec);
}

@Test
public void assertCliqueDetachedHeaderValidationPreMerge() {
BlockHeaderValidator cliqueValidator =
BlockHeaderValidationRulesetFactory.cliqueBlockHeaderValidator(
5L, new EpochManager(5L), Optional.of(FeeMarket.london(1L)), true)
.build();
assertDetachedRulesForPostMergeBlocks(cliqueValidator);
}

@Test
public void assertPoWDetachedHeaderValidationPreMerge() {
BlockHeaderValidator powValidator =
MainnetBlockHeaderValidator.createBaseFeeMarketValidator(FeeMarket.london(1L), true)
.build();
assertDetachedRulesForPostMergeBlocks(powValidator);
}

void assertDetachedRulesForPostMergeBlocks(final BlockHeaderValidator validator) {
var preMergeProtocolSpec = mock(ProtocolSpec.class);
when(preMergeProtocolSpec.getBlockHeaderValidator()).thenReturn(validator);

when(preMergeProtocolSchedule.getByBlockNumber(anyLong())).thenReturn(preMergeProtocolSpec);

var mockParentBlock =
new BlockHeaderTestFixture()
.number(100L)
.baseFeePerGas(Wei.of(7L))
.gasLimit(5000L)
.buildHeader();

var mockBlock =
new BlockHeaderTestFixture()
.number(101L)
.timestamp(1000L)
.baseFeePerGas(Wei.of(7L))
.gasLimit(5000L)
.difficulty(Difficulty.of(0L))
.parentHash(mockParentBlock.getHash())
.buildHeader();

var mergeFriendlyValidation =
transitionProtocolSchedule
.getPreMergeSchedule()
.getByBlockNumber(1L)
.getBlockHeaderValidator()
.validateHeader(
mockBlock, mockParentBlock, protocolContext, HeaderValidationMode.DETACHED_ONLY);
assertThat(mergeFriendlyValidation).isTrue();
}

TransitionCoordinator buildTransitionCoordinator(
final BesuControllerBuilder preMerge, final MergeBesuControllerBuilder postMerge) {
var builder = new TransitionBesuControllerBuilder(preMerge, postMerge);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import static org.hyperledger.besu.ethereum.mainnet.AbstractGasLimitSpecification.DEFAULT_MAX_GAS_LIMIT;
import static org.hyperledger.besu.ethereum.mainnet.AbstractGasLimitSpecification.DEFAULT_MIN_GAS_LIMIT;

import org.hyperledger.besu.config.MergeConfigOptions;
import org.hyperledger.besu.consensus.clique.headervalidationrules.CliqueDifficultyValidationRule;
import org.hyperledger.besu.consensus.clique.headervalidationrules.CliqueExtraDataValidationRule;
import org.hyperledger.besu.consensus.clique.headervalidationrules.CoinbaseHeaderValidationRule;
Expand All @@ -28,6 +29,7 @@
import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator;
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AncestryValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AttachedComposedFromDetachedRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.BaseFeeMarketBlockHeaderGasPriceValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantFieldValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasLimitRangeAndDeltaValidationRule;
Expand All @@ -37,6 +39,8 @@

import java.util.Optional;

import com.google.common.annotations.VisibleForTesting;

public class BlockHeaderValidationRulesetFactory {

/**
Expand All @@ -54,22 +58,28 @@ public static BlockHeaderValidator.Builder cliqueBlockHeaderValidator(
final long secondsBetweenBlocks,
final EpochManager epochManager,
final Optional<BaseFeeMarket> baseFeeMarket) {
return cliqueBlockHeaderValidator(
secondsBetweenBlocks, epochManager, baseFeeMarket, MergeConfigOptions.isMergeEnabled());
}

@VisibleForTesting
public static BlockHeaderValidator.Builder cliqueBlockHeaderValidator(
final long secondsBetweenBlocks,
final EpochManager epochManager,
final Optional<BaseFeeMarket> baseFeeMarket,
final boolean isMergeEnabled) {

final BlockHeaderValidator.Builder builder =
new BlockHeaderValidator.Builder()
.addRule(new AncestryValidationRule())
.addRule(new TimestampBoundedByFutureParameter(10))
.addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks))
.addRule(
new GasLimitRangeAndDeltaValidationRule(
DEFAULT_MIN_GAS_LIMIT, DEFAULT_MAX_GAS_LIMIT, baseFeeMarket))
.addRule(
new ConstantFieldValidationRule<>("MixHash", BlockHeader::getMixHash, Hash.ZERO))
.addRule(
new ConstantFieldValidationRule<>(
"OmmersHash", BlockHeader::getOmmersHash, Hash.EMPTY_LIST_HASH))
.addRule(new CliqueExtraDataValidationRule(epochManager))
.addRule(new VoteValidationRule())
.addRule(new CliqueDifficultyValidationRule())
.addRule(new SignerRateLimitValidationRule())
.addRule(new CoinbaseHeaderValidationRule(epochManager))
Expand All @@ -79,6 +89,20 @@ public static BlockHeaderValidator.Builder cliqueBlockHeaderValidator(
builder.addRule(new BaseFeeMarketBlockHeaderGasPriceValidationRule(baseFeeMarket.get()));
}

var mixHashRule =
new ConstantFieldValidationRule<>("MixHash", BlockHeader::getMixHash, Hash.ZERO);
var voteValidationRule = new VoteValidationRule();
var cliqueTimestampRule = new TimestampMoreRecentThanParent(secondsBetweenBlocks);

if (isMergeEnabled) {
builder
.addRule(new AttachedComposedFromDetachedRule(mixHashRule))
.addRule(new AttachedComposedFromDetachedRule(voteValidationRule))
.addRule(new AttachedComposedFromDetachedRule(cliqueTimestampRule));
} else {
builder.addRule(mixHashRule).addRule(voteValidationRule).addRule(cliqueTimestampRule);
}

return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
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.AttachedComposedFromDetachedRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.BaseFeeMarketBlockHeaderGasPriceValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.CalculatedDifficultyValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantFieldValidationRule;
Expand All @@ -31,6 +31,7 @@

import java.util.Optional;

import com.google.common.annotations.VisibleForTesting;
import org.apache.tuweni.bytes.Bytes;

public final class MainnetBlockHeaderValidator {
Expand Down Expand Up @@ -124,6 +125,12 @@ public static BlockHeaderValidator.Builder createPgaBlockHeaderValidator(

public static BlockHeaderValidator.Builder createBaseFeeMarketValidator(
final BaseFeeMarket baseFeeMarket) {
return createBaseFeeMarketValidator(baseFeeMarket, MergeConfigOptions.isMergeEnabled());
}

@VisibleForTesting
public static BlockHeaderValidator.Builder createBaseFeeMarketValidator(
final BaseFeeMarket baseFeeMarket, final boolean isMergeEnabled) {
var builder =
new BlockHeaderValidator.Builder()
.addRule(CalculatedDifficultyValidationRule::new)
Expand All @@ -138,19 +145,16 @@ public static BlockHeaderValidator.Builder createBaseFeeMarketValidator(
.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)));

var powValidationRule =
new ProofOfWorkValidationRule(
new EpochCalculator.DefaultEpochCalculator(),
PoWHasher.ETHASH_LIGHT,
Optional.of(baseFeeMarket));

if (isMergeEnabled) {
builder.addRule(new AttachedComposedFromDetachedRule(powValidationRule));
} else {
builder.addRule(
new ProofOfWorkValidationRule(
new EpochCalculator.DefaultEpochCalculator(),
PoWHasher.ETHASH_LIGHT,
Optional.of(baseFeeMarket)));
builder.addRule(powValidationRule);
}
return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,18 @@
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;
import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule;

/**
* 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 {
public class AttachedComposedFromDetachedRule implements AttachedBlockHeaderValidationRule {

private final ProofOfWorkValidationRule detachedRule;
private final DetachedBlockHeaderValidationRule detachedRule;

public AttachedProofOfWorkValidationRule(
final EpochCalculator epochCalculator,
final PoWHasher hasher,
final Optional<FeeMarket> feeMarket) {
this.detachedRule = new ProofOfWorkValidationRule(epochCalculator, hasher, feeMarket);
public AttachedComposedFromDetachedRule(final DetachedBlockHeaderValidationRule detachedRule) {
this.detachedRule = detachedRule;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public void stop() {
clearListeners();
started.set(false);
} else {
LOG.warn("Attempted to stop when we are not even running...");
LOG.debug("Attempted to stop when we are not even running...");
}
}

Expand Down