Skip to content

Commit eebf5c1

Browse files
committed
fix: list delivered events in order of delivery
1 parent b1143dc commit eebf5c1

File tree

5 files changed

+43
-12
lines changed

5 files changed

+43
-12
lines changed

docs/implementing-protocols.md

+25-9
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,30 @@ This document describes the steps to implement a new BFT protocol in ByzzBench.
44

55
A BFT Protocol implementation in ByzzBench consists of the following components:
66

7-
- A protocol replica that *extends* `Replica<T>`: these are the nodes that run the protocol and communicate with each other
7+
- A protocol replica that *extends* [`Replica<T>`](../simulator/src/main/java/byzzbench/simulator/Replica.java): these
8+
are the nodes that run the protocol and communicate with each other
89
via messages. `T` is the type of each of the entries in the commit log (this should be simplified!).
9-
- Example: [PBFT-Java Replica](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/PbftReplica.java)
10-
- The `Replica` constructor requires a `replicaId`, `nodeIds` (set of all replica IDs in the *cluster*), `transport` (the virtualized network instance) and a `commitLog` (instance where all committed operations from the replica are sent to).
11-
- A set of protocol message POJOs that *implement* `MessagePayload`: these are the messages that are exchanged between replicas.
12-
- They just need to have a `String getType()` method that returns e.g. that it is a `PREPARE` message.
13-
- Examples from PBFT-Java: [Checkpoint](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/CheckpointMessage.java), [Commit](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/CommitMessage.java), [NewView](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/NewViewMessage.java), [Phase](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/PhaseMessage.java), [Prepare](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/PrepareMessage.java), [PrePrepare](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/PrePrepareMessage.java), [Reply](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/ReplyMessage.java), [Request](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/RequestMessage.java), [ViewChange](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/ViewChangeMessage.java)
10+
- Example: [PBFT-Java Replica](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/PbftReplica.java)
11+
- The `Replica` constructor requires a `replicaId`, `nodeIds` (set of all replica IDs in the
12+
*cluster*), `transport` (the virtualized network instance) and a `commitLog` (instance where all committed
13+
operations from the replica are sent to).
14+
- A set of protocol message POJOs that
15+
*implement* [`MessagePayload`](../simulator/src/main/java/byzzbench/simulator/transport/MessagePayload.java): these
16+
are the messages that are exchanged between
17+
replicas.
18+
- They just need to have a `String getType()` method that returns e.g. that it is a `PREPARE` message.
19+
- Examples from
20+
PBFT-Java: [Checkpoint](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/CheckpointMessage.java), [Commit](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/CommitMessage.java), [NewView](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/NewViewMessage.java), [Phase](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/PhaseMessage.java), [Prepare](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/PrepareMessage.java), [PrePrepare](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/PrePrepareMessage.java), [Reply](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/ReplyMessage.java), [Request](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/RequestMessage.java), [ViewChange](../simulator/src/main/java/byzzbench/simulator/protocols/pbft_java/message/ViewChangeMessage.java)
1421

1522
## Communication and Timeouts
1623

17-
Communication between replicas is done via message-passing through the `Transport`. The `Replica` superclass exposes a few methods:
24+
Using the Actor model, replicas communicate with each other via
25+
a [`Transport`](../simulator/src/main/java/byzzbench/simulator/transport) instance.
26+
The `Transport` is a virtualized network that allows replicas to send messages to each other.
27+
The `Transport` is responsible for delivering messages to the correct recipient, and also for handling timeouts.
28+
29+
Communication between replicas is done via message-passing through the `Transport`. The `Replica` superclass exposes a
30+
few methods:
1831

1932
- `sendMessage`: send a message to a recipient
2033
- `multicastMessage`: send a message to a set of replicas
@@ -23,9 +36,12 @@ Communication between replicas is done via message-passing through the `Transpor
2336

2437
Timeouts are implemented via callbacks to a `Runnable`, also handled by the `Transport`:
2538

26-
- `setTimeout(Runnable, timeout)`: Creates a timeout event of `timeout` milliseconds, which will then invoke the `Runnable`. The time is currently being ignored, and is instead triggered just like any other event by the scheduler.
39+
- `setTimeout(Runnable, timeout)`: Creates a timeout event of `timeout` milliseconds, which will then invoke
40+
the `Runnable`. The time is currently being ignored, and is instead triggered just like any other event by the
41+
scheduler.
2742
- `clearAllTimeouts()`: Invalidates all outstanding timeouts for the current replica.
2843

2944
## Commit Log
3045

31-
Each replica has its own instance of a `CommitLog`: an immutable and total ordered sequence of records. This is used to check whether safety invariants of distributed consensus are broken.
46+
Each replica has its own instance of a `CommitLog`: an immutable and total ordered sequence of records. This is used to
47+
check whether safety invariants of distributed consensus are broken.

simulator/src/main/java/byzzbench/simulator/controller/SimulatorController.java

+9
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ public List<Long> getDeliveredMessages() {
8080
.toList();
8181
}
8282

83+
@GetMapping("/schedule")
84+
public List<Long> getSchedule() {
85+
return simulatorService.getScenarioExecutor().getTransport()
86+
.getSchedule()
87+
.stream()
88+
.map(Event::getEventId)
89+
.toList();
90+
}
91+
8392
@GetMapping("/event/{eventId}")
8493
public Event getMessage(@PathVariable Long eventId) {
8594
return simulatorService.getScenarioExecutor().getTransport().getEvents().get(eventId);

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

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ public class Transport<T extends Serializable> {
2323
@JsonIgnore
2424
private final Map<Long, Event> events = new TreeMap<>();
2525

26+
@Getter(onMethod_ = {@Synchronized})
27+
private final List<Event> schedule = new ArrayList<>();
28+
2629
@Getter(onMethod_ = {@Synchronized})
2730
@JsonIgnore
2831
private final Map<Long, MessageMutator> mutators = new TreeMap<>();
@@ -90,7 +93,10 @@ public void deliverEvent(long eventId) throws Exception {
9093
throw new RuntimeException("Event not in QUEUED state");
9194
}
9295

96+
// deliver the event
97+
this.schedule.add(e);
9398
e.setStatus(Event.Status.DELIVERED);
99+
94100
switch (e) {
95101
case MessageEvent m -> nodes.get(m.getRecipientId()).handleMessage(m.getSenderId(), m.getPayload());
96102
case TimeoutEvent t -> t.getTask().run();

webui/app/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export default function Home() {
2222
<Title order={3}>Nodes</Title>
2323
<NodeList />
2424
<br />
25-
<Title order={3}>Delivered Messages</Title>
25+
<Title order={3}>Schedule</Title>
2626
<DeliveredMessagesList />
2727
<br />
2828
<Title order={3}>Dropped Messages</Title>
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"use client";
22

33
import { MessagesList } from "@/components/messages/MessagesList";
4-
import { useGetDeliveredMessages } from "@/lib/byzzbench-client/generated";
4+
import { useGetSchedule } from "@/lib/byzzbench-client";
55
import React from "react";
66

77
export const DeliveredMessagesList = () => {
8-
const { data } = useGetDeliveredMessages({ query: { retry: true } });
8+
const { data } = useGetSchedule({ query: { retry: true } });
99
return <MessagesList messageIds={data?.data ?? []} />;
1010
};

0 commit comments

Comments
 (0)