Add embedded smoldot light-client transport to the provider node#297
Open
ilchu wants to merge 5 commits into
Open
Add embedded smoldot light-client transport to the provider node#297ilchu wants to merge 5 commits into
ilchu wants to merge 5 commits into
Conversation
The provider can now follow the chain without any operated RPC
infrastructure: --chain-transport light boots an embedded smoldot
instance that warp-syncs the relay chain and derives parachain
finality from it. The RPC transport remains the default; the switch
is config-level because all chain access already flows through the
chain_connection seam introduced with the event-driven coordinators.
- ChainTransport::Light { relay_spec, para_spec } with SpecSource
being either a vetted spec file (production: trust-preserving) or
fetched from a node's RPC at startup (dev convenience for zombienet,
which regenerates genesis every run; logged loudly as trust-defeating).
- ChainHandle keeps the LightClient alive; the follower's stall
watchdog rebuilding the connection therefore boots a fresh smoldot,
recovering even from a wedged smoldot background task (the silent-
hang failure mode tracked upstream as subxt#1536).
- The first finalized block after a (re)connect gets a 300s budget
(warp sync + peer discovery) before the 60s stall watchdog applies.
- scripts/test-light-client.sh: manual e2e against a running zombienet.
It synthesizes the light-client parachain spec from zombienet's
network directory - convert-to-raw genesis (smoldot cannot execute
runtimeGenesis), inject the collator's boot nodes, and align
relay_chain with the relay spec's exact id (smoldot matches
parachain to relay by exact id; omni-node tolerates the westend-local
vs westend_local_testnet mismatch, smoldot does not).
Verified live: the provider ran with --chain-transport light against
a local zombienet, synced the relay + parachain via smoldot, followed
finalized blocks, and served its on-chain registration on /info.
282 provider-node tests pass; clippy clean.
The merge from the base branch brought mock-connection tests that built ChainHandle with struct-literal syntax; the _light keep-alive field added on this branch is private outside chain_connection, so the RPC arm and those tests now construct handles via from_api.
Enabling subxt's light-client feature put smoldot and smoldot-light into cargo-deny's feature-resolved graph for the first time, and their GPL-3.0-or-later WITH Classpath-exception-2.0 expression was not in the allow list. Allowed via exceptions scoped to those two crates - compatible with the GPL-3.0-only provider node, and the exception only grants additional linking permissions - rather than allowing the expression workspace-wide. Also covers the Light transport's failure paths for the patch gate: missing spec file, invalid spec contents rejected by smoldot, and an unreachable spec-fetch node.
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.
Implements the embedded smoldot light-client transport from #222: with
--chain-transport light, the provider node follows the chain through an embedded smoldot instance that syncs the relay chain and derives parachain finality from it — no operated RPC infrastructure required. The RPC transport remains the default; flipping the default is a deliberate follow-up decision after soak time, per the investigation's sequencing.This PR is small by design: all chain access already flows through the
chain_connectionseam and the single-follower architecture from #291, so the transport is a construction-site change plus spec handling.What's in it
ChainTransport::Light { relay_spec, para_spec }inchain_connection, each spec aSpecSource: a vetted spec file (the trust-preserving production path; for Paseo the relay spec comes frompaseo-network/paseo-chain-specs) or fetched from a node's RPC at startup (dev convenience for zombienet, which regenerates genesis every run — logged loudly as trust-defeating, since it reintroduces exactly the node trust the light client exists to remove).ChainHandlekeeps theLightClientinstance alive; the follower's stall watchdog rebuilding the connection therefore boots a fresh smoldot, so the recovery path covers even a wedged smoldot background task (the silent-hang failure mode tracked upstream as Light Client: subxt API will do nothing after smoldot thread panic. subxt#1536), not just a dropped subscription.--chain-transport {rpc|light},--relay-chain-spec,--para-chain-spec,--relay-rpc(relay-spec fetch fallback);--chain-rpckeeps double duty as the RPC endpoint and the para-spec fetch source. Resolution logic is unit-tested, including the error when the light transport has no relay-spec source.scripts/test-light-client.sh: manual e2e against a running zombienet. It synthesizes the light-client para spec from zombienet's network directory, encoding three non-obvious requirements: smoldot needs raw genesis storage (zombienet's collator spec isruntimeGenesis, so the script runschain-spec-builder convert-to-rawon it, preserving the genesis hash), the advertised boot nodes live only in the non-raw variant and get injected, and the para spec'srelay_chainid must exactly match the relay spec's id (omni-node tolerateswestend-localvswestend_local_testnet; smoldot does not). The same three facts will drive the real Paseo chain-spec packaging for the default flip.Verification
283 provider-node tests pass; clippy clean. Live on this exact HEAD (i.e. including the event-driven follower and static-bindings event decoding from #291 running over the light transport):
scripts/test-light-client.shagainst a local zombienet — embedded smoldot synced the relay and parachain, followed finalized blocks, and/infoserved the provider's on-chain registration read through it.Relates to #222. Stacked on #291.