Skip to content

fix(sofi): the verifier's reads are Core's, and the chain memo is anchored and linked - #1013

Merged
cryptskii merged 2 commits into
mainfrom
fix/sofi-verifier-reads-in-core
Sep 26, 2026
Merged

cryptskii merged 2 commits into
mainfrom
fix/sofi-verifier-reads-in-core

Conversation

@cryptskii

Copy link
Copy Markdown
Collaborator

What

The SoFi verifier's reads are Core's, and the recorded vault chain is stood on only anchored at the genesis Core accepts and linked row to row. Follows #1011 (the facts and the ladder), on the owner's "get the real wire in": what is read, in what order, and what it establishes are now all decided in Core; the SDK answers reads with bytes, cells and this device's own rows, and nothing else.

Placeholder sweep, C5. CONFORMANCE_GAPS.md §6.30 records the finding and the state.

The finding

After #1011 the facts were Core's, but the SDK still decided what to read (sofi_resolve.rs, sofi_chain.rs, sofi_evidence.rs, sofi_register.rs), with acquisition rounds and budgets of its own, and the recorded vault chain was a Vec of roots read back from sofi_vault_root rows that nothing checked and that record_resolved_with_conn overwrote on conflict — a rows-of-roots puncture standing in for the chain.

How

  • dsm/src/sofi/resolve.rs (new): Verifier<R: SofiReads> — read_registration, read_attempt_cell, acquire_conformance_evidence, acquire_evidence, vault_genesis (candidates, the owner's walk, genesis_accepted with the token policies it names), chain (the genesis first, then one Core-recomputed consumption at a time), walk_parent / continue_walk (a resumed walk carries what it classified, so a walked key's liveness is a real walk from key zero), establish_own. Every cell derived by Core from committed state, every read evaluated by Core, every object recognized by Core, every predicate recomputed by Core, every budget Core's. LocalLeaves, VaultGenesis, Acquired move into Core.
  • SofiReads (Core trait) ← dsm_sdk/src/sdk/sofi_reads.rs::LiveSofiReads: block_in_place + block_on on the multi-thread runtime, the shape LiveRegisterResolver already gives the peer lineage walk. sofi_resolve.rs, sofi_chain.rs, sofi_evidence.rs deleted; sofi_register.rs keeps the install; sofi_exercise.rs keeps the build and the write; sofi_advance, sofi_flow and the node e2e tests call the Verifier. A relay verifies with no standing of its own (local: None → NoSource for any trader's leaves).
  • The memo: sofi_vault_root (client DB schema 24) records, past genesis, the root each generation was built on and the E of the operation that consumed it (VaultPostState::consumed_by). VaultChain::from_recorded(genesis, rows) stands on the rows only anchored at the genesis accepted from the network now and linked row to row — row zero is the accepted root, every later row is built on the one before it and names its consumption, generations are contiguous — and anything else is MemoBroken, a refusal. write_root refuses a different root or a different link at an established generation: a record is written once and stands. The unchecked constructor is gone.
  • ci/sofi_validated_root_constructors.sh §5 pins from_recorded to its one production caller (the verifier's chain walk) and fails if the unchecked constructor returns; ci/admitted_predecessor_readers_fenced.sh classifies the moved reader; complete_pending_fulfillment crosses descendant_fence on its way to the pending position's install.

Verification (release, dsm_client/deterministic_state_machine, on the rebased tree)

  • cargo test --locked --release -p dsm --lib sofi:: -- --test-threads=1 → dsm sofi 211/0 (the facts, advance, walk and anchored-memo tests).
  • cargo test --locked --release -p dsm_sdk --lib -- sofi node_e2e_tests --test-threads=1 on the storage node's own code on Postgres → dsm_sdk sofi + node_e2e 11/0 (the whole resolve path through the Core verifier: realized trades, the chain walk, a refuted exercise, RetriesExhausted, the genesis-candidate rule; the memo writer's refusals and the linked read).
  • make lint → exit 0. ci/production_safety_checks.sh (incl. the conformance-evidence check of every cited item), ci/sofi_reachability.py (99 reachable, 3 baseline), ci/sofi_validated_root_constructors.sh, ci/sofi_no_default_evidence.sh → pass. cargo ndk … check --features=jni,bluetooth → exit 0. cargo check -p dsm_vertical_validation → clean. lean -DwarningAsError=true lean4/DSMSofiAtomicity.lean → clean.

Mutation controls (run, restored)

  • VaultChain::from_recorded taking the rows as recorded, neither anchored nor linked → dsm::sofi::resolution::tests::the_memo_becomes_a_chain_only_anchored_at_the_genesis_and_linked_row_to_row red.
  • write_root updating the root on conflict → dsm_sdk::storage::client_db::sofi_vault_head::tests::an_established_generation_is_never_rewritten red.
  • (fix(sofi): the verdict is Core's — facts built from reads, the ladder inside the advance #1011's controls stand unchanged: the advance installing Realized regardless; the walk's key binding removed; liveness read off a walk not from key zero; TLA InstallFromCaller.)

Open (recorded in §6.30)

  • What a recorded generation memoizes — that its consumption happened — is not re-established from the network on a later walk; anchoring and linking are what can be checked without walking again.
  • P15-9 stays: the peer walk still refuses a resolved SoFi position; the verifier that could establish one is Core's now, and wiring it into the peer walk is that round's work.
  • Another trader's route stays unresolvable by a foreign verifier (NoSource, §6.5).

…hored and linked

The facts were Core's since the previous change; what was read, and in
what order, was still the SDK's: sofi_resolve.rs, sofi_chain.rs and
sofi_evidence.rs decided which cells and objects to fetch, with
acquisition rounds and budgets of their own, and the recorded vault chain
was a Vec of roots read back from rows nothing checked and that
record_resolved_with_conn overwrote on conflict.

dsm::sofi::resolve::Verifier is the verifier now, over a SofiReads trait
the SDK implements with bytes, cells and this device's own rows and
nothing else — the shape of the peer lineage walker. It reads the
position pair, the attempt cells, the objects conformance and validation
consume, a vault's genesis candidates and its owner's walk, and walks a
vault's chain from the genesis it accepts, one Core-recomputed
consumption at a time; every cell is derived by Core, every read
evaluated by Core, every object recognized by Core, every budget Core's.
LocalLeaves, VaultGenesis and Acquired move into Core. The SDK's
sofi_reads.rs answers reads with block_in_place on the multi-thread
runtime, as LiveRegisterResolver does; the three SDK orchestration
modules are deleted, sofi_register keeps the install, sofi_exercise the
build and the write, and sofi_advance, sofi_flow and the node e2e tests
call the Verifier.

The memo: sofi_vault_root (schema 24) records, past genesis, the root
each generation was built on and the E of the operation that consumed
it (VaultPostState::consumed_by). VaultChain::from_recorded stands on
the rows only anchored at the genesis accepted from the network now and
linked row to row — row zero is the accepted root, every later row is
built on the one before it and names its consumption, generations are
contiguous — and anything else is MemoBroken, a refusal. write_root
refuses a different root or link at an established generation, so a
record is written once and stands. The unchecked constructor is gone,
and the CI gate pins from_recorded to its one caller, the chain walk.

Verification (release): dsm sofi:: 211/0; dsm_sdk sofi + node_e2e_tests
11/0 on Postgres; make lint exit 0; production safety checks, the SoFi
gates, the Android jni,bluetooth check and the vertical-validation tool
clean. Mutation controls: from_recorded taking the rows as recorded, and
write_root updating on conflict, each turn their named test red;
restored. CONFORMANCE_GAPS §6.30 and VERIFICATION_MATRIX record the
state and what stays open (the memo's consumptions are not re-established
on a later walk; P15-9).
#1011 registered SofiFulfillment/install-on-caller-value and
SofiFulfillment/install-reachable in the vertical-validation runner
without moving EXPECTED_STANDARD_SPECS, so the registry test — and the
Formal Validation job on main — went red on a count of 87 against 85.
The tripwire exists to make an added or removed spec a deliberate act;
87 is now the deliberate number, with the two entries named beside it.

dsm_vertical_validation tests 28/0.
@cryptskii
cryptskii merged commit b045705 into main Sep 26, 2026
19 of 21 checks passed
@cryptskii
cryptskii deleted the fix/sofi-verifier-reads-in-core branch September 26, 2026 06:09
cryptskii added a commit that referenced this pull request Sep 26, 2026
…ice (#1017)

Main's SDK board was red on
sdk::sofi_reads::tests::an_unestablished_genesis_candidate_is_not_read_as_unpublished
since #1013: the test started the nodes but no device, and VerifierContext
reads the committed network from this device's stored genesis, so it failed
("no genesis identity") wherever no earlier test had left an identity behind
— and passed in targeted runs only because node_e2e_tests ran first. It now
boots a Device (storage dir, nodes on Postgres, a created and published
identity), as the admission tests do; the assertions are unchanged.
cryptskii added a commit that referenced this pull request Sep 26, 2026
… board (#1019)

The Rust tests (dsm_sdk) job of 97d6d55 (run 36226702605): 46 failed of
1020; 45 on the ERA refusal at an ERA transfer or burn, listed by name in
§6.32; the one other, sofi_reads' unestablished-genesis-candidate test, is
main's pre-existing red (#1013) fixed by #1017 and is named as such.
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