# Verification in the IdentityVerificationHub

{% hint style="info" %}
**Who is this for?** This page explains the internal verification flow of the on-chain IdentityVerificationHub contract — how proofs are decoded, routed, and verified. It's useful if you're building custom verification hooks or need to understand the on-chain data structures. For basic smart contract integration, see [Smart Contract Integration](/self-pass/basic-integration-1.md).
{% endhint %}

The IdentityVerificationHub V2 is the core verification engine that processes zero-knowledge proofs and executes identity verification workflows.

## How the Hub Works

The Hub operates as a central verification coordinator that:

* **Receives Verification Requests** from contracts implementing `ISelfVerificationRoot`
* **Processes ZK Proofs** using specialized circuit verifiers
* **Applies Verification Rules** based on stored configurations
* **Returns Structured Results** to the calling contract

## Complete Verification Flow

### 1. Request Initiation

```solidity
// User contract calls Hub with proof data
function verifySelfProof(bytes calldata proofPayload, bytes calldata userContextData) external;
```

**What happens:**

#### TEE Proof Generation (Gas-Free for Users)

* **User Input**: User completes a supported document flow in the mobile app (passport, ID, Aadhaar, or KYC)
* **TEE Processing**: Trusted Execution Environment securely processes identity data
* **ZK Proof Creation**: TEE generates zero-knowledge proof without revealing raw identity data

#### Relayer (Sponsored Transactions)

* **Proof Relay**: Relayer receives ZK proof from TEE
* **Gas Sponsorship**: Relayer pays all transaction gas fees on behalf of user
* **Onchain Submission**: Relayer submits proof to user's contract via blockchain transaction
* **User Experience**: User gets verified identity without any crypto/gas requirements

#### Contract Processing

* Contract receives ZK proof from TEE/Relayer
* Calls Hub's `verifySelfProof` with proof + user context data
* Hub begins processing the verification request

### 2. Input Decoding & Context Processing

```solidity
// Hub internal: _decodeInput() and _decodeUserContextData()
(HubInputHeader memory header, bytes calldata proofData) = _decodeInput(baseVerificationInput);
(configId, destChainId, userIdentifier, remainingData) = _decodeUserContextData(userContextData);
```

**What happens:**

* **Header Extraction**: Gets contract version, scope, attestation ID
* **Context Parsing**: Extracts config ID, destination chain, user identifier
* **Data Preparation**: Prepares proof data for verification

### 3. Configuration Retrieval

```solidity
// Hub loads verification configuration by configId
VerificationConfigV2 memory config = $v2._v2VerificationConfigs[configId];
```

**What happens:**

* Hub looks up stored verification configuration using configId
* Configuration contains all verification rules (age, countries, OFAC, etc.)
* If config doesn't exist, verification fails

### 4. Document Type Detection & Routing

```solidity
// Based on attestationId in header
if (attestationId == AttestationId.E_PASSPORT) {
    // Route to passport verification logic
} else if (attestationId == AttestationId.EU_ID_CARD) {
    // Route to EU ID card verification logic
} else if (attestationId == AttestationId.AADHAAR) {
    // Route to Aadhaar verification logic
} else if (attestationId == AttestationId.KYC) {
    // Route to KYC verification logic
}
```

**What happens:**

* Hub identifies document type from attestation ID
* Routes to appropriate verification pipeline
* Uses document-specific circuit verifiers

### 5. Basic Verification (\_basicVerification)

**Purpose:** Validates the **cryptographic correctness** and **security** of the ZK proof itself.

```solidity
// Hub performs 4 core verification steps
bytes memory proofOutput = _basicVerification(
    header,
    vcAndDiscloseProof,
    userContextData,
    userIdentifier
);
```

**What happens (4 verification scopes):**

#### Scope 1: Contract Validation

* **Scope Check**: Ensures proof was generated for the correct contract
* **User Identifier Check**: Validates user identity consistency

#### Scope 2: Registry & Timestamp Validation

* **Root Check**: Validates against Merkle tree in identity registry
* **Current Date Check**: Ensures proof is within valid time window

#### Scope 3: Cryptographic Proof Verification

* **Groth16 Proof Verification**: Validates ZK proof using circuit verifier
* **Public Signals Validation**: Verifies proof inputs/outputs match expectations

#### Scope 4: Raw Data Extraction

* **Output Generation**: Creates `PassportOutput` or `EuIdOutput` with raw field data
* **Data Preparation**: Prepares extracted data for business logic verification

**Output:** Raw identity data (`PassportOutput`/`EuIdOutput`) ready for custom verification.

### 6. Custom Verification (CustomVerifier.customVerify)

**Purpose:** Applies **business logic rules** and validates **identity attributes** against configuration requirements.

```solidity
// Hub applies custom verification logic
GenericDiscloseOutputV2 memory output = CustomVerifier.customVerify(
    header.attestationId,
    config,
    proofOutput
);
```

**What happens:**

* **Document Type Routing**: Routes to passport, ID card, Aadhaar, or KYC-specific verification
* **Business Rule Application**: Applies age, geographic, and sanctions requirements
* **Identity Data Extraction**: Converts raw data to structured, human-readable format
* **Final Validation**: Ensures all configuration requirements are met

**Output:** Structured identity data (`GenericDiscloseOutputV2`) with verification results.

#### Age Verification (olderThanEnabled)

```solidity
if (verificationConfig.olderThanEnabled) {
    if (!CircuitAttributeHandlerV2.compareOlderThan(
        attestationId, 
        passportOutput.revealedDataPacked, 
        verificationConfig.olderThan
    )) {
        revert InvalidOlderThan();
    }
}
```

* Validates user meets minimum age requirement
* Uses circuit-extracted age data for verification
* Example: config requires 18+, user is 20 → ✅ passes
* Example: config requires 21+, user is 18 → ❌ fails

#### Geographic Restrictions (forbiddenCountriesEnabled)

```solidity
if (verificationConfig.forbiddenCountriesEnabled) {
    for (uint256 i = 0; i < 4; i++) {
        if (passportOutput.forbiddenCountriesListPacked[i] != 
            verificationConfig.forbiddenCountriesListPacked[i]) {
            revert InvalidForbiddenCountries();
        }
    }
}
```

* Validates forbidden countries list matches exactly
* Uses packed representation for gas efficiency (4 uint256 array)
* Order in config must match proof's forbidden countries list

#### OFAC Sanctions Verification

```solidity
if (verificationConfig.ofacEnabled[0] || 
    verificationConfig.ofacEnabled[1] || 
    verificationConfig.ofacEnabled[2]) {
    if (!CircuitAttributeHandlerV2.compareOfac(
        attestationId,
        passportOutput.revealedDataPacked,
        verificationConfig.ofacEnabled[0], // passport number
        verificationConfig.ofacEnabled[1], // name + DOB
        verificationConfig.ofacEnabled[2]  // name + YOB
    )) {
        revert InvalidOfacCheck();
    }
}
```

* **Mode 0**: OFAC check using passport number
* **Mode 1**: OFAC check using name + date of birth
* **Mode 2**: OFAC check using name + year of birth
* Each mode can be independently enabled/disabled
* Uses circuit-provided OFAC verification results

### 7. Output Formatting & Generation

```solidity
// Hub formats verification results into structured output
output = _formatVerificationOutput(header.contractVersion, genericDiscloseOutput);
```

**What happens:**

* Raw proof signals converted to human-readable data
* Structured identity information extracted
* Verification results (age, OFAC, etc.) included

### 8. Result Delivery

```solidity
// Hub calls back to the original contract
ISelfVerificationRoot(callingContract).onVerificationSuccess(
    abi.encode(output), 
    userData
);
```

**What happens:**

* Hub calls `onVerificationSuccess` on the requesting contract
* Passes structured output + user-defined data
* Contract can then execute its custom business logic

## Data Structures

### VerificationConfigV2

```solidity
struct VerificationConfigV2 {
    bool olderThanEnabled;                    // Enable age verification
    uint256 olderThan;                        // Minimum age requirement  
    bool forbiddenCountriesEnabled;           // Enable country restrictions
    uint256[4] forbiddenCountriesListPacked;  // Packed forbidden countries
    bool[3] ofacEnabled;                      // OFAC verification modes
}
```

### GenericDiscloseOutputV2 (Verification Result)

```solidity
struct GenericDiscloseOutputV2 {
    bytes32 attestationId;                    // E_PASSPORT, EU_ID_CARD, AADHAAR, or KYC
    uint256 userIdentifier;                   // User's unique identifier
    uint256 nullifier;                        // Anti-replay nullifier
    uint256[4] forbiddenCountriesListPacked;  // Forbidden countries used
    
    // Disclosed identity information
    string issuingState;                      // Document issuing country
    string[] name;                            // [first, middle, last] names
    string idNumber;                          // Passport/ID number
    string nationality;                       // User's nationality
    string dateOfBirth;                       // Birth date (DD-MM-YY)
    string gender;                            // User's gender
    string expiryDate;                        // Document expiry date
    
    // Verification results
    uint256 olderThan;                        // Verified minimum age
    bool[3] ofac;                             // OFAC results [passport number, name+dob, name+yob]
}
```

## Key V2 Improvements

### Multi-Document Support

* Automatic routing for attestation types: E\_PASSPORT, EU\_ID\_CARD, AADHAAR and KYC
* Document-specific verification pipelines
* Unified interface for different document types

### Structured Output

* Rich `GenericDiscloseOutputV2` with pre-extracted attributes
* No more manual parsing of raw field elements
* Type-safe access to identity data

### Flexible Configuration Management

* Reusable `VerificationConfigV2` stored in Hub
* Create configurations without contract redeployment
* Use [Self Configuration Tools](https://tools.self.xyz/) to register configs

### Enhanced Security

* Separate verification logic for each document type
* Improved timestamp and replay protection
* Gas-optimized verification checks


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.self.xyz/self-pass/overview/verification-hub.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
