Panda print only when crossing TTD the first time (#4194)

* add oldState to MergeStateHandler, move Pandas to Transition watcher

Signed-off-by: garyschulte <garyschulte@gmail.com>
pull/4204/head
garyschulte 2 years ago committed by GitHub
parent 0d7eaf16d4
commit 9b2fcde2b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  2. 8
      besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java
  3. 21
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PandaPrinter.java
  4. 10
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PostMergeContext.java
  5. 4
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionBestPeerComparator.java
  6. 39
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/PandaPrinterTest.java
  7. 4
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/PostMergeContextTest.java
  8. 2
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/TransitionBestPeerComparatorTest.java
  9. 5
      ethereum/eth/src/main/java/org/hyperledger/besu/consensus/merge/MergeStateHandler.java
  10. 4
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/MergePeerFilter.java
  11. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncState.java
  12. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java

@ -21,7 +21,6 @@ import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.consensus.merge.FinalizedBlockHashSupplier;
import org.hyperledger.besu.consensus.merge.MergeContext;
import org.hyperledger.besu.consensus.merge.PandaPrinter;
import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfiguration;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.datatypes.Hash;
@ -379,7 +378,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
final EthContext ethContext = new EthContext(ethPeers, ethMessages, snapMessages, scheduler);
final boolean fastSyncEnabled = !SyncMode.isFullSync(syncConfig.getSyncMode());
final SyncState syncState = new SyncState(blockchain, ethPeers, fastSyncEnabled, checkpoint);
syncState.subscribeTTDReached(new PandaPrinter());
final TransactionPool transactionPool =
TransactionPoolFactory.createTransactionPool(

@ -15,6 +15,7 @@
package org.hyperledger.besu.controller;
import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.consensus.merge.PandaPrinter;
import org.hyperledger.besu.consensus.merge.PostMergeContext;
import org.hyperledger.besu.consensus.merge.TransitionBackwardSyncContext;
import org.hyperledger.besu.consensus.merge.TransitionContext;
@ -180,7 +181,7 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
PostMergeContext postMergeContext = protocolContext.getConsensusContext(PostMergeContext.class);
postMergeContext.observeNewIsPostMergeState(
(isPoS, difficultyStoppedAt) -> {
(isPoS, priorState, difficultyStoppedAt) -> {
if (isPoS) {
// if we transitioned to post-merge, stop and disable any mining
composedCoordinator.getPreMergeObject().disable();
@ -190,6 +191,11 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
.getBlockchain()
.setBlockChoiceRule((newBlockHeader, currentBlockHeader) -> -1);
if (priorState.filter(prior -> !prior).isPresent()) {
// only print pandas if we had a prior merge state, and it was false
PandaPrinter.printOnFirstCrossing();
}
} else if (composedCoordinator.isMiningBeforeMerge()) {
// if our merge state is set to mine pre-merge and we are mining, start mining
composedCoordinator.getPreMergeObject().enable();

@ -16,8 +16,6 @@
package org.hyperledger.besu.consensus.merge;
import org.hyperledger.besu.plugin.services.BesuEvents.TTDReachedListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@ -28,11 +26,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PandaPrinter implements TTDReachedListener {
public class PandaPrinter {
private static final Logger LOG = LoggerFactory.getLogger(PandaPrinter.class);
private static final String pandaBanner = PandaPrinter.loadBanner();
private final AtomicBoolean beenDisplayed = new AtomicBoolean();
private static final AtomicBoolean beenDisplayed = new AtomicBoolean();
private static String loadBanner() {
Class<PandaPrinter> c = PandaPrinter.class;
@ -50,10 +48,19 @@ public class PandaPrinter implements TTDReachedListener {
return resultStringBuilder.toString();
}
@Override
public void onTTDReached(final boolean reached) {
if (reached && beenDisplayed.compareAndSet(false, true)) {
public static boolean printOnFirstCrossing() {
boolean shouldPrint = beenDisplayed.compareAndSet(false, true);
if (shouldPrint) {
LOG.info("\n" + pandaBanner);
}
return shouldPrint;
}
static boolean hasDisplayed() {
return beenDisplayed.get();
}
static void resetForTesting() {
beenDisplayed.set(false);
}
}

@ -57,7 +57,12 @@ public class PostMergeContext implements MergeContext {
@VisibleForTesting
PostMergeContext() {
this.terminalTotalDifficulty = new AtomicReference<>(Difficulty.ZERO);
this(Difficulty.ZERO);
}
@VisibleForTesting
PostMergeContext(final Difficulty difficulty) {
this.terminalTotalDifficulty = new AtomicReference<>(difficulty);
this.syncState = new AtomicReference<>();
}
@ -100,7 +105,8 @@ public class PostMergeContext implements MergeContext {
if (oldState.isEmpty() || oldState.get() != newState) {
newMergeStateCallbackSubscribers.forEach(
newMergeStateCallback ->
newMergeStateCallback.mergeStateChanged(newState, Optional.of(totalDifficulty)));
newMergeStateCallback.mergeStateChanged(
newState, oldState, Optional.of(totalDifficulty)));
}
}

@ -56,7 +56,9 @@ public class TransitionBestPeerComparator implements Comparator<EthPeer>, MergeS
@Override
public void mergeStateChanged(
final boolean isPoS, final Optional<Difficulty> difficultyStoppedAt) {
final boolean isPoS,
final Optional<Boolean> oldState,
final Optional<Difficulty> difficultyStoppedAt) {
if (isPoS && difficultyStoppedAt.isPresent()) {
terminalTotalDifficulty.set(difficultyStoppedAt.get());
}

@ -16,13 +16,48 @@
package org.hyperledger.besu.consensus.merge;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.junit.Test;
public class PandaPrinterTest {
final MergeStateHandler fauxTransitionHandler =
(isPoS, priorState, ttd) -> {
if (isPoS && priorState.filter(prior -> !prior).isPresent())
PandaPrinter.printOnFirstCrossing();
};
@Test
public void printsPanda() {
PandaPrinter panda = new PandaPrinter();
panda.onTTDReached(true);
PandaPrinter.resetForTesting();
assertThat(PandaPrinter.printOnFirstCrossing()).isTrue();
assertThat(PandaPrinter.printOnFirstCrossing()).isFalse();
}
@Test
public void doesNotPrintAtInit() {
PandaPrinter.resetForTesting();
var mergeContext = new PostMergeContext(Difficulty.ONE);
mergeContext.observeNewIsPostMergeState(fauxTransitionHandler);
assertThat(PandaPrinter.hasDisplayed()).isFalse();
mergeContext.setIsPostMerge(Difficulty.ONE);
assertThat(PandaPrinter.hasDisplayed()).isFalse();
}
@Test
public void printsWhenCrossingOnly() {
PandaPrinter.resetForTesting();
var mergeContext = new PostMergeContext(Difficulty.ONE);
mergeContext.observeNewIsPostMergeState(fauxTransitionHandler);
assertThat(PandaPrinter.hasDisplayed()).isFalse();
mergeContext.setIsPostMerge(Difficulty.ZERO);
assertThat(PandaPrinter.hasDisplayed()).isFalse();
mergeContext.setIsPostMerge(Difficulty.ONE);
assertThat(PandaPrinter.hasDisplayed()).isTrue();
}
}

@ -173,7 +173,9 @@ public class PostMergeContextTest {
@Override
public void mergeStateChanged(
final boolean isPoS, final Optional<Difficulty> difficultyStoppedAt) {
final boolean isPoS,
final Optional<Boolean> oldState,
final Optional<Difficulty> difficultyStoppedAt) {
stateChanges.add(isPoS);
}

@ -60,7 +60,7 @@ public class TransitionBestPeerComparatorTest {
assertThat(comparator.compare(a, b)).isEqualTo(-1);
// update TTD with actual value
comparator.mergeStateChanged(true, Optional.of(Difficulty.of(5002)));
comparator.mergeStateChanged(true, Optional.empty(), Optional.of(Difficulty.of(5002)));
assertThat(comparator.compare(a, b)).isEqualTo(1);
}
}

@ -22,5 +22,8 @@ import java.util.Optional;
public interface MergeStateHandler {
void mergeStateChanged(final boolean isPoS, final Optional<Difficulty> difficultyStoppedAt);
void mergeStateChanged(
final boolean isPoS,
final Optional<Boolean> priorState,
final Optional<Difficulty> difficultyStoppedAt);
}

@ -88,7 +88,9 @@ public class MergePeerFilter implements MergeStateHandler, ForkchoiceMessageList
@Override
public void mergeStateChanged(
final boolean isPoS, final Optional<Difficulty> difficultyStoppedAt) {
final boolean isPoS,
final Optional<Boolean> oldState,
final Optional<Difficulty> difficultyStoppedAt) {
if (isPoS && difficultyStoppedAt.isPresent()) {
LOG.debug("terminal difficulty set to {}", difficultyStoppedAt.get().getValue());
long lockStamp = this.powTerminalDifficultyLock.writeLock();

@ -177,8 +177,6 @@ public class SyncState {
}
public void setReachedTerminalDifficulty(final boolean stoppedAtTerminalDifficulty) {
// TODO: this is an inexpensive way to stop sync when we reach TTD,
// we should revisit when merge sync is better defined
this.reachedTerminalDifficulty = Optional.of(stoppedAtTerminalDifficulty);
ttdReachedListeners.forEach(listener -> listener.onTTDReached(stoppedAtTerminalDifficulty));
}

@ -235,7 +235,7 @@ public final class EthProtocolManagerTest {
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(stakePeer, stakePeerStatus));
mergePeerFilter.mergeStateChanged(
true, Optional.of(blockchain.getChainHead().getTotalDifficulty()));
true, Optional.empty(), Optional.of(blockchain.getChainHead().getTotalDifficulty()));
mergePeerFilter.onNewForkchoiceMessage(
Hash.EMPTY, Optional.of(Hash.hash(Bytes.of(1))), Hash.EMPTY);
mergePeerFilter.onNewForkchoiceMessage(

Loading…
Cancel
Save