> ## Documentation Index
> Fetch the complete documentation index at: https://docs.herodotus.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrity Verifier

> Integrity allows you to verify STARK proofs on Starknet. It also registers all verified proofs in its storage, so other Cairo contracts can access them. It is crucial to understand how programs are stored inside Integrity’s Fact Registry.

<img src="https://mintcdn.com/herodotuscloudservices/pl9YHvqFmlRGTcMb/images/atlantic/integrity.webp?fit=max&auto=format&n=pl9YHvqFmlRGTcMb&q=85&s=3bf02b1cdcd0134bc5f4bd64bec3b500" alt="integrity verifier logo" width="1200" height="289" data-path="images/atlantic/integrity.webp" />

[Full Integrity documentation](https://github.com/HerodotusDev/integrity)

## Cairo memory sections

Cairo memory consists of 3 main sections - program, execution and output. That's a simplification, but for understanding hashes calculated by Integrity, it will be enough. The program section contains your Cairo code compiled to Cairo VM instructions. Execution and output depend on program and input data. They are both calculated when running the program, but only output is exposed in public memory.

## Fact and Verification Hash

After verifying the proof, Integrity calculates two hashes: `program_hash` and `output_hash`. They are Poseidon hashes of corresponding memory sections. Then, those two hashes are hashed together to get `fact_hash`.

<img src="https://mintcdn.com/herodotuscloudservices/S302XnSN--WAs0sk/images/atlantic/integrity-hashes-standard.png?fit=max&auto=format&n=S302XnSN--WAs0sk&q=85&s=6f609bd2362008dbfc13117277724a77" style={{ maxHeight: '24rem' }} className="mx-auto" width="1032" height="786" data-path="images/atlantic/integrity-hashes-standard.png" />

If your contract needs to check whether certain proof was verified, you have to calculate those hashes in your contract and pass a `fact_hash` (or better `verification_hash`) to Integrity's function. Usually you would verify proofs for some constant set of programs with arbitrary input and output, which means that you can hardcode `program_hash` while calculating `output_hash` and `fact_hash` dynamically.

However, as is usually the case, the reality is more complicated. To reduce public memory size, Cairo programs are often bootloaded, which means that your program isn’t run directly, but rather a special program called “bootloader” is placed in program segment, which is responsible for loading your program (called child program) to memory, executing it and calculating `program_hash` of the child program. This means that every bootloaded program will have the same `program_hash` and the `program_hash` of child program will only be present in bootloader’s output. This flow and hash calculation is represented in the following diagram:

<img src="https://mintcdn.com/herodotuscloudservices/S302XnSN--WAs0sk/images/atlantic/integrity-hashes-bootloaded.png?fit=max&auto=format&n=S302XnSN--WAs0sk&q=85&s=bfb4c57879d59d03dac443f95e2778a8" style={{ maxHeight: '24rem' }} className="mx-auto" width="1586" height="1064" data-path="images/atlantic/integrity-hashes-bootloaded.png" />

Fortunately, you don't need to implement above logic yourself, because Integrity provides a Scarb package with many useful utility functions, namely `calculate_fact_hash` and `calculate_bootloaded_fact_hash`. For more details, see ["Calls from Starknet contracts" section in Integrity documentation](https://github.com/HerodotusDev/integrity#calls-from-starknet-contracts).

If you have `fact_hash` calculated, you can call integrity’s `get_all_verifications_for_fact_hash` function to check whether given `fact_hash` has been verified. However, because Integrity accepts proofs with many settings and any number of security bits, you need to check if the proof has been verified with enough number of security bits. For that you can use `is_fact_hash_valid_with_security` utility function.

Here is an example of how to use those functions:

```rust theme={null}
use integrity::{
    Integrity, calculate_bootloaded_fact_hash,
    SHARP_BOOTLOADER_PROGRAM_HASH,
};

const SECURITY_BITS: u32 = 70;
const FIBONACCI_PROGRAM_HASH: felt252 = 0x59874649ccc5a0a15ee77538f1eb760acb88cab027a2d48f4246bf17b7b7694;
const IS_MOCKED: bool = false;

fn is_fibonacci_verified(fib_index: felt252, fib_value: felt252) -> bool {
    let fact_hash = calculate_bootloaded_fact_hash(
        SHARP_BOOTLOADER_PROGRAM_HASH,
        FIBONACCI_PROGRAM_HASH,
        [fib_index, fib_value].span()
    );

    let integrity = Integrity::new_satellite(IS_MOCKED); // automatically uses current Satellite address
    // Alternatively, you can call Integrity Verifier directly with `Integrity::new()`
    integrity.is_fact_hash_valid_with_security(fact_hash, SECURITY_BITS)
}
```

An alternative way is using `verification_hash`, which is composed from `fact_hash`, configuration and security bits. That means that no additional checks are needed.

<img src="https://mintcdn.com/herodotuscloudservices/S302XnSN--WAs0sk/images/atlantic/integrity-hashes-verification.png?fit=max&auto=format&n=S302XnSN--WAs0sk&q=85&s=963877fa73746b88d43511b24d14064c" style={{ maxHeight: '24rem' }} className="mx-auto" width="562" height="409" data-path="images/atlantic/integrity-hashes-verification.png" />

And here is how you would check verification of multiple proofs with the same configuration using `verification_hash`:

```rust theme={null}
use integrity::{
    Integrity, IntegrityWithConfig,
    calculate_bootloaded_fact_hash,
    SHARP_BOOTLOADER_PROGRAM_HASH,
    VerifierConfiguration,
};

fn is_multi_fibonacci_verified(fib: Span<(felt252, felt252)>) -> bool {
    let config = VerifierConfiguration {
        layout: 'recursive_with_poseidon',
        hasher: 'keccak_160_lsb',
        stone_version: 'stone6',
        memory_verification: 'relaxed',
    };

    let integrity = Integrity::new().with_config(config, SECURITY_BITS);

    let mut result = true;
    for f in fib {
        let (fib_index, fib_value) = *f;

        let fact_hash = calculate_bootloaded_fact_hash(
            SHARP_BOOTLOADER_PROGRAM_HASH, FIBONACCI_PROGRAM_HASH, [fib_index, fib_value].span()
        );

        if !integrity.is_fact_hash_valid(fact_hash) {
            result = false;
        }
    };
    result
}
```

If you are having trouble calculating any of those hashes, check out [Integrity Hashes Calculator](https://integrity-hashes-calculator.vercel.app/). Not only does it automatically calculate hashes for provided `program_hash` and output array, but also supports proof uploading, so you can get data directly from it.
