Skip to content

Commit 604dcf8

Browse files
authored
Merge pull request #168 from joaomlneto/tendermint-main-fix-byzzfuzz-partitions
Tendermint main fix byzzfuzz partitions
2 parents a4fdb90 + fffdcd9 commit 604dcf8

21 files changed

+1919
-7
lines changed

simulator/src/main/java/byzzbench/simulator/Client.java

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import lombok.Getter;
88
import lombok.RequiredArgsConstructor;
99
import lombok.experimental.SuperBuilder;
10+
import lombok.extern.java.Log;
1011

1112
import java.io.Serializable;
1213
import java.time.Duration;
@@ -22,6 +23,7 @@
2223
@Getter
2324
@SuperBuilder
2425
@RequiredArgsConstructor
26+
@Log
2527
public class Client implements Serializable, Node {
2628
/**
2729
* The scenario object that this client belongs to.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package byzzbench.simulator.protocols.tendermint;
2+
3+
import byzzbench.simulator.protocols.tendermint.message.*;
4+
5+
import lombok.Getter;
6+
import lombok.RequiredArgsConstructor;
7+
import lombok.extern.java.Log;
8+
9+
import java.util.*;
10+
import java.util.stream.Collectors;
11+
12+
@Log
13+
@RequiredArgsConstructor
14+
public class MessageLog {
15+
private final TendermintReplica node;
16+
17+
@Getter
18+
private final SortedMap<String, SortedSet<GenericMessage>> receivedMessages = new TreeMap<>();
19+
20+
@Getter
21+
private final SortedSet<GenericMessage> sentMessages = new TreeSet<>();
22+
23+
@Getter
24+
private final SortedMap<Block, List<PrevoteMessage>> prevotes = new TreeMap<>();
25+
@Getter
26+
private final SortedMap<Block, List<PrecommitMessage>> precommits = new TreeMap<>();
27+
@Getter
28+
private final SortedMap<Block, List<ProposalMessage>> proposals = new TreeMap<>();
29+
30+
@Getter
31+
private final Set<RequestMessage> requests = new HashSet<>();
32+
33+
public static final Block NULL_BLOCK = new Block(Long.MIN_VALUE, "NULL VALUE", null);
34+
35+
@Getter
36+
private long proposalCount = 0;
37+
@Getter
38+
private long prevotesCount = 0;
39+
@Getter
40+
private long precommitCount = 0;
41+
42+
/**
43+
* Adds a message to the message log, maintaining the appropriate mappings.
44+
*
45+
* @param voteMessage the message to add
46+
* @return true if the message was added successfully (not seen before), false otherwise
47+
*/
48+
public boolean addMessage(GenericMessage voteMessage) {
49+
// Get the set of received messages for the author
50+
SortedSet<GenericMessage> authorMessages = receivedMessages
51+
.computeIfAbsent(voteMessage.getAuthor(), k -> new TreeSet<>());
52+
53+
// Check if the message already exists
54+
boolean isNewMessage = authorMessages.add(voteMessage);
55+
56+
if (!isNewMessage) {
57+
// Message already exists, return false
58+
return false;
59+
}
60+
61+
// Process the message based on its type
62+
Block block = voteMessage.getBlock() == null ? NULL_BLOCK : voteMessage.getBlock();
63+
64+
switch (voteMessage) {
65+
case PrevoteMessage prevoteMessage -> {
66+
prevotes.computeIfAbsent(block, k -> new ArrayList<>()).add(prevoteMessage);
67+
prevotesCount++; // Increment prevote count
68+
}
69+
case PrecommitMessage precommitMessage -> {
70+
precommits.computeIfAbsent(block, k -> new ArrayList<>()).add(precommitMessage);
71+
precommitCount++; // Increment precommit count
72+
}
73+
case ProposalMessage proposalMessage -> {
74+
proposals.computeIfAbsent(block, k -> new ArrayList<>()).add(proposalMessage);
75+
proposalCount++; // Increment proposal count
76+
}
77+
default -> {
78+
// No action needed for other message types
79+
}
80+
}
81+
82+
return true; // Successfully added a new message
83+
}
84+
85+
/**
86+
* Returns the total number of messages stored.
87+
*/
88+
public long getMessageCount() {
89+
return receivedMessages.values().stream().mapToLong(Set::size).sum();
90+
}
91+
92+
/**
93+
* Checks if a block has enough prevotes.
94+
*/
95+
public boolean hasEnoughPreVotes(Block block) {
96+
return prevotes.getOrDefault(block, Collections.emptyList()).size() >= 2 * node.getTolerance() + 1;
97+
}
98+
99+
/**
100+
* Checks if a block has enough precommits.
101+
*/
102+
public boolean hasEnoughPreCommits(Block block) {
103+
return precommits.getOrDefault(block, Collections.emptyList()).size() >= 2 * node.getTolerance() + 1;
104+
}
105+
106+
/**
107+
* Gets the count of prevote messages for a specific block.
108+
*/
109+
public int getPrevoteCount(Block block) {
110+
return prevotes.getOrDefault(block, Collections.emptyList()).size();
111+
}
112+
113+
/**
114+
* Checks if there are f+1 messages in a specific sequence after a given sequence.
115+
*/
116+
public boolean fPlus1MessagesInSequence(long height, long sequence) {
117+
// Flatten the received messages map and filter by height and sequence > sequence
118+
Map<Long, Long> sequenceMessageCounts = receivedMessages.values().stream()
119+
.flatMap(Set::stream) // Flatten all sets of messages into a single stream
120+
.filter(m -> m.getHeight() == height && m.getSequence() > sequence) // Apply filters
121+
.collect(Collectors.groupingBy(GenericMessage::getSequence, Collectors.counting())); // Group by sequence and count
122+
123+
// Check if any sequence group has at least f + 1 messages
124+
return sequenceMessageCounts.values().stream()
125+
.anyMatch(count -> count >= node.getTolerance() + 1);
126+
}
127+
128+
public void bufferRequest(RequestMessage request) {
129+
requests.add(request);
130+
}
131+
132+
public void removeRequest(Block block) {
133+
Set<RequestMessage> toDelete = requests.stream().filter(r -> r.getOperation() == block.getRequestMessage().getOperation()).collect(Collectors.toSet());
134+
for (RequestMessage d : toDelete){
135+
requests.remove(d);
136+
}
137+
}
138+
139+
public void clear(Block block) {
140+
// messages.clear();
141+
prevotes.remove(block);
142+
prevotes.remove(NULL_BLOCK);
143+
precommits.remove(block);
144+
precommits.remove(NULL_BLOCK);
145+
proposals.remove(block);
146+
precommitCount = 0;
147+
prevotesCount = 0;
148+
proposalCount = 0;
149+
}
150+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package byzzbench.simulator.protocols.tendermint;
2+
3+
public enum Step implements Comparable<Step> {
4+
PROPOSE,
5+
PREVOTE,
6+
PRECOMMIT,
7+
}

0 commit comments

Comments
 (0)