# Halo2

## 1. Halo2란?

Zcash의 초기 zk-SNARK 생태계는 거의 전부 Groth16 위에서 돌아가고 있었다. \
Groth16은 증명 크기가 작고 검증이 빠르다는 큰 장점이 있지만, 실제 운영을 하다 보니 몇 가지 한계가 드러났다.

* 회로별(trusted setup per circuit) 셋업이 필요하다.
* 회로를 조금만 바꿔도 다시 ceremony를 해야 한다. (phase2)
* 실서비스에서 자주 회로를 업데이트하려면 부담이 크다.
* 재귀(Recursive SNARK)와 집계(Aggregation) 설계가 불편하다.

Groth16도 재귀가 가능은 하지만 구조상 복잡하고, 새로운 요구에 최적화되어 있지 않다.

또한 복잡한 연산(lookup, 테이블 기반 연산, custom gate 최적화 등)을 표현하기가 점점 불편해졌다.

이 배경에서 나온 것이 Halo1 이다.

Sean Bowe가 제안한 프로토콜로, inner-product argument(IPA) 기반 polynomial commitment를 사용하고, 신뢰 설정 없이 재귀 SNARK를 가능하게 하는 아이디어를 제시하였다.

핵심 포인트는 증명을 또 다른 증명 안에 넣어도 보안이 유지되는 구조, universal / transparent한 설정으로도 재귀가 가능한 것이다.

Zcash 입장에서는 우리가 새로운 회로를 계속 도입하고, 재귀/집계를 적극적으로 쓰려면 Groth16이 아니라 Halo 계열이 필요하다는 방향성이 생겼고, 여기서 실제 개발에 쓰기 위한 개선판으로 등장한 것이 Halo2이다.

Halo2는 Zcash 팀이 Halo 아이디어와 PLONKish Arithmetization을 결합해 만든, 유연한 회로 표현과 재귀/집계를 지원하는 SNARK 프루빙 시스템이다.

***

## 2. 사용법

```rust
/// The full circuit implementation.
///
/// In this struct we store the private input variables. We use `Option<F>` because
/// they won't have any value during key generation. During proving, if any of these
/// were `None` we would get an error.
#[derive(Default)]
struct MyCircuit<F: Field> {
    constant: F,
    a: Value<F>,
    b: Value<F>,
}

impl<F: Field> Circuit<F> for MyCircuit<F> {
    // Since we are using a single chip for everything, we can just reuse its config.
    type Config = FieldConfig;
    type FloorPlanner = SimpleFloorPlanner;

    fn without_witnesses(&self) -> Self {
        Self::default()
    }

    fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
        // We create the two advice columns that FieldChip uses for I/O.
        let advice = [meta.advice_column(), meta.advice_column()];

        // We also need an instance column to store public inputs.
        let instance = meta.instance_column();

        // Create a fixed column to load constants.
        let constant = meta.fixed_column();

        FieldChip::configure(meta, advice, instance, constant)
    }

    fn synthesize(
        &self,
        config: Self::Config,
        mut layouter: impl Layouter<F>,
    ) -> Result<(), Error> {
        let field_chip = FieldChip::<F>::construct(config);

        // Load our private values into the circuit.
        let a = field_chip.load_private(layouter.namespace(|| "load a"), self.a)?;
        let b = field_chip.load_private(layouter.namespace(|| "load b"), self.b)?;

        // Load the constant factor into the circuit.
        let constant =
            field_chip.load_constant(layouter.namespace(|| "load constant"), self.constant)?;

        // We only have access to plain multiplication.
        // We could implement our circuit as:
        //     asq  = a*a
        //     bsq  = b*b
        //     absq = asq*bsq
        //     c    = constant*asq*bsq
        //
        // but it's more efficient to implement it as:
        //     ab   = a*b
        //     absq = ab^2
        //     c    = constant*absq
        let ab = field_chip.mul(layouter.namespace(|| "a * b"), a, b)?;
        let absq = field_chip.mul(layouter.namespace(|| "ab * ab"), ab.clone(), ab)?;
        let c = field_chip.mul(layouter.namespace(|| "constant * absq"), constant, absq)?;

        // Expose the result as a public input to the circuit.
        field_chip.expose_public(layouter.namespace(|| "expose c"), c, 0)
    }
}
```

* `configure`에서 회로 구조(제약식)를 정의하고,
* `synthesize`에서 실제 값(witness)을 어떻게 넣을지를 정한다.

한 번 회로 구성이 정해지면:

* keygen\_pk(params, vk, \&circuit)
* keygen\_vk(params, \&circuit)

같은 API로 **proving key / verification key**를 생성한다.

#### 4) 증명 생성 / 검증

* 증명 생성:
  * create\_proof(params, pk, circuit, public\_inputs, rng)
* 검증:
  * verify\_proof(params, vk, public\_inputs, proof, strategy)

***

## 3. References

* [https://zcash.github.io/halo2](https://zcash.github.io/halo2/)
* <https://hackmd.io/@YaoGalteland/ry6g_V8Xyx>


---

# 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://upsidezkp.gitbook.io/upside-zkp-docs/step-4/zkp-dsl-proving-system/halo2.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.
