Skip to content

[solana]: host, handler and verifier programs#801

Draft
royvardhan wants to merge 6 commits intomainfrom
royvardhan/solana-ismp-host
Draft

[solana]: host, handler and verifier programs#801
royvardhan wants to merge 6 commits intomainfrom
royvardhan/solana-ismp-host

Conversation

@royvardhan
Copy link
Copy Markdown
Collaborator

Solana on-chain verification of Hyperbridge BEEFY consensus proofs and inbound ISMP message delivery. Inbound-only by design.

Ref: #797

@royvardhan royvardhan force-pushed the royvardhan/solana-ismp-host branch 2 times, most recently from 7fcf414 to 778b6a5 Compare April 29, 2026 08:46
@royvardhan royvardhan force-pushed the royvardhan/solana-ismp-host branch from 778b6a5 to e0ce6e0 Compare April 29, 2026 09:11
@royvardhan royvardhan force-pushed the royvardhan/solana-ismp-host branch from 4b76ba4 to 68087da Compare April 30, 2026 08:37
Comment thread solana/programs/host/src/instructions/close_expired_receipt.rs Outdated
Comment thread solana/programs/host/src/instructions/set_consensus_state.rs
Comment thread solana/programs/handler/src/ismp/state_machine_client.rs Outdated
Comment thread solana/programs/handler/src/ismp/consensus_client.rs
Comment thread solana/programs/host/src/lib.rs
royvardhan added 2 commits May 4, 2026 13:39
Addresses PR review on the inbound-only Solana ISMP host + handler:

- Drop `close_expired_receipt`. Closing the receipt PDA removes the
  replay guard — `dispatch_incoming.init` would succeed again for the
  same commitment and re-dispatch the message. Mirrors EVM, which only
  deletes `_requestReceipts[c]` on dispatch *failure* (for retry).

- Pin `set_consensus_state.params.id` to `host_config.consensus_client_id`
  so admin can't bootstrap unrelated `[b"consensus", id]` PDAs. The
  `init` constraint already enforces once-per-id by construction.

- Switch `verify_membership` to Keccak MMR multi-proofs against
  `state.overlay_root` (mirrors EVM `HandlerV2.handlePostRequests`).
  Adds `ckb-merkle-mountain-range` — same no_std crate the BEEFY verifier
  uses. Wire: `MmrMembershipProof { leaf_indices, items, leaf_count }`.
  Storage-trie path kept for `verify_state_proof`'s non-membership queries.

- Walk parachain-header digests to extract `mmr_root` + `child_trie_root`
  (engine_id `b"ISMP"`) and `timestamp` (engine_id `b"ISTM"`). Without
  this `overlay_root` stays `None` and the MMR check above rejects
  every inbound POST. Hand-rolled SCALE digest decoder to avoid pulling
  `sp_runtime`. `StateCommitment` now matches EVM `Header.sol::stateCommitment`.

- Doc-link `host/src/lib.rs` to `handler::ismp::host_facade::SolanaHostFacade`
  as the `IsmpHost` impl — a Solana `#[program]` module isn't a Rust
  value, so the trait can't sit on it directly.
The MMR `verify_membership` from the prior commit reads
`StateCommitment.overlay_root` to validate request multi-proofs, but
nothing on the host-side write path was carrying it: the PDA struct
had no field for it, `StoreStateCommitmentParams` didn't accept it,
and the facade dropped it before the CPI. So in production the
verifier always saw `overlay_root: None` and rejected every inbound
POST. Tests passed only because `RecordingHost` bypasses the host
CPI path entirely.

Adds the field end-to-end: `StateCommitment` PDA + params struct,
host write, facade `CommitmentSnapshot`, facade reader, and the
snapshot built by `handle_post_requests`. Facade writer rejects
`None` rather than zero-filling, so a misbehaving consensus client
fails loudly instead of poisoning future membership checks.
@royvardhan
Copy link
Copy Markdown
Collaborator Author

The mental model behind the EVM host and handler inspired Solana programs: https://claude.ai/share/e69ff8b0-a1f6-45ae-a522-aa14269e64c2

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.

2 participants