Skip to content

One plan doc asserted that no SHA-256 computation exists in .dag; it does, and the real blocker is a different one - #11997

Merged
briansrls merged 2 commits into
mainfrom
storage-substrate-laws
Sep 22, 2026
Merged

briansrls merged 2 commits into
mainfrom
storage-substrate-laws

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

DRAFT for operator read. Doc-only.

docs/plans/dag-native-scm-design.md §5 and open question 2 both assert that no SHA-256 computation exists in .dag — "std.content_hash sha256_hex_digest and extdeps.crypto.hash sha256_digest validate hex; they do not hash bytes."

That was true when written and is not now. extdeps.crypto.sha2 computes SHA-256 in the substrate (sha256, sha256_hex, FIPS 180-4), witnessed by test.claim.sha256_fips_witness. I asserted the same stale fact myself earlier in this lane, from a search scoped to dag/std/ that never looked in extdeps/crypto/.

Why that witness is evidence rather than a restatement of the type — the part easiest to get wrong, and the reason it can be cited at all: sha2 never relies on the type to wrap. Every 32-bit operation routes through std.bitwise, whose word32_add takes the modulus explicitly (if a >= word32_modulus - b { a - (word32_modulus - b) } else { a + b }), so the interpreter's unbounded-Int evaluation yields the same residues and a wrong wrap changes the digest. Cite it for the computation, never as evidence that UInt32 wraps — the filed class bounded_natural_arithmetic_evaluated_as_unbounded_int is untouched by this.

What the doc now says instead

The dissolve-on condition was "a computing cryptographic digest reachable from .dag". It is half met, so it is restated as what remains rather than deleted: v2.std.node Hash minted from a cryptographic family, gated on native emission of the sha2 closure.

Also recorded here, because this note would otherwise invite the wrong arm: gunbc#11996 refused the shell-out realization for a structural reason, not an economic one. fabric_object_preimage produces bytes in memory, so a shell transport over a file path means a temp-file write per object — which manufactures the custody gap (hash one file, store another) that verification exists to close. Worth having in the doc so the next reader does not re-derive it from the throughput numbers, where it looks like a close call.

Scope note

The matching stale bullet in docs/plans/fabric-storage.md is deliberately not touched. gunbc#11996 is already editing that file and is the authority for the fabric half; correcting it in two PRs would be the §3 fork this repo exists to avoid. I had written that hunk and dropped it.

Related

  • gunbc#11996 (nimble-hawk-154) — the digest migration and #11819.
  • gunbc-private#165 — the two storage laws this correction was found underneath.

🤖 Generated with Claude Code

…does, and the real blocker is a different one

docs/plans/dag-native-scm-design.md section 5's "Verified:" paragraph and open question 2 both
say no SHA-256 computation exists in .dag, with "std.content_hash sha256_hex_digest and
extdeps.crypto.hash sha256_digest validate hex; they do not hash bytes". That was true when
written and is not now: extdeps.crypto.sha2 computes SHA-256 in the substrate (sha256,
sha256_hex, FIPS 180-4), witnessed by test.claim.sha256_fips_witness.

Why that witness is evidence rather than a restatement of the type, since it is the part
easiest to get wrong: sha2 never relies on the type to wrap. Every 32-bit operation routes
through std.bitwise, whose word32_add takes the modulus explicitly, so the interpreter's
unbounded-Int evaluation yields the same residues and a wrong wrap changes the digest. Cite it
for the computation, never as evidence that UInt32 wraps.

The dissolve-on condition was "a computing cryptographic digest reachable from .dag", which is
now half met, so it is restated as what remains rather than deleted: v2.std.node Hash minted
from a cryptographic family. std.fabric_storage's refs are being moved onto the pure kernel in
gunbc#11996, and that PR's reason for refusing the shell-out arm is recorded here because this
note would otherwise invite it -- fabric_object_preimage produces bytes IN MEMORY, so a shell
transport over a file path costs a temp-file write per object, which manufactures the custody
gap that verification exists to close.

SCOPE NOTE: the matching stale bullet in docs/plans/fabric-storage.md is deliberately NOT
touched here. gunbc#11996 is already editing that file and is the authority for the fabric
half, so correcting it in two PRs would be the fork DESIGN section 3 forbids.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@briansrls
briansrls marked this pull request as ready for review September 22, 2026 03:00
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-22T03:03:55.584304Z 30b79d6 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 30b79d6cd0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +204 to +207
remains, and it is gated on native emission of the `sha2` closure — blocked by
`gunbc.recurring_failure_mode` `bounded_natural_arithmetic_evaluated_as_unbounded_int`, whose
prerequisite is `MachineWidth<N>` reified as a value. Both halves are owned by the lane holding
`#11819`; open question 2 below is narrowed accordingly rather than closed.

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 Badge Remove the spurious MachineWidth reification gate

This incorrectly makes the v2.std.node migration contingent on #11819. dag/std/bounded_nat.dag:20-29 explicitly says reification is not required for the first consumer because std.bitwise can pass bit_width(count: 32) today; it identifies the actual blocker as the std.bounded_nat/std.bitwise import cycle, followed by threading BoundedNatArith through SHA-256. Leaving this dependency here directs the migration lane to wait for an unrelated prerequisite while omitting the work that actually enables native emission.

Useful? React with 👍 / 👎.

rather than implying cross-party agreement it cannot support. **Dissolve-on:** a computing
cryptographic digest reachable from `.dag`.
do not hash bytes)". That was true when written. `extdeps.crypto.sha2` now computes SHA-256 in the
substrate (`sha256`, `sha256_hex`, FIPS 180-4), witnessed by `test.claim.sha256_fips_witness` — and

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 Badge Use the declared witness module name

The cited module does not exist under this name: dag/test/claim/sha256_fips_witness_test.dag:1 declares test.claim.sha256_fips_witness_test. A reader attempting to resolve or execute the evidence named here will get a missing-module result, undermining the correction's verification trail.

Useful? React with 👍 / 👎.

… parameter

Review 69880 (non-blocking). The load-bearing claim -- no value transits
above 2^32-1, so unbounded-Int evaluation yields the same residues -- was
right; the mechanism named beside it was not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@briansrls
briansrls added this pull request to the merge queue Sep 22, 2026
Merged via the queue into main with commit 9f25cc5 Sep 22, 2026
4 checks passed
@briansrls
briansrls deleted the storage-substrate-laws branch September 22, 2026 18:22
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