test(integration): regtest coverage residuals and test-only contracts - #147
Merged
Conversation
Add integration/contracts/ for fund-safety and language-feature fixtures outside examples/, with a machine-checked coverage matrix. Phase A pins Palmer constructs, MultiSig, raw/data outputs, and 1-byte ByteString state on all seven tiers; TS/Go decode on-chain state/output layout. Soft-warn for multi-null Sig no longer fires on OP_CHECKMULTISIG. Phase B/C language and extract/intent/asm residual contracts ship with TS+Go regtest spends.
icellan
force-pushed
the
feat/regtest-coverage-gaps
branch
from
August 27, 2026 22:19
1c9aeee to
cd7a637
Compare
…scoping The must-move-a-golden gate failed on PR #147: three constructor-slot-splicing paths changed and no pinned byte artifact moved with them. ✗ packages/runar-py/runar/sdk/contract.py ✗ packages/runar-rs/src/sdk/contract.rs ✗ packages/runar-sdk/src/contract.ts The gate matched the FILES, not the change. Each has exactly two hunks: a new read-only OR-CHECKSIG probe, and one added '&& <probe>' conjunct on the existing 'sigIndices.length >= 2' guard around an INFORMATIONAL warning — so a genuine OP_CHECKMULTISIG unlock is no longer told to pass EMPTY_SIG. Neither hunk is in the splicing path, and the probe's result feeds a warn() call and nothing else, so no encoder, offset or byte-producing branch can observe it. Evidence produced BEFORE granting the exception, not asserted: * conformance sdk-output — 59 fixtures x 7 SDKs, rust OK 59 / FAIL 0, exit 0. This is the cross-SDK deployed-locking-hex pin. * conformance sdk-vertical:check — 39 matrix rows match a fresh recompile (the compiler<->SDK byte pin). * conformance corpus 72/72, full vitest 9258 passed / 0 failed. Three earlier sdk-output runs reported rust FAILED; every one was 'Blocking waiting for file lock on build directory' — the runner falls back to 'cargo run' when tools/rs-sdk-tool is not pre-built, and the per-fixture invocations contend on one target dir. Pre-building that binary makes rust pass 59/59. Not a byte divergence, and worth knowing before anyone reads a rust FAIL there as signal. Entries are per-exact-path, pinned to each file's reviewed sha256 (so they authorise this version only and self-invalidate on the next edit), expire 2026-11-26, and print in full on every gate run. The exceptions file requires the entry count to be a deliberate edit to scripts/__tests__/wire-format-pr-audit.test.ts rather than a quiet JSON append, so that assertion is updated to pin the paths, the expiry, the reviewer and the sha256 shape. Doing so surfaced a real interaction: HISTORICAL_110_WIRE_PATHS — the changed set of the #110 incident this gate exists for — CONTAINS packages/runar-sdk/src/contract.ts, so the exception moved it out of wireHits and the '--json' test went 8 -> 7. Lowering that expectation to 7 would delete the property the test holds, so it now asserts wireHits + exceptionsUsed == the historical set, plus set equality on the union: an exception can move a path between buckets, never make one vanish.
icellan
added a commit
to E-Jacko/runar
that referenced
this pull request
Aug 29, 2026
CI's Python SDK job went red on main at a3fc34d with bsv/transaction_preimage.py:77 AttributeError: 'NoneType' object has no attribute 'serialize' across 5 tests. Nothing in that merge touched the Python SDK: bsv-sdk 2.4.0 was PUBLISHED THE SAME DAY (2026-08-28) and pyproject declares 'bsv-sdk>=1.0' with no ceiling, so icellan#147's PR run resolved <=2.3.3 and passed while the merge run resolved 2.4.0 and failed. Same commit content, different dependency. 2.4.0 tightened the batch preimage path: _inputs_to_tuples now dereferences inp.locking_script.serialize() for EVERY input, and its docstring calls a missing one 'a caller error'. That is a legitimate tightening, so the fix belongs here rather than in a version pin. _sign_with_bsv receives a SERIALIZED tx, which carries no source-output data, so it populated locking_script only on the input it was signing; on a 2-input call (contract UTXO + funding UTXO) input 0 was left None. Every input now gets one, with an empty Script() placeholder where unknown. That is sound rather than a workaround: BIP-143 binds only the SIGNING input's scriptCode into its digest, and the other inputs reach that digest solely through hashPrevouts and hashSequence, which hash outpoints and sequence numbers — never scripts. Verified, not argued: signing the exact 2-input shape that broke produces a BYTE-IDENTICAL signature under both versions — 2.3.3 30450221008c7345754faa4fda6ec9589734205dab67a22af441aff0eaf65835... 2.4.0 30450221008c7345754faa4fda6ec9589734205dab67a22af441aff0eaf65835... so the placeholders provably do not enter the digest. Full suite: 746 passed under 2.4.0 AND under 2.3.3, so this does not trade a new break for the old one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
integration/contracts/for test-only fixtures (not human examples), plus a machine-checkedcoverage-matrix.json/check-matrix.mjs.addRawOutputlayout, andcheckMultiSig2-of-3 — with TS/Go on-chain state/output decode (not only SDK memory).PrepareCall/FinalizeCallon TS+Go.OP_CHECKMULTISIG(TS / Python / Rust).Test plan
vitestunderintegration/ts)go test -tags integration -run 'BranchMerged|…|PhaseB|PhaseC')SDK_CALL_PATH; no OR-CHECKSIG soft-warn on MultiSig happy pathnode integration/contracts/check-matrix.mjsexit 0zig build test-phase-a— 5 PhaseA_PASS + 7/7 suite (MultiSig deferred)packages/runar-sdksoft-warning unit tests green