fix: substConstants serializer-level parity: body-verbatim, OOB no-op, first-wins, v3 size-gate (match sigma-state)#871
Open
mwaddip wants to merge 2 commits into
Conversation
`SubstConstants` eval full-parsed the script bytes (`ErgoTree:: sigma_parse_bytes`) and errored when a requested position was >= the tree's constant count. sigma-state's `ErgoTreeSerializer. substituteConstants` is byte-surgery: it parses only the header and constants segment, keeps the tree body verbatim (never deserializing it), substitutes constants at in-range positions, and silently no-ops out-of-range ones. sigma-rust therefore rejected scripts the JVM accepts -- an out-of-range position, or an unparseable tree body -- a latent consensus fork (not seen on mainnet). Add `ErgoTree::substitute_constants` mirroring the Scala serializer (header + constants parsed, body bytes kept raw, OOB positions dropped, first position per index wins) and call it from `SubstConstants::eval`. Verified byte-exact against SANTA's JVM-blessed v5 vectors (`substConstants_equivalence.json`): the five out-of-range entries (incl. `[0,0,8,-45]`, whose body the full parser rejects with InvalidTypeCode) return the input unchanged; in-range substitution stays covered by the existing proptests. New `substitute_constants_oob_is_noop` regression test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ErgoTree::substitute_constants re-emitted the tree-size slot whenever the template header has_size bit was set. sigma-state's ErgoTreeSerializer.substituteConstants re-emits it only when the evaluation's ErgoTree version is >= V3 (the V6 soft-fork isV3OrLaterErgoTreeVersion gate); for v<=2 the slot is dropped even though the bit stays set. Thread the evaluation's tree_version (ctx.tree_version()) into the fn and gate the size emit on it. Completes the substConstants serializer-level parity (body-verbatim and first-wins were already handled here). The v<=2 hasSize path is not mainnet-reachable, so it is covered by a unit test (v2 drops / v3 keeps the slot) certified against the Scala source rather than a blessed vector. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
|
Addendum: scope grew beyond the original out-of-range no-op to the full serializer-level substConstants rewrite (title updated). All four behaviors match sigma-state's ErgoTreeSerializer.substituteConstants. The v3 size-gate isn't mainnet-reachable, so it's covered by a unit test rather than a blessed vector. |
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.
SubstConstantsfull-parsed the script bytes and errored when a position was >= the tree's constant count. sigma-state'sErgoTreeSerializer.substituteConstantsis byte-surgery: it parses only the header + constants, keeps the body verbatim (never deserializing it), substitutes in-range positions and no-ops out-of-range ones. sigma-rust thus rejected scripts the JVM accepts — an OOB position or an unparseable body — a latent consensus fork (not seen on mainnet).Adds
ErgoTree::substitute_constantsmirroring the Scala serializer;SubstConstants::evalcalls it. Verified byte-exact vs JVM-blessed v5 vectors (5 OOB entries, incl. one with an unparseable body, return input unchanged); in-range covered by proptests. Newsubstitute_constants_oob_is_nooptest.