Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -20,21 +19,21 @@
* Stores all output of consensus used in testing. This output can be used to validate consensus results.
*/
public class ConsensusOutput implements Clearable {
private final LinkedList<ConsensusRound> consensusRounds;
private final LinkedList<PlatformEvent> preConsensusEvents;
private final LinkedList<PlatformEvent> addedEvents;
private final LinkedList<PlatformEvent> staleEvents;
private final List<ConsensusRound> consensusRounds;
private final List<PlatformEvent> preConsensusEvents;
private final List<PlatformEvent> addedEvents;
private final List<PlatformEvent> staleEvents;

private EventWindow eventWindow;

/**
* Creates a new instance.
*/
public ConsensusOutput() {
addedEvents = new LinkedList<>();
preConsensusEvents = new LinkedList<>();
consensusRounds = new LinkedList<>();
staleEvents = new LinkedList<>();
addedEvents = new ArrayList<>();
preConsensusEvents = new ArrayList<>();
consensusRounds = new ArrayList<>();
staleEvents = new ArrayList<>();

eventWindow = EventWindow.getGenesisEventWindow();
}
Expand All @@ -60,9 +59,9 @@ public void consensusRound(@NonNull final ConsensusRound consensusRound) {
}

/**
* @return a queue of all events that have been marked as stale
* @return a list of all events that have been marked as stale
*/
public @NonNull LinkedList<PlatformEvent> getStaleEvents() {
public @NonNull List<PlatformEvent> getStaleEvents() {
return staleEvents;
}

Expand All @@ -76,9 +75,9 @@ public void consensusRound(@NonNull final ConsensusRound consensusRound) {
}

/**
* @return a queue of all rounds that have reached consensus
* @return a list of all rounds that have reached consensus
*/
public @NonNull LinkedList<ConsensusRound> getConsensusRounds() {
public @NonNull List<ConsensusRound> getConsensusRounds() {
return consensusRounds;
}

Expand All @@ -92,7 +91,7 @@ public void consensusRound(@NonNull final ConsensusRound consensusRound) {
return consensusRounds.getLast();
}

public @NonNull LinkedList<PlatformEvent> getAddedEvents() {
public @NonNull List<PlatformEvent> getAddedEvents() {
return addedEvents;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.swirlds.metrics.api.Metrics;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.stream.IntStream;
import org.hiero.consensus.hashgraph.impl.test.fixtures.event.generator.StandardGraphGenerator;
Expand All @@ -31,7 +30,7 @@ private GenerateConsensus() {}
* @param seed the seed to use
* @return consensus rounds
*/
public static Deque<ConsensusRound> generateConsensusRounds(
public static List<ConsensusRound> generateConsensusRounds(
@NonNull final Configuration configuration,
@NonNull final Metrics metrics,
@NonNull final Time time,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ public void addEvent(@NonNull final PlatformEvent event) {
}

/**
* @return a queue of all rounds that have reached consensus
* @return a list of all rounds that have reached consensus
*/
public @NonNull LinkedList<ConsensusRound> getConsensusRounds() {
public @NonNull List<ConsensusRound> getConsensusRounds() {
return output.getConsensusRounds();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import com.swirlds.config.api.Configuration;
import com.swirlds.metrics.api.Metrics;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.LinkedList;
import java.util.Objects;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.hiero.consensus.hashgraph.impl.test.fixtures.consensus.ConsensusOutput;
import org.hiero.consensus.hashgraph.impl.test.fixtures.consensus.TestIntake;
Expand Down Expand Up @@ -65,9 +65,8 @@ public ConsensusTestNode(@NonNull final EventEmitter eventEmitter, @NonNull fina
public void restart() {
// clear all generators
eventEmitter.reset();
final ConsensusSnapshot snapshot = Objects.requireNonNull(
getOutput().getConsensusRounds().peekLast())
.getSnapshot();
final ConsensusSnapshot snapshot =
getOutput().getConsensusRounds().getLast().getSnapshot();
intake.reset();
intake.loadSnapshot(snapshot);
}
Expand All @@ -78,13 +77,12 @@ public void restart() {
*/
public void removeNode(@NonNull final NodeId nodeId) {
eventEmitter.getGraphGenerator().removeNode(nodeId);
final ConsensusSnapshot snapshot = Objects.requireNonNull(
getOutput().getConsensusRounds().peekLast())
.getSnapshot();
final ConsensusSnapshot snapshot =
getOutput().getConsensusRounds().getLast().getSnapshot();
intake.loadSnapshot(snapshot);
// the above will clear all events from the linker and consensus, so we need to add all non-ancient events
// adding events will also add the events to the output, so we make a copy of the list and add them back
final LinkedList<PlatformEvent> added = new LinkedList<>(getOutput().getAddedEvents());
final List<PlatformEvent> added = new ArrayList<>(getOutput().getAddedEvents());
getOutput().getAddedEvents().clear();
for (final PlatformEvent e : added) {
intake.addEvent(e.copyGossipedData());
Expand Down Expand Up @@ -113,8 +111,7 @@ public void removeNode(@NonNull final NodeId nodeId) {
time,
newEmitter.getGraphGenerator().getRoster()));
consensusTestNode.intake.loadSnapshot(
Objects.requireNonNull(getOutput().getConsensusRounds().peekLast())
.getSnapshot());
getOutput().getConsensusRounds().getLast().getSnapshot());

assertThat(consensusTestNode.intake.getConsensusRounds())
.withFailMessage("we should not have reached consensus yet")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private ConsensusRoundValidator() {}
public static void validate(
@NonNull final List<ConsensusRound> rounds1, @NonNull final List<ConsensusRound> rounds2) {
assertThat(rounds1)
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"The number of consensus rounds is not the same."
+ "first argument has %d rounds, second has %d rounds",
rounds1.size(), rounds2.size()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ public record NumberOfConsensusRoundsValidation(int numberOfRounds) implements C
@Override
public void validate(@NonNull final ConsensusOutput output1, @NonNull final ConsensusOutput output2) {
for (final ConsensusOutput output : List.of(output1, output2)) {
Assertions.assertThat(output.getConsensusRounds().size())
final int actualRounds = output.getConsensusRounds().size();
Assertions.assertThat(actualRounds)
.withFailMessage(
"Expected %d rounds, but got %d",
numberOfRounds, output.getConsensusRounds().size())
() -> String.format("Expected %d rounds, but got %d", numberOfRounds, actualRounds))
.isEqualTo(numberOfRounds);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ public void validate(@NonNull final ConsensusOutput output1, @NonNull final Cons
final double consensusRatio = ((double) numConsensus) / allEvents1.size();

assertThat(consensusRatio)
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"Consensus ratio %s is less than the expected minimum %s",
consensusRatio, minimumConsensusRatio))
.isGreaterThanOrEqualTo(minimumConsensusRatio);
assertThat(consensusRatio)
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"Consensus ratio %s is more than the expected maximum %s",
consensusRatio, maximumConsensusRatio))
.isLessThanOrEqualTo(maximumConsensusRatio);
Expand All @@ -115,11 +115,11 @@ public void validate(@NonNull final ConsensusOutput output1, @NonNull final Cons
final double staleRatio = ((double) output1.getStaleEvents().size()) / allEvents1.size();

assertThat(staleRatio)
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"Stale ratio %s is less than the expected minimum %s", staleRatio, minimumStaleRatio))
.isGreaterThanOrEqualTo(minimumStaleRatio);
assertThat(staleRatio)
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"Stale ratio %s is more than the expected maximum %s", staleRatio, maximumStaleRatio))
.isLessThanOrEqualTo(maximumStaleRatio);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.hiero.base.crypto.Hash;
import org.hiero.base.crypto.Hashable;
import org.hiero.consensus.hashgraph.config.ConsensusConfig;
import org.hiero.consensus.hashgraph.impl.test.fixtures.consensus.ConsensusOutput;
import org.hiero.consensus.model.event.PlatformEvent;
import org.hiero.consensus.model.hashgraph.ConsensusRound;
import org.hiero.consensus.round.RoundCalculationUtils;

@SuppressWarnings("unused") // issue tracked #6998
Expand All @@ -29,31 +31,33 @@ private OutputNoEventsLostValidation() {}
* neither, so they are not checked.
*/
public void validate(@NonNull final ConsensusOutput output, @NonNull final ConsensusOutput ignored) {
final List<ConsensusRound> consensusRounds = output.getConsensusRounds();
if (consensusRounds.isEmpty()) {
// no consensus reached, nothing to check
return;
}

final Map<Hash, PlatformEvent> stale =
output.getStaleEvents().stream().collect(Collectors.toMap(Hashable::getHash, e -> e));
final Map<Hash, PlatformEvent> cons = output.getConsensusRounds().stream()
final Map<Hash, PlatformEvent> cons = consensusRounds.stream()
.flatMap(r -> r.getConsensusEvents().stream())
.collect(Collectors.toMap(PlatformEvent::getHash, e -> e));
if (output.getConsensusRounds().isEmpty()) {
// no consensus reached, nothing to check
return;
}
final long nonAncientThreshold = RoundCalculationUtils.getAncientThreshold(
CONFIG.roundsNonAncient(), output.getConsensusRounds().getLast().getSnapshot());
CONFIG.roundsNonAncient(), consensusRounds.getLast().getSnapshot());

for (final PlatformEvent event : output.getAddedEvents()) {
if (event.getBirthRound() >= nonAncientThreshold) {
// non-ancient events are not checked
continue;
}
if (stale.containsKey(event.getHash()) == cons.containsKey(event.getHash())) {
final Hash hash = event.getHash();
final boolean isStale = stale.containsKey(hash);
final boolean isConsensus = cons.containsKey(hash);
if (isStale == isConsensus) {
fail(String.format(
"An ancient event should be either stale or consensus, but not both!\n"
+ "nonAncientGen=%d, Event %s, stale=%s, consensus=%s",
nonAncientThreshold,
event.getDescriptor(),
stale.containsKey(event.getHash()),
cons.containsKey(event.getHash())));
nonAncientThreshold, event.getDescriptor(), isStale, isConsensus));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@ public void validate(@NonNull final List<ConsensusRound> rounds) {
return;
}

for (int i = 1; i < rounds.size(); i++) {
// Carry the previous round's threshold across iterations so each round's snapshot chain is
// resolved only once instead of once as "current" and again as "previous".
MinimumJudgeInfo previousThresholdInfo =
rounds.getFirst().getSnapshot().minimumJudgeInfoList().getLast();
for (int i = 1, n = rounds.size(); i < n; i++) {

final MinimumJudgeInfo previousThresholdInfo =
rounds.get(i - 1).getSnapshot().minimumJudgeInfoList().getLast();
final MinimumJudgeInfo currentThresholdInfo =
rounds.get(i).getSnapshot().minimumJudgeInfoList().getLast();

assertThat(currentThresholdInfo.minimumJudgeBirthRound())
.withFailMessage("the ancient threshold should never decrease")
.isGreaterThanOrEqualTo(previousThresholdInfo.minimumJudgeBirthRound());

previousThresholdInfo = currentThresholdInfo;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void validate(@NonNull final List<ConsensusRound> rounds) {
final MinimumJudgeInfo minimumJudgeInfo =
round.getSnapshot().minimumJudgeInfoList().getLast();
assertThat(round.getRoundNum())
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"the last threshold should be equal for the current round %d", round.getRoundNum()))
.isEqualTo(minimumJudgeInfo.round());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.Iterator;
import java.util.Objects;
import java.util.function.Supplier;
import org.hiero.consensus.model.event.PlatformEvent;
import org.hiero.consensus.model.hashgraph.ConsensusRound;

Expand All @@ -26,15 +27,15 @@ public void validate(@NonNull final ConsensusRound round1, @NonNull final Consen
final long firstRoundNumber = round1.getRoundNum();
final long secondRoundNumber = round2.getRoundNum();
assertThat(round1.getRoundNum())
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"round diff at rounds with numbers %d and %d", firstRoundNumber, secondRoundNumber))
.isEqualTo(round2.getRoundNum());
assertThat(round1.getEventCount())
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"event number diff at rounds with numbers %d and %d", firstRoundNumber, secondRoundNumber))
.isEqualTo(round2.getEventCount());
assertThat(round1.getSnapshot())
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"snapshot diff at rounds with numbers %d and %d", firstRoundNumber, secondRoundNumber))
.isEqualTo(round2.getSnapshot());
final Iterator<PlatformEvent> evIt1 = round1.getConsensusEvents().iterator();
Expand All @@ -43,20 +44,21 @@ public void validate(@NonNull final ConsensusRound round1, @NonNull final Consen
while (evIt1.hasNext() && evIt2.hasNext()) {
final PlatformEvent e1 = evIt1.next();
final PlatformEvent e2 = evIt2.next();
final int index = eventIndex;
assertThat(e1.getConsensusData())
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"output:1, roundNumberFromFirstNode:%d, roundNumberFromSecondRound:%d, eventIndex%d is not consensus",
firstRoundNumber, secondRoundNumber, eventIndex))
firstRoundNumber, secondRoundNumber, index))
.isNotNull();
assertThat(e2.getConsensusData())
.withFailMessage(String.format(
.withFailMessage(() -> String.format(
"output:1, roundNumberFromFirstNode:%d, roundNumberFromSecondRound:%d, eventIndex%d is not consensus",
firstRoundNumber, secondRoundNumber, eventIndex))
firstRoundNumber, secondRoundNumber, index))
.isNotNull();
assertConsensusEvents(
String.format(
() -> String.format(
"roundNumberFromFirstNode:%d, roundNumberFromSecondRound:%d, event index %d",
firstRoundNumber, secondRoundNumber, eventIndex),
firstRoundNumber, secondRoundNumber, index),
e1,
e2);
eventIndex++;
Expand All @@ -67,16 +69,16 @@ public void validate(@NonNull final ConsensusRound round1, @NonNull final Consen
* Assert that two events are equal. If they are not equal then cause the test to fail and print
* a meaningful error message.
*
* @param description a string that is printed if the events are unequal
* @param description supplies a string that is printed if the events are unequal; only evaluated on failure
* @param e1 the first event
* @param e2 the second event
*/
private static void assertConsensusEvents(
final String description, final PlatformEvent e1, final PlatformEvent e2) {
final Supplier<String> description, final PlatformEvent e1, final PlatformEvent e2) {
final boolean equal = Objects.equals(e1, e2);
if (!equal) {
final StringBuilder sb = new StringBuilder();
sb.append(description).append("\n");
sb.append(description.get()).append("\n");
sb.append("Events are not equal:\n");
sb.append("Event 1: ").append(e1).append("\n");
sb.append("Event 2: ").append(e2).append("\n");
Expand Down
Loading
Loading