Skip to content

Commit d486f3e

Browse files
authored
Merge pull request #600 from input-output-hk/hjeljeli32/voting-demo
Leios's Voting Demo
2 parents 92b7fd1 + 27dd526 commit d486f3e

File tree

14 files changed

+3672
-0
lines changed

14 files changed

+3672
-0
lines changed

crypto-benchmarks.rs/.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
11
target/
22
*.cbor
33
*.txt
4+
5+
# Demo artifacts
6+
demo/**/*.pretty.json
7+
demo/**/*.json
8+
demo/**/*.png
9+
demo/**/*.csv
10+
demo/scripts/.env_cli
11+
12+
# Python cache
13+
__pycache__/
14+
*.pyc
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
2+
3+
# Demo Scripts for Leios Crypto Benchmarks
4+
5+
This folder contains scripts that orchestrate end-to-end demonstrations of BLS-based vote aggregation and certificate generation/verification for the Leios project.
6+
7+
## Prerequisites
8+
9+
- Ensure the CLI built from the repository root is available; see `crypto-benchmarks.rs/ReadMe.md` for build instructions and usage details.
10+
- Ensure Python 3 is available with `cbor2` installed.
11+
For example:
12+
13+
```bash
14+
python3 -m venv .venv
15+
source .venv/bin/activate
16+
pip install cbor2
17+
```
18+
19+
## Workflow
20+
21+
The scripts are designed to be run from the `demo/` directory.
22+
23+
### Run Step by Step (Manual Mode)
24+
25+
You can run each script individually to understand and control each step of the process for a given number of voters (e.g., 100). Use the `-d` option to specify the output directory (e.g., `run100`).
26+
27+
#### 10_init_inputs.sh
28+
29+
Initialize inputs for N voters:
30+
31+
```bash
32+
scripts/10_init_inputs.sh -d run100 --pools 500 --stake 100000 --alpha 9 --beta 1
33+
```
34+
35+
#### 20_make_registry.sh
36+
37+
Build the registry from initialized inputs:
38+
39+
```bash
40+
./scripts/20_make_registry.sh -d run100 -n 100
41+
```
42+
43+
#### 30_cast_votes.sh
44+
45+
Cast votes with a specified fraction of voters voting (e.g., 1.0 means all vote):
46+
47+
```bash
48+
scripts/30_cast_votes.sh -d run100 -f 0.75
49+
```
50+
51+
#### 40_make_certificate.sh
52+
53+
Generate the aggregated certificate:
54+
55+
```bash
56+
scripts/40_make_certificate.sh -d run100
57+
```
58+
59+
#### 50_verify_certificate.sh
60+
61+
Verify the generated certificate:
62+
63+
```bash
64+
scripts/50_verify_certificate.sh -d run100
65+
```
66+
67+
### Run a Single End-to-End Demo
68+
69+
```bash
70+
scripts/70_run_one.sh -d run100 -p 500 -n 100 -f 0.75
71+
```
72+
73+
This will:
74+
75+
1. Initialize inputs (`10_init_inputs.sh`)
76+
2. Build a registry (`20_make_registry.sh`)
77+
3. Cast votes (`30_cast_votes.sh`)
78+
4. Make a certificate (`40_make_certificate.sh`)
79+
5. Verify the certificate (`50_verify_certificate.sh`)
80+
6. Export data for the UI (`60_export_demo_json.sh`)
81+
82+
All files are placed in `demo/run100/`.
83+
84+
### Launch the Demo UI
85+
86+
After generating a demo run (for example via `scripts/70_run_one.sh`), start the UI server from this directory:
87+
88+
```bash
89+
python3 ui/server.py
90+
```
91+
92+
Then open your browser at [http://127.0.0.1:5050/ui](http://127.0.0.1:5050/ui) to explore the results.
93+
94+
## Notes
95+
96+
- All scripts must be run from within the `demo/` directory.
97+
- Directories passed via `-d` will be created automatically under `demo/`.
98+
- Compression ratio is defined as:
99+
100+
```
101+
votes_bytes / certificate_bytes
102+
```
103+
104+
which illustrates the storage/bandwidth savings achieved by BLS aggregation.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
# Usage: demo/scripts/00_set_cli.sh [-p /abs/path/to/leios_crypto_benchmarks]
4+
# Writes demo/scripts/.env_cli with an absolute CLI path so other scripts can source it.
5+
6+
DIR_SCRIPT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7+
ENV_FILE="$DIR_SCRIPT/.env_cli"
8+
CLI_PATH=""
9+
10+
while getopts ":p:" opt; do
11+
case "$opt" in
12+
p) CLI_PATH="$OPTARG" ;;
13+
*) echo "Usage: $0 [-p /abs/path/to/leios_crypto_benchmarks]"; exit 2 ;;
14+
esac
15+
done
16+
17+
if [[ -z "${CLI_PATH}" ]]; then
18+
read -r -p "Absolute path to leios_crypto_benchmarks binary: " CLI_PATH
19+
fi
20+
21+
if [[ ! -x "${CLI_PATH}" ]]; then
22+
echo "Error: '${CLI_PATH}' is not an executable file." >&2
23+
exit 1
24+
fi
25+
26+
mkdir -p "$DIR_SCRIPT"
27+
cat > "$ENV_FILE" <<EOF
28+
# Auto-generated by 00_set_cli.sh
29+
export CLI="${CLI_PATH}"
30+
EOF
31+
32+
echo "Saved CLI path to $ENV_FILE"
33+
echo "Example: source \"$ENV_FILE\" && \$CLI --help"
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
# Usage: demo/scripts/10_init_inputs.sh [-d DEMO_DIR] [--pools 5000] [--stake 100000] [--alpha 5] [--beta 1]
4+
DIR_SCRIPT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
source "$DIR_SCRIPT/.env_cli"
6+
7+
DEMO_DIR="$(cd "$DIR_SCRIPT/.." && pwd)"
8+
POOLS=500
9+
TOTAL_STAKE=1000000
10+
ALPHA=9
11+
BETA=1
12+
13+
while [[ $# -gt 0 ]]; do
14+
case "$1" in
15+
-d) DEMO_DIR="$2"; shift 2;;
16+
--pools) POOLS="$2"; shift 2;;
17+
--stake) TOTAL_STAKE="$2"; shift 2;;
18+
--alpha) ALPHA="$2"; shift 2;;
19+
--beta) BETA="$2"; shift 2;;
20+
*) echo "Unknown arg: $1"; exit 2;;
21+
esac
22+
done
23+
24+
mkdir -p "$DEMO_DIR"
25+
26+
echo "== [10_init_inputs] DIR=${DEMO_DIR} POOLS=${POOLS} TOTAL_STAKE=${TOTAL_STAKE} =="
27+
28+
pushd "$DEMO_DIR" >/dev/null
29+
"$CLI" gen-eid > eid.txt
30+
"$CLI" gen-eb-hash > ebhash.txt
31+
32+
"$CLI" gen-stake \
33+
--pool-count "${POOLS}" \
34+
--total-stake "${TOTAL_STAKE}" \
35+
--shape-alpha "${ALPHA}" \
36+
--shape-beta "${BETA}" \
37+
--stake-file stake.cbor
38+
39+
"$CLI" gen-pools \
40+
--stake-file stake.cbor \
41+
--pools-file pools.cbor
42+
43+
# Pretty-print some of the generated values
44+
echo "EID: $(cat eid.txt)"
45+
echo "EB Hash: $(cat ebhash.txt)"
46+
47+
# Print first 3 pools and their stakes from pools.cbor using cbor2
48+
PYTHON_EXEC="${VIRTUAL_ENV:+$VIRTUAL_ENV/bin/python}"
49+
PYTHON_EXEC="${PYTHON_EXEC:-python3}"
50+
"$PYTHON_EXEC" - <<'PY'
51+
import sys, os
52+
try:
53+
import cbor2
54+
except ImportError:
55+
print('cbor2 not installed! (pip install cbor2)', file=sys.stderr)
56+
sys.exit(1)
57+
58+
if not os.path.exists('pools.cbor'):
59+
print('pools.cbor not found', file=sys.stderr)
60+
sys.exit(1)
61+
62+
with open('pools.cbor', 'rb') as f:
63+
pools = cbor2.load(f)
64+
65+
print('First 3 pools and their stakes:')
66+
for i, entry in enumerate(pools[:3]):
67+
# Expected structure: {"secret": <bytes>, "reg": {"pool": "<hex>", ...}, "stake": <int>}
68+
reg = entry.get('reg', {})
69+
pool_id = reg.get('pool', '<unknown>')
70+
stake = entry.get('stake', '<unknown>')
71+
print(f' {i:>2}: pool={pool_id} stake={stake}')
72+
PY
73+
popd >/dev/null
74+
75+
echo "Initialized inputs in ${DEMO_DIR}"
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
3+
#!/usr/bin/env bash
4+
set -euo pipefail
5+
# Usage: demo/scripts/20_make_registry.sh -d RUN_DIR -n N
6+
# Example (from demo/): scripts/20_make_registry.sh -d run16 -n 16
7+
DIR_SCRIPT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8+
source "$DIR_SCRIPT/.env_cli"
9+
10+
RUN_DIR=""
11+
N=""
12+
13+
while [[ $# -gt 0 ]]; do
14+
case "$1" in
15+
-d) RUN_DIR="$2"; shift 2;;
16+
-n) N="$2"; shift 2;;
17+
*) echo "Usage: $0 -d RUN_DIR -n N"; exit 2;;
18+
esac
19+
done
20+
21+
if [[ -z "$RUN_DIR" || -z "$N" ]]; then
22+
echo "Error: need -d RUN_DIR and -n N" >&2; exit 2
23+
fi
24+
25+
RUN_DIR="$(cd "$DIR_SCRIPT/.."; cd "$RUN_DIR" && pwd)"
26+
echo "== [20_make_registry] DIR=${RUN_DIR} N=${N} =="
27+
28+
pushd "$RUN_DIR" >/dev/null
29+
"$CLI" make-registry \
30+
--pools-file pools.cbor \
31+
--voter-count "$N" \
32+
--registry-file registry.cbor
33+
popd >/dev/null
34+
35+
# --- Pretty-print a short registry summary for the audience ---
36+
PYTHON_EXEC="${VIRTUAL_ENV:+$VIRTUAL_ENV/bin/python}"
37+
PYTHON_EXEC="${PYTHON_EXEC:-python3}"
38+
pushd "$RUN_DIR" >/dev/null
39+
"$PYTHON_EXEC" - <<'PY'
40+
import sys, os
41+
try:
42+
import cbor2
43+
except ImportError:
44+
print("CBOR summary skipped (cbor2 not installed). Run: pip install cbor2", file=sys.stderr)
45+
raise SystemExit(0)
46+
47+
path = "registry.cbor"
48+
if not os.path.exists(path):
49+
print("CBOR summary skipped (registry.cbor missing).", file=sys.stderr)
50+
raise SystemExit(0)
51+
52+
c = cbor2.load(open(path, "rb"))
53+
54+
voters = c.get("voters")
55+
total_stake = c.get("total_stake")
56+
persistent_pool = c.get("persistent_pool") or {}
57+
info = c.get("info") or {}
58+
59+
print("Registry summary:")
60+
print(f" Seats requested (N): {voters}")
61+
print(f" Persistent seats: {len(persistent_pool)}")
62+
print(f" Total stake: {total_stake}")
63+
64+
# Top 3 stakepools by stake (from .info)
65+
tops = []
66+
for pool_id, rec in info.items():
67+
stake = rec.get("stake")
68+
if isinstance(stake, int):
69+
tops.append((stake, pool_id))
70+
tops.sort(reverse=True)
71+
tops = tops[:3]
72+
73+
if tops:
74+
print(" Top 3 stakepools by stake:")
75+
for i, (stake, pool) in enumerate(tops, 1):
76+
print(f" {i}. pool={pool} stake={stake}")
77+
78+
# Show up to first 3 persistent IDs → pools
79+
if isinstance(persistent_pool, dict) and persistent_pool:
80+
items = sorted(persistent_pool.items(), key=lambda kv: kv[0])[:3]
81+
print(" Persistent mapping (first 3):")
82+
for pid, pool in items:
83+
print(f" id={pid} -> pool={pool}")
84+
PY
85+
popd >/dev/null
86+
# --- End summary ---

0 commit comments

Comments
 (0)