Skip to content

fix(consensus): structure-delimit the nested SBox-constant inner tree skip - #124

Merged
arkadianet merged 1 commit into
mainfrom
fix/nested-box-structure-delimited
Jun 21, 2026
Merged

fix(consensus): structure-delimit the nested SBox-constant inner tree skip#124
arkadianet merged 1 commit into
mainfrom
fix/nested-box-structure-delimited

Conversation

@arkadianet

@arkadianet arkadianet commented Jun 21, 2026

Copy link
Copy Markdown
Owner

What

A follow-up to #123 (structure-delimited top-level size parse), applying the same fix to the
nested SBox-constant path. skip_ergo_tree still skipped a nested box's size-delimited inner
tree by the declared size (get_bytes(size)). Scala deserializes a nested box's proposition
inline via ErgoTreeSerializer.deserializeErgoTree (ErgoBoxCandidate.parseBody), which is
structure-delimited — it leaves the reader at the actual body end, where creationHeight is
read next. So for any nested box whose declared tree size ≠ its body length (adversarial-only, same
reject-valid / accept-invalid class as #123), the node consumed the wrong number of bytes and
desynced the box and the enclosing tree's parse.

How

Rewind to before the header skip_ergo_tree already read, and delegate to
read_ergo_tree_tracking_wrap — which (since #123) parses the inner tree structurally, advances the
reader by the true body length on success or to Scala's numBytes boundary on a soft-fork wrap,
forwards the inner tree's group elements onto the outer reader (the JVM curve-checks an off-curve
point inside a nested box), and re-raises DepthLimitExceeded / HardReject so they escape the
enclosing tree's wrap. check_tree_version_supported still hard-rejects a future-version inner tree
afterward. The sizeless nested path (parse_sizeless_inner_box_script + harden_sizeless_inner_error)
is intentionally unchanged.

Validation

Reviewed source-level against the Scala reference (no substantive issues): the success / soft-wrap
cursor positions, GE forwarding (no double-count), and the nested error classes — non-SigmaProp root
→ wrap, pre-v3 v6 method → wrap, version > max → hard-reject, over-depth → escape — all match Scala.

New skip_ergo_tree_size_delimited_advances_by_body_not_declared_size pins the structural advance
(a size-5 / body-2 inner tree followed by trailing box bytes advances by 2, leaving the 3 trailing
bytes). The existing nested-box v6 / rule-1012 / version tests still pass.

Test plan

cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace      # 4400 passed

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability of parsing nested data structures by refining how the parser advances through complex file formats, ensuring correct positioning for subsequent data elements.

… skip

Following #123 (which made the top-level size-delimited ErgoTree parse
structure-delimited), the nested `SBox`-constant path still skipped its inner
size-delimited tree by the DECLARED size: `skip_ergo_tree` read `size` and did
`get_bytes(size)`. Scala deserializes a nested box's proposition INLINE via
`ErgoTreeSerializer.deserializeErgoTree` (`ErgoBoxCandidate.parseBody`), which is
structure-delimited — the declared size does not bound the parse or advance the
reader, which is left at the actual body end where the box's `creationHeight` is
read next. So for any nested box whose declared tree size ≠ its body length
(adversarial-only, but the same reject-valid / accept-invalid class as #123), the
node consumed the wrong number of bytes and desynced the box (and the enclosing
tree's parse).

Rewind to before the header and delegate to `read_ergo_tree_tracking_wrap`, which
(since #123) parses the inner tree structurally, advances the reader by the true
body length on success or to Scala's `numBytes` boundary on a soft-fork wrap,
forwards the inner tree's group elements onto the outer reader (the JVM
curve-checks an off-curve point inside a nested box while deserializing it), and
re-raises `DepthLimitExceeded` / `HardReject` so they escape the enclosing tree's
wrap. `check_tree_version_supported` still hard-rejects a future-version inner
tree afterward. The box stays opaque for round-trip via the caller's preserved
bytes; only the reader advance moves. The sizeless nested path
(`parse_sizeless_inner_box_script` + `harden_sizeless_inner_error`) is unchanged.

New `skip_ergo_tree_size_delimited_advances_by_body_not_declared_size` test pins
the structural advance (a size-5 / body-2 tree followed by trailing box bytes
advances by 2, leaving the 3 trailing bytes). The existing nested-box v6 /
rule-1012 / version tests still pass (4400 green).

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

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8a669ff5-61f1-481e-8c50-427f2c59fd63

📥 Commits

Reviewing files that changed from the base of the PR and between 458e581 and b2c355a.

📒 Files selected for processing (1)
  • ergo-ser/src/sigma_value.rs

📝 Walkthrough

Walkthrough

In ergo-ser/src/sigma_value.rs, the size-delimited nested SBox path of skip_ergo_tree is changed to rewind to the tree header and delegate parsing and reader advancement to read_ergo_tree_tracking_wrap, followed by check_tree_version_supported. The previous manual byte-skip and sub-reader approach is removed. A regression test is added.

skip_ergo_tree size-delimited fix and regression test

Layer / File(s) Summary
skip_ergo_tree delegation and regression test
ergo-ser/src/sigma_value.rs
The size-delimited nested SBox path rewinds to the tree header and calls read_ergo_tree_tracking_wrap to advance by the actual body end, then calls check_tree_version_supported; the prior manual byte-skip, sub-reader construction, and manual group-element forwarding are removed. A regression test constructs bytes with a mismatched declared vs. actual body size, calls skip_ergo_tree, and asserts the reader is positioned immediately after the body.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • arkadianet/ergo#123: Directly connected — that PR fixes read_ergo_tree_tracking_wrap to advance by the actual structure-delimited inner-tree length rather than the declared size, which is the same root behavior this PR relies on when delegating from skip_ergo_tree.
  • arkadianet/ergo#122: Modifies read_ergo_tree_tracking_wrap's count/id reading and error-handling, directly affecting the call site introduced by this PR's delegation change.
  • arkadianet/ergo#117: Both PRs modify skip_ergo_tree logic for nested SBox inner-tree skipping, error handling, and reader advancement/validation behavior.

Poem

🐇 Hop, hop — the reader was lost,
declaring a size that never was true,
but now we rewind without extra cost,
and the tracking wrapper sees the path through.
The bytes align, the test stands tall,
no more desync to trip us up at all!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(consensus): structure-delimit the nested SBox-constant inner tree skip' is specific and clearly relates to the main change: fixing a byte-alignment bug in nested SBox-constant inner tree parsing by using structure-delimited parsing instead of declared-size-based parsing.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/nested-box-structure-delimited

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@arkadianet

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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