Skip to content

fix: pre-JIT ErgoScript leniency for v0/v1 ErgoTree scripts#859

Open
mwaddip wants to merge 2 commits into
ergoplatform:developfrom
mwaddip:fix/pre-jit-leniency-tree-version
Open

fix: pre-JIT ErgoScript leniency for v0/v1 ErgoTree scripts#859
mwaddip wants to merge 2 commits into
ergoplatform:developfrom
mwaddip:fix/pre-jit-leniency-tree-version

Conversation

@mwaddip
Copy link
Copy Markdown

@mwaddip mwaddip commented Apr 13, 2026

Three pre-JIT (v4.x) compatibility paths missing: BoolToSigmaProp passthrough for SigmaProp input, xorOf using distinct.length == 2 (both per-script, gated on tree_version()), and selfBoxIndex returning -1 in pre-v5 blocks (block-level, gated on activated_script_version() — JVM eq/== bug fixed globally in v5).

Verified: full mainnet validation from genesis through 966k+ blocks, no checkpoint, zero errors. (Per May 20: full validation from genesis to tip)

mwaddip and others added 2 commits April 12, 2026 21:16
Three pre-JIT compatibility paths in the interpreter were either missing
or wrongly gated on the network's activated script version. The JVM
sigmastate-interpreter applies these lenient v4.x semantics to ErgoTree
scripts whose header version is < V2 (i.e. V0 or V1), regardless of the
block they are spent in. A v0 tree spent in a v3+ block must still get
the lenient path because the leniency is a property of how the old
script was originally written and validated.

The previous selfBoxIndex fix (now superseded) gated on
`activated_script_version() < V2`, which only triggered the lenient
path for v0/v1 *blocks*. This was incomplete: a buggy v0 script spent
in a v3+ block (the common case post-mainnet-v5-activation) still
needs the lenient -1 return value to match the JVM.

Three behaviors fixed:

1. selfBoxIndex (CContext.scala equivalent): pre-V2 trees return -1
   instead of the real input index. JVM bug ergoplatform#603 - historical scripts
   set output R4=-1 to match the buggy value.

2. BoolToSigmaProp (trees.scala): pre-V2 trees pass a SigmaProp input
   through unchanged instead of strict bool extraction. Mainnet has
   `sigmaProp(sigmaProp(...))` patterns at e.g. tx 5fe235558... block
   680692 (address Fo6oijFP2JM87ac7w) which the JVM has a property
   test for.

3. xorOf (CSigmaDslBuilder.scala): pre-V2 trees compute
   `distinct.length == 2` (true iff coll contains BOTH true and false,
   count and order independent) instead of the proper left-fold XOR.
   The JVM source comment labels this "buggy version used in v4.x
   interpreter".

All three gates use `ctx.tree_version() < ErgoTreeVersion::V2` so the
script's header version determines the path, not the block's activated
version. This matches how the JVM dispatches v4.x semantics through
its `VersionContext` propagation.

Tests added/updated:
- selfBoxIndex: V0, V1, V2 cases
- BoolToSigmaProp: V0 passthrough, V2 strict-error
- xorOf: V0 distinct-length, V2 left-fold; concrete [true,true,false]
  cases proving the divergence

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

The JVM bug ergoplatform#603 (eq vs == in CostingDataContext.scala) was a global
implementation bug fixed in v5.x for ALL scripts, not a per-script
semantic difference. Using tree_version caused V0 scripts in v5+ blocks
to incorrectly return -1, failing mainnet block 942664.

Gate on activated_script_version (block level) so pre-v5 blocks
reproduce the bug and v5+ blocks return the correct index regardless
of script version. bool_to_sigma and xor_of gates are unchanged —
those ARE per-script semantics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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