Skip to content

feat(dlv): a trader can find and verify the owner's reserve proof - #765

Merged
cryptskii merged 1 commit into
mainfrom
feat/dlv-reserve-consumption-producer
Sep 4, 2026
Merged

feat(dlv): a trader can find and verify the owner's reserve proof#765
cryptskii merged 1 commit into
mainfrom
feat/dlv-reserve-consumption-producer

Conversation

@cryptskii

Copy link
Copy Markdown
Collaborator

Summary

Step one of the 0x0026 producer: a trader can now find and verify the owner's reserve proof. Both of the trader-side blockers were the same missing thing.

admitted create publishes EconomicProofArtifactV1
        ↓
vault record stamps (addr, position)
        ↓
routing advertisement carries them          ← a LOCATOR, on an unsigned object
        ↓
trader resolves the position's root from the OWNER's write-once register cell
        ↓
fetches by content address, re-derives every inclusion path against that root
        ↓
verified reserve leaves

What had no source

The 0x0026 arm needs the owner's two reserve leaves with their 256-sibling paths, and owner_economic_position. The paths existed only inside the owner's own tree — the artifact that carries them shipped last cut, but its content address was carried by no published object. And nothing anywhere mapped a vault, or a (genesis, device) pair, to an economic position: the register key is a hash over the position, so it is not enumerable, and the lineage walk takes the position as an input.

The locator is never believed

The advertisement is unsigned and this change does not make it authoritative. A reader resolves the position's root from the publisher's own register cell and recomputes every leaf key, commitment and path against it. A wrong address or position can only make the lookup fail; it cannot produce leaves under a root the owner did not register. Two arms of the test are exactly that.

piece change
AdmittedOutcome carries the published artifact's content address
dlv.create stamps (addr, position) after the admitted create; a funded create that published no artifact is refused, since it always writes two reserve leaves
amm_vault_records two columns, read back as one Option — both halves or neither; a present address of the wrong width drops the row as a bad policy commit does; narrow updater refuses a zero address
RoutingVaultAdvertisementV1 new fields 15 and 16, filled by the publish route from the record, never from the request
verified_owner_reserve_leaves the trader's read: lineage walk → fetch → recompute → filter to this vault

Wipe boundary

Client schema 12 → 13. CREATE TABLE IF NOT EXISTS does not add columns to an existing file, so an older database is structurally invalid and enforce_schema_version refuses it by design. No migration, deliberately; beta runs on dsm-testnet with no production user state. Recorded in CHANGELOG.md.

Proof

check result
two devices: owner creates and publishes; a trader with no record of the vault finds the ad through storage alone and verifies both reserve legs at the create's vault generation green
a locator naming another position, or another artifact, yields nothing green
mutation: the stamp's UPDATE, the ad's fill from the record, the reader's verification each reddens only its own named test; restored checksum-verified
boards workspace 74 binaries, 3965 passed / 0 failed / 17 ignored (dsm lib 1692/0, dsm_sdk lib 1814/0/7 ignored), exit 0; node 11 binaries, 276/0, exit 0; root make lint exit 0; frontend type-check 0, lint 0, jest 1101 passed; ci/production_safety_checks.sh PASS (pinned 1.98.0, incl. TLA+); scripts/ci_scan.sh PASS — all on tree stamp 842c29c0ac4b, identical before and after every run

Two mutation attempts were no-ops that proved nothing and were redone. One of them was informative: it showed this test does not isolate the artifact verification, because the lineage walk fails first — that gate's real control is the artifact's own test, where the wrong position is handed straight to the reader.

Not in this PR

The 0x0026 bundle itself. ReserveConsumptionEvidenceV1 still carries its own leaf and path fields instead of consuming the generic artifact, and nothing builds one. That is the next cut, which this one exists to make possible.

The generic proof artifact landed with nothing pointing at it. Its content
address was carried by no published object, and nothing anywhere mapped a
vault to its owner's economic position, so the two inputs the 0x0026 arm needs
from the owner's side — the reserve leaves' 256-sibling inclusion paths, and
the position whose registered root they prove into — had no source a
counterparty could reach. Both are the same missing thing: a locator.

    admitted create publishes the artifact
            -> record stamps (addr, position)
            -> routing advertisement carries them
            -> trader resolves the position's root from the OWNER's register
            -> fetches by content address, re-derives every path
            -> verified reserve leaves

The locator is untrusted at every hop, and the advertisement is unsigned. A
reader never believes either half: it resolves the root from the publisher's
own write-once register cell and recomputes the inclusion paths against it. A
wrong address or position can only make the lookup FAIL — it cannot yield
leaves under a root the owner did not register — and what it does yield is
still just "what that root committed", never "the state you should trade
against".

- `AdmittedOutcome` carries the artifact's address, so the create can stamp
  what it just published. A funded create always writes two reserve leaves, so
  a missing artifact is a contradiction between the route and the producer and
  is refused rather than left to surface later as an unexplained absence.
- `amm_vault_records` gains `economic_proof_addr` + `economic_proof_position`,
  read back as one `Option` — both halves or neither, a present address of the
  wrong width dropping the row exactly as a bad policy commit does. Written by
  a narrow updater that refuses a zero address.
- `RoutingVaultAdvertisementV1` carries the same pair; the publish route fills
  it from the record, never from the request, like the policy digest and the
  baseline beside it.
- `verified_owner_reserve_leaves` is the trader's read: lineage walk to the
  owner's validated root, fetch, recompute, filter to this vault.

Proven across TWO DEVICES: the owner creates and publishes; a trader on its
own database, holding no record of the vault, finds the ad through storage
alone, and turns the advertised pair into both reserve legs at the create's
vault generation. A locator naming another position, or another artifact,
yields nothing. Three mutation cycles — the stamp's UPDATE, the ad's fill from
the record, and the reader's verification — each reddening only its own named
test, restored checksum-verified. Two earlier attempts were no-ops that proved
nothing and were redone; one of them showed this test does not isolate the
artifact verification, which its own test does.

WIPE BOUNDARY (CHANGELOG): client schema 12 -> 13. `CREATE TABLE IF NOT
EXISTS` does not add columns, so an older database is structurally invalid and
is refused by design. No migration, deliberately.

NOT in this change: the 0x0026 bundle itself. `ReserveConsumptionEvidenceV1`
still carries its own leaf and path fields rather than consuming the generic
artifact, and nothing builds one. That is the next cut, which this one exists
to make possible.

Boards: workspace 74 binaries, 3965 passed / 0 failed / 17 ignored (dsm lib 1692/0, dsm_sdk lib 1814/0/7 ignored), exit 0; node 11 binaries, 276/0, exit 0; make lint exit 0; frontend
type-check, lint and jest green; production safety PASS (pinned 1.98.0);
ci_scan PASS.
@cryptskii
cryptskii merged commit d4f3c13 into main Sep 4, 2026
18 checks passed
@cryptskii
cryptskii deleted the feat/dlv-reserve-consumption-producer branch September 4, 2026 03:50
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