Skip to content

Commit f363717

Browse files
Seed for leader (#14)
* progress * fix seed selection * add network key * fix legend
1 parent 66dbc08 commit f363717

File tree

9 files changed

+158
-66
lines changed

9 files changed

+158
-66
lines changed

chain/src/actors/application/supervisor.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use alto_types::leader_index;
12
use commonware_consensus::{
23
threshold_simplex::View, Activity, Proof, Supervisor as Su, ThresholdSupervisor as TSu,
34
};
@@ -8,7 +9,6 @@ use commonware_cryptography::{
89
},
910
ed25519::PublicKey,
1011
};
11-
use commonware_utils::modulo;
1212
use std::collections::HashMap;
1313

1414
/// Implementation of `commonware-consensus::Supervisor`.
@@ -73,8 +73,8 @@ impl TSu for Supervisor {
7373

7474
fn leader(&self, _: Self::Index, seed: Self::Seed) -> Option<Self::PublicKey> {
7575
let seed = seed.serialize();
76-
let index = modulo(&seed, self.participants.len() as u64);
77-
Some(self.participants[index as usize].clone())
76+
let index = leader_index(&seed, self.participants.len());
77+
Some(self.participants[index].clone())
7878
}
7979

8080
fn identity(&self, _: Self::Index) -> Option<&Self::Identity> {

explorer/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
```bash
88
cd ../types
99
wasm-pack build --release --target web
10-
mv pkg/alto_types.js ../explorer/public
11-
mv pkg/alto_types_bg.wasm ../explorer/public
10+
mv pkg/alto_types.js ../explorer/src/alto_types
11+
mv pkg/alto_types_bg.wasm ../explorer/src/alto_types
1212
cd ../explorer
1313
```
1414

explorer/src/App.css

Lines changed: 101 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -75,24 +75,25 @@ body {
7575
.legend-container {
7676
display: flex;
7777
flex-wrap: wrap;
78-
gap: 12px;
79-
margin-bottom: 16px;
80-
padding: 10px;
81-
background: white;
82-
border: 1px solid #ccc;
78+
gap: 8px;
8379
font-family: 'Consolas', monospace;
80+
justify-content: flex-end;
8481
}
8582

8683
.legend-item {
8784
display: flex;
8885
align-items: center;
8986
gap: 5px;
87+
padding: 2px 6px;
88+
border-radius: 0;
89+
background-color: #fafafa;
90+
border: 1px solid #eee;
9091
}
9192

9293
.legend-color {
9394
width: 12px;
9495
height: 12px;
95-
border: 1px solid black;
96+
border: 1px solid #888;
9697
}
9798

9899
.legend-label {
@@ -101,6 +102,15 @@ body {
101102
}
102103

103104
/* Bars container */
105+
.bars-header {
106+
display: flex;
107+
justify-content: space-between;
108+
align-items: center;
109+
margin-bottom: 16px;
110+
flex-wrap: wrap;
111+
gap: 12px;
112+
}
113+
104114
.bars-container {
105115
background: white;
106116
border: 1px solid #ccc;
@@ -111,7 +121,7 @@ body {
111121
}
112122

113123
.bars-title {
114-
margin: 0 0 16px 0;
124+
margin: 0;
115125
font-size: 18px;
116126
font-weight: normal;
117127
font-family: 'Consolas', monospace;
@@ -286,15 +296,6 @@ body {
286296
margin-bottom: 20px;
287297
}
288298

289-
.legend-label {
290-
font-size: 14px;
291-
}
292-
293-
.bars-title {
294-
font-size: 20px;
295-
margin-bottom: 20px;
296-
}
297-
298299
.bar-row {
299300
margin-bottom: 20px;
300301
}
@@ -311,6 +312,22 @@ body {
311312
.view-signature {
312313
font-size: 12px;
313314
}
315+
316+
.bars-header {
317+
margin-bottom: 20px;
318+
}
319+
320+
.bars-title {
321+
font-size: 20px;
322+
}
323+
324+
.legend-label {
325+
font-size: 14px;
326+
}
327+
328+
.legend-item {
329+
padding: 2px 8px;
330+
}
314331
}
315332

316333
@media (max-width: 480px) {
@@ -326,25 +343,10 @@ body {
326343
height: 250px;
327344
}
328345

329-
.legend-container {
330-
justify-content: space-between;
331-
gap: 6px;
332-
padding: 8px;
333-
}
334-
335-
.legend-item {
336-
font-size: 10px;
337-
}
338-
339346
.bars-container {
340347
padding: 10px 4px 10px 12px;
341348
}
342349

343-
.bars-title {
344-
font-size: 16px;
345-
margin-bottom: 12px;
346-
}
347-
348350
.bar-row {
349351
margin-bottom: 12px;
350352
width: 100%;
@@ -380,6 +382,38 @@ body {
380382
.latency-text {
381383
font-size: 9px;
382384
}
385+
386+
.bars-header {
387+
flex-direction: column;
388+
align-items: flex-start;
389+
margin-bottom: 12px;
390+
gap: 8px;
391+
}
392+
393+
.bars-title {
394+
font-size: 16px;
395+
}
396+
397+
.legend-container {
398+
width: 100%;
399+
justify-content: flex-start;
400+
flex-wrap: wrap;
401+
gap: 6px;
402+
}
403+
404+
.legend-item {
405+
font-size: 10px;
406+
padding: 1px 4px;
407+
}
408+
409+
.legend-color {
410+
width: 10px;
411+
height: 10px;
412+
}
413+
414+
.legend-label {
415+
font-size: 10px;
416+
}
383417
}
384418

385419
/* Fix for Leaflet popups */
@@ -402,4 +436,40 @@ body {
402436
/* Style override for map tiles to use monochrome */
403437
.leaflet-tile {
404438
filter: grayscale(100%) !important;
439+
}
440+
441+
/* Public Key Display */
442+
.public-key-display {
443+
background-color: #f4f4f4;
444+
border: 1px solid #ddd;
445+
padding: 8px;
446+
margin-bottom: 16px;
447+
word-break: break-all;
448+
font-size: 12px;
449+
display: flex;
450+
align-items: center;
451+
}
452+
453+
.public-key-label {
454+
font-weight: bold;
455+
margin-right: 8px;
456+
white-space: nowrap;
457+
}
458+
459+
.public-key-value {
460+
color: #333;
461+
overflow: hidden;
462+
text-overflow: ellipsis;
463+
}
464+
465+
@media (max-width: 480px) {
466+
.public-key-display {
467+
flex-direction: column;
468+
align-items: flex-start;
469+
gap: 4px;
470+
}
471+
472+
.public-key-label {
473+
margin-right: 0;
474+
}
405475
}

explorer/src/App.tsx

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import React, { useEffect, useState, useRef } from "react";
22
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
33
import { LatLng, DivIcon } from "leaflet";
44
import "leaflet/dist/leaflet.css";
5-
import init, { parse_seed, parse_notarized, parse_finalized } from "./alto_types/alto_types.js";
6-
import { WS_URL, PUBLIC_KEY, LOCATIONS } from "./config";
5+
import init, { parse_seed, parse_notarized, parse_finalized, leader_index } from "./alto_types/alto_types.js";
6+
import { WS_URL, PUBLIC_KEY, LOCATIONS, PUBLIC_KEY_HEX } from "./config";
77
import { SeedJs, NotarizedJs, FinalizedJs, BlockJs } from "./types";
88
import "./App.css";
99

1010
type ViewStatus = "growing" | "notarized" | "finalized" | "timed_out";
1111

1212
interface ViewData {
1313
view: number;
14-
location: [number, number];
15-
locationName: string;
14+
location?: [number, number];
15+
locationName?: string;
1616
status: ViewStatus;
1717
startTime: number;
1818
notarizationTime?: number;
@@ -200,17 +200,15 @@ const App: React.FC = () => {
200200

201201
// Add any missed views as skipped/timed out
202202
for (let missedView = startViewIndex; missedView < view; missedView++) {
203-
const locationIndex = missedView % LOCATIONS.length;
204-
205203
// Check if this view already exists
206204
const existingIndex = newViews.findIndex(v => v.view === missedView);
207205

208206
if (existingIndex === -1) {
209207
// Only add if it doesn't already exist
210208
newViews.unshift({
211209
view: missedView,
212-
location: LOCATIONS[locationIndex][0],
213-
locationName: LOCATIONS[locationIndex][1],
210+
location: undefined,
211+
locationName: undefined,
214212
status: "timed_out",
215213
startTime: Date.now(),
216214
});
@@ -235,7 +233,7 @@ const App: React.FC = () => {
235233
}
236234

237235
// Create the new view data
238-
const locationIndex = view % LOCATIONS.length;
236+
const locationIndex = leader_index(seed.signature, LOCATIONS.length);
239237
const newView: ViewData = {
240238
view,
241239
location: LOCATIONS[locationIndex][0],
@@ -316,11 +314,10 @@ const App: React.FC = () => {
316314
}
317315

318316
// If view doesn't exist, create it
319-
const locationIndex = view % LOCATIONS.length;
320317
return [{
321318
view,
322-
location: LOCATIONS[locationIndex][0],
323-
locationName: LOCATIONS[locationIndex][1],
319+
location: undefined,
320+
locationName: undefined,
324321
status: "notarized",
325322
startTime: Date.now(),
326323
notarizationTime: Date.now(),
@@ -361,11 +358,10 @@ const App: React.FC = () => {
361358
}
362359

363360
// If view doesn't exist, create it
364-
const locationIndex = view % LOCATIONS.length;
365361
return [{
366362
view,
367-
location: LOCATIONS[locationIndex][0],
368-
locationName: LOCATIONS[locationIndex][1],
363+
location: undefined,
364+
locationName: undefined,
369365
status: "finalized",
370366
startTime: Date.now(),
371367
finalizationTime: Date.now(),
@@ -422,14 +418,20 @@ const App: React.FC = () => {
422418
</header>
423419

424420
<main className="app-main">
421+
{/* Network Key */}
422+
<div className="public-key-display">
423+
<span className="public-key-label">Network Key:</span>
424+
<span className="public-key-value">{PUBLIC_KEY_HEX}</span>
425+
</div>
426+
425427
{/* Map */}
426428
<div className="map-container">
427429
<MapContainer center={center} zoom={isMobile ? 1 : 2} style={{ height: "100%", width: "100%" }}>
428430
<TileLayer
429431
url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png"
430432
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
431433
/>
432-
{views.length > 0 && (
434+
{views.length > 0 && views[0].location !== undefined && (
433435
<Marker
434436
key={views[0].view}
435437
position={views[0].location}
@@ -453,17 +455,17 @@ const App: React.FC = () => {
453455
</MapContainer>
454456
</div>
455457

456-
{/* Legend */}
457-
<div className="legend-container">
458-
<LegendItem color="#aaa" label="Notarization" />
459-
<LegendItem color="#d9ead3ff" label="Finalization" />
460-
<LegendItem color="#274e13ff" label="Finalized" />
461-
<LegendItem color="#f4ccccff" label="Skipped" />
462-
</div>
463-
464-
{/* Bars */}
458+
{/* Bars with integrated legend */}
465459
<div className="bars-container">
466-
<h2 className="bars-title">Consensus Views</h2>
460+
<div className="bars-header">
461+
<h2 className="bars-title">Views</h2>
462+
<div className="legend-container">
463+
<LegendItem color="#aaa" label="Notarization" />
464+
<LegendItem color="#d9ead3ff" label="Finalization" />
465+
<LegendItem color="#274e13ff" label="Finalized" />
466+
<LegendItem color="#f4ccccff" label="Skipped" />
467+
</div>
468+
</div>
467469
<div className="bars-list">
468470
{views.slice(0, 100).map((viewData) => (
469471
<Bar

explorer/src/alto_types/alto_types.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ export function parse_block(bytes) {
8383
return ret;
8484
}
8585

86+
/**
87+
* @param {Uint8Array} seed
88+
* @param {number} participants
89+
* @returns {number}
90+
*/
91+
export function leader_index(seed, participants) {
92+
const ptr0 = passArray8ToWasm0(seed, wasm.__wbindgen_malloc);
93+
const len0 = WASM_VECTOR_LEN;
94+
const ret = wasm.leader_index(ptr0, len0, participants);
95+
return ret >>> 0;
96+
}
97+
8698
async function __wbg_load(module, imports) {
8799
if (typeof Response === 'function' && module instanceof Response) {
88100
if (typeof WebAssembly.instantiateStreaming === 'function') {
326 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)