Skip to content

Commit 54e7d27

Browse files
committed
add GST (logic still missing from simulatorservice)
1 parent 0a94052 commit 54e7d27

23 files changed

+123
-64
lines changed

simulator/src/main/java/byzzbench/simulator/Replica.java

-9
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,6 @@ public void initialize() {
161161
// do nothing by default
162162
}
163163

164-
/**
165-
* Handle a request received from a client.
166-
*
167-
* @param clientId the ID of the client
168-
* @param request the request payload
169-
* @throws Exception if an error occurs while handling the request
170-
*/
171-
public abstract void handleClientRequest(String clientId, Serializable request) throws Exception;
172-
173164
/**
174165
* Send a reply to a client.
175166
*

simulator/src/main/java/byzzbench/simulator/faults/faults/ByzzFuzzNetworkFault.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import byzzbench.simulator.faults.BaseFault;
44
import byzzbench.simulator.faults.behaviors.CreateNetworkPartitionsBehavior;
5+
import byzzbench.simulator.faults.predicates.ANDPredicate;
6+
import byzzbench.simulator.faults.predicates.IsBeforeGST;
57
import byzzbench.simulator.faults.predicates.MessageRoundPredicate;
68

79
import java.util.Set;
@@ -22,7 +24,7 @@ public class ByzzFuzzNetworkFault extends BaseFault {
2224
public ByzzFuzzNetworkFault(Set<String> partition, int round) {
2325
super(
2426
"byzzfuzznetworkfault-%d-%s".formatted(round, String.join("-", partition)),
25-
new MessageRoundPredicate(round),
27+
new ANDPredicate(new IsBeforeGST(), new MessageRoundPredicate(round)),
2628
new CreateNetworkPartitionsBehavior(partition)
2729
);
2830
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package byzzbench.simulator.faults.predicates;
2+
3+
import byzzbench.simulator.faults.FaultContext;
4+
import byzzbench.simulator.faults.FaultPredicate;
5+
6+
import java.util.List;
7+
8+
public class ANDPredicate implements FaultPredicate {
9+
private final List<FaultPredicate> predicates;
10+
11+
public ANDPredicate(FaultPredicate... predicates) {
12+
this.predicates = List.of(predicates);
13+
}
14+
15+
@Override
16+
public String getId() {
17+
return "AND(%s)".formatted(predicates.stream()
18+
.map(FaultPredicate::getId)
19+
.reduce("", (a, b) -> a + "," + b));
20+
}
21+
22+
@Override
23+
public String getName() {
24+
return predicates.stream()
25+
.map(FaultPredicate::getName)
26+
.reduce("", (a, b) -> a + " AND " + b);
27+
}
28+
29+
@Override
30+
public boolean test(FaultContext faultContext) {
31+
return predicates.stream().allMatch(p -> p.test(faultContext));
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package byzzbench.simulator.faults.predicates;
2+
3+
import byzzbench.simulator.faults.FaultContext;
4+
import byzzbench.simulator.faults.FaultPredicate;
5+
6+
public class IsBeforeGST implements FaultPredicate {
7+
@Override
8+
public String getId() {
9+
return "IsBeforeGST";
10+
}
11+
12+
@Override
13+
public String getName() {
14+
return "Is before GST";
15+
}
16+
17+
@Override
18+
public boolean test(FaultContext faultContext) {
19+
return !faultContext.getScenario().getTransport().isGlobalStabilizationTime();
20+
}
21+
}

simulator/src/main/java/byzzbench/simulator/protocols/XRPL/XRPLReplica.java

+4-9
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
import byzzbench.simulator.protocols.XRPL.messages.XRPLTxMessage;
88
import byzzbench.simulator.protocols.XRPL.messages.XRPLValidateMessage;
99
import byzzbench.simulator.state.TotalOrderCommitLog;
10+
import byzzbench.simulator.transport.DefaultClientRequestPayload;
1011
import byzzbench.simulator.transport.MessagePayload;
1112
import lombok.Getter;
1213

13-
import java.io.Serializable;
1414
import java.time.Duration;
1515
import java.util.*;
1616
import java.util.Map.Entry;
@@ -55,7 +55,9 @@ protected XRPLReplica(String nodeId, Scenario scenario, List<String> UNL, XRPLLe
5555

5656
@Override
5757
public void handleMessage(String sender, MessagePayload message) throws Exception {
58-
if (message instanceof XRPLProposeMessage propmsg) {
58+
if (message instanceof DefaultClientRequestPayload req) {
59+
recvTxHandler(new XRPLTxMessage(req.getOperation().toString(), sender));
60+
} else if (message instanceof XRPLProposeMessage propmsg) {
5961
proposeMessageHandler(propmsg);
6062
} else if (message instanceof XRPLSubmitMessage submsg) {
6163
submitMessageHandler(submsg);
@@ -511,11 +513,4 @@ private void playbackProposals() {
511513
}
512514
}
513515
}
514-
515-
@Override
516-
public void handleClientRequest(String clientId, Serializable request) throws Exception {
517-
String tx = request.toString();
518-
XRPLTxMessage txmsg = new XRPLTxMessage(tx, clientId);
519-
this.handleMessage(clientId, txmsg);
520-
}
521516
}

simulator/src/main/java/byzzbench/simulator/protocols/dummy/DummyReplica.java

-7
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
import lombok.ToString;
1010
import lombok.extern.java.Log;
1111

12-
import java.io.Serializable;
13-
1412
@Log
1513
@ToString(callSuper = true)
1614
public class DummyReplica extends Replica {
@@ -23,11 +21,6 @@ public void initialize() {
2321
// nothing to do
2422
}
2523

26-
@Override
27-
public void handleClientRequest(String clientId, Serializable request) {
28-
throw new UnsupportedOperationException("Unsupported operation: handleClientRequest");
29-
}
30-
3124
@Override
3225
public void handleMessage(String sender, MessagePayload m) {
3326
if (m instanceof DefaultClientRequestPayload clientRequestMessage) {

simulator/src/main/java/byzzbench/simulator/protocols/fasthotstuff/FastHotStuffReplica.java

-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import lombok.Getter;
99
import lombok.extern.java.Log;
1010

11-
import java.io.Serializable;
1211
import java.time.Duration;
1312
import java.util.*;
1413
import java.util.concurrent.atomic.AtomicLong;
@@ -50,11 +49,6 @@ public void initialize() {
5049
this.resetTimeout();
5150
}
5251

53-
@Override
54-
public void handleClientRequest(String clientId, Serializable request) throws Exception {
55-
throw new UnsupportedOperationException("Client requests not supported in FastHotStuff");
56-
}
57-
5852
private void createGenesisBlocks() {
5953
List<String> nodeIds = this.getNodeIds().stream().sorted().toList();
6054

simulator/src/main/java/byzzbench/simulator/protocols/hbft/HbftReplica.java

-7
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import lombok.ToString;
99
import lombok.extern.java.Log;
1010

11-
import java.io.Serializable;
12-
1311
/**
1412
* A Replica in the hBFT protocol.
1513
* <p>
@@ -42,11 +40,6 @@ public void initialize() {
4240
// TODO
4341
}
4442

45-
@Override
46-
public void handleClientRequest(String clientId, Serializable request) throws Exception {
47-
// TODO
48-
}
49-
5043
@Override
5144
public void handleMessage(String sender, MessagePayload m) {
5245
// TODO

simulator/src/main/java/byzzbench/simulator/protocols/pbft/PbftReplica.java

-10
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import lombok.Getter;
1111
import lombok.extern.java.Log;
1212

13-
import java.io.Serializable;
1413
import java.time.Duration;
1514
import java.time.Instant;
1615
import java.util.*;
@@ -440,15 +439,6 @@ public String primary(long vi) {
440439
return (vi == v) ? this.cur_primary : replicaIds[(int) (vi % replicaIds.length)];
441440
}
442441

443-
@Override
444-
public void handleClientRequest(String clientId, Serializable request) throws Exception {
445-
if (request instanceof RequestMessage) {
446-
this.handleMessage(clientId, (RequestMessage) request);
447-
} else {
448-
throw new UnsupportedOperationException("Unknown request type: " + request.getClass().getName());
449-
}
450-
}
451-
452442
@Override
453443
public void handleMessage(String sender, MessagePayload message) throws Exception {
454444
// for some reason the original code does this before receiving a message.

simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/PbftJavaReplica.java

-1
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,6 @@ public Serializable compute(long sequenceNumber, LogEntry operation) {
720720
return operation;
721721
}
722722

723-
@Override
724723
public void handleClientRequest(String clientId, Serializable request) {
725724
// FIXME: should not get timestamp from system time
726725
RequestMessage m = new RequestMessage(request, System.currentTimeMillis(), clientId);

simulator/src/main/java/byzzbench/simulator/scheduler/RandomScheduler.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public synchronized Optional<EventDecision> scheduleNext(Scenario scenario) thro
4747

4848
// if there are no events, return empty
4949
if (availableEvents.isEmpty()) {
50-
log.warning("No actions available!");
50+
log.warning("No queued events (messages, timeouts)!");
5151
return Optional.empty();
5252
}
5353

simulator/src/main/java/byzzbench/simulator/scheduler/twins/TwinsReplica.java

-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import lombok.Getter;
99
import lombok.extern.java.Log;
1010

11-
import java.io.Serializable;
1211
import java.util.ArrayList;
1312
import java.util.List;
1413
import java.util.Random;
@@ -129,11 +128,6 @@ private Replica getInternalReplicaFromId(String id) {
129128
return replicas.get(index);
130129
}
131130

132-
@Override
133-
public void handleClientRequest(String clientId, Serializable request) {
134-
throw new UnsupportedOperationException("Not implemented");
135-
}
136-
137131
/**
138132
* Get the internal replicas that should handle the given message.
139133
*

simulator/src/main/java/byzzbench/simulator/service/SimulatorService.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import byzzbench.simulator.Scenario;
44
import byzzbench.simulator.config.ByzzBenchConfig;
5+
import byzzbench.simulator.scheduler.EventDecision;
56
import byzzbench.simulator.state.ErroredPredicate;
67
import byzzbench.simulator.transport.Event;
78
import byzzbench.simulator.transport.messages.MessageWithRound;
@@ -19,6 +20,7 @@
1920
import java.nio.file.Files;
2021
import java.nio.file.Path;
2122
import java.time.Instant;
23+
import java.util.Optional;
2224
import java.util.OptionalLong;
2325
import java.util.Set;
2426
import java.util.concurrent.ExecutorService;
@@ -128,7 +130,30 @@ public void start() {
128130

129131
try {
130132
while (true) {
131-
this.scenario.getScheduler().scheduleNext(this.scenario);
133+
Optional<EventDecision> decision = this.scenario.getScheduler().scheduleNext(this.scenario);
134+
System.out.println("Decision: " + decision);
135+
136+
// if the scheduler did not make a decision, and we're before GST, set GST!
137+
if (decision.isEmpty() && !this.scenario.getTransport().isGlobalStabilizationTime()) {
138+
this.scenario.getTransport().globalStabilizationTime();
139+
continue;
140+
}
141+
142+
if (decision.isEmpty()) {
143+
System.out.println("We're after GST and still no events!!");
144+
// print num of events in the scenario
145+
System.out.println("Number of events in the scenario: " + this.scenario.getSchedule().getEvents().size());
146+
// print number of delivered events
147+
System.out.println("Number of delivered events: " + this.scenario.getTransport().getEventsInState(Event.Status.DELIVERED).size());
148+
// print ALL events in the scenario, independent of their status
149+
System.out.println("All events in the scenario:");
150+
this.scenario.getTransport().getEvents().values().forEach(System.out::println);
151+
// print the event IDs in the schedule
152+
System.out.println("Event IDs in the schedule:");
153+
this.scenario.getSchedule().getEvents().forEach(e -> System.out.println(e.getEventId()));
154+
this.shouldStop = true;
155+
break;
156+
}
132157

133158
long numEvents = this.scenario.getSchedule().getEvents().size();
134159
long terminationSamplingFreq = this.byzzBenchConfig.getScenario().getTermination().getSamplingFrequency();

simulator/src/main/java/byzzbench/simulator/state/LivenessPredicate.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@ public String getId() {
1515

1616
@Override
1717
public boolean test(Scenario scenarioExecutor) {
18-
boolean hasNoQueuedEvents = scenarioExecutor.getTransport().getEventsInState(Event.Status.QUEUED).isEmpty();
19-
if (hasNoQueuedEvents) {
18+
// If we are before GST, the scenario is considered live
19+
if (!scenarioExecutor.getTransport().isGlobalStabilizationTime()) {
20+
return true;
21+
}
22+
23+
boolean hasQueuedEvents = !(scenarioExecutor.getTransport().getEventsInState(Event.Status.QUEUED).isEmpty());
24+
if (!hasQueuedEvents) {
2025
System.out.println("LivenessPredicate: No events in the QUEUED state");
2126
}
22-
return !hasNoQueuedEvents;
27+
return hasQueuedEvents;
2328
}
2429
}

simulator/src/main/java/byzzbench/simulator/transport/BaseEvent.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ public abstract class BaseEvent implements Event {
3737
private Status status = Status.QUEUED;
3838

3939
public void setStatus(Status status) {
40-
if (this.status != Status.QUEUED) {
41-
throw new IllegalStateException("Can only change the status of a queued event");
42-
}
40+
// XXX during GST, dropped messages are re-queued
41+
//if (this.status != Status.QUEUED) {
42+
// throw new IllegalStateException("Can only change the status of a queued event");
43+
//}
4344
this.status = status;
4445
}
4546
}

simulator/src/main/java/byzzbench/simulator/transport/BaseMessageEvent.java

+2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
import byzzbench.simulator.utils.NonNull;
44
import lombok.Data;
55
import lombok.EqualsAndHashCode;
6+
import lombok.ToString;
67
import lombok.experimental.SuperBuilder;
78

89
import java.io.Serializable;
910

1011
@EqualsAndHashCode(callSuper = true)
1112
@Data
1213
@SuperBuilder
14+
@ToString(callSuper = true)
1315
public abstract class BaseMessageEvent<T extends Serializable> extends BaseEvent implements MailboxEvent {
1416
/**
1517
* The unique identifier of the receiving node

simulator/src/main/java/byzzbench/simulator/transport/ClientRequestEvent.java

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.fasterxml.jackson.annotation.JsonTypeName;
44
import lombok.Data;
55
import lombok.EqualsAndHashCode;
6+
import lombok.ToString;
67
import lombok.experimental.SuperBuilder;
78

89
/**
@@ -14,5 +15,6 @@
1415
@Data
1516
@JsonTypeName("ClientRequest")
1617
@SuperBuilder
18+
@ToString(callSuper = true)
1719
public class ClientRequestEvent extends BaseMessageEvent<MessagePayload> {
1820
}

simulator/src/main/java/byzzbench/simulator/transport/Event.java

+3
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@
2222
public interface Event extends Serializable {
2323
/**
2424
* Get the eventId
25+
*
2526
* @return a long representing the eventId
2627
*/
2728
@NonNull
2829
long getEventId();
2930

3031
/**
3132
* Get the time at which the event was created
33+
*
3234
* @return an Instant representing the time at which the event was created
3335
*/
3436
Instant getCreatedAt();
3537

3638
/**
3739
* Get the time at which the event was delivered
40+
*
3841
* @return an Instant representing the time at which the event was delivered
3942
*/
4043
Instant getDeliveredAt();

simulator/src/main/java/byzzbench/simulator/transport/GenericFaultEvent.java

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.fasterxml.jackson.annotation.JsonTypeName;
55
import lombok.Data;
66
import lombok.EqualsAndHashCode;
7+
import lombok.ToString;
78
import lombok.experimental.SuperBuilder;
89

910
/**
@@ -15,6 +16,7 @@
1516
@Data
1617
@JsonTypeName("GenericFault")
1718
@SuperBuilder
19+
@ToString(callSuper = true)
1820
public class GenericFaultEvent extends BaseEvent {
1921
/**
2022
* The payload of the request.

0 commit comments

Comments
 (0)