fix: variable-length Context.headers; lastBlockUtxoRoot as its own context input#889
Open
mwaddip wants to merge 2 commits into
Open
fix: variable-length Context.headers; lastBlockUtxoRoot as its own context input#889mwaddip wants to merge 2 commits into
mwaddip wants to merge 2 commits into
Conversation
The JVM models lastBlockUtxoRoot as its own ErgoLikeContext input and CContext.LastBlockUtxoRootHash returns it directly; deriving it from headers(0).stateRoot only coincides when headers are non-empty (the JVM requires digest agreement then, ErgoLikeContext.scala:85) and has no value for an empty header chain. Add Context.last_block_utxo_root and return it from the eval; make_context derives it from the newest header, which is exactly the JVM-required relationship. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The JVM models ErgoLikeContext.headers as a variable-length Coll[Header]: empty is explicitly legal, and at block height h <= 10 the window that headerChainBack gathers stops at genesis, so scripts see h - 1 headers. sigma-rust's fixed [Header; 10] cannot represent that; a node bridging it must pad, and a script reading CONTEXT.headers.size or a high index in the first blocks of a chain gets a different answer than the JVM — a silent value fork (practical exposure: testnet from-genesis validation). Context.headers becomes ContextHeaders (BoundedVec 0..=10), and the SDK ErgoStateContext.headers becomes BoundedVec 1..=10 — signing always has a chain tip, and make_context still derives the root from the newest header. The wasm/python/C constructors relax accordingly: every existing caller passing 10 headers keeps working; passing fewer becomes possible. Regression tests drive the two JVM-blessed Context.properties vectors (empty headers -> empty Coll[Header]; LastBlockUtxoRootHash on an empty-headers context -> the standalone root field). Co-Authored-By: Claude Opus 4.8 <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.
JVM
ErgoLikeContext.headersis variable-length — empty is legal, and at height h ≤ 10headerChainBackyields h−1 headers — withlastBlockUtxoRootas its own context input (CContextreturns it directly, neverheaders(0)). sigma-rust pinned[Header; 10]and derived the root fromheaders[0]: a node bridging the fixed type must pad, soCONTEXT.headers.size/ high-index reads in a chain's first blocks diverge from the JVM — a silent value fork (exposure: testnet from-genesis validation).Fix:
Context.headers→BoundedVec<Header, 0, 10>+ standaloneContext.last_block_utxo_root; SDK headers →BoundedVec<Header, 1, 10>(signing always has a chain tip); bindings relax==10→1..=10. Regression tests drive JVM-blessed vectors against the truly-empty context.