Skip to content

chore: follow the upstream leanMultisig → leanVM repository rename - #25

Merged
adust09 merged 1 commit into
mainfrom
chore/leanvm-rename-20260817-1723
Aug 17, 2026
Merged

chore: follow the upstream leanMultisig → leanVM repository rename#25
adust09 merged 1 commit into
mainfrom
chore/leanvm-rename-20260817-1723

Conversation

@adust09

@adust09 adust09 commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Upstream renamed leanEthereum/leanMultisig to leanEthereum/leanVM on 2026-08-14 (discovered during the leanEthereum org sweep for the sync-pipeline design; the old URL redirects, and the repo's internal layout — crates/xmss/xmss.md, crates/backend/symetric, crates/lean_vm, … — is unchanged, verified against the current tree).

This PR updates every reference in the repo:

  • Prose docs: CLAUDE.md, README.md, ARCHITECTURE.md + its docs/src/reference/architecture.md mirror, DOMAIN_MODEL.md, docs/src/concepts/formal-verification.md (frontmatter last_updated bumped on the two edited docs pages). First prose mentions carry a "(formerly leanMultisig)" note so older discussions and memories stay traceable.
  • Skills: .claude/skills/leanMultisig/ renamed to .claude/skills/leanVM/ with the old name kept as an explicit legacy trigger; the four cross-referencing skills (leanSpec, leanMetrics, leanQuickstart, hive) updated.
  • Config: the _typos.toml comment (the upstream-misspelled symetric directory still exists in leanVM — path re-verified).

The upstream repo leanEthereum/leanMultisig was renamed to
leanEthereum/leanVM on 2026-08-14 (the old URL redirects). Update
every reference: CLAUDE.md, README.md, ARCHITECTURE.md and its docs
mirror, DOMAIN_MODEL.md, formal-verification.md, the _typos.toml
comment, and the skill set (directory renamed to leanVM; the old name
kept as a legacy trigger; cross-referencing skills updated). First
mentions in prose carry a '(formerly leanMultisig)' note so older
discussions stay traceable.
@adust09
adust09 merged commit 02e3d77 into main Aug 17, 2026
6 checks passed
@adust09
adust09 deleted the chore/leanvm-rename-20260817-1723 branch August 17, 2026 08:25
adust09 added a commit that referenced this pull request Aug 20, 2026
* docs: specify the verity-db storage schema (#19)

* docs: specify the verity-db storage schema

Settles the table layout under the engine and retention decisions already
recorded in ARCHITECTURE.md: keys, pruning rules, and how state is stored.

The layout is driven by a growth model that the SSZ fixtures alone hide. A
state measures 342-774 B there, but process_slots appends to
historical_block_hashes every slot and cannot trim it, because that list is
indexed by absolute slot. State size is therefore ~300 B + 32 B x slot: ~691 KB
one day in, ~8.4 MB at the 2^18 limit. A full state per block would cost ~7.5 GB
over the first day and grow quadratically — heavier than the aggregate proofs.
Snapshots every 1,024 slots plus parent-linked diffs bring the same data to
~10-15 MB/day, provided a diff omits historical_block_hashes and regenerates it
from base_root and the slot gap.

Full state history is retained: snapshots and diffs are never pruned, so any
past block's state stays reconstructible. The diff chain grows monotonically;
that cost is accepted for the leverage it gives while the upstream spec moves.

Blocks are stored unsigned with the proof as a separate row, so a block whose
proof has been pruned still reads back. Attestation-level signatures and
aggregated payloads stay in memory, matching what leanSpec's reference node
persists — the one addition is block proofs, which are persisted so BlocksByRange
serving survives a restart.

Also adds STORAGE.md to the scheduled link check, alongside the other root docs.

* docs(storage): tighten Metadata, StateRootIndex, and fork-scoping wording

- Metadata: drop genesis_time from the scalar list; note it is a field of
  config used to derive the network fingerprint, not a separate column.
- StateRootIndex: align the Pruned cell with Blocks (never), keeping the
  tie-to-block note, so the two rows no longer read as contradictory.
- Snapshot/diff recovery: scope the config/validators-immutability claim to
  the current lstar STF and flag validator-mutating forks as the revisit point.

* docs(storage): align schema with persistence decisions

Capture the agreed recovery, fork-choice, and range-sync invariants in the
existing storage-schema pull request so the first implementation has one
consistent repository contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: settle the I/O Edge concurrency model (#20)

* docs: settle the I/O Edge concurrency model

Settle the question ARCHITECTURE.md left open: which concurrency
primitive enforces the single-writer discipline, where signature and
proof verification execute, and how inbound work reaches the chain task.

Decisions, selected for verifiability (Loom tractability, sequential
FFI, fold-refinement against leanSpec) rather than throughput:

- verity-chain is one dedicated tokio task owning Store and State;
  reads leave as watch-published Arc<ChainView> snapshots.
- Verification runs in a dedicated stage between the network task and
  the chain task, on spawn_blocking (no rayon, no promotion path), with
  a private-constructor Verified* type boundary and a bounded pending
  buffer for unknown-parent items.
- Three inbound channels split by full-queue policy (tick = watch and
  coalescable, local duty products = never dropped, network = shed at
  the network edge only, pre-verification), read via biased select.

Evidence recorded in the document: leanSpec constrains ordering only
(read at cce7955), and a four-client survey (ethlambda e16f477,
ream 842a709, zeam 6495beb, qlean-mini 55b6eb3) shows no client gates
propagation on verification while maturing clients offload it.

* docs: close the cold-start gaps in the concurrency model

A cold-start review (reader with no design-discussion context) found
the document non-self-sufficient. Close every gap at the document
level:

- Define the ChainView contract (head + checkpoints + registry
  resolution by root) and state that the watch snapshot is the entire
  read path — no query channel into the chain task.
- Define what Verified* values carry (typed container + computed
  roots).
- Specify the pending-buffer mechanics: select on input +
  watch::changed, retry only newly-resolvable entries, FIFO eviction,
  silent eviction recovered by range sync, never blocks, failed
  verification drops immediately.
- Specify the chain-task loop: one event per biased-select iteration;
  tick handling must step interval-by-interval to the target.
- Add a Lifecycle section (startup order, first-ChainView readiness
  signal, shutdown drain/discard policy per channel).
- Add a deliberately-deferred list (capacities, struct layouts, peer
  scoring) so deferrals are not mistaken for omissions.
- State the escaped-panic policy (abort, availability failure).

* docs: resolve the second cold-start round on the concurrency model

Second no-context review still found divergence points; fix each at
the design level and fence the rest:

- ChainView: fix the retention bound (unfinalized tree + finalized
  anchor; historical reads are verity-db's job, so an RPC historical
  query is a database read, not a snapshot miss), publication cadence
  (at most once per loop iteration, post-import), and distribution
  (receiver handed out at construction; doubles as the readiness
  signal — no separate mechanism).
- Tick: current interval IS Store.time and the handler is the spec's
  own on_tick loop; leanSpec's tick_interval is the authoritative
  action map (the listed actions are orientation, not restated spec);
  catch-up replays cheaply (no STF work in interval actions).
- Aggregation wiring: the interval-2 action hands the signature-pool
  snapshot to verity-validator's worker; the chain task never awaits.
- Verification failures: definitive failures (malformed SSZ, root
  mismatch, invalid signature/proof) drop immediately with metrics;
  the pending buffer holds only the one recoverable case.
- Network edge: try_send into the stage's bounded input channel named
  as the pipeline's single drop point.
- Shutdown: drained = sender dropped + recv to None, no side-channel.
- Deferred list: add sizing anchors (tens for local, hundreds for
  network/pending) and internal data structures.

* docs: settle the third-round cold-start findings

- The pending buffer holds both recoverable cases under one policy: a
  block awaiting its parent post-state and an attestation awaiting its
  target post-state, keyed by the awaited root. Eviction recovery
  differs per kind and is stated: blocks via range sync, attestation
  votes re-arrive embedded in an aggregate or block body.
- Shutdown: channel closure is the only signal (no broadcast); the
  binary stops edge producers, sender drops cascade, downstream tasks
  exit on None.
- Startup: the verity binary opens/validates the database and hands
  the chain task its handle; Store initialization (time included)
  follows leanSpec.

* docs: close the fourth-round cold-start findings on the concurrency model

- Specify the production side of channel 2: validator-duty tasks are
  driven by the same slot clock that feeds channel 1 (one clock in the
  binary, two consumers), read the ChainView snapshot for proposal
  head / attestation target, and push signed products into channel 2;
  the chain task never triggers production by callback (sole
  involvement: the interval-2 aggregation handoff).
- Define in-flight disposal at shutdown: running spawn_blocking
  verifications finish and their results are discarded (blocking work
  is uncancellable); the pending buffer is dropped.
- Make the interval-action map normative by reference to leanSpec
  main (tracked revision), not a frozen restatement.

* docs: settle XMSS validator key-state management (#23)

* docs: settle XMSS validator key-state management

Settle design area 2 of the client-specific design campaign: how
Verity manages stateful XMSS signing keys. The asset protected is the
key's cryptographic soundness (reuse = forgeability), not a protocol
penalty — the lean protocol has no slashing.

Decisions:
- Signing watermark with persist-before-sign: last-signed slot per
  (validator, role) in a dedicated verity-db column family, fsynced
  before any signature leaves the process; equality refused even for
  identical messages; clock-rewind fails closed at startup. The
  validator signing path is the family's sole writer — the one
  documented exception to the chain writer, one-writer-per-family.
- Key material: lean-quickstart-compatible layout, Verity-owned
  loader in verity-crypto (none exists in the ecosystem), manifest
  roles authoritative, fail-closed rejects (missing/identical role
  keys, pubkey mismatch), fully memory-resident (~67 MB/validator).
- Preparation: midpoint check per duty tick, advance on
  spawn_blocking via clone-advance-swap so signing never waits,
  advanced key persisted by atomic replace (bounds startup catch-up
  by downtime, not node age), panic-containing sign wrapper, startup
  catch-up gated before validator readiness.

Grounded in leanSpec cce7955 (epoch = slot; two keys per validator;
deterministic signatures; no slashing) and leanSig c08a3ba (no reuse
guard; panics outside the ~6-day prepared window; no loader exists),
plus a four-client survey (ethlambda e16f477, ream 842a709, zeam
6495beb, qlean-mini 55b6eb3): none persists signing state; ream never
advances the window; zeam falls back to one key for both roles.

* docs: close the first cold-start round on key management

- Startup: key preparation is verity-validator's own init task, runs
  in parallel with chain startup (needs no consensus state); duty
  readiness is a join of two independent gates (first ChainView AND
  keys prepared), not a step inserted into the lifecycle sequence.
- Absent watermark row = normal first-run state, first sign creates
  it; the fail-closed clock-rewind condition is watermark >= current
  slot, matching the sign path's own comparison.
- State why the original key stays signable during clone-advance:
  midpoint advancing makes old and new windows overlap ~3 days around
  the current slot.
- Advanced-key persistence: the spawn_blocking worker writes the file
  (atomic temp+rename) before returning the clone; write failure is
  non-fatal (watermark, not the key file, carries no-reuse).

* docs: reconcile validator startup between the concurrency and key docs

The second cold-start round found the one remaining defect: CONCURRENCY.md
said validator-duty tasks 'start' only after the first ChainView, while
KEY_MANAGEMENT.md ran key preparation in parallel with chain startup.
Resolve it on both sides: the first ChainView gates *serving*, not
construction — the binary spawns the validator task at process start,
its key preparation runs in parallel with chain startup, and the duty
loop serves only on the join of (first ChainView observed) and (keys
prepared).

* docs: state that the first ChainView is a necessary, not sufficient, serving gate

Third cold-start round: CONCURRENCY.md alone read as if ChainView were
the only serving gate, while KEY_MANAGEMENT.md adds a second gate for
the duty loop (keys prepared). Name the rule in CONCURRENCY.md itself:
ChainView is necessary for every component, components may add their
own conditions, and validator-duty is the named case.

* chore(lint): allow the leanSig commit SHA c08a3ba as an identifier

typos tokenizes the abbreviated SHA and flags its trailing 'ba' as a
typo of 'by'/'be'; the SHA is cited in KEY_MANAGEMENT.md.

* docs: settle the sync pipeline (#24)

* docs: settle the sync pipeline

Settle design area 3 of the client-specific design campaign: how
Verity joins the network and catches up. Pays the two debts recorded
by CONCURRENCY.md and KEY_MANAGEMENT.md: the gap-noticing mechanism
(the verification stage signals awaited/evicted parent roots to the
sync service) and the peer-scoring policy.

Decisions:
- Lifecycle: the reference node's IDLE -> SYNCING -> SYNCED machine;
  trigger = our head below the majority-voted network finalized slot
  (not head-lag - zeam's documented deadlock; not max - one liar);
  continuously re-evaluated (Status re-exchanged periodically, unlike
  ethlambda/qlean-mini's once-per-connection); duties require SYNCED
  as the duty loop's third serving gate; checkpoint sync is an HTTP
  entry procedure verified at ethlambda depth, fail-closed with no
  silent fallback.
- Fetch pipeline: sync service as its own I/O Edge task; small gaps
  by BlocksByRoot (capped walk), large gaps by BlocksByRange forward,
  one batch in flight; all fetched blocks pass through the
  verification stage into channel 3 - no side door; structural
  response validation in the sync service feeds the peer score;
  during SYNCING the block topic stays subscribed while attestation/
  aggregation processing pauses.
- Peers: the reference reliability score (100, +10/-20, weighted
  random, never fully excluding, 2 concurrent/peer); transient
  failures never set capability conclusions (TTL'd flags on genuine
  protocol rejection only); invalid gossip is metrics-only (relays
  are not originators under forward-before-verify); no automatic
  disconnects or bans, with named revisit triggers.

Grounded in leanSpec cce7955 (wire contract fixed, behavior free,
reference sync implementation as precedent) and the four-client
survey (ethlambda e16f477, ream 842a709, zeam 6495beb, qlean-mini
55b6eb3).

* docs: close the first cold-start round on the sync pipeline

- Entry: exhaustive three-path decision tree (checkpoint URL given /
  populated DB / empty DB -> genesis); on the checkpoint path DB and
  genesis are not fallbacks.
- Checkpoint failures split: transient fetch errors retry within a
  bounded budget, definitive failures (decode, verification, 4xx)
  exit immediately; exhausted budget fails closed.
- 'Majority vote' defined precisely: median of peers' claimed
  finalized slots, lower-middle on even counts.
- Range pagination terminates on the state machine's own condition,
  read from the watch-published ChainView (no query channel).
- Failure-consequence table: one fixed (score, capability-flag)
  outcome per event class; RESOURCE_UNAVAILABLE is the spec's legal
  answer (no penalty, re-route); the capability flag's only trigger
  is protocol-negotiation failure.

* docs: resolve the second cold-start round on the sync pipeline

- Define checkpoint-root consistency exactly: the fetched anchor
  block's hash_tree_root equals the state's latest_finalized.root,
  and same-slot justified/finalized checkpoints share one root.
- Fix the gap signal's slot field: it is the waiting child's slot
  (the awaited block is known only by root), which upper-bounds the
  gap for the by-root/by-range split.

* docs: align the duty-loop gate count across all three runtime docs

The final cold-start round caught KEY_MANAGEMENT.md and CONCURRENCY.md
still asserting exactly two serving gates while SYNC.md adds a third
(sync state SYNCED). State the same rule in all three places: the join
is of independent conditions - ChainView observed, keys prepared, and
node SYNCED.

* chore: follow the upstream leanMultisig -> leanVM repository rename (#25)

The upstream repo leanEthereum/leanMultisig was renamed to
leanEthereum/leanVM on 2026-08-14 (the old URL redirects). Update
every reference: CLAUDE.md, README.md, ARCHITECTURE.md and its docs
mirror, DOMAIN_MODEL.md, formal-verification.md, the _typos.toml
comment, and the skill set (directory renamed to leanVM; the old name
kept as a legacy trigger; cross-referencing skills updated). First
mentions in prose carry a '(formerly leanMultisig)' note so older
discussions stay traceable.

* feat(types): define the consensus containers as verity-types (#26)

Start the Rust implementation with the crate every other one depends on.
verity-types holds container shapes and their SSZ codec, transcribed field for
field from leanSpec at 0588c2d. Field order is consensus-critical because it
determines hash_tree_root, so the transcription follows leanSpec's order rather
than any reading convenience.

The crate takes no dependency beyond SSZ. leanSpec defines predicates such as
Slot.is_justifiable_after and Checkpoint.advance_to as methods on these
containers; they are omitted here on purpose. Those predicates are the leading
candidates to move into the Verified Core, and binding them to the foundational
crate would make every crate that merely uses a type link the FFI boundary once
that move happens. They land behind the capability that owns them.

The Uint64 newtypes carry hand-written SSZ impls rather than #[ssz(transparent)]
because the derive does not forward is_basic_type. A basic type reporting itself
composite merkleizes one element per chunk instead of packing, producing a wrong
root with no other symptom.

SignedAttestation is not defined: its signature field is an XMSS container from
the signature library, and it lands with verity-crypto.

proptest is introduced for the SSZ round trip only. This narrows the kickoff
decision that no verification harness ships on day one: a codec is one of the few
places the property is writable directly, and leanSpec's fixtures only supply the
shapes the spec happened to generate. The graduated harness of MODEL_CHECK.md is
still introduced later.

Retiring the verity-consensus canary stub removes the last member depending on
leanSig, so cargo pruned the Plonky3 rev pin from Cargo.lock along with leansig,
rocksdb, and libp2p. CLAUDE.md records that the pin must be re-established by
whoever adds leanSig back.

* chore(ci): run checks on develop without deploying PRD from it

develop is DEV and main is PRD, but push triggers only listed main, so
DEV never ran the quality gates. Build and lint on both branches;
docs.verityclient.com still deploys only from main.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <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.

1 participant