Skip to content

wiki / systems

hierarchical consensus, the ipc way

How Interplanetary Consensus spawns child subnets, moves state up with checkpoints and down with parent finality, and what that costs.

updated · 5 min read

Interplanetary Consensus (IPC) scales a blockchain horizontally. Instead of making one chain faster, you spawn child chains, called subnets, that run their own consensus and periodically anchor themselves to a parent. I worked in the IPC working group on checkpointing and cross-subnet messaging. These are my notes on how the pieces fit.

the shape

A hierarchy starts at a rootnet, a layer 1 such as Filecoin. Subnets spawn from it, and any subnet can spawn its own children. Each child has exactly one parent.

          /r314                      rootnet (Filecoin mainnet)
          /     \
   subnet A     subnet B             L2s, each with its own validators
      |
   subnet A1                         L3, anchored to A

A subnet’s ID is the root chain ID plus the route of subnet actor addresses down the tree. As a string that’s /r314 for Filecoin mainnet, then each subnet actor’s f410 address separated by /.

Two contracts make it work. The subnet actor lives on the parent, one per child, created through a registry contract. It holds that child’s validators, stake, and checkpoints. The gateway lives inside each subnet and implements the hierarchy logic, including one hard rule: you can’t withdraw more native tokens out of a subnet than were deposited into it. The docs call subnets “firewalled” from the parent; this rule is the firewall.

why spawn a subnet

Lower fees, higher throughput, or grouping activity by geography, topic, or application. Subnets can be long-lived or spun up for one job and discarded. The design lets each subnet pick its consensus. The current implementation, Fendermint, runs each subnet on CometBFT with an EVM-compatible FVM.

Creating one means setting a minimum collateral on the parent. Validators join with stake from their parent accounts. A subnet can’t be killed until its circulating supply is zero, meaning everyone has moved funds back up.

moving state up: bottom-up checkpoints

The child tells the parent what happened through checkpoints. A checkpoint carries:

  • subnet_id, so it can’t be replayed against another subnet run by the same validators
  • block_height and block_hash of the child, which anchor its history to the parent and block long-range attacks
  • next_configuration_number, identifying the validator set that will sign the next checkpoint
  • the bottom-up messages, or a commitment to them

A checkpoint is created when any trigger fires: a fixed block period, enough queued bottom-up messages to hit a batch limit, or a smaller batch that has waited too long. Every full node creates it deterministically. Validators then sign it in follow-up transactions until more than 2/3 of voting power has signed, each signature carrying a Merkle proof that the signer was in the right committee. A relayer picks up the quorum-signed checkpoint and submits it to the parent, where the subnet actor checks the signatures against the validator configuration it expects.

moving state down: parent finality

The other direction runs through the child’s own consensus. Child validators run a parent syncer that polls the parent over RPC, treating a block as final only once it’s a fixed number of blocks behind the head. They vote on what they’ve seen over a gossipsub channel. Once a quorum agrees, the block proposer includes a ParentFinality { height, blockHash } in its CometBFT proposal, and other validators check it against their own view. Executing it commits the finality, applies validator set changes, and runs the queued top-down messages.

cross-net messages

The user-facing interactions are fund (move tokens down into a child), release (move them back up), and general cross-net calls between actors. General calls hit a real problem: the gas a message will use depends on where it executes, so it can’t be known when the checkpoint is built. A checkpoint that exceeds the parent’s block gas limit can never be included, and checkpointing stalls behind it. Per the bottom-up spec, only fund and release are currently allowed for that reason. The fix being discussed is to commit messages in the checkpoint and let senders trigger and pay for execution later.

trade-offs

  • Whose security? Checkpointed history can’t be reverted while the parent behaves, and checkpoints propagate recursively to the rootnet. But the parent verifies a quorum of signatures; it does not re-execute the child. A child’s safety still rests on its own validators. The firewall caps the damage a broken subnet can do to the parent at what was deposited into it.
  • Latency. Bottom-up messages wait for a checkpoint trigger, a signature quorum, and a relayer. Top-down messages wait for the parent’s finality delay plus a vote in the child.
  • Operational cost. Subnet validators run full nodes for both the parent and the child, and need funds on the child to pay for their signature transactions.
  • Open incentives. Relayer rewards are unresolved. Fendermint’s fixed-reward scheme was removed over a vulnerability, so relayers currently earn nothing.
  • Maturity. The repo’s README warns that the stack hasn’t been audited and advises against mainnet use with real value.

sources

← all notes