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
22 changes: 22 additions & 0 deletions Logbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,28 @@

Updated the Leios Slide Deck with reusable slides about this sim

### Micro-mainnet

To accommodate the speed limitations of the Haskell simulation, an even smaller "micro-mainnet" has been created.

- Methodology: [topology-v3.ipynb](data/simulation/pseudo-mainnet/topology-v3.ipynb)
- Network: [topology-v3.yaml](data/simulation/pseudo-mainnet/topology-v3.yaml)
- Metrics: [topology-v3.md](data/simulation/pseudo-mainnet/topology-v3.md)
- Experiment comparing micro- vs mini-mainnet: [analysis.ipynb](analysis/sims/micro-mainnet/analysis.ipynb)

| Metric | Value |
| ---------------------------: | ---------: |
| Total nodes | 100 |
| Block producers | 22 |
| Relay nodes | 78 |
| Total connections | 2123 |
| Network diameter | 4 hops |
| Average connections per node | 21.23 |
| Average latency | 97.5 ms |
| Maximum latency | 529.1 ms |
| Bidirectional connections | 389 |
| Asymmetry ratio | 63.35% |

## 2025-09-11

### Compendium of data for Delta QSD modeling
Expand Down
3,256 changes: 3,256 additions & 0 deletions analysis/sims/micro-mainnet/analysis.ipynb

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions analysis/sims/micro-mainnet/combine-results.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p gnused gzip pigz "rWrapper.override { packages = with rPackages; [ data_table R_utils bit64 ggplot2 magrittr stringr ]; }"

set -e

mkdir -p results/$d
for f in lifecycle resources receipts cpus sizes
do
DIR=$(find experiments -type f -name $f.csv.gz \( -not -empty \) -printf %h\\n -quit)
HL=$(sed -n -e '1p' "$DIR/case.csv")
HR=$(zcat "$DIR/$f.csv.gz" | sed -n -e '1p')
if [[ "$f" == "lifecycle" || "$f" == "resources" || "$f" == "sizes" ]]
then
FRACT=1.00
else
FRACT=0.33
fi
(
echo "$HL,$HR"
for g in $(find experiments -type f -name $f.csv.gz \( -not -empty \) -printf %h\\n)
do
if [ ! -e "$g/stderr" ]
then
echo "Skipping $g because it has no stderr." >> /dev/stderr
elif [ -s "$g/stderr" ]
then
echo "Skipping $g because its stderr is not empty." >> /dev/stderr
else
BL=$(sed -n -e '2p' "$g/case.csv")
zcat "$g/$f.csv.gz" | gawk 'FNR > 1 && rand() <= '"$FRACT"' { print "'"$BL"'" "," $0}'
fi
done
) | pigz -p 3 -9c > results/$f.csv.gz
R --vanilla << EOI > /dev/null
require(data.table)
sampleSize <- $FRACT
print(sampleSize)
$f <- fread("results/$f.csv.gz", stringsAsFactors=TRUE)
save($f, sampleSize, file="results/$f.Rdata", compression_level=9)
EOI
done
10 changes: 10 additions & 0 deletions analysis/sims/micro-mainnet/experiments.list
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
experiments/topology-v2,0.100/run.sh
experiments/topology-v3,0.100/run.sh
experiments/topology-v2,0.150/run.sh
experiments/topology-v3,0.150/run.sh
experiments/topology-v2,0.200/run.sh
experiments/topology-v3,0.200/run.sh
experiments/topology-v2,0.250/run.sh
experiments/topology-v2,0.300/run.sh
experiments/topology-v3,0.250/run.sh
experiments/topology-v3,0.300/run.sh
110 changes: 110 additions & 0 deletions analysis/sims/micro-mainnet/experiments/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@

# Simulation parameters.
timestamp-resolution-ms: 0.1
simulate-transactions: true
cleanup-policies:
- cleanup-expired-vote

# Protocol parameters for Linear Leios.
leios-variant: linear-with-tx-references
linear-eb-propagation-criteria: eb-received
linear-vote-stage-length-slots: 4
linear-diffuse-stage-length-slots: 7
praos-fallback-enabled: true
leios-stage-active-voting-slots: 1
leios-mempool-sampling-strategy: ordered-by-id
relay-strategy: request-from-first
treat-blocks-as-full: false
eb-diffusion-strategy: peer-order
eb-referenced-txs-max-size-bytes: 12000000
eb-size-bytes-constant: 240
eb-size-bytes-per-ib: 32

# A conservative upper bound based on empiricial data of empty Praos blocks on
# Cardano mainnet.
leios-header-diffusion-time-ms: 1000.0

# Scenario-specific parameters for transaction generation.
tx-start-time: 60
tx-stop-time: 960
tx-generation-distribution:
distribution: constant
value: 10.0
tx-size-bytes-distribution:
distribution: constant
value: 1500
tx-conflict-fraction: 0
tx-overcollateralization-factor-distribution:
distribution: constant
value: 0

# Based on a linear model fit from `db-analyser` measurements of mainnet blocks
# for the `Apply` operation, either with or without a term for Plutus execution
# steps.
#
# `Apply CPU [ms]` / `Tx count` ~ (0.6201 ms/tx)
#
# `Apply CPU [ms]` ~ 0 + (0.2624 ms/tx) * `Tx count`
# + (0.9487 ms/Gstep) * `Tx exec [Gstep]`
#
tx-validation-cpu-time-ms: 0.6201

# Inherited from Cardano mainnet protocol parameters for Praos.
tx-max-size-bytes: 16384
rb-generation-probability: 0.05
rb-head-size-bytes: 1024
rb-body-max-size-bytes: 90112

# Worst case based on benchmark cluster "Forging: Slot start to announced".
rb-generation-cpu-time-ms: 71.02

# Based on `apply` statistics for empty blocks using `db-analyser` on blocks
# from the Cardano mainnet.
rb-head-validation-cpu-time-ms: 0.4438
eb-header-validation-cpu-time-ms: 0.4438

# Based on a linear model fit from `db-analyser` measurements of mainnet blocks
# for the `Reapply` operation, either with or without a term for Plutus
# execution steps.
#
# `Reapply CPU [ms]` ~ (0.3539 ms) + (0.02151 ms/kB) * `Block size [kB]`
#
# `Reapply CPU [ms]` ~ (0.3478 ms) + (0.01943 ms/kB) * `Block size [kB]`
# + (0.02127 ms/Gstep) * `Block exec [Gstep]`
#
rb-body-legacy-praos-payload-validation-cpu-time-ms-constant: 0.3539
rb-body-legacy-praos-payload-validation-cpu-time-ms-per-byte: 0.00002151
eb-body-validation-cpu-time-ms-constant: 0.3539
eb-body-validation-cpu-time-ms-per-byte: 0.00002151

# Based on analysis of wFA+LS sortition for realistic stake distribution similar
# to that of Cardano mainnet, and on the security requirement.
vote-generation-probability: 600
vote-threshold: 450

# Based on CDDL for votes, worst case for non-persistent voters.
vote-bundle-size-bytes-constant: 0
vote-bundle-size-bytes-per-eb: 164

# Worst case based on benchmarks from cryptography prototype.
vote-generation-cpu-time-ms-constant: 0.280
vote-generation-cpu-time-ms-per-tx: 0
vote-validation-cpu-time-ms: 2.9

# Vote diffusion settings.
vote-diffusion-strategy: peer-order
vote-diffusion-max-bodies-to-request: 1
vote-diffusion-max-headers-to-request: 100
vote-diffusion-max-window-size: 100

# Worst case based on CDDL for certificates and on empirical study of wFA+LS
# sortition.
cert-size-bytes-constant: 8000
cert-size-bytes-per-node: 0

# Worst case based on benchmarks from cryptography prototype.
cert-generation-cpu-time-ms-constant: 92.5
cert-generation-cpu-time-ms-per-node: 0
cert-validation-cpu-time-ms-constant: 157.2
cert-validation-cpu-time-ms-per-node: 0

111 changes: 111 additions & 0 deletions analysis/sims/micro-mainnet/experiments/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p ansifilter gnugrep gnused gzip pigz bc

set -eo pipefail

cd "$(dirname "${BASH_SOURCE[0]}")"

TX_START=60
TX_STOP=960
SIM_STOP=1500
BW=10
CPU_COUNT=4
SIM=Rust
VARIANT=linear-with-tx-references
BLOCK_SIZE=12
TX_SIZE=1500
LABEL=$(basename "$PWD")
PROPAGATION=eb-received
STAGE_LENGTH_DIFF=7
STAGE_LENGTH_VOTE=4
NETWORK=$(echo -n "$LABEL" | sed -e 's/^\(.*\),\(.*\)/\1/')
THROUGHPUT=$(echo -n "$LABEL" | sed -e 's/^\(.*\),\(.*\)/\2/')
TX_SPACING_HONEST=$(echo "scale=3; $TX_SIZE / $THROUGHPUT / 1000" | bc)

ulimit -S -m 48000000 -v 48000000

if [[ -e sim.log ]]
then
rm sim.log
fi

mkfifo sim.log

sed -e 's/"bandwidth-bytes-per-second":125000000/"bandwidth-bytes-per-second":'"$((125000 * BW))"'/g' \
-e 's/"cpu-core-count":6,/"cpu-core-count":'"$CPU_COUNT"',/g' \
"../../../../../data/simulation/pseudo-mainnet/$NETWORK.yaml" \
> network.yaml

yaml2json ../config.yaml \
| jq '. +
{
"leios-variant": "'"$VARIANT"'"
, "linear-eb-propagation-criteria": "'"$PROPAGATION"'"
, "linear-diffuse-stage-length-slots": '"$STAGE_LENGTH_DIFF"'
, "linear-vote-stage-length-slots": '"$STAGE_LENGTH_VOTE"'
, "leios-stage-length-slots": '"$STAGE_LENGTH_VOTE"'
, "eb-referenced-txs-max-size-bytes": ('"$BLOCK_SIZE"' * 1000000)
, "eb-body-avg-size-bytes": ('"$BLOCK_SIZE"' * 1000000)
, "tx-size-bytes-distribution": {distribution: "constant", value: '"$TX_SIZE"'}
, "tx-generation-distribution": {distribution: "constant", value: '"$TX_SPACING_HONEST"'}
, "tx-start-time": '"$TX_START"'
, "tx-stop-time": '"$TX_STOP"'
}
' > config.yaml

function cleanup() {
rm sim.log
rm network.yaml
}
trap cleanup EXIT

grep -E -v '(Slot|CpuTask|Lottery)' sim.log | pigz -p 3 -9c > sim.log.gz &

case "$SIM" in
Rust)
../../sim-cli --parameters config.yaml network.yaml --slots "$SIM_STOP" --conformance-events sim.log > stdout 2> stderr
;;
Haskell)
../../ols sim leios --leios-config-file config.yaml --topology-file network.yaml --shared-log-format JSON --conformance-events --output-file sim.log --output-seconds "$SIM_STOP" > stdout 2> stderr
;;
*)
false
esac

wait

cat << EOI > case.csv
Network,Bandwidth,CPU,Diffusion duration,Voting duration,Max EB size,Tx size,Throughput,Tx start [s],Tx stop [s],Sim stop [s]
$NETWORK,$BW Mb/s,$CPU_COUNT vCPU/node,L_diff = $STAGE_LENGTH_DIFF slots,L_vote = $STAGE_LENGTH_VOTE slots,$BLOCK_SIZE MB/EB,$TX_SIZE B/Tx,$THROUGHPUT TxMB/s,$TX_START,$TX_STOP,$SIM_STOP
EOI

zcat sim.log.gz \
| ../../leios-trace-processor \
+RTS -N5 -RTS \
--trace-file /dev/stdin \
--lifecycle-file lifecycle.csv \
--cpu-file cpus.csv \
--resource-file resources.csv \
--receipt-file receipts.csv

(
echo 'Kind,Item,Generated [s],Transactions,Endorses'
zcat sim.log.gz \
| grep -E '(EB|RB)Generated' \
| jq -r '
.message.type[0:2]
+ "," + .message.id
+ "," + (.time_s | tostring)
+ "," + (.message.transactions | length | tostring)
+ "," + (if .message.endorsement then .message.endorsement.eb.id else "NA" end)
'
) > sizes.csv

pigz -p 3 -9f {cpus,lifecycle,receipts,resources,sizes}.csv

cat case.csv

if [[ "$SIM" == "Rust" ]]
then
ansifilter stdout | grep -E '^ INFO (praos|leios|network): ' > summary.txt
fi
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Network,Bandwidth,CPU,Diffusion duration,Voting duration,Max EB size,Tx size,Throughput,Tx start [s],Tx stop [s],Sim stop [s]
topology-v2,10 Mb/s,4 vCPU/node,L_diff = 7 slots,L_vote = 4 slots,12 MB/EB,1500 B/Tx,0.100 TxMB/s,60,960,1500
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"timestamp-resolution-ms": 0.1,
"simulate-transactions": true,
"cleanup-policies": [
"cleanup-expired-vote"
],
"leios-variant": "linear-with-tx-references",
"linear-eb-propagation-criteria": "eb-received",
"linear-vote-stage-length-slots": 4,
"linear-diffuse-stage-length-slots": 7,
"praos-fallback-enabled": true,
"leios-stage-active-voting-slots": 1,
"leios-mempool-sampling-strategy": "ordered-by-id",
"relay-strategy": "request-from-first",
"treat-blocks-as-full": false,
"eb-diffusion-strategy": "peer-order",
"eb-referenced-txs-max-size-bytes": 12000000,
"eb-size-bytes-constant": 240,
"eb-size-bytes-per-ib": 32,
"leios-header-diffusion-time-ms": 1000.0,
"tx-start-time": 60,
"tx-stop-time": 960,
"tx-generation-distribution": {
"distribution": "constant",
"value": 15.000
},
"tx-size-bytes-distribution": {
"distribution": "constant",
"value": 1500
},
"tx-conflict-fraction": 0,
"tx-overcollateralization-factor-distribution": {
"distribution": "constant",
"value": 0
},
"tx-validation-cpu-time-ms": 0.6201,
"tx-max-size-bytes": 16384,
"rb-generation-probability": 0.05,
"rb-head-size-bytes": 1024,
"rb-body-max-size-bytes": 90112,
"rb-generation-cpu-time-ms": 71.02,
"rb-head-validation-cpu-time-ms": 0.4438,
"eb-header-validation-cpu-time-ms": 0.4438,
"rb-body-legacy-praos-payload-validation-cpu-time-ms-constant": 0.3539,
"rb-body-legacy-praos-payload-validation-cpu-time-ms-per-byte": 0.00002151,
"eb-body-validation-cpu-time-ms-constant": 0.3539,
"eb-body-validation-cpu-time-ms-per-byte": 0.00002151,
"vote-generation-probability": 600,
"vote-threshold": 450,
"vote-bundle-size-bytes-constant": 0,
"vote-bundle-size-bytes-per-eb": 164,
"vote-generation-cpu-time-ms-constant": 0.28,
"vote-generation-cpu-time-ms-per-tx": 0,
"vote-validation-cpu-time-ms": 2.9,
"vote-diffusion-strategy": "peer-order",
"vote-diffusion-max-bodies-to-request": 1,
"vote-diffusion-max-headers-to-request": 100,
"vote-diffusion-max-window-size": 100,
"cert-size-bytes-constant": 8000,
"cert-size-bytes-per-node": 0,
"cert-generation-cpu-time-ms-constant": 92.5,
"cert-generation-cpu-time-ms-per-node": 0,
"cert-validation-cpu-time-ms-constant": 157.2,
"cert-validation-cpu-time-ms-per-node": 0,
"leios-stage-length-slots": 4,
"eb-body-avg-size-bytes": 12000000
}
Loading