fix: box token gate is the MaxBoxSize parse window, not a count cap#902
Open
mwaddip wants to merge 3 commits into
Open
fix: box token gate is the MaxBoxSize parse window, not a count cap#902mwaddip wants to merge 3 commits into
mwaddip wants to merge 3 commits into
Conversation
…ader mirror) Add a PositionLimit capability to readers and check it once at the START of each primitive read (get_u8/get_u64/get_bits/new get_bytes_into), failing strictly on position > limit -- the reference impl's CheckPositionLimit (validation rule 1014) in CoreByteReader. A primitive that starts within the limit may run past it unchecked (the JVM's lazy per-read semantics), so the VLQ continuation loop reads raw bytes. SigmaByteReader stores the limit (the decorating reader, like CoreByteReader.positionLimit); bare Cursors are documented no-limit stubs (the unchecked underlying reader). Behavior-neutral: nothing sets a limit yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Swap raw read_exact for the position-limit-checked get_bytes_into at every chunk read reachable from consensus parsing (digests/token ids, group elements, header fields, BigInt/UnsignedBigInt bodies, Coll[Byte] and string payloads, type-var names, sized-tree bodies) -- the reference impl's getBytes goes through the checked CoreByteReader at all of these. Behavior-neutral: no reader sets a limit yet; p2p peer_addr reads stay raw (no window concept on that path). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The reference impl has NO token-count rule at the data layer: nTokens is a bare getUByte() (ErgoBoxCandidate.scala:200) and SigmaConstants.MaxTokens(255) binds only in SDK builders. The real gate is a MaxBoxSize(4096) position-limit window over the candidate span (:191-192, restored :235), checked lazily before each read -- crossing it AT a read is rule 1014, while a final field may overrun the window. Our BoundedVec<Token, 1, 122> cap diverged in both directions: a 123-token box that fits 4096 was over-rejected, and with no window at all a register read starting past 4096 was over-accepted. Relax BoxTokens to the u8 wire ceiling (255) and put the window into parse_box_with_indexed_digests, restored on the success path only like the JVM (nested candidate parses save/restore the outer window). The box selector keeps a local fit-derived 122 packing policy so wallet change boxes stay under the node's size rule; arbitrary candidates are filtered to window-parseable serializations (anything else cannot round-trip here or on the JVM, which also retires test_max_tokens in favor of the window pins). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
The reference impl has no token-count rule at the data layer:
nTokensis a baregetUByte()(ErgoBoxCandidate.scala:200);MaxTokens(255) binds only in SDK builders. The real gate is aMaxBoxSize(4096) position-limit window over the candidate span (:191-235), checked before each primitive read (CheckPositionLimit, rule 1014): a final field may overrun the window, a read starting past it throws.Our 122-token cap diverged both ways: over-rejecting 123-token boxes that fit 4096, and over-accepting reads past the limit.
Commits: (1) position-limit infra mirroring
CoreByteReader(one check per primitive; checkedget_bytes_into); (2) chunk reads routed through it; (3) the window in the candidate parser +BoxTokens1..=255 (the box selector keeps its 122 packing policy).