# IBC v2 & sharding

> IBC v2 on NeuroChain — post-quantum commit headers, ICS-20-style token transfers with escrow and vouchers, VMGuardian attestations as packets, the relayer and operator setup, configuration, current status and how it is tested; plus operating shards.

Source: https://docs.nro.world/operate/ibc

## IBC v2 <Badge type="warning" text="experimental" />

NeuroChain connects to other chains with **IBC v2** — the simplified, client-centric version of the Inter-Blockchain Communication protocol (also known as *Eureka*). The first counterparty is the Cosmos ecosystem, starting with Neutron (CosmWasm).

What NeuroChain adds is **post-quantum interoperability**: its commits are signed with ML-DSA-65, so the counterparty's light client verifies NeuroChain with a post-quantum signature instead of the ECDSA / Ed25519 schemes classic IBC relies on.

### What travels over a channel

| Packet | Wire format | Purpose |
|--------|-------------|---------|
| Fungible transfer | `nc-ics20-v1|denom|amount|sender|receiver|channel|memo` | Move NRO or vouchers between chains, ICS-20 style |
| Security attestation | `nc-ibc-attest-v1|bytecode_hash|score|model|timestamp|subject` | Carry a [VMGuardian](/ai/vmguardian) score to another chain |
| Commit header | `nc-pq-lc-v1|chain_id|height|block_hash|state_root`, signed ML-DSA-65 | What the counterparty light client checks |

The attestation packet is where the two main bets meet: an AI security proof produced on NeuroChain that another chain can rely on.

### Token transfers

![IBC v2 transfer: the user signs an ibc_transfer; validators lock the NRO in the channel escrow; every 1 000 blocks they sign a commit header; the relayer fetches the header, updates the counterparty client and delivers the packet; the counterparty mints a voucher; the relayer acknowledges, and the escrow is burned; without an acknowledgement before the timeout the sender is refunded](/diagrams/ibc-v2-transfer.svg)

**Outbound (NeuroChain → counterparty)**

1. `POST /api/v1/ibc/transfer` locks the amount in the channel's escrow account `neuro:ibc.escrow.<channel>`; the packet is `locked`.
2. A relayer delivers it; the counterparty mints a voucher.
3. `POST /api/v1/ibc/ack` marks it `committed` and burns the escrow.
4. No acknowledgement within the timeout → the sender is refunded automatically.

**Inbound (counterparty → NeuroChain)**

1. A relayer submits `POST /api/v1/ibc/recv` with the packet and its commitment.
2. The receiver is credited an **IBC voucher** with the denom `ibc/<SHA-256 of the trace path>`, as ibc-go does. A packet id can be received only once.
3. `POST /api/v1/ibc/redeem` burns the voucher and sends the asset back through the channel.

Amounts on the wire are integers in the base denom (`unro` for NRO).

### Who signs what

| Operation | Who may submit | Signature |
|-----------|----------------|-----------|
| `transfer`, `redeem` | Any account, for its own funds | Covers every field — receiver, channel, chain, denom, amount |
| `recv`, `ack`, `channel/open`, `channel/pause`, `client/update`, `attest` | **IBC operators** only: keys listed in `NEUROCHAIN_IBC_OPERATOR_PUBKEYS` | Same, by the operator's key |

Authority is the operator's **public key**, not a claimed address. All IBC operations are applied in consensus and sign for `neuro:system.ibc`.

### Current status and limits

| Piece | Status |
|-------|--------|
| Escrow, vouchers, denom traces, timeouts, packet records | Implemented in the node, unit-tested |
| PQ commit headers signed every 1 000 blocks | Implemented; served at `GET /api/v1/ibc/header/latest` |
| Field-binding signatures on every IBC operation | Implemented, with golden test vectors |
| Counterparty contract `neuro-pq-client` (CosmWasm) | Built (`neurochain/contracts/neuro_pq_client`). **Not yet trustless:** it checks the relayer's trusted key and a rising height; the ML-DSA-65 signature is verified by the relayer, off-chain |
| Inbound packets | Accepted from IBC operators with a commitment over the credited fields; a Merkle membership proof from the counterparty is proposed, not implemented |
| End-to-end transfer with Neutron testnet | **Not done yet** — the deployment script is ready (`tools/ibc-relayer/deploy_neutron.js`) and needs a funded testnet account |
| Full IBC v2 handshake with ibc-go | Planned |

Until the counterparty verifies ML-DSA-65 on chain, an IBC channel trusts its relayer. Keep `NEUROCHAIN_IBC_MAX_PACKET_UNRO` and `NEUROCHAIN_IBC_MAX_CHANNEL_ESCROW_UNRO` low on any network with real value.

**How it is tested:** node unit tests cover locking, acknowledgement, timeout refund, voucher credit and redeem, duplicate packets, reserved packet ids, commitment mismatches, operator authority and the canonical signed messages (`cargo test -p neurochain-node ibc`). `GET /api/v1/ibc/pq/test-vector` returns a fixed header, key and signature so a counterparty implementation can check it encodes and verifies the same bytes.

### Running a relayer (lab)

```bash
# 1. Start the node with your operator key allowed
NEUROCHAIN_IBC_OPERATOR_PUBKEYS=<operator ML-DSA-65 public key hex> ./target/debug/neurochain

# 2. Open a channel (signed by the operator)
#    POST /api/v1/ibc/channel/open  { from, channel, port, counterparty_chain, allowed_denoms, … }

# 3. After a checkpoint, export the header for the counterparty client
NODE_RPC=http://localhost:9933 node neurochain/tools/ibc-relayer/export_update_client.js
```

The script prints the `UpdateClient` message for `neuro-pq-client`. Request fields for every IBC endpoint are in the [REST reference](/reference/rest#ibc-v2).

### Configuration

| Variable | Default | Meaning |
|----------|---------|---------|
| `NEUROCHAIN_IBC_OPERATOR_PUBKEYS` | empty | Comma-separated public keys allowed to relay and administer channels |
| `NEUROCHAIN_IBC_TRUSTED_PUBKEYS` | empty | ML-DSA-65 keys whose header signatures are accepted on inbound packets; empty accepts any valid signature (lab only) |
| `NEUROCHAIN_IBC_REQUIRE_HEADER` | on mainnet | Inbound packets must come with a verified header |
| `NEUROCHAIN_IBC_REQUIRE_PACKET_COMMITMENT` | on mainnet | Inbound packets must carry the commitment over their fields |
| `NEUROCHAIN_IBC_TIMEOUT_BLOCKS` | 10 | Blocks before an unacknowledged outbound packet is refunded |
| `NEUROCHAIN_IBC_MAX_PACKET_UNRO` | no limit | Largest single transfer |
| `NEUROCHAIN_IBC_MAX_CHANNEL_ESCROW_UNRO` | no limit | Most that one channel may hold in escrow |
| `NEUROCHAIN_IBC_NATIVE_DENOM` | `unro` | Base denom of NRO on the wire |

## Sharding <Badge type="warning" text="experimental" />

Each shard runs its own consensus instance with its own validators and height; accounts belong to `FNV-1a(address) mod n_shards`. How cross-shard transfers settle is described in [Consensus → Sharding](/learn/consensus#sharding).

Run one node per shard:

```bash
NEUROCHAIN_SHARDS=4 NEUROCHAIN_SHARD_ID=0 NEUROCHAIN_DATA_DIR=./data-s0 NEUROCHAIN_RPC_PORT=9933 … ./target/debug/neurochain
NEUROCHAIN_SHARDS=4 NEUROCHAIN_SHARD_ID=1 NEUROCHAIN_DATA_DIR=./data-s1 NEUROCHAIN_RPC_PORT=9934 … ./target/debug/neurochain
```

- Without `NEUROCHAIN_SHARD_ID` a node runs a single shard and creates no cross-shard transfers.
- The gateway routes each transaction to the node of the sender's shard.
- Monitor relays with `GET /api/v1/cross-shard/queue?status=locked` and per-shard heights with `GET /api/v1/shards`.

Internally, cross-shard relays use the same packet engine as IBC v2 — a shard is one kind of channel end, an external chain another.
