May 21, 11-12 PM (27)
May 21, 12-1 PM (63)
May 21, 1-2 PM (68)
May 21, 2-3 PM (60)
May 21, 3-4 PM (53)
May 21, 4-5 PM (20)
May 21, 5-6 PM (27)
May 21, 6-7 PM (27)
May 21, 7-8 PM (25)
May 21, 8-9 PM (23)
May 21, 9-10 PM (3)
May 21, 10-11 PM (29)
May 21, 11-12 AM (10)
May 22, 12-1 AM (16)
May 22, 1-2 AM (6)
May 22, 2-3 AM (8)
May 22, 3-4 AM (4)
May 22, 4-5 AM (11)
May 22, 5-6 AM (10)
May 22, 6-7 AM (21)
May 22, 7-8 AM (13)
May 22, 8-9 AM (38)
May 22, 9-10 AM (12)
May 22, 10-11 AM (18)
May 22, 11-12 PM (25)
May 22, 12-1 PM (24)
May 22, 1-2 PM (34)
May 22, 2-3 PM (56)
May 22, 3-4 PM (13)
May 22, 4-5 PM (29)
May 22, 5-6 PM (13)
May 22, 6-7 PM (19)
May 22, 7-8 PM (20)
May 22, 8-9 PM (12)
May 22, 9-10 PM (12)
May 22, 10-11 PM (41)
May 22, 11-12 AM (12)
May 23, 12-1 AM (9)
May 23, 1-2 AM (0)
May 23, 2-3 AM (3)
May 23, 3-4 AM (1)
May 23, 4-5 AM (1)
May 23, 5-6 AM (4)
May 23, 6-7 AM (12)
May 23, 7-8 AM (1)
May 23, 8-9 AM (3)
May 23, 9-10 AM (1)
May 23, 10-11 AM (1)
May 23, 11-12 PM (5)
May 23, 12-1 PM (1)
May 23, 1-2 PM (6)
May 23, 2-3 PM (5)
May 23, 3-4 PM (5)
May 23, 4-5 PM (4)
May 23, 5-6 PM (0)
May 23, 6-7 PM (3)
May 23, 7-8 PM (23)
May 23, 8-9 PM (1)
May 23, 9-10 PM (9)
May 23, 10-11 PM (21)
May 23, 11-12 AM (27)
May 24, 12-1 AM (9)
May 24, 1-2 AM (0)
May 24, 2-3 AM (1)
May 24, 3-4 AM (1)
May 24, 4-5 AM (0)
May 24, 5-6 AM (3)
May 24, 6-7 AM (1)
May 24, 7-8 AM (2)
May 24, 8-9 AM (2)
May 24, 9-10 AM (4)
May 24, 10-11 AM (4)
May 24, 11-12 PM (1)
May 24, 12-1 PM (7)
May 24, 1-2 PM (46)
May 24, 2-3 PM (5)
May 24, 3-4 PM (3)
May 24, 4-5 PM (18)
May 24, 5-6 PM (2)
May 24, 6-7 PM (4)
May 24, 7-8 PM (13)
May 24, 8-9 PM (10)
May 24, 9-10 PM (15)
May 24, 10-11 PM (34)
May 24, 11-12 AM (42)
May 25, 12-1 AM (9)
May 25, 1-2 AM (5)
May 25, 2-3 AM (6)
May 25, 3-4 AM (1)
May 25, 4-5 AM (6)
May 25, 5-6 AM (14)
May 25, 6-7 AM (17)
May 25, 7-8 AM (17)
May 25, 8-9 AM (32)
May 25, 9-10 AM (43)
May 25, 10-11 AM (64)
May 25, 11-12 PM (33)
May 25, 12-1 PM (43)
May 25, 1-2 PM (40)
May 25, 2-3 PM (20)
May 25, 3-4 PM (27)
May 25, 4-5 PM (16)
May 25, 5-6 PM (6)
May 25, 6-7 PM (7)
May 25, 7-8 PM (11)
May 25, 8-9 PM (12)
May 25, 9-10 PM (16)
May 25, 10-11 PM (44)
May 25, 11-12 AM (26)
May 26, 12-1 AM (12)
May 26, 1-2 AM (11)
May 26, 2-3 AM (8)
May 26, 3-4 AM (11)
May 26, 4-5 AM (6)
May 26, 5-6 AM (9)
May 26, 6-7 AM (26)
May 26, 7-8 AM (43)
May 26, 8-9 AM (39)
May 26, 9-10 AM (42)
May 26, 10-11 AM (45)
May 26, 11-12 PM (59)
May 26, 12-1 PM (34)
May 26, 1-2 PM (50)
May 26, 2-3 PM (50)
May 26, 3-4 PM (18)
May 26, 4-5 PM (20)
May 26, 5-6 PM (13)
May 26, 6-7 PM (20)
May 26, 7-8 PM (12)
May 26, 8-9 PM (15)
May 26, 9-10 PM (15)
May 26, 10-11 PM (35)
May 26, 11-12 AM (30)
May 27, 12-1 AM (16)
May 27, 1-2 AM (8)
May 27, 2-3 AM (9)
May 27, 3-4 AM (5)
May 27, 4-5 AM (32)
May 27, 5-6 AM (9)
May 27, 6-7 AM (49)
May 27, 7-8 AM (63)
May 27, 8-9 AM (37)
May 27, 9-10 AM (74)
May 27, 10-11 AM (83)
May 27, 11-12 PM (30)
May 27, 12-1 PM (50)
May 27, 1-2 PM (38)
May 27, 2-3 PM (53)
May 27, 3-4 PM (37)
May 27, 4-5 PM (6)
May 27, 5-6 PM (17)
May 27, 6-7 PM (18)
May 27, 7-8 PM (24)
May 27, 8-9 PM (14)
May 27, 9-10 PM (13)
May 27, 10-11 PM (29)
May 27, 11-12 AM (27)
May 28, 12-1 AM (9)
May 28, 1-2 AM (3)
May 28, 2-3 AM (4)
May 28, 3-4 AM (2)
May 28, 4-5 AM (8)
May 28, 5-6 AM (34)
May 28, 6-7 AM (26)
May 28, 7-8 AM (83)
May 28, 8-9 AM (33)
May 28, 9-10 AM (52)
May 28, 10-11 AM (48)
May 28, 11-12 PM (9)
3,438 commits this week May 21, 2026 - May 28, 2026
Improvements and explanations
1. Extends simulate_one_run to also return n_effective_losses (loss
events that actually reshaped cwnd; losses in the file-completing
round don't count). Adds monte_carlo_with_losses() helper alongside
the existing monte_carlo() so backward-compat is preserved.

tools/chunk_compare.py grows a --conditional flag that prints a
companion table reporting P[≥1 loss] and P99|≥1 loss at both chunk
and whole-file levels. The file-level conditional uses a resampling
estimator (default B=200000) over the chunk samples.

The new metric is the meaningful one at low p (e.g. p=1e-6) where
marginal P99 collapses to the no-loss minimum time + jitter and tells
you nothing about loss-tail behavior. Documented in a new note,
parallel-chunking-low-p.md, with concrete numbers showing that the
conditional baseline P99 at p=1e-6 is ~9 s vs the marginal P99 of
~0.57 s, and that chunking reduces the conditional file P99 from
~9 s (n=1) to ~0.9 s (n=32).

2. Replaces the imprecise "high-RTT / file-fits-in-slow-start" claim with
the accurate mechanism: chunking attacks the loss-induced tail but
cannot reduce the per-chunk slow-start ramp T_floor ≈ ceil(log2(N/n)) ·
RTT, so the achievable relative gain shrinks as RTT (and thus the
floor) grows. Adds an RTT-sweep table at 50/250/1000 ms showing the
benefit dropping from -75% to -63% as evidence.

3. Two new diagnostics for the parallel-chunking analysis, plus a note
documenting the underlying problem (file-P99 lives deep in the chunk
distribution's tail, especially for n >= 8, so single-run estimates
can be unreliable around CDF steps):

- tools/chunking_stability.py: reruns the chunk-distribution sim K
  times with different seeds and reports mean/std/range/CoV per n
  with a verdict flag. Catches CDF-step-induced instability that
  bootstrap CIs can miss (e.g. n=16 in the default config shows
  CoV ~10% with a 30% seed-to-seed range).

- tools/plot_chunking.py --ci: keeps the main multi-curve plot
  unchanged and additionally emits one per-n SVG with a pointwise
  bootstrap 95% CI band. Uses random.binomialvariate for an
  efficient exact-bootstrap of the empirical CDF at each x-point.

- notes/parallel-chunking-mc-confidence.md: quantifies the tail-
  data problem, presents both bootstrap CI and seed-to-seed tables,
  and lists mitigations from "bump --runs" to importance sampling.

4. Adds a "Validation at M=500 000" section comparing the 10-seed sweep
at M=50k vs M=500k. Key finding: n=16 was the only n materially wrong
at M=50k (CoV 9.9% → 0.3%, mean shifted +3%), and chunk_compare's
shipped n=16 number was correct but seed-fragile. Refreshes the
per-regime recommendation with concrete M=500k numbers and rewrites
the "Diagnostic tooling" section now that both tools ship.

5. Records the explanation for why the chunking plot curves rise →
plateau → rise rather than forming smooth S-curves. The model
genuinely concentrates runs at a small finite set of outcome modes
(no loss; loss in slow-start round r for each r; rare multi-loss),
and F_file = F_chunk^n amplifies the existing steps at large n.
Cross-links to the four other chunking notes.

Co-authored with Claude.
Produce CDF of time to transmit a datum over TCP
Monte carlo simulation of TCP CUBIC, taking into account slow start,
transition into congestion avoidance, and packet losses which affect
the cwnd.

The `tools` directory contains `plot_chunking.py` script for producing
a CDF showing the benefit of chunking a large datum and requesting
from multiple peers.

1. Extends the De Silva et al. throughput model with random loss
(Bernoulli or Gilbert-Elliott Markov), runs a Monte Carlo to build a
CDF of download times, and reports a user-specified percentile to
stdout and as an SVG plot.

2. Each round now draws its own RTT from a configurable distribution
(lognormal default, normal/uniform/none alternatives), and the CUBIC
formula uses real elapsed wall-clock seconds instead of round count ×
nominal RTT. This breaks up the hard CDF step that arose when many
no-loss runs all completed at exactly N · RTT. Setting model: none
reproduces the prior round-quantized behavior.

3. Reuses estimator.load_config / monte_carlo / percentile_of to compare
a single-shot download against n-chunk parallel downloads at n = 2, 4,
8, 16, 32. Reports both an optimistic (full link per chunk) and a
realistic (link/n per chunk) bandwidth model, alongside the paired
note in notes/parallel-chunking.md.

Co-authored with Claude
Add Spec.Data.Value.Budget — non-builtin valueOf evidence
Adds `Spec.Data.Value.Budget` with the lookup matrix for `valueOf` across
S1 / S3 / S8 / S100 value shapes at ada / middle / last / miss positions,
plus the standalone `unsafeDataAsValue` baseline per shape. Generated 96
golden files (eval / pir / uplc per bundle, 32 bundles total) capture CPU
and Memory cost evidence.

Companion to the merge PR for `valueOf` rewrite. This branch is kept
separate so the goldens — which only regenerate on upstream plugin or
cost-model changes, not on actual regressions — don't bloat the main
PR's diff or CI.

For IntersectMBO/plutus-private#2242.
Add valueOf golden coverage in Spec.Data.Budget
Adds a PIR-readable snapshot and four budget snapshots for the new `valueOf`
implementation, registered alongside the existing golden coverage for
`gt`, `geq`, and `currencySymbolValueOf`.

Scenarios:
- valueOf_hit_first: ada-like first-position lookup, exercises short-circuit on the first outer step.
- valueOf_hit_middle: key at the middle of the outer map.
- valueOf_hit_last: key at the last entry, full outer scan.
- valueOf_miss: absent key, full scan with no inner walk.

These tests catch regressions in `valueOf` compilation and cost that would
otherwise surface only through downstream callers (`currencySymbolValueOf`,
`assetClassValueOf`, `geq`, etc.).
Optimal non-builtin valueOf in plutus-ledger-api Data.Value
Rewrites `PlutusLedgerApi.V1.Data.Value.valueOf` so the non-builtin lookup
path walks the underlying `BuiltinList` directly via `unsafeDataAsMap` /
`unsafeDataAsB` / `unsafeDataAsI`, compares keys with `equalsByteString`,
and short-circuits on the first match. No `Maybe` is materialised: the
"absent" answer is `0`, returned in-place by the `nilCase` of each
traversal. Avoids `withCurrencySymbol`'s continuation + `Map.lookup`'s
`Maybe`-wrapping, and bypasses the `ToData k`/`UnsafeFromData a` dictionary
work that `AssocMap.lookup` does per element. Semantics preserved.

Adds `Spec.Data.Value.test_valueOf`: a QuickCheck property that compiles
`valueOf` via TH, evaluates it on the CEK machine, and compares the result
against the host-Haskell `valueOf` for the same inputs. Differential test
against the Plinth compiler — any divergence is a compilation bug, not a
semantics bug.

Budget evidence (lookup matrix, `unsafeDataAsValue` baseline) lives on the
companion experimental branch `yura/issue-2242-valueof-evidence`, kept out
of this PR to avoid carrying ~96 golden files that would only ever regenerate
on upstream plugin/cost-model changes.

For IntersectMBO/plutus-private#2242.
feat(offchain): add --allow-private-offchain-urls flag
cardano-db-sync's off-chain pool and vote metadata fetchers reject
URLs whose host or resolved IP is in a private, loopback, or
link-local range as an SSRF mitigation (see parseOffChainUrl and
newRestrictedManager in cardano-db-sync/src/Cardano/DbSync/
OffChain/Http.hs). Local-cluster test setups whose metadata is
served from http://localhost:.../poolN.json or similar therefore
cannot exercise the success path of the fetcher.

This adds an opt-in CLI flag that replaces both layers of the
restriction with a no-op for the duration of the run, intended
for local-cluster testing only. Off by default; the existing
restriction continues to apply to every production deployment.

* New SyncNodeParams field enpAllowPrivateOffChainUrls plumbed
  through SyncOptions (soptAllowPrivateOffChainUrls) into the
  off-chain fetcher threads.
* parseOffChainUrl now takes a Bool: when True the isLocalhostHost
  rejection is skipped.
* newRestrictedManager now takes a Bool: when True it installs a
  permissiveRestriction (addressRestriction returning Nothing for
  every address) instead of offchainRestriction, so DNS-resolved
  private IPs are no longer blocked at connect time either.
* New Hedgehog suite Cardano.DbSync.OffChain.HttpTest covering
  both modes for localhost/127./[::1]/10./192.168. plus a public
  URL and non-HTTP schemes.