Skip to content

feat(foreign-tx): wire svm chains into node - #4138

Open
frolvanya wants to merge 2 commits into
feat/svm-inspectorfrom
feat/svm-node-wiring
Open

feat(foreign-tx): wire svm chains into node#4138
frolvanya wants to merge 2 commits into
feat/svm-inspectorfrom
feat/svm-node-wiring

Conversation

@frolvanya

Copy link
Copy Markdown
Collaborator

Connects config -> inspector -> signing, so a node actually serves Solana and
Fogo verification requests. Before this PR the node still rejects them.

  • node config: fogo section added (solana already existed);
  • verify_foreign_tx: one typed inspector fan-out per chain
    (SolanaInspector / FogoInspector, so a slot mix-up is a compile error)
    and dispatch arms that replace the old
    bail!("ForeignChainRpcRequest::Solana is unsupported"); tests pin that
    each chain's config feeds its own slot;
  • health check: golden check + network-fingerprint probe for both chains;
  • operator docs, localnet templates and user-config gain both chains.

Every genesis hash committed here was read from a live node:
solana mainnet 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d
solana devnet EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG
fogo mainnet CDLtwKnaCoK157uaHQDj4fHu72AyD2519Cphmpiq6hvT
fogo testnet 9GGSFo95raqzZxWqKM5tGYvJp5iv4Dm565S4r8h5PEu9

Verified with the config tester against live endpoints (mainnet and testnet both
pass), including a negative check: pointing the Solana entry at Fogo's URL fails
with "chain id mismatch", so the check is not passing vacuously.

Copilot AI lite review requested due to automatic review settings August 13, 2026 13:20
@frolvanya
frolvanya force-pushed the feat/svm-node-wiring branch from 80ebf9c to 285b50c Compare August 13, 2026 13:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Wires SVM-based foreign chain verification (Solana and Fogo) end-to-end in the MPC node, connecting operator config through inspector fan-out into verify_foreign_tx, and extending health-check/config-tester/docs so nodes can validate and serve these chains instead of rejecting them.

Changes:

  • Adds typed Solana/Fogo inspector fan-out and request dispatch for verify_foreign_tx (plus config parsing / wiring tests).
  • Extends foreign-chain health checks with SVM genesis-hash fingerprint probing and golden vectors for Solana/Fogo.
  • Updates operator/localnet documentation and templates to include Solana/Fogo configuration and Solana localnet request args.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/running-an-mpc-node-in-tdx-external-guide.md Adds Solana/Fogo foreign_chains examples for testnet/mainnet deployments.
docs/localnet/mpc-configs/config.yaml.template Adds Solana config to localnet YAML template (needs follow-up for Fogo + comment correctness per PR comments).
docs/localnet/mpc-config.template.toml Adds Solana config to localnet TOML template (needs follow-up for Fogo + comment correctness per PR comments).
docs/localnet/localnet.md Documents how to generate a fresh Solana signature and run a Solana verify_foreign_transaction call.
docs/localnet/args/verify_foreign_tx_solana.json Adds a localnet request fixture for Solana verification (with placeholder tx id).
docs/foreign-chain-transactions.md Documents SVM fingerprint probing (getGenesisHash) and tabulates Solana/Fogo genesis hashes.
deployment/cvm-deployment/user-config.toml Adds Solana/Fogo config blocks for CVM deployment user config (testnet + commented mainnet variant).
crates/node/src/web.rs Extends debug/config surface to report configured provider counts for Fogo.
crates/node/src/tests/foreign_chain_configuration.rs Ensures foreign chain configuration setup includes the new fogo slot.
crates/node/src/providers/verify_foreign_tx/sign.rs Adds Solana/Fogo dispatch to SVM inspectors for request execution.
crates/node/src/providers/verify_foreign_tx.rs Adds Solana/Fogo inspectors to the node wiring and tests to pin correct config-to-slot mapping.
crates/node-config/src/foreign_chains.rs Adds fogo to config model and parsing/validation tests.
crates/foreign-chain-health-check/src/probe.rs Implements provider probing for Solana and Fogo using their inspectors.
crates/foreign-chain-health-check/src/lib.rs Runs SVM checks for Solana/Fogo instead of skipping them as “not yet supported”.
crates/foreign-chain-health-check/src/golden.rs Introduces SVM golden vectors (genesis hash) for mainnet/testnet Solana/Fogo.
crates/foreign-chain-health-check/src/checks.rs Adds check_svm that validates chain identity via canonicalized genesis hash.
crates/foreign-chain-config-tester/README.md Updates config tester docs to reflect SVM chain checks and expected output.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/localnet/mpc-configs/config.yaml.template
Comment thread docs/localnet/mpc-config.template.toml
Comment thread crates/node/src/providers/verify_foreign_tx.rs
@claude

claude Bot commented Aug 13, 2026

Copy link
Copy Markdown

Pull request overview

This PR connects the already-merged SVM inspector to the rest of the node so that Solana and Fogo verification requests are actually served instead of rejected. It adds a fogo node-config section (solana already existed), fills the solana/fogo inspector slots in ForeignChainInspectors, replaces the bail!("ForeignChainRpcRequest::Solana is unsupported") arm with a shared execute_svm_request helper used by both SVM chains, and wires both chains into the two health-check routes (golden identity check + network-fingerprint probe). Operator-facing templates and docs gain both chains, with every genesis hash reportedly read back from a live node.

Changes:

  • mpc-node-config: new fogo: Option<ForeignChainConfig> section, mapped to dtos::ForeignChain::Fogo in all_configured_chains, so it feeds registration, validation and the whitelist verifier like every other chain.
  • mpc-node: solana/fogo FanOut<SvmInspector<HttpClient, _>> slots built through with_http_client; sign.rs dispatches both variants through one generic execute_svm_request; /debug provider counts gain fogo.
  • foreign-chain-health-check: SvmVector golden entries (mainnet + testnet), check_svm genesis-hash identity check, run_svm fan-out, and getGenesisHash probe arms for Solana and Fogo.
  • Docs/config: user-config.toml, TDX guide, localnet templates and a new verify_foreign_tx_solana.json fixture; the fingerprint tables in docs/foreign-chain-transactions.md are updated and the stale "solana … has no inspector" passage is corrected.

Reviewed changes

Per-file summary
File Description
crates/foreign-chain-config-tester/README.md Describes SVM chains as identity-checked rather than replayed; sample output gains a solana row.
crates/foreign-chain-health-check/src/checks.rs New check_svm<Chain>: compares the provider's canonicalized getGenesisHash against the golden value.
crates/foreign-chain-health-check/src/golden.rs SvmVector type plus solana/fogo genesis hashes for mainnet and testnet; base58 decode test extended.
crates/foreign-chain-health-check/src/lib.rs run_svm per-provider loop; solana moves out of the "not yet supported" block, fogo added; chain-list test updated.
crates/foreign-chain-health-check/src/probe.rs Fingerprint-probe arms for ForeignChain::Solana and ForeignChain::Fogo; TODO comment narrowed.
crates/node-config/src/foreign_chains.rs fogo config section, DTO mapping, and a parse/validate test for it.
crates/node/src/providers/verify_foreign_tx.rs solana/fogo inspector slots; new tests pinning that each config feeds only its own slot.
crates/node/src/providers/verify_foreign_tx/sign.rs Solana/Fogo dispatch arms delegating to the new generic execute_svm_request.
crates/node/src/tests/foreign_chain_configuration.rs fogo: None added to the exhaustive ForeignChainsConfig literal.
crates/node/src/web.rs fogo provider count in the debug endpoint; Fogo URL added to the redaction assertions.
deployment/cvm-deployment/user-config.toml Testnet solana (devnet) + fogo sections, and the commented mainnet variants.
docs/foreign-chain-transactions.md Fingerprint tables gain solana/fogo; corrects the passage claiming Solana has no inspector.
docs/localnet/args/verify_foreign_tx_solana.json New request fixture: placeholder tx_id, rent-sysvar AccountState extractor.
docs/localnet/localnet.md Solana walkthrough, including a snippet that patches in a fresh finalized signature.
docs/localnet/mpc-config.template.toml, docs/localnet/mpc-configs/config.yaml.template Localnet solana section with the mainnet genesis hash.
docs/running-an-mpc-node-in-tdx-external-guide.md Solana/Fogo blocks for the testnet and mainnet config examples.

Findings

Blocking (must fix before merge):

  • crates/node/src/providers/verify_foreign_tx/sign.rs:140 — the dispatch arms are the exact hazard the PR guards against one file over (verify_foreign_tx.rs:157: "a config.solana/config.fogo swap still type-checks"), but nothing pins them. execute_svm_request is generic over Chain, so Solana(request) => … self.inspectors.fogo … compiles cleanly, and the consequence is worse than a config-slot swap: every node substitutes identically, so FanOut's cross-provider agreement check cannot catch it and the network signs a ForeignTxSignPayloadV1 asserting a Solana transaction over data read from Fogo. Please pin request-variant → inspector-slot the same way you pinned config → slot. A cheap seam is to extract the selection, e.g.

    impl ForeignChainInspectors<HttpClient> {
        fn svm(&self, chain: dtos::ForeignChain) -> Option<&FanOut<SvmInspector<HttpClient, ???>>> {}
    }

    — or, since the two slots have different Chain types, a small #[cfg(test)] assertion that each arm reaches the fan-out built from the corresponding config (two mock SVM endpoints answering distinguishable getTransaction payloads works, mirroring crates/e2e-tests/tests/foreign_chain_tx_validation.rs).

  • crates/foreign-chain-health-check/src/checks.rs:218, crates/foreign-chain-health-check/src/lib.rs:102, crates/foreign-chain-health-check/src/probe.rs:111 — the new health-check code paths ship untested, against engineering-standards.md §Add tests ("if the change was reverted, these tests would fail"). Concretely, all of these survive the current suite: stubbing check_svm to Ok(()), dropping the got != expected comparison, swapping golden.solanagolden.fogo in run_svm calls, or reverting the two probe arms to ProbeNotImplemented. golden.rs:242 only proves the constants are 32 base58 bytes — it cannot catch a mainnet/devnet or solana/fogo mix-up. The sibling check_sui landed with check_sui__should_pass_when_provider_is_on_the_expected_network and check_sui__should_fail_when_chain_id_differs (checks.rs:385, checks.rs:400), and probe.rs already tests every other wired chain (probe_all_providers__should_report_every_evm_chain_on_its_expected_network_as_healthy). httpmock is in scope in both modules and getGenesisHash is a single-value JSON-RPC response, so the equivalents are a few lines each.

Non-blocking (nits, follow-ups, suggestions):

  • docs/localnet/localnet.md:507 — the snippet rewrites the tracked docs/localnet/args/verify_foreign_tx_solana.json in place, so following the walkthrough leaves the operator's working tree dirty with a mainnet signature that goes stale anyway. Suggest leaving the patched copy in /tmp and pointing the call at it:
    jq --arg tx "$TX_HEX" '.request.request.Solana.tx_id = $tx' \
      docs/localnet/args/verify_foreign_tx_solana.json > /tmp/verify_foreign_tx_solana.json
    with file-args /tmp/verify_foreign_tx_solana.json in the near contract call-function line below.
  • crates/foreign-chain-health-check/src/golden.rs:34, lib.rs:322, checks.rs:215 — the same rationale ("SVM providers prune historical transactions, so identity is checked instead") is restated in three doc comments within one crate. Per engineering-standards.md §Write helpful code comments, keep it at the definition (check_svm) and let the other two be intra-doc links to it.
  • crates/foreign-chain-health-check/src/checks.rs:218 — for SVM, check_svm is now byte-for-byte the same assertion the fingerprint probe already makes (getGenesisHash, canonicalized, compared), unlike check_sui, which additionally inspects a checkpointed transaction. Given TODO(#3969) plans to retire the golden route, it may be worth deciding now whether the SVM golden entries earn their keep or whether the probe alone should cover these chains.
  • deployment/cvm-deployment/user-config.toml:286 — Fogo ships with a single public provider on both networks, so its fan-out degenerates to one source and FanOut's cross-provider agreement check is vacuous for that chain (every other chain in the template has 2–4). A short comment saying that is intentional until a second Fogo endpoint exists would save operators the question.

⚠️ Issues found

@frolvanya
frolvanya force-pushed the feat/svm-node-wiring branch from 285b50c to 33f3143 Compare August 13, 2026 13:31
@frolvanya
frolvanya force-pushed the feat/svm-node-wiring branch from 33f3143 to b9f01ce Compare August 13, 2026 14:36
@frolvanya
frolvanya force-pushed the feat/svm-node-wiring branch 2 times, most recently from 796ab4b to 3cb07e1 Compare August 13, 2026 15:51
@frolvanya
frolvanya force-pushed the feat/svm-node-wiring branch from e88458d to b904c1d Compare August 13, 2026 16:49
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