Skip to content

fix: make debugging linear in the number of inputs - #470

Open
mr-zwets wants to merge 1 commit into
nextfrom
fix/debug-quadratic-scenarios
Open

mr-zwets wants to merge 1 commit into
nextfrom
fix/debug-quadratic-scenarios

Conversation

@mr-zwets

@mr-zwets mr-zwets commented Oct 2, 2026

Copy link
Copy Markdown
Member

Closes #469.

Summary

debug() evaluates one scenario per input, and each scenario described every other input, source output and output by template scripts. libauth compiled all of those from CashAssembly in every scenario, so debugging was quadratic in the number of inputs. That cost also hits send() on the MockNetworkProvider and the toFailRequire* matchers.

  • getLibauthTemplate() gets an internal useTransactionBytecode option. With it, the entries a scenario does not evaluate are given as the built transaction's bytecode in hex, worked out once per template. Each scenario then compiles only its slot. debug() uses this template.
  • The compiler and VM are created once per debug run, instead of once per input.
  • The locking-bytecode mapping of the readable template is worked out once per template instead of once per scenario. This also speeds up the public getLibauthTemplate().

Unchanged

  • The output of the public TransactionBuilder.getLibauthTemplate() and getBitauthUri(). The existing template fixtures pass untouched.
  • BitAuth IDE links in errors are still built from the readable template, only when an error is thrown, and through the same fallback send() already used. Building the link can therefore never replace the error it belongs to.

Measurements

A trivial one-require contract spent by N inputs, debug() on Node 24:

inputs next this PR failing last input, next failing last input, this PR
20 397 ms 63 ms
80 3,717 ms 286 ms 3,762 ms 510 ms
160 13,962 ms 780 ms
320 57,170 ms 2,324 ms 64,773 ms 5,014 ms

On the failing path most of the remaining time is the readable template and its compressed IDE link. These are inherently quadratic in size, so making them faster would mean making the link lazy on the error object.

Tests

  • Equivalence, for every single- and multi-contract template fixture: debugging gives the same results, or the same error, with either template, and only the slot is left to template scripts.

  • A 40-input transaction failing at input 33 reports input 33.

  • An independent review also compared both templates on a 16-input transaction mixing:

    • p2sh20, p2sh32 and p2s contracts;
    • every sighash type, with both Schnorr and ECDSA signatures;
    • fungible tokens and NFTs, a raw-bytecode output and an OP_RETURN output;
    • per-input sequence numbers and a locktime.

    All outcomes were identical.

  • yarn test in packages/cashscript: 243 passed. Lint and cspell are clean.

🤖 Generated with Claude Code

debug() evaluates one scenario per input, and each scenario described every other
input, source output and output by template scripts, which libauth compiled from
CashAssembly for every scenario. Debugging now uses a template that gives those
entries as the built transaction's bytecode, so each scenario only compiles its
slot, and the compiler and VM are created once per debug run. The public
getLibauthTemplate() output is unchanged, and error links are still built from it.

Closes #469

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cashscript Ready Ready Preview Oct 2, 2026 11:00am UTC

Request Review

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

Pull request stats

Source Tests Docs Total Net Share
SDK (cashscript) +147 −46 +64 −0 +211 −46 +165 100%
Website +1 −0 +1 −0 +1 <1%
Total +147 −46 +64 −0 +1 −0 +212 −46 +166 100%

Reviewable churn: 258 lines (net +166), version bumps and generated files excluded.
Test lines per line of source: 0.33.
Comments: 4 of 134 added source lines, 3%.

@codecov

codecov Bot commented Oct 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.67925% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.27%. Comparing base (ac35856) to head (937ad03).

Files with missing lines Patch % Lines
packages/cashscript/src/debugging.ts 72.22% 4 Missing and 1 partial ⚠️
packages/cashscript/src/TransactionBuilder.ts 85.71% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (88.67%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             next     #470      +/-   ##
==========================================
+ Coverage   89.23%   89.27%   +0.03%     
==========================================
  Files          61       61              
  Lines        5074     5099      +25     
  Branches      949      959      +10     
==========================================
+ Hits         4528     4552      +24     
  Misses        421      421              
- Partials      125      126       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This branch was successfully deployed

1 active deployment
Preview — 937ad038 Deployed Oct 2, 2026 by vercel[bot]
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