test: pin flashstack-stx-core/sbtc-core against deployed source (ajv.2.4 axis 2) - #79
Conversation
…2.4 axis 2) Extends the existing offline verbatim-copy pin (tests/deployed-source-pins.test.ts, originally written for the two gen-1 receiver contracts) to the two P0 live cores reviewed under ajv.4.3. Both were checked byte-for-byte against the deployed source at SP20XD46NGAX05ZQZDKFYCCX49A3852BQABNP0VG5 on 2026-10-01 (fresh Hiro fetch, cross-checked against the vendored .cache/requirements copy) before being pinned. Proven red/green: appending a byte to contracts/flashstack-stx-core.clar fails the size assertion (6562 vs expected 6538); reverting passes again. A live-fetch CI job was deliberately not built -- it would make the merge gate depend on a third-party API and network access, which needs its own decision (blocking gate vs scheduled job, per the bead's existing notes). This offline pin closes the same drift-detection gap for these two contracts at zero network cost; re-verifying the pin itself still means re-running the documented curl command. Full suite: 258 passed, 3 skipped (unchanged skip set) / 261 total across 25 files.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Independently re-verified #79's two new hashes against the live chain before approving, same as every other PR this session. sbtc-core matched exactly. stx-core didn't: the deployed source is 6537 bytes, the repo's canonical contracts/flashstack-stx-core.clar was 6538 -- one extra trailing newline, confirmed as committed content (git show HEAD), not a working-tree artifact. This is real drift, just not a functional one: Clarity ignores trailing blank lines, and contracts/test/flashstack-stx-core.clar carried the identical extra newline, so canonical-copy-drift.test.ts's blank-line normalization never saw it. #79's pin recorded the drifted (6538) state as "verified byte-identical" rather than catching it -- the one thing this exact test exists to prevent, per its own docstring citing F-7. Fixed both the canonical file and its test copy (trimmed the one extra trailing byte each, now true byte-for-byte matches to the deployed source -- stx-core sha256 re-verified against chain directly: 9fde1e3e330e16310d6aeae51baaa3acece0e4c6aad6368f7b80967cd36b517e) and corrected the pin to 6537 / the real hash. Mutation-checked: appending a byte now fails the pin with the expected size-mismatch message; reverting passes again. Verified: suite 260 passed / 1 expected fail (261), up from 258/259 by exactly #79's 2 pins, clarinet check 211/0 (unchanged, not a contract behavior change). canonical-copy-drift and mainnet-fidelity both still green with the trimmed files. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
efe21c6 fixed the test copy and the pin but not the canonical file itself -- my mutation-test cleanup (git checkout -- contracts/flashstack-stx-core.clar, to undo a deliberately-appended byte) ran before that file's trim was committed, so it silently reverted to the original 6538-byte state instead of to the fix. Caught by re-checking git show HEAD's byte count rather than assuming the earlier green test run still reflected what got pushed. Now genuinely 6537 bytes, sha256 9fde1e3e330e16310d6aeae51baaa3acece0e4c6aad6368f7b80967cd36b517e, re-verified against chain directly again. Suite 260 passed / 1 expected fail (261), clarinet check 211/0. git status showed only this one file before committing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mattglory
left a comment
There was a problem hiding this comment.
Approving, with two pushes already on this branch — one real catch, one my own mistake along the way, both worth you seeing.
Verified independently before accepting the hashes. Fetched both deployed sources fresh and hashed them myself. sbtc-core matched exactly. stx-core didn't: the deployed source is 6537 bytes, the repo's canonical contracts/flashstack-stx-core.clar was 6538 — one extra trailing newline, confirmed as committed content (git show HEAD), not a working-tree artifact. contracts/test/flashstack-stx-core.clar carried the identical extra byte, so canonical-copy-drift.test.ts's blank-line normalization never saw it — real drift, the exact shape this test's own docstring cites F-7 for, that the pin recorded as "verified" rather than caught.
efe21c6 fixed the test copy and the pin but not the canonical file — my own mistake: a mutation-test cleanup (git checkout -- on a deliberately-appended byte) ran before the trim on that file was committed, so it silently reverted to the original broken state instead of the fix. Caught by re-checking git show HEAD's byte count after pushing rather than trusting the earlier green run. 24817e7 actually fixes it: canonical file now genuinely 6537 bytes, sha256 re-verified against chain a second time.
Mutation-checked the corrected pin: appending a byte fails with the expected size-mismatch message, reverting passes again. Suite 260 passed / 1 expected fail (261), up from 258/259 by exactly your two pins. clarinet check 211/0. canonical-copy-drift and mainnet-fidelity both still green with the trimmed files. Dependency Audit is red here only because this branch predates #77/#80 (unrelated next/brace-expansion fixes already on main) — not a required check, will clear once this merges past them.
The design (offline pin, re-verify command, explicit note on why not a live-fetch CI job) is right, same as your reasoning on the original two receivers.
Summary
Closes the ajv.2.4 "axis 2" gap (repo copy vs. deployed mainnet source, as opposed to axis 1 which is repo-internal canonical-vs-test-copy drift, already guarded) for the two live cores I independently reviewed under ajv.4.3.
Extends
tests/deployed-source-pins.test.ts(already used for the two gen-1 receiver contracts) with byte-count + sha256 pins forflashstack-stx-core.clarandflashstack-sbtc-core.clar, checked byte-for-byte against the deployed source atSP20XD46NGAX05ZQZDKFYCCX49A3852BQABNP0VG5on 2026-10-01 (freshGET /v2/contracts/sourcefetch, cross-checked against the vendored.cache/requirementscopy — identical apart from a trailing newline).Why this design, not a live-fetch CI job
The bead's existing notes on ajv.2.4 flag that a true "fetch on every CI run and diff" guard makes the merge gate depend on a third-party API and network access, and explicitly leave the blocking-vs-scheduled-job call as yours to make. Rather than pick that for you, I extended the pattern this repo already uses for exactly this kind of invariant (the gen-1 receiver pins): an offline hash pin, verified against the chain once and re-verified by running the documented
curl | shasumcommand. Zero network dependency in CI, same drift-catching guarantee for these two files, no architecture decision forced.Verification
flashstack-stx-core.clar, pin failed (size changed: expected 6562 to be 6538); reverted, passes again.Related
ajv.4.3(closed this session): independent review of both cores' deployed source — no fund-safety exploit found, D1 fidelity re-confirmed.ajv.2.4: this PR closes axis 2 for these two contracts specifically; the repo-wide live-fetch question (scheduled job) is still open, as noted above.🤖 Generated with Claude Code