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
161 changes: 161 additions & 0 deletions demo/proto-devnet/config/dashboards/proto-devnet-throughput.json
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,167 @@
}
],
"type": "timeseries"
},
{
"id": 5,
"type": "histogram",
"title": "Announcement age upon arrival",
"gridPos": {
"x": 0,
"y": 16,
"h": 8,
"w": 12
},
"fieldConfig": {
"defaults": {
"custom": {
"stacking": {
"mode": "normal",
"group": "A"
},
"lineWidth": 1,
"fillOpacity": 80,
"gradientMode": "none",
"hideFrom": {
"tooltip": false,
"viz": false,
"legend": false
}
},
"color": {
"mode": "palette-classic-by-name"
},
"unit": "s",
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "age Node1"
},
"properties": [
{
"id": "color",
"value": {
"mode": "fixed",
"fixedColor": "#5794F2"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "age Node2"
},
"properties": [
{
"id": "color",
"value": {
"mode": "fixed",
"fixedColor": "#FF9830"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "age Node3"
},
"properties": [
{
"id": "color",
"value": {
"mode": "fixed",
"fixedColor": "#73BF69"
}
}
]
}
]
},
"transformations": [
{
"id": "extractFields",
"options": {
"delimiter": ",",
"format": "json",
"jsonPaths": [
{
"path": "age"
},
{
"path": "instance"
}
],
"source": "labels"
}
},
{
"id": "convertFieldType",
"options": {
"conversions": [
{
"destinationType": "number",
"targetField": "age"
}
],
"fields": {}
}
},
{
"id": "partitionByValues",
"options": {
"fields": [
"instance"
],
"keepFields": false
}
}
],
"pluginVersion": "12.3.1",
"targets": [
{
"datasource": {
"type": "loki",
"uid": "P8E80F9AEF21F6940"
},
"direction": "backward",
"editorMode": "code",
"expr": "{kind=\"LeiosAnnouncementAccepted\"} | json age=\"announcementAgeSeconds\" | age != \"\"",
"legendFormat": "{{instance}}",
"queryType": "range",
"refId": "A"
}
],
"datasource": {
"type": "loki",
"uid": "P8E80F9AEF21F6940"
},
"options": {
"tooltip": {
"mode": "single",
"sort": "none",
"hideZeros": false
},
"legend": {
"showLegend": true,
"displayMode": "list",
"placement": "bottom",
"calcs": []
}
}
}
],
"preload": false,
Expand Down
17 changes: 14 additions & 3 deletions demo/proto-devnet/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ fi
# X-ray observability (on by default, disable with XRAY=0)
: "${XRAY:=1}"
: "${XRAY_SOURCE_DIR:="${SOURCE_DIR}/../extras/x-ray"}"
# Network topology: "mesh" (default, all-to-all) or "line" (Node1-Node2-Node3
# with no direct Node1<->Node3 edge, so Node2 is the only path between the
# ends). Opt in with TOPOLOGY=line.
: "${TOPOLOGY:=mesh}"
set +a

# Check for required commands
Expand Down Expand Up @@ -119,10 +123,16 @@ for i in "${nodes[@]}"; do
yq ".TraceOptions.\"\".backends[1] = \"PrometheusSimple 0.0.0.0 $((12900 + "$i"))\"" \
>"$NODE_DIR/config.yaml"

# Generate upstream endpoints to other nodes
# Generate upstream endpoints. "mesh": every other node. "line": only
# adjacent nodes (|i-j| == 1), i.e. Node1-Node2-Node3 with no Node1<->Node3.
# These localRoots are the whole enforcement: config.yaml sets
# PeerSharing: false with no public/ledger peers, so a node only ever
# connects to the peers listed here (re-enabling PeerSharing would let the
# line collapse back toward a mesh).
accessPoints=$(for j in "${nodes[@]}"; do
# Except self
if [ "$i" -ne "$j" ]; then
absdiff=$((i - j)); absdiff=${absdiff#-}
if { [ "$TOPOLOGY" = "line" ] && [ "$absdiff" -eq 1 ]; } \
|| { [ "$TOPOLOGY" != "line" ] && [ "$i" -ne "$j" ]; }; then
port="PORT_NODE$j"
address="IP_NODE$j"
echo "{ \"port\": ${!port}, \"address\": \"${!address}\" }"
Expand Down Expand Up @@ -154,6 +164,7 @@ export ALLOY_CONFIG="${WORKING_DIR}/config.alloy"
envsubst <"${CONFIG_DIR}/alloy.template" >"${ALLOY_CONFIG}"

echo "Starting proto-devnet ..."
echo " Topology: ${TOPOLOGY}"
# Traffic control integration
TC_COMPOSE=()
if [ "$TC" = "1" ]; then
Expand Down
27 changes: 26 additions & 1 deletion ui/schema/trace.ui.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,29 @@ export interface UITxsReceived {
num_txs?: number;
}

// --- Network: EB announcements (prototype only) ---------------------------

/** Sent event for a `MsgLeiosBlockAnnouncement` relay hop over LeiosNotify.
* The message is an RB header; `id`/`slot` identify the EB it announces, so
* an announcement's diffusion can be linked to its endorser block. */
export interface UIAnnouncementSent {
type: "AnnouncementSent";
/** Hash of the announced EB, extracted from the relayed RB header. */
id: string;
sender: string;
recipient: string;
/** Slot of the announced EB. */
slot: number;
}

export interface UIAnnouncementReceived {
type: "AnnouncementReceived";
id: string;
recipient: string;
sender?: string;
slot: number;
}

// --- Union ----------------------------------------------------------------

/** Union of every message shape the UI renders. */
Expand All @@ -227,7 +250,9 @@ export type UIMessage =
| UIRBReceived
| UIEBReceived
| UIVotesReceived
| UITxsReceived;
| UITxsReceived
| UIAnnouncementSent
| UIAnnouncementReceived;

/** Set of `message.type` strings the UI renders — also used by CI to filter
* a trace before validating it against this schema. */
Expand Down
18 changes: 16 additions & 2 deletions ui/src/components/Graph/hooks/useHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const getHighestPriorityMessageType = (counts: {
const MESSAGE_PRIORITY_ORDER = [
EMessageType.RB, // Highest priority
EMessageType.EB,
EMessageType.Announcement,
EMessageType.Votes,
EMessageType.Txs, // Lowest priority
];
Expand Down Expand Up @@ -151,6 +152,9 @@ export const useHandlers = () => {
case EMessageType.Votes:
context.strokeStyle = EMessageColor.VOTES;
break;
case EMessageType.Announcement:
context.strokeStyle = EMessageColor.ANNOUNCEMENT;
break;
default:
context.strokeStyle = ELinkColor.LINK_DEFAULT;
}
Expand Down Expand Up @@ -213,6 +217,9 @@ export const useHandlers = () => {
case EMessageType.Votes:
context.fillStyle = EMessageColor.VOTES;
break;
case EMessageType.Announcement:
context.fillStyle = EMessageColor.ANNOUNCEMENT;
break;
default:
context.fillStyle = node.data.stake
? ENodeColor.STAKE_NODE
Expand Down Expand Up @@ -256,10 +263,17 @@ export const useHandlers = () => {
case EMessageType.RB:
context.fillStyle = EMessageColor.RB;
break;
case EMessageType.Announcement:
context.fillStyle = EMessageColor.ANNOUNCEMENT;
break;
}

// Votes: draw as small circles (fixed size, no bandwidth scaling)
if (message.type === EMessageType.Votes) {
// Votes and announcements: small fixed-size circles (no bandwidth
// scaling) — both are lightweight control messages, not bulk data.
if (
message.type === EMessageType.Votes ||
message.type === EMessageType.Announcement
) {
const radius = Math.min((0.4 / canvasScale) * 6, 0.4);
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI);
Expand Down
2 changes: 2 additions & 0 deletions ui/src/components/Graph/modules/EdgeStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ const messageTypeColor: Record<EMessageType, string> = {
[EMessageType.EB]: EMessageColor.EB,
[EMessageType.Votes]: EMessageColor.VOTES,
[EMessageType.RB]: EMessageColor.RB,
[EMessageType.Announcement]: EMessageColor.ANNOUNCEMENT,
};

const messageTypeLabel: Record<EMessageType, string> = {
[EMessageType.Txs]: "Tx",
[EMessageType.EB]: "EB",
[EMessageType.Votes]: "Vote",
[EMessageType.RB]: "RB",
[EMessageType.Announcement]: "Announce",
};

const shortBits = (bytes: number): string => {
Expand Down
5 changes: 5 additions & 0 deletions ui/src/components/Graph/modules/NodeStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ export const NodeStats: FC = () => {
{ name: "Endorser Blocks", ...getCounts(EMessageType.EB), color: EMessageColor.EB },
{ name: "Votes", ...getCounts(EMessageType.Votes), color: EMessageColor.VOTES },
{ name: "Blocks", ...getCounts(EMessageType.RB), color: EMessageColor.RB },
{
name: "Announcements",
...getCounts(EMessageType.Announcement),
color: EMessageColor.ANNOUNCEMENT,
},
];

return (
Expand Down
Loading
Loading