Skip to main content

Inter-chain Confirmation Facility (ICCF)

Overview

ICCF (Inter-Chain Confirmation Facility) is a client-driven protocol for cross-chain transaction verification within the Chromia network. It enables dapps to prove that a specific transaction was confirmed on one blockchain and use that proof to trigger state changes on another. ICCF provides cryptographic verification without relying on trusted intermediaries, making it a secure foundation for multi-chain dapp architectures.

Multi-chain dapps need mechanisms for one chain to verify and trust events that occurred on another. Common use cases include:

  • Token transfers — when one chain must confirm that a transaction was finalized on another
  • Access control — when one chain must verify that a specific action was completed on another
  • State synchronization — when multiple chains must keep shared data consistent
  • Workflow coordination — when chains need to trigger or react to verified events across chains
  • Security and audit consistency — when chains must provide verifiable proofs for auditing, compliance, or dispute resolution.

Traditional cross-chain solutions often rely on external oracles or complex custom verification logic, introducing additional trust assumptions. ICCF addresses this by leveraging Chromia's anchoring system to provide built-in, cryptographically verifiable cross-chain proofs. When a transaction occurs on a source chain, ICCF can generate a proof that confirms not only that the transaction was finalized, but also that the block containing it was securely anchored through Chromia's anchoring hierarchy (source chain → cluster anchoring chain → system anchoring chain). The proof can then be presented to a target chain, which independently verifies its validity and acts on that information.

ICCF is client-driven, meaning the client applications or wallets construct and submit proofs, providing application-level control over error handling, retry logic, and user experience. ICCF operates asynchronously and does not require real-time coordination between chains. The protocol supports both intra-cluster (optimized) and inter-cluster (full anchoring) proof flows.

ICCF is not necessary when all functionality can be implemented within a single chain — use standard Rell operations in that case. If your use case requires near real-time messaging between chains, consider ICMF (Inter-Chain Messaging Facility) instead.

Protocol Fundamentals

ICCF is implemented as a combination of two components that work together: a GTX module called IccfGtxModule responsible for low-level proof validation, and a Rell library that helps process and interact with the proved transaction. Both components operate on the target chain, where the proof is verified. The GTX module handles all cryptographic verification of the ICCF proof, including its structure, anchoring paths, and witness signatures. The Rell library provides utility functions that let the dapp access and interpret the proved transaction — for example, extracting operation names and arguments, or adding custom dapp-level validation and logic based on the transaction's contents.

Data Flow

The typical ICCF data flow involves the following steps:

  • Transaction submission on source chain -- The client (user) submits a transaction to the source chain containing the operations or data that need to be proven and acted upon on the target chain.

  • Inclusion and finalization -- The transaction is processed and included in a block on the source chain. Once the block receives sufficient signatures from the chain's validators, it is committed to the blockchain and considered finalized.

  • Anchoring of the block -- The committed block containing the transaction is anchored into the cluster anchoring chain. For inter-cluster flow, the cluster anchoring chain block is subsequently anchored to the system anchoring chain.

  • Proof collection by the client -- This is where the ICCF protocol starts. The client begins by querying the source chain for a confirmation proof and the cluster anchoring chain for the necessary anchoring proofs and block headers. If the transaction or block has not been anchored yet, this is the stage where the client may need to retry querying the cluster anchoring chain until all required anchoring information becomes available.

  • Proof submission to target chain -- The client builds a GTX transaction for the target chain and includes the iccf_proof operation with the necessary proof data. For intra-cluster flow, this includes the source blockchain RID, the source transaction hash, and the source transaction confirmation proof data. Inter-cluster flow requires the same information and additionally the anchoring transaction data, the anchoring operation index (opIndex), and the anchoring transaction confirmation proof data. The client then adds the target operation and submits the complete transaction to the target chain.

  • Proof verification by the target chain -- When the target chain validates the transaction, it first validates the iccf_proof operation, which takes as input the proof data required to validate that the source transaction was finalized on the source chain. The ICCF GTX module validates the submitted proof through several steps: (1) Merkle proof verification confirms the transaction exists in the block's Merkle tree and matches the block header, (2) Block signature verification validates the block was signed by authorized signers at the specified height, (3) Anchoring verification checks the source block is properly anchored in the cluster anchoring chain (intra-cluster flow) or validates the complete anchoring path through both cluster and system anchoring chains, requiring the cluster anchoring chain block that contains the source block to be anchored to the system anchoring chain (inter-cluster flow). Once all verifications pass, the GTX module verifies the target operation and allows the transaction to proceed; otherwise, it rejects the transaction with a proof failure reason.

  • Application logic execution -- After the ICCF proof is verified and the transaction is being applied, the target chain's dapp logic accesses the proven transaction data through ICCF Rell library utilities. The dapp extracts and validates the operation name and arguments, performs additional dapp-level validation, and then applies its business logic — such as updating state, minting tokens, or granting access.

note

Intra-cluster proofs are an optimization with a tradeoff: replica nodes cannot verify that the proven transaction was anchored in the cluster anchoring chain (only signers verify this). If this tradeoff is unacceptable, inter-cluster proofs should be used instead.

The following sequence diagram shows the complete ICCF workflow — from submitting a source chain transaction to validation and execution a target chain transaction.

ICCF data flow

The iccf_proof operation

The iccf_proof operation is a core module-level operation provided by the ICCF GTX module. It is not part of the ICCF Rell library. This operation takes the ICCF proof data as input, which includes all necessary information for the target chain to verify cross-chain proofs, and has the following signature:

operation iccf_proof(
/** The source blockchain RID from which the proven transaction originated */
blockchain_rid: byte_array,

/** The source transaction hash that is being proven */
tx_hash: byte_array,

/** The source transaction confirmation proof (includes block header, Merkle proof, and witness signatures) */
tx_proof: byte_array,

/** The GTV-encoded anchoring transaction data on the cluster anchoring chain, or null for intra-cluster flow */
raw_cluster_anchoring_tx: byte_array?,

/** The index of the anchoring operation in the cluster anchoring transaction, or null for intra-cluster flow */
cluster_anchoring_tx_op_index: integer?,

/** The GTV-encoded confirmation proof for the cluster anchoring transaction, or null for intra-cluster flow */
cluster_anchoring_tx_proof: byte_array?
)

If verification succeeds, the iccf_proof operation exposes the proven transaction data, making it available to subsequent dapp-specific operations within the same transaction. This design separates protocol-level proof validation from dapp business logic, enabling any target chain dapp to safely utilize cross-chain proofs without reimplementing verification logic.

The ICCF Rell Library

The ICCF Rell library provides multiple utility functions that simplify working with ICCF proofs in dapp logic. All utility functions share similar signatures and common verification behavior. They all verify that an iccf_proof operation is present in the current transaction. By default, they also require that all signers of the proven transaction have signed the current transaction. Optionally, they can require inter-cluster mode, restrict which source blockchain RIDs are accepted and require that the proven transaction was finalized within a specific time range. If any verification fails, the transaction is rejected.

When a dapp needs to verify that a specific operation exists in the proven transaction and retrieve its arguments, the extract_operation_args() function is available. The extract_operation_arg() function returns a single argument from a specific operation in the proven transaction. To obtain the operation itself, the require_operation() function can be used.

function extract_operation_args(
/** The transaction to verify and extract from */
gtx_transaction,

/** Name of the operation in the proven transaction to extract */
op_name: text,

/** Whether or not the signers in the proven transaction must sign the current transaction */
verify_signers: boolean = true,

/** Whether inclusion of a proof that the block containing the proven transaction has been anchored in the cluster anchoring chain is required */
require_anchored_proof: boolean = false,

/** Minimum allowed timestamp for the proven transaction, disabled if 0 */
min_timestamp: integer = 0,

/** Maximum allowed timestamp for the proven transaction, disabled if 0 */
max_timestamp: integer = 0,

/** Set of valid source blockchain RIDs for the proven transaction */
valid_source_blockchain_rids: set<byte_array>? = null
): gtv

To verify and extract the confirmation proof of the proven transaction, the require_and_return_valid_proof() function can be used. The make_transaction_unique() function can be used to ensure that the proven transaction is unique and not already processed. Other utility functions can be found in the ICCF Rell library reference.

Building with ICCF

This section demonstrates how to build a cross-chain dapp using ICCF, covering target chain configuration, cross-chain operation implementation in Rell, and client-side proof integration.

Target Chain Setup

The target chain must be configured to accept ICCF proofs from the source chain. This is done by adding the ICCF GTX module to the target chain configuration. The source chain does not require any special ICCF setup.

blockchains:
target:
module: main
config:
gtx:
modules:
- "net.postchain.d1.iccf.IccfGTXModule"
libs:
com.chromia.iccf:
version: 1.90.1

Cross-Chain Operations

The following example demonstrates a simple cross-chain subscription flow where users subscribe on one chain and are authorized on another. The source chain provides a subscribe operation that records the subscriptions:

operation subscribe(pubkey, period: integer) { 
// Subscribe to the service
}

The target chain provides an authorize operation that verifies that an ICCF proof is present (validated by the GTX module), checks signers, ensures that the proven transaction contains a subscribe operation, and then extracts its arguments. Based on those arguments, the authorize operation performs additional validation and grants access to the service.

import lib.iccf;

operation authorize(tx: gtx_transaction) {
val args = iccf.extract_operation_args(tx, "subscribe", verify_signers = true);
val pubkey = args[0];
val period = args[1];
// Authorize the subscriber
}

Client Integration

ICCF is supported across multiple Chromia clients, making it accessible from Kotlin, JavaScript/TypeScript, Python, Go, and Rust. Each client provides high-level functionality for constructing, submitting, and verifying ICCF proofs. For example, snippet below shows how to submit a transaction to the source chain using the JavaScript/TypeScript client.

const { status, statusCode, sourceTransactionRid } = await sourceClient.signAndSendUniqueTransaction(
{
operations: [
{ name: "subscribe", args: [signatureProvider.pubKey, 365] }
],
signers: [signatureProvider.pubKey],
},
signatureProvider
);

Next, the following code snippet shows how to construct and submit the ICCF proof transaction to the target chain.

var sourceTransactionInfo = await sourceClient.getTransactionInfo(sourceTransactionRid);

const { iccfTx, verifiedTx } = await createIccfProofTx(
directoryClient,
sourceTransactionRid,
sourceTransactionInfo.txHash,
[keypair.pubKey],
sourceBlockchainRid,
targetBlockchainRid,
[keypair.pubKey],
true
);

const { status, statusCode, transactionRid2 } = await targetClient.signAndSendUniqueTransaction(
{
operations: [
iccfTx.operations[0],
{ name: "authorize", args: [verifiedTx] },
],
signers: [signatureProvider.pubKey],
},
signatureProvider
);

Examples and Further Resources

The following resources provide practical examples, learning materials, reference documentation, and production implementations demonstrating ICCF integration.

1. ICCF Example Project

A Kotlin-based reference implementation demonstrating ICCF fundamentals across source and target chains, including both intra-cluster and inter-cluster proof flows, client-side proof construction and submission, with setup instructions and annotated code.

Link: https://gitlab.com/chromaway/example-projects/iccf-example

2. ICCF Course on Chromia Learning

An interactive course covering ICCF theory, protocol mechanics, implementation patterns, and common pitfalls through guided exercises and real-world scenarios.

Link: https://learn.chromia.com/courses/iccf-course/introduction/

3. ICCF Rell Library Reference

Source code and inline documentation for the ICCF Rell library, providing complete reference for all utility functions including signatures, parameters, validation logic, and return types.

Link: https://gitlab.com/chromaway/postchain-chromia/-/blob/dev/chromia-infrastructure/rell/src/lib/iccf/module.rell

4. FT4 Cross-Chain Transfer Example

Production implementation of ICCF-based cross-chain asset transfers in FT4 library, demonstrating asset locking on source chain, proof generation and submission, and equivalent asset minting on target chain.

Link: https://gitlab.com/chromaway/ft4-lib/-/blob/v1.1.0/examples/crosschain-cli-example/README.md

5. Blockchain ICCF Authentication

Production implementation of blockchain authentication using ICCF in Directory Chain. This mechanism allows blockchains to prove their identity and trigger administrative actions on Directory Chain, including starting or stopping blockchains, proposing configuration updates, or launching new blockchains. This cross-chain authentication pattern is fundamental for building DAOs and decentralized governance systems where blockchain management is controlled by the DAO rather than the dapp provider or developer.

Link: https://gitlab.com/chromaway/core/directory-chain/-/blob/1.104.1/doc/blockchain_auth/Blockchain-Authentication.md