The Same Bridge, the Parity Way — and the Bill
We rebuilt our trustless bridge with the stack that runs Polkadot↔Kusama: pallet-bridge-grandpa plus ordered message lanes. Same trust model, different machinery — and this time every proof lands as a signed transaction with a fee on the record. The head-to-head, measured.
In ISMP Bridging with Satsuma we bridged two
satsuma chains with : on-chain
,
, an untrusted courier. That’s not
the only implementation of the idea. Parity has shipped it for years as
parity-bridges-common — the stack that moves value between Polkadot and
Kusama today.
So we built the same bridge again. Same two 500ms chains, same
feature (literally the same
— pallet-xtransfer grew a second
), same untrusted
role. Different machinery. This is the
head-to-head.
Same idea, different shape
Both stacks do exactly two things on-chain: verify the peer’s GRANDPA finality, then verify state proofs against the finalized root. The differences are all in the plumbing:
pallet-bridge-grandpais a header chain: relayers feed it the peer’s finalized headers with (submit_finality_proof_ex), it keeps the verified head. Justifications on our single-validator chains are a tidy 178 bytes.pallet-bridge-messagesadds ordered : outbound messages get consecutive , deliveries carry storage proofs of the outbound queue (~1 KB per batch), inbound tracking enforces exactly-once, in-order dispatch, and a third transaction type — the confirmation — proves delivery back to the source so it can prune its queue.
Where ISMP gives you a request/response protocol with timeouts and refunds, lanes give you a conveyor belt: strict ordering, explicit confirmation, nothing else. Our transfer pallet needed a custom dispatcher on the receiving side (decode payload → mint) — ~130 lines of runtime config in total.
The demo

Same choreography as before: two sovereign chains, seeds each side’s light client with the other’s , the relayer starts working, and 5 UNIT crosses A→B and B→A — verified, minted, balanced. The difference you can see is step 6: the bill. Every relayer action is a signed transaction with a fee:
| Relayer action | Fee (UNIT) | Size |
|---|---|---|
| Finality import | 0.001440 | 550 B tx (178 B justification) |
| Message delivery | 0.000865 | ~1 KB storage proof |
| Delivery confirmation | ~0.000900 | lane state proof |
A demo run’s total came to ~0.025 UNIT of relayer spend — versus zero for
ISMP, whose datagrams ride in unsigned, proof-validated extrinsics admitted by
the on the strength of
their proofs alone.
Production Parity-stack deployments bolt on pallet-bridge-relayers to
reimburse relayers from bridge fees; between two chains we operate ourselves,
the “bill” is money moving between our own pockets — but it sizes the subsidy
honestly.
The measured head-to-head
Ten transfers each way, same machine, same block time:
| ISMP direct peering | Parity bridges | |
|---|---|---|
| Delivery p50 / p90 | 4.0 s / 5.0 s | 6.5 s / 7.0 s |
| Message proof | ~300 B | ~1 KB |
| Finality artifact | 1.2–2 KB (justification + ancestry) | 178 B justification |
| Relayer cost per message | 0 | ~0.0023 UNIT (finality+delivery+confirm) |
| User fee | 0.0006 UNIT | 0.0006 UNIT |
| Ordering | unordered, per-request timeouts | strictly ordered lanes |
| Reach | Hyperbridge → EVM chains later | Substrate↔Substrate (BridgeHub lineage) |
The latency gap is plumbing, not cryptography: our lane relayer needs two sequential transactions (finality, then delivery) where the ISMP relayer ships consensus + request in one pass. Both bridges’ true heartbeat is the justification cadence — we generate one every 4 blocks (2 s).
Which one should a satsuma-class chain use?
ISMP direct peering is our default. Faster in practice, 3x smaller message proofs, request/response + timeout/refund semantics that map straight onto product features, no funded relayer account required — and the same pallets upgrade into a connection when we want reach beyond chains we operate.
The Parity stack is the conservative pick when strict per-lane ordering is a hard requirement, when “this exact code runs Polkadot↔Kusama” is the sentence your auditor wants to read, or when you need a crates.io-only supply chain (Polytope’s aggressive version yanking made us pin git tags and seed a lockfile — real, if minor, operational friction). Its relayer was also the easiest code of the whole study: 208 lines of JavaScript against plain RPC.
Either way, the conclusion of the pair of posts stands: two sovereign chains can hold each other to cryptographic truth — no custodian, no committee, no favors. The technology is here, it’s open source, and it runs at satsuma’s block time.
Caveats
Same list as the ISMP post — single-validator chains (178 B justifications
grow with the authority set), loopback latency, no relayer incentive layer.
Plus two stack-specific ones: message lanes must be opened at
(there’s no extrinsic; production uses
pallet-xcm-bridge-hub), and our JS relayer is a prototype — the production
substrate-relay binary exists but is built around Parity’s own chain pairs.