Skip to content

refactor: Move ClarityRuntimeTxError into clarity and expose whether failed txs are included in block - #7486

Open
jbencin-stacks wants to merge 11 commits into
stacks-network:mainfrom
jbencin-stacks:refactor/clarity-runtime-tx-error
Open

refactor: Move ClarityRuntimeTxError into clarity and expose whether failed txs are included in block#7486
jbencin-stacks wants to merge 11 commits into
stacks-network:mainfrom
jbencin-stacks:refactor/clarity-runtime-tx-error

Conversation

@jbencin-stacks

@jbencin-stacks jbencin-stacks commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Description

This PR contains a couple more changes needed for Clarinet:

  • Move ClarityRuntimeTxError into clarity, so it builds for WASM
  • Refactor ClarityRuntimeTxError to make it clear which failed transactions are included in blocks
  • Add is_included_in_block() so Clarinet can tell if failed transaction was included in block

This will expose information to Clarinet about why a transaction failed, which it needs to know if the transaction charges a fee and consumes a nonce

Applicable issues

Additional info (benefits, drawbacks, caveats)

Checklist

  • Test coverage for new or modified code paths
  • For new Clarity features or consensus changes, add property tests (see docs/property-testing.md)
  • Changelog fragment(s) or "no changelog" label added (see changelog.d/README.md)
  • Required documentation changes (e.g., rpc/openapi.yaml for RPC endpoints, event-dispatcher.md for new events)
  • New clarity functions have corresponding PR in clarity-benchmarking repo

jbencin-stacks and others added 2 commits August 10, 2026 14:09
Move `ClarityRuntimeTxError` and `handle_clarity_runtime_error` from `stackslib`
to `clarity`, and add `ClarityRuntimeTxError::is_included_in_block` plus
`analysis_failure_is_included_in_block`.

This will allow Clarinet to tell if a failed transaction was included
in a block, and whether to charge the sender a fee and increment its nonce.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jbencin-stacks
jbencin-stacks force-pushed the refactor/clarity-runtime-tx-error branch from aa0fa92 to 94b2f43 Compare August 10, 2026 18:09
@jbencin-stacks
jbencin-stacks marked this pull request as ready for review August 11, 2026 19:22
@jbencin-stacks jbencin-stacks changed the title Feat: Move ClarityRuntimeTxError into clarity and expose whether failed txs are included in block refactor: Move ClarityRuntimeTxError into clarity and expose whether failed txs are included in block Aug 12, 2026
@dhaney-stacks
dhaney-stacks requested review from aaronb-stacks, brice-stacks and hstove-stacks and removed request for aaronb-stacks August 13, 2026 16:26
hstove-stacks
hstove-stacks previously approved these changes Aug 14, 2026

@hstove-stacks hstove-stacks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

jbencin-stacks added a commit to jbencin-stacks/clarinet that referenced this pull request Aug 17, 2026
Repoint the seven stacks-core git dependencies at
jbencin-stacks/stacks-core rev 87f95946, the head of
stacks-network/stacks-core#7486, which moves `ClarityRuntimeTxError` into
`clarity` and exposes whether a failed transaction is included in a block.
Clarinet needs that to decide nonce consumption without re-deriving the
rule; the previous pin `b17d3a12` is 103 commits behind its base.

Migration fallout from that jump, all mechanical:

- `EvalHook` moved to `clarity::vm::hooks`. The trait itself is unchanged
  for our purposes — `will_begin_eval`, `did_finish_eval` and
  `did_complete` keep their signatures, and upstream documents
  `did_complete` as clarinet-driven — so this is an import change only.
- `clarity::vm::time_tracker` is gone; `run_analysis` now takes a
  `ResourceLimiter`.
- `CallableType`'s native/special variants moved under
  `CallableType::Builtin { kind: BuiltinKind::… }`.
- Upstream added `StacksEpochId::Epoch41`, so the exhaustive matches in
  `clarity-static-cost` and `datastore.rs` gain an arm. Clarinet has no
  `EpochSpec` for 4.1, cannot name it in a manifest, and still defaults to
  4.0, so `From<StacksEpochId> for EpochSpec` mirrors its existing
  `Epoch10` arm rather than growing user-facing 4.1 surface here.

`set_epoch_command` asserted that `StacksEpochId::latest()` is settable,
which stopped holding the moment 4.1 landed upstream. Re-aim it at the
epoch clarinet actually supports, pin 4.1 as the known-pending one so the
test fires again on the next upstream epoch, and assert that an unadopted
epoch is reported as unusable instead of silently ignored.

Verified: 996 Rust tests pass; the 15 failures are the pre-existing
network-dependent `mxs` tests, which fail identically on `main`.
`cargo fmt-stacks --check`, both clippy invocations, and
`pnpm run build:sdk-wasm` are clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jbencin-stacks added a commit to jbencin-stacks/clarinet that referenced this pull request Aug 17, 2026
Bump the sender's nonce for every simnet operation that is a transaction —
contract deploys, STX transfers, public and private contract calls, and a
deployment plan's emulated contract calls.

The hard part is not *which* operations are transactions but *which
failures still count as one*. Mainnet mines a transaction that reverts: the
fee is charged and the nonce advances even though the call failed. Deciding
that by hand means re-deriving a consensus rule that changes whenever a
`ClarityError` variant is added upstream, so the decision is delegated to
`clarity`'s `handle_clarity_runtime_error` / `handle_clarity_analysis_error`
(stacks-network/stacks-core#7486), which the node itself calls on the block
assembly path. `BlockInclusion` is the only place clarinet touches it.

Getting the verdict to the bump sites required keeping the typed
`ClarityError` alive: `interpreter.rs` used to flatten every failure into
`format!("Runtime error while interpreting …")` before anyone could classify
it. Failures now carry `ExecutionError { diagnostics, inclusion }` (or
`ContractCallFailure` / `OperationFailure` at the call and wasm layers). Every
`Display` output is unchanged, so the tracer hook, `interpreter.rs`'s runtime
error test, and `simnet-usage.test.ts` need no edits.

`Session::eval` keeps its diagnostics-only signature — it also backs bare
REPL snippets and function-argument evaluation, which are not transactions —
and `stx_transfer` uses a private `eval_with_inclusion` instead. Likewise
`Session::call_contract_fn` stays nonce-neutral because `callReadOnlyFn`
shares it; only callers that know an operation is a transaction bump.

This closes three divergences the previous approach had, where clarinet
keyed the bump off `result.is_ok()`: divide-by-zero and `unwrap-panic`
(`Runtime` / `EarlyReturn` → `Acceptable`), and a deploy that fails analysis
or parsing with a non-`rejectable_in_epoch` error. All three are reported as
failures by clarinet but mined by mainnet.

Tests were mutation-checked rather than assumed. Restoring the `is_ok()`
rule fails exactly the three new divergence tests and no others. Separately,
mapping every failure to `Included` passed the entire suite — the end-to-end
tests can only reach *included* failures, since cost overruns and
`rejectable_in_epoch` errors are impractical to provoke from contract source
— so `block_inclusion_delegates_to_clarity` pins both directions directly;
it fails under either an always-included or an always-rejected mutation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@brice-stacks brice-stacks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this looks good, I just had a couple of naming comments, but feel free to push back.

Comment thread clarity/src/vm/clarity.rs Outdated
Comment thread clarity/src/vm/clarity.rs Outdated
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.

3 participants