Skip to content

chore: vendor consensus.h and uint256.h, and use them - #609

Merged
Zyrtnin merged 2 commits into
mainfrom
chore/vendor-consensus-and-uint256
Sep 4, 2026
Merged

chore: vendor consensus.h and uint256.h, and use them#609
Zyrtnin merged 2 commits into
mainfrom
chore/vendor-consensus-and-uint256

Conversation

@Zyrtnin

@Zyrtnin Zyrtnin commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Closes the two highest-value gaps in the consensus oracle. 44% of pyrxd's 112 citations into Radiant Core point at files that aren't vendored, so nothing can check them — which is exactly how #592 happened: validation.h was cited in comments, not vendored, the ref backing-subset rule lives in it, and a verifier shipped calling forged collection membership authentic.

local upstream sha256
consensus.h src/consensus/consensus.h c344ba58…
uint256.h src/uint256.h e4cc8933…

I re-fetched both from upstream independently and confirmed the digests match the vendored files and the manifest.

The uint288 comparator supports the sighash claim — the citation didn't

transaction_preimage.py claims refs hash "ascending by the uint288 numeric value … little-endian". Verified myself: Compare starts at WIDTH - 1 and counts down, commented "compare MSB-first (in reverse because data is little endian)". So ref[::-1] is right.

The citation was wrong, not the rule — primitives/transaction.h holds the std::set<uint288> but no comparator. Corrected the citation, not the rule. That distinction matters: rewriting the rule to match a bad citation is how the inverted timelock got its authority.

Now checkable that wasn't

  • MAX_SCRIPT_STACK_MEMORY_USAGE = 128,000,000 and MAX_SCRIPT_OPCODE_COST = 1,000,000,000. Note ONE_MEGABYTE = 1000000, not 2²⁰ — reading it as a power of two overstates the ceiling by 6.3 MB. pyrxd has no constant for either (no interpreter), so they're pinned in the test, with the set of budgets derived from EvalScript's own comparisons rather than hand-listed.
  • The ref sort order as a real differential, run against production _get_push_refs on a ref pair whose little- and big-endian orders disagree, plus a non-vacuity test asserting they disagree.

It found the same hand-kept list I did

test_vendored_sources_match_manifest_digest was parametrized over two of eight filenames — structurally correct, hand-kept about its set, and would have passed vacuously over both new files. Now derived from the manifest, both directions closed.

⚠️ That overlaps #592, which makes the same fix. Test-merged: 4 files conflict (refresh_radiant_core_vendor.py, consensus_oracle.py, test_consensus_opcode_parity.py, MANIFEST.json). Whichever merges second needs a manual resolve — the two changes agree in intent, so it should be mechanical.

Six plants, each caught, each restored and confirmed with git status --porcelain.

Verified independently: 11,013 passed, 192 skipped, 1 xfailed.

🤖 Generated with Claude Code

Mudwood Labs and others added 2 commits September 3, 2026 22:24
pyrxd's Python carries citations into Radiant Core for the rules it
re-implements. A citation is only evidence if the cited file is here, and
two of the load-bearing ones were not:

* `interpreter.cpp` enforces MAX_SCRIPT_STACK_MEMORY_USAGE (128,000,000)
  and MAX_SCRIPT_OPCODE_COST (1,000,000,000) and declares neither. Their
  VALUES were uncheckable by anything in the repo.

* `transaction_preimage.py` claims an output's refs are hashed ascending by
  little-endian uint288 value and cites `src/primitives/transaction.h`.
  That header holds the `std::set<uint288>`; it does not define the order.
  The order is `base_blob::Compare` (walks m_data from WIDTH-1 down, so
  byte[35] is most significant) and `operator<` (`Compare(...) < 0`) in
  `src/uint256.h`. The claim IS correct — now shown against the C++ rather
  than asserted. Sorting the raw bytes instead made dMint contract-output
  signing fail about half the time.

Both files are vendored at the pin already in MANIFEST.json (v3.1.2,
45e0aa40) via scripts/refresh_radiant_core_vendor.py, and `--check` reports
them identical at v3.1.1, the tag the regtest image's binary is built from,
so the source/image gap the README documents still holds.

New in the oracle: `consensus_limit` (a separate parser — consensus.h uses
`inline constexpr` with expression initialisers over ONE_MEGABYTE, which is
1,000,000 and not 2^20), `script_budgets_enforced_by_interpreter` (derived
from EvalScript's own comparisons, so a budget added upstream fails the pin
rather than being missed), and the uint288 comparator extractors feeding
`uint288_sorted`, which the differential runs against the production
`_get_push_refs` on a ref pair whose little- and big-endian orders DISAGREE.

Also fixes the digest check itself. It was parametrised over
`["script.h", "script.cpp"]` while eight files were vendored — structural
about the digest, hand-kept about the set, and so vacuous for everything
added after it was written. It now derives its parameters from the manifest
(10 files, up from 2), with both other directions closed: a file on disk
with no manifest entry, and a manifest entry the refresh script would never
re-fetch.

Six plants, each restored and confirmed with `git status --porcelain`:

1. one byte changed in consensus.h -> only the [consensus.h] digest case
   fails (9 others pass), so the new file really is covered
2. same in uint256.h -> only [uint256.h] fails
3. Compare's loop flipped to ascending in uint256.h -> 4 uint288 tests fail,
   including the differential through production `_get_push_refs`
4. uint64_t(128) -> uint64_t(129) in consensus.h -> the budget pin fails
5. one interpreter.cpp comparison retargeted at MAX_COINBASE_SCRIPTSIG_SIZE
   -> "no enforced budget is unpinned" fails on a name it was not built from
6. a stray .h dropped in the vendor dir -> the coverage test fails

Full offline suite: 11005 passed, 197 skipped, 4 xfailed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Zyrtnin
Zyrtnin merged commit 74d809c into main Sep 4, 2026
15 checks passed
@Zyrtnin
Zyrtnin deleted the chore/vendor-consensus-and-uint256 branch September 4, 2026 08:40
Zyrtnin pushed a commit that referenced this pull request Sep 4, 2026
#592 vendors validation.h (where the ref backing-subset rule lives, and whose
absence let a verifier ship reporting forged collection membership as authentic);
#609 vendors consensus.h and uint256.h (the two script budgets, and the uint288
comparator behind the sighash ref ordering). Different files, so the resolution
is the union - verified three ways: the FILES map, MANIFEST.json and the vendor
directory all agree on the same 11 files.

Both branches independently added an every-file-is-digest-checked guard, having
found the same hand-kept list of two. Kept main's, which derives the parametrised
set from the manifest, checks both directions and asserts non-vacuity - it fully
covers what the other did, and two copies of one guard is how they drift apart.
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