Skip to content

Un-stale spec vs latest charon main; add Pluto - #11

Open
OisinKyne wants to merge 5 commits into
mainfrom
oisin/fable
Open

Un-stale spec vs latest charon main; add Pluto#11
OisinKyne wants to merge 5 commits into
mainfrom
oisin/fable

Conversation

@OisinKyne

Copy link
Copy Markdown
Contributor

Why

This repo went stale after 2025-11-12 while charon accumulated 336 commits
(now at 2eb6798e, 2026-07-14). Its purpose is to formally specify the Obol
DV protocol so that Pluto (Nethermind's Rust implementation) can be assured
of perfect interop with Charon. This PR brings the spec back in line with
charon main for everything it already covers, and records the project's
interop framing.

What's in this PR

Corrections (spec did not match the wire)

  • Priority protocol ID: charon's wire string is charon/priority/2.0.0
    no leading slash (core/priority/prioritiser.go:39). The spec
    claimed /charon/priority/2.0.0. Fixed in helpers.py, priority.md,
    and tests, each with a warning that the missing slash is
    accidental-but-normative (pluto deliberately accommodates it; do not
    "correct" it unless charon versions the protocol).
  • MsgSync.nickname (field 6, charon #4105, in v1.9.5): added to the
    dkg_sync model, proto/dkg_sync.proto, and docs. Max 32 chars,
    informational only.

Behavior updates (charon changed since 2025-11-12)

  • Deterministic round deadlines (charon #4243, in v1.9.5): the
    DoubleEagerLinearRoundTimer now derives each round's first deadline from
    genesis_time + slot * slot_duration + duty_start_delay instead of the
    local wall clock, so round boundaries and leader election stay aligned
    across peers. Added get_duty_start_delay (attester: slot/3;
    aggregator/sync-contribution: 2·slot/3). Wall-clock fallback retained,
    matching charon.
  • QBFT hardening (charon #4557, in v1.11.0):
    • DECIDED-resend rate limit: at most one rebroadcast per source per
      strictly-increasing round, capped at 16 per source
      (MAX_DECIDED_RESENDS), preventing amplification DoS.
    • MAX_CONSENSUS_MSG_SIZE (32 MiB) wire read limit.
    • verify_msg_limits: justifications ≤ 2·nodes, values ≤
      2·(justifications+1), enforced before expensive verification.
    • Documented in consensus.md (timers, message limits, decided-resend).

Structure / framing

  • Renamed subspecs/bcastsubspecs/reliable_bcast (and tests dir) to
    stop the name colliding with charon's core/bcast (beacon-node broadcast,
    a different component). Wire protocol ID /charon/dkg/bcast/1.0.0
    unchanged; disambiguation note added to reliable-broadcast.md.
  • Pluto added: README gains an Implementations table (Charon = Go
    reference implementation; Pluto = Rust, Nethermind, targeting wire
    compatibility) and an explicit interop mission statement.
  • docs/index.md fixed: was still the un-edited "Lean Ethereum" page
    from the September fork; now describes the DV specs and both clients.
  • Charon version anchor: README states the spec tracks charon main, last
    validated against 2eb6798e, with a table flagging which behaviors landed
    after v1.7.1 (pluto's current pin) and why they remain wire-compatible.
  • Fixed a stray duplicated return True in qbft/protocol.py.

Tests

24 new tests (155 → 179, all passing; ruff + mypy clean):

  • Deterministic timer: deadline derivation, cross-node alignment, late-start
    behavior, doubling from deterministic deadline, wall-clock fallback,
    duty start delays.
  • DECIDED-resend rate limit: per-round, per-peer, cap, own-message cases.
  • verify_msg_limits bounds.
  • MsgSync.nickname validation.

Deliberately NOT changed

  • Cluster definition doc stays at v1.10 (agreed target for now; charon
    is on v1.11 — revisit when the target moves).
  • Pedersen DKG spec untouched; FROST (charon's default and pluto's near-term
    DKG target) is not yet spec'd — it is the top follow-up item.

Follow-up phases (see plans/spec-completion.md for detail)

  • Phase 2 (next commit/session): FROST DKG + /charon/dkg/node_sig +
    reshare flows; sigagg (threshold BLS aggregation); infosync (priority
    protocol's actual use, gates consensus-protocol selection); validatorapi
    conformance; scheduler/core-bcast prose specs.
  • Phase 3: spec-generated test vectors as the interop contract, consumed
    by Go (charon) and Rust (pluto) test suites; conformance CI here with a
    weekly charon@main staleness alarm; wire-level mixed-cluster harness with
    the spec as passive protocol oracle.
  • Agreed aspirations: adversarial/negative vectors, differential fuzzing
    of the three QBFT state machines, pluto link-back PR, spec versioning
    policy mapped to charon MAJOR.MINOR, proto-parity CI (buf breaking-change
    diff against charon's protos — would have caught the nickname miss).

Comment thread docs/dv-spec/consensus.md
Comment on lines +68 to +70
- The default strategy is the *eager double linear* timer: round `r` lasts
`r` seconds, and the first deadline of each round is computed
deterministically from the chain (`genesis_time + slot * slot_duration +

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Describe eager rounds as absolute deadlines

When round 1 expires at duty_start + 1s and round 2 begins, calculate_timeout(2) sets its deadline to duty_start + 2s, leaving roughly one second rather than making round 2 last two seconds. An implementation following “round r lasts r seconds” would use cumulative deadlines and diverge from Charon’s schedule, undermining the alignment this section requires.

Comment thread README.md Outdated
Comment on lines +31 to +32
| `MsgSync.nickname` field (DKG sync) | `v1.9.5` |
| Deterministic (genesis-derived) eager double linear round deadlines | `v1.9.5` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Anchor these features to v1.9.0

For implementers comparing against v1.9.0–v1.9.4, these rows incorrectly imply both features are absent: Charon commits d33572f2 and 31ff2996 are ancestors of the v1.9.0 tag, whose source already contains both MsgSync.nickname and the genesis-derived timer. The same incorrect v1.9.5 attribution is repeated in plans/spec-completion.md.

pinebit and others added 3 commits July 28, 2026 14:42
Doc pages linked their Python modules and .proto files with paths like
../../src/dv_spec/..., which resolve when browsing the repository but
warn on `mkdocs build` and 404 on the published site. All 48 are now
absolute github.com/ObolNetwork/distributed-validator-specs/blob/main
URLs, which work in both contexts.

mkdocs does not validate absolute URLs, so tests/test_docs_links.py
checks that every linked path exists in the repository and that no page
reintroduces a ../../ escape or a #L line anchor. tox's docs-build env
now runs `mkdocs build --strict` so a relative escape fails rather than
printing a warning.

Fixed while here:

- consensus.md and peerinfo.md still carried #L line anchors.
- networking.md's #Encodings anchor had the wrong case, and
  consensus.md's #duty-types pointed at a heading that does not exist
  on the page; it now links DutyType in types/duty.py.
- networking.md linked ../../ssz/simple-serialize.md, which resolves
  only inside ethereum/consensus-specs, where that text originated.
  It now points upstream.
- The QBFT validation-rule list repeated one identical link across
  eight bullets. The module is linked once above the list and each
  bullet names the symbol.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants