# o1js-zk-utils

A collection of zk-programs and utilities to support **Nori Bridge**.

## EthVerifier

A zk-program to verify an Ethereum consensus MPT transition proof, made verifiable (converted) in o1js.

It depends on:

- Public input 0 from the SP1 consensus MPT transition proof (`sp1Proof.proof.Plonk.public_inputs[0]`), the Nori SP1 Helios program identifier (`bridgeHeadNoriSP1HeliosProgramPi0`), stored in [`src/integrity/nori-sp1-helios-program.pi0.json`](./src/integrity/nori-sp1-helios-program.pi0.json) — a copy of [`nori-elf/nori-sp1-helios-program.pi0.json`](https://github.com/Nori-zk/nori-bridge-head/blob/develop/nori-elf/nori-sp1-helios-program.pi0.json) from [bridge-head](https://github.com/Nori-zk/nori-bridge-head). Changes frequently as the Helios light client evolves — when bridge-head releases a new version, copy [`nori-elf/nori-sp1-helios-program.pi0.json`](https://github.com/Nori-zk/nori-bridge-head/blob/develop/nori-elf/nori-sp1-helios-program.pi0.json) from the appropriate release tag into [`src/integrity/nori-sp1-helios-program.pi0.json`](./src/integrity/nori-sp1-helios-program.pi0.json) before re-running `bake-vk-hashes`.
- Public output 2 from the converted consensus MPT transition proof (`proofConversionOutput.proofData.publicOutput[2]`). Infrequently changes, for instance when SP1 undergoes a major version upgrade (e.g. v5 -> v6) that affects the cryptography of proof conversion.
- The verification key data from the `sp1Plonk` zk-program in [proof-conversion](https://github.com/Nori-zk/proof-conversion). Unlikely to change.

Whenever any of these change, you must run:

    npm run bake-vk-hashes

This updates the integrity files (used to ensure zk compilation is correct and not affected by stale o1js cache). Commit any changes to the `integrity` folder.

```typescript
import { EthVerifier, EthProof, EthInput } from '@nori-zk/o1js-zk-utils';
```

## Merkle Leaf Attestor Generator / Utils

A generator that produces zk-programs for proving a leaf’s inclusion (via a witness, generatable from all leaves) in a dynamically sized Merkle tree, with a constraint on the tree’s maximum height.

**Utilties**

```typescript
import {
    buildMerkleTree,
    foldMerkleLeft,
    getMerklePathFromLeaves,
    getMerklePathFromTree,
    computeMerkleRootFromPath,
    merkleLeafAttestorGenerator,
} from '@nori-zk/o1js-zk-utils';
```

**Example Usage**

```typescript
import { Bytes, Field, Poseidon, Struct, UInt8 } from 'o1js';
import { Bytes32 } from '@nori-zk/o1js-zk-utils';
import { merkleAttestorGenerator } from '@nori-zk/o1js-zk-utils';

export class YourLeafType extends Struct({
    value: Bytes32.provable,
}) {}

export function leafHashFunction(contractDeposit: YourLeafType) {
    const valueBytes = contractDeposit.value.bytes; // UInt8[]
    const leafBytes: UInt8[] = [];

    for (let i = 0; i < 32; i++) {
        leafBytes.push(valueBytes[i]);
    }

    let firstField = new Field(0);
    for (let i = 31; i >= 0; i--) {
        firstField = firstField.mul(256).add(firstBytes.bytes[i].value);
    }

    return Poseidon.hash([firstField]);
}

const {
    MerkleTreeAttestorInput: LeafInclusionAttestorInput,
    MerkleTreeAttestor: LeafInclusionAttestor,
    buildLeaves,
    getMerklePathFromLeaves: getLeafInclusionWitness,
} = merkleAttestorGenerator(
    16,
    'YourLeafInclusionAttestor',
    ContractDeposit,
    leafHashFunction
);

export {
    LeafInclusionAttestorInput,
    LeafInclusionAttestor,
    buildLeaves,
    getLeafInclusionWitness,
};
```

## Contract Deposit Attestor

A zk-program to prove that a user's deposit is included within a consensus MPT transition proof window.

**Leaf format:**

```typescript
export class ContractDeposit extends Struct({
    codeChallenge: Bytes32.provable, // SCRAM code challenge (Poseidon hash of Mina signature)
    value: Bytes32.provable, // Total locked amount (cumulative)
}) {}
```

**Imports**

```typescript
import {
    ContractDepositAttestorInput,
    ContractDepositAttestor,
    buildContractDepositLeaves,
    getContractDepositWitness,
    ContractDeposit,
} from '@nori-zk/o1js-zk-utils';
```

For example usage see the [test](./src/contractDepositAttestor.spec.ts).

## Utils

A range of utilities for handling proof byte encodings and ensuring zk compilation integrity.

```typescript
import {
    fieldToHexBE,
    fieldToHexLE,
    fieldToBigIntBE,
    fieldToBigIntLE,
    decodeConsensusMptProof,
    compileAndVerifyContracts,
    extractEthTokenBridgeAddressFromSP1Proof,
} from '@nori-zk/o1js-zk-utils';
```

## Types

Types for various proof and encoding formats.

```typescript
import {
    PlonkProof,
    ConvertedProof,
    EthVerifierComputeOutput,
    Bytes32,
} from '@nori-zk/o1js-zk-utils';
```
