feat(foreign-tx): svm inspector - #4137
Conversation
9f6d07f to
bb63b69
Compare
Pull request overviewAdds the Solana JSON-RPC wire types ( Changes:
Reviewed changesPer-file summary
The core protocol decisions read correct to me: reading the rooted slot before the transaction (a root read afterwards would admit a slot orphaned in between), querying FindingsBlocking (must fix before merge):
Non-blocking (nits, follow-ups, suggestions):
|
bb63b69 to
1476144
Compare
There was a problem hiding this comment.
Pull request overview
Adds first-class SVM (Solana VM) support to the foreign-chain inspector stack by introducing Solana JSON-RPC request/response types and a generic SvmInspector<Client, Chain> with chain-marker types to prevent accidentally wiring a Solana inspector into a Fogo slot (and vice versa).
Changes:
- Introduces
foreign-chain-rpc-interfaces::svmwith typed RPC params/partial responses forgetTransaction,getAccountInfo, andgetSlot. - Adds
foreign-chain-inspector::svmwithSvmInspector(plusSolanaInspector/FogoInspectoraliases), finality gating, and extractors for inner instructions and account state. - Extends contract-interface conversion plumbing and error surface (
AccountNotFound), plus adds comprehensive mocked tests and ignored live-RPC manual tests.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| crates/foreign-chain-rpc-interfaces/src/svm.rs | Adds SVM JSON-RPC types and param serialization helpers used by the inspector. |
| crates/foreign-chain-rpc-interfaces/src/lib.rs | Exposes the new svm module. |
| crates/foreign-chain-rpc-interfaces/Cargo.toml | Adds dependencies needed for SVM RPC parsing/serialization tests (base64, serde_json). |
| crates/foreign-chain-inspector/src/svm/inspector.rs | Implements the generic SvmInspector with finality checks and extraction logic. |
| crates/foreign-chain-inspector/src/svm.rs | Defines SVM extracted value types and exposes the inspector module. |
| crates/foreign-chain-inspector/src/lib.rs | Exposes svm and adds the AccountNotFound inspection error variant. |
| crates/foreign-chain-inspector/src/contract_interface_conversions.rs | Adds DTO conversions for SvmFinality, SvmExtractor, and SvmExtractedValue. |
| crates/foreign-chain-inspector/tests/svm_inspector.rs | Adds mocked test coverage for SVM extraction, finality semantics, and hostile-provider bounds. |
| crates/foreign-chain-inspector/tests/svm_rpc_manual.rs | Adds ignored live-RPC sanity checks against Solana mainnet. |
| crates/foreign-chain-inspector/Cargo.toml | Adds base64 dev-dependency for SVM inspector tests. |
| Cargo.lock | Locks new dependency usage introduced by the SVM modules/tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
1476144 to
64c50ae
Compare
64c50ae to
4f01e83
Compare
|
@claude review |
Pull request overviewRe-review after Changes:
Reviewed changesPer-file summary
The finality argument holds: a transaction served at a slot at or below a previously observed root can only come from the rooted block, since roots never revert — reading the root afterwards would also admit a block orphaned in between. The new account-read floor is the right shape too: a floor rather than FindingsBlocking (must fix before merge):
Non-blocking (nits, follow-ups, suggestions):
Previously raised, still open, not re-argued here: nothing constructs a |
|
@claude review |
a55ca6e to
b5dc987
Compare
Pull request overviewRe-review after Changes:
Reviewed changesPer-file summary
The FindingsBlocking (must fix before merge):
Non-blocking (nits, follow-ups, suggestions):
Previously raised, still open, not re-argued here: the fingerprint value table in |
Adds the Solana JSON-RPC types and an
SvmInspector, shared by Solana and Fogo behind chain-marker types(
SolanaInspector/FogoInspector, mirroringEvmInspector<Client, Chain>)so an inspector built for one chain cannot be wired into the other's slot.
What it does per request:
for;
Details worth reviewing:
Finalized, the rooted slot is read BEFORE the transaction. Reading itafterwards would let a block that got orphaned in between pass the check.
meta.erris a required field, not anOption: serde maps an absent fieldto
None, which would make a provider that omits it indistinguishable fromone reporting success. Absence is rejected; explicit
nullmeans success.innerInstructions: nullmeans the node was not started with extendedtransaction metadata, i.e. it cannot answer — not that the instruction is
absent. Reported as a transient provider failure so the fan-out falls
through to a provider that does record it, instead of signing an absence.
u8(the wire format),inner-instruction data is capped at the runtime's 10 KiB CPI limit, the
account list at the runtime's 255-meta limit (checked before indices are
resolved into 32-byte pubkeys), and error messages never echo unbounded
provider strings.
Extracted values are normalised so independent providers produce byte-identical
output — account indices are resolved against the static account keys plus the
addresses loaded from lookup tables (so v0 transactions work), and instruction
data is decoded from base58.
Tested with mocked providers, including a params-recording mock that pins the
commitment levels and encodings actually sent, plus manual (#[ignore]d) tests
that were run against live Solana mainnet.