Skip to content

Feat/sdk 2606 migration - #140

Merged
nol4lej merged 31 commits into
mainfrom
feat/sdk-2606-migration
Sep 2, 2026
Merged

Feat/sdk 2606 migration#140
nol4lej merged 31 commits into
mainfrom
feat/sdk-2606-migration

Conversation

@nol4lej

@nol4lej nol4lej commented Sep 2, 2026

Copy link
Copy Markdown
Member

What this does

Two changes that had to land together: the polkadot-sdk bump from stable2512 to
2606, and the Hyperbridge/ISMP integration that depends on it. pallet-ismp 2606.1.0
pins polkadot-sdk =2606.0.0 exactly, so the integration could not be built against
the old SDK line.

124 files changed, +20064 −12757 across 25 commits.

SDK migration

Crate Before After
frame-support 45.1.3 48.0.0
sp-runtime 45.0.0 48.0.0
sp-core 40.1.0 43.0.0
pallet-ismp 2606.1.0

Also in here:

  • 17 obsolete deny.toml advisory ignores removed. They were pinned by
    stable2512's wasmtime 35.0.0 — three of them sandbox escapes. SDK 2606 brings
    wasmtime 36.0.14, which fixes every one. Verified by emptying the list and
    re-running cargo deny check advisories.
  • Dead core2 git patch dropped. Its cid -> sc-network dependency chain is
    gone since 2606, so the patch silently applied to nothing and emitted a warning.
  • Frontier upstream security and correctness patches applied; vendored test
    harnesses dropped to resolve the fc-* test-target split.

Weights were not invalidated by the bump. The SDK weight constants
(block_weights, extrinsic_weights, rocksdb_weights, paritydb_weights) are
byte-identical between frame-support 45.1.3 and 48.0.0 — checked before trusting the
existing measurements.

Hyperbridge integration

Orbinum joins as a solochain via the GRANDPA consensus client, following
Polytope's solochain guide.

Field Value
Host state machine SUBSTRATE-orbi
Coprocessor (testnet) Kusama(4009)
Coprocessor (mainnet) Polkadot(3367)
Slot duration 6000 ms

The testnet coprocessor is Kusama(4009) even though the deployment runs on the
Paseo relay: StateMachine has no Paseo variant, so Hyperbridge labels its
Paseo deployment as Kusama. Confirmed against their published relayer config
(# For Paseo Testnet: KUSAMA-4009), not inferred.

Runtime block length raised to 8 MiB with extrinsics at 85%, per the guide's
recommendation for large GRANDPA proofs.

The compile-time constant that bites

The coprocessor is selected by the hyperbridge-testnet cargo feature. Build a
testnet node without it and the runtime ships mainnet's Polkadot(3367). Since
is_allowed_proxy compares the whole SCALE variant with ==, every proxied request
is then rejected with RequestProxyProhibited — and nothing fails at build or
deploy time
. It surfaces when a relayer first tries to work.

Three things now guard that:

  1. scripts/verify-coprocessor.sh <testnet|mainnet> [binary] boots a node and reads
    OrbinumIsmpApi_coprocessor back off it. Asking the runtime what it was compiled
    with is the one check that cannot be self-consistently wrong.
  2. release.yml passes the feature per environment, for both the native build and
    the Docker image, and runs the verifier on each.
  3. docker-publish is now build → verify → push. It compiles its own image
    independently of the build job, so a wrong build-args there would have passed
    build green and shipped the wrong deployment. Once a tag reaches GHCR the
    validators may pull it before anyone can delete it, so the check gates the push
    rather than following it.

Verified locally against a real image, not just the shell expansion:

coprocessor: 0x0102a90f0000    = Some(Kusama(4009))
host:        0x036f726269      = Substrate("orbi")
slot:        0x7017000000000000 = 6000 ms

Conclusive because the control — a binary built without the feature — reports
0x0101270d0000 = Polkadot(3367). Different values, so the --build-arg genuinely
changed what the compiler produced.

Benchmarks

pallet-ismp-messaging weights are now real measurements (Hetzner CPX62, 16 vCPU /
32 GB), replacing hand-written estimates. type WeightInfo went from () to
SubstrateWeight<Runtime>, so measured weights enter block calculation for the first
time.

One value is hand-corrected: dispatch_post's proof_size is 3550, not the
generator's 2585700789447993344. frame-benchmarking's min_squares_iqr
(analysis.rs:419) lacks the .max(0f64) clamp that median_slopes
(analysis.rs:338) has, so a negative regression coefficient underflows on cast to
u64. Reported upstream; the file header documents it, because regenerating the
file reintroduces the bad value
.

The runner also got fixes worth noting: it no longer targets pallet_ismp (which has
no define_benchmarks! entry post-2606), and it reports a SIGKILLed pallet as a
failure instead of printing "All benchmarks completed successfully" — if ! cmd; then local rc=$? captured the if's status, not the command's.

Also here

  • slot_duration.rs went from dead code to a compile-time assertion on the value
    this runtime whitelists. Mutation-tested: 0, 999, 3_600_001 each fail the
    build.
  • SignedExtra's ordering invariant is now documented — Tesseract builds signed
    payloads against that exact tuple, so reordering it invalidates every signature the
    relayer produces.
  • .dockerignore added (the repo had none). Without it COPY . . ships a
    developer's target/ — over 100 GB here — to the daemon. CI never noticed because
    its checkout is clean. .git/ is deliberately not excluded: substrate's build
    script reads .git/HEAD to stamp the commit hash into --version, and dropping it
    leaves every image reporting a bare version.
  • spec_version 10 → 11.

Testing

  • Runtime and node build in both feature configurations
  • cargo test -p pallet-ismp-messaging, -p orbinum-runtime --lib configs::ismp
  • ISMP E2E and adversarial suites
  • make clippy-release
  • Live setCode upgrade on a 2-validator chain running the old 2512 binary — the
    exact operation this enables on testnet
  • Docker image built from node-deploy/common/Dockerfile and its coprocessor read
    back from a node running inside the container

Known debt (not blocking)

  • polkavm 0.29.1 vs 0.33.1 available
  • Node-side SDK crates sit one minor behind 2606.2.0, frozen by pallet-ismp's exact
    =2606.0.0 pin
  • dispatch_post's proof_size correction is lost if weights are regenerated
  • DispatchOrigin is root-only

Deploy order

  1. Merge, then tag → release.yml builds with hyperbridge-testnet and verifies
    before publishing
  2. Runtime upgrade to testnet, then confirm OrbinumIsmpApi_coprocessor,
    IsmpRuntimeApi_host_state_machine and OrbinumIsmpApi_hyperbridge_slot_duration
    over RPC
  3. Then Hyperbridge onboarding: Tesseract consensus config
    (KUSAMA-4009 / PAS0 / para_ids [4009] / Keccak),
    create_consensus_client, and the onboarding request to polytope-labs

One thing to watch on the first release run: if Push Docker image takes ~25 minutes
instead of seconds, the buildx cache didn't carry over from the verify step and it
should move to outputs: type=docker,dest=… plus docker load.

nol4lej added 30 commits August 24, 2026 10:02
@nol4lej
nol4lej merged commit 0da2c69 into main Sep 2, 2026
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.

1 participant