Bind speculative base by state_id chain instead of byte equality#146
Draft
ikehara wants to merge 1 commit into
Draft
Bind speculative base by state_id chain instead of byte equality#146ikehara wants to merge 1 commit into
ikehara wants to merge 1 commit into
Conversation
The canonical store's Any encoding is not stable across writers: create_client stores the submitter's encoding verbatim while update_client stores the enclave light client's re-encoded form (e.g. JSON-embedded config fields re-serialized). A base rebuilt by the relayer therefore cannot reproduce the stored bytes in general, so the stored/supplied byte comparisons deterministically rejected every batch whose base was not a verbatim round-trip of the store (first hit at the second batch of an initial sync, where the base is rebuilt rather than queried). Replace the client_state/consensus_state byte checks with the encoding-independent binding that already closes the chain: the enclave-observed prev_state_id must match the state_id recorded at prev_height. Keep the stale-base protection the latest-client_state byte check provided by tracking a host-managed speculative-commit high-water mark and rejecting bases below it.
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.
Problem
verify_expected_base_state_in_txbyte-compares the supplied speculative baseclient_state/consensus_stateAnys against the canonical store. This comparison is structurally unsatisfiable whenever the relayer rebuilds the base instead of echoing back queried bytes:create_clientstores the submitter's Any encoding verbatim, butupdate_clientstores the enclave light client's re-encoded form. For ELCs that embed JSON config in the client state, decode/encode is not byte-stable (e.g. an emptychain_info_jsondecodes to a default struct and re-encodes as a non-empty JSON object), so the stored representation changes after the first update.Observed effect: an initial sync's first batch (queried base, verbatim round-trip) commits, then the second batch deterministically fails with
stored speculative base client_state mismatchat exactlybase_height + max_units * blocks_per_chunk, and retries stay stuck at the same height.This is the same class of issue as the earlier removal of the raw-Any state_id recompute (#145): the host cannot reproduce ELC-specific encodings, so byte-level invariants across encoders do not hold.
Fix
client_state/consensus_statebyte comparisons. The base is bound by content via the existing encoding-independent check: the enclave-observedprev_state_id(computed in-enclave over the supplied base) must match the height-indexedstate_idrecorded by a previous create/serial/speculative update.clients/<id>/speculativeCommitHeight): bases below the mark are rejected with a distinctstale speculative base heighterror, and the mark monotonically advances to the batch's lastpost_heighton every successful apply.Notes
validation.rs: base fields erased by ELC canonicalization (e.g.latest_height) are not compared; a divergent base from the authenticated relayer cannot affect the on-chain proof chain and at worst corrupts this client's host-store cache, which a serial update_client rewrites.prev_height >= mark).lcp-go/prover) needs no change.Tests
stitch_accepts_first_base_state_when_stored_bytes_use_different_encoding(regression for this failure: stored bytes differ from supplied base, state_id matches → accepted; high-water mark recorded).stitch_rejects_stale_first_base_below_speculative_commit_height(replaces the byte-equality-basedstitch_rejects_first_base_state_when_canonical_client_state_advanced).stitch_rejects_first_base_state_that_is_not_in_store(its scenarios are covered by the prev_state_id-missing and stored-state_id-missing tests).cargo test -p service(42 passed),cargo test -p enclave-api -p lcp-types, fmt/clippy clean.🤖 Generated with Claude Code