참고 :
https://erroldrummond.gitbook.io/halo2-tutorial/section-1/chips-fish-sold-separately

증명 가능한 계산 시스템을 만들기 위해, 아래를 달성해야함 :
Config 정의 → Chip 구조체로 감싸기 → Trait로 연산 게이트 정의 → Layouter로 값을 할당 → Circuit으로 synthesize → Prove
| 컴포넌트 | 목적 |
|---|---|
Column<Advice> | witness (private input, wire) (= 증명 과정 중 채워지는 값들) |
Column<Fixed> | 컴파일 타임에 고정된 상수 또는 selector (게이트 활성화 여부) |
Column<Instance> | 공개 입력값 |
Selector | Fixed의 특수 버전으로, 특정 행(row)에만 제약조건을 활성화 |
#[allow(non_snake_case, dead_code )]
#[derive(Debug, Clone)]
struct TutorialConfig {
l: Column<Advice>,
r: Column<Advice>,
o: Column<Advice>,
sl: Column<Fixed>,
sr: Column<Fixed>,
so: Column<Fixed>,
sm: Column<Fixed>,
sc: Column<Fixed>,
PI: Column<Instance>,
}
🔗 왜 필요 한가?
- 증명 시스템은 각 행에 대해 어떤 열들이 어떤 조건을 만족하는지 계산해야 하므로, 형식을 정하고 열들을 구분해서 관리해야 함
Config를 감싸는 구조체PhantomData<F>를 포함struct TutorialChip<F: FieldExt> {
config: TutorialConfig,
marker: PhantomData<F>,
}
🔗 왜 필요 한가?
- 여러 종류의 계산 기능을 모듈처럼 분리하고, 타입별로 맞게 구성하기 위함
- 이를 통해, 재사용성/확장성 높은 회로 구성 가능
l⋅sl + r⋅sr + l⋅r⋅sm − o⋅so + sc + PI = 0pub trait TutorialComposer<F: FieldExt> {
fn add_gate(...);
}
🔗 왜 필요 한가?
- 여러 게이트 종류들을 추상화된 인터페이스로 정의하여, 다양한 chip에서 공통적으로 적용 가능
- 특정 구조에 묶이지 않고, 다양한 기능의 회로 설계 가능
assign_region() 사용Region::assign_advice, assign_fixed, enable_selector 등으로 실제 물리적인 값 넣음🔗 왜 필요 한가?
- 구조에 값을 집어 넣어야 제약이 만족되는지 검증 가능
- Layouter를 통하여 구조에 따른 실제 작동을 가능하게 함
Circuit<F> Trait을 구현 -> configure(), synthesize() 필요impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
fn configure(cs: &mut ConstraintSystem<F>) -> Self::Config { ... }
fn synthesize(&self, cs: &mut impl Layouter<F>) -> Result<(), Error> { ... }
}
🔗 왜 필요 한가?
configure는 static한 회로 구조를 정의synthesize는 실제 증명 시 이 회로가 어떻게 작동할지를 정의
let prover = MockProver::run(k, &circuit, vec![...])?;
prover.assert_satisfied();
MockProver::run()으로 증명 실행.assert_satisfied()로 constraint 충족 여부 확인🔗 왜 필요한가?
- 우리가 정의한 회로 구조가 논리적으로 맞는지 확인
| 단계 | 반도체 설계 (디지털 논리 회로) | Halo2 회로 설계 | 공통 개념 (설계 레벨) |
|---|---|---|---|
| 1️⃣ 구조 정의 | Gate-Level 설계: NAND, AND, XOR 조합으로 회로 구성 (Verilog module로 표현) | Config: Advice, Fixed, Instance 열 정의 | Gate-level abstraction |
| 2️⃣ 기능 모듈화 | Module wrapping: 작은 기능 단위로 모듈화 (ex. ALU, MUX) | Chip: config를 감싸고 타입화 | 모듈 단위로 기능 분리 |
| 3️⃣ 기능 명세 | always 블록/assign 문로 로직 명세 | Trait: 각 게이트 함수 정의 (예: add_gate) | 동작(연산) 명세 |
| 4️⃣ 레이아웃 생성 | 배선 및 시뮬레이션 준비: 파형 시뮬레이션 위한 testbench / value assignment | Layouter: 값 할당, selector 활성화 | Netlist-level wiring & simulation |
| 5️⃣ 전체 회로 생성 | Top module + 하위 모듈 연결 | Circuit 구조체: configure() + synthesize() | 구조적 설계 / 회로 전체 연결 |
| 6️⃣ 검증 | 시뮬레이션 (ModelSim, Vivado) 또는 Formal Verification | MockProver로 constraint 만족 확인 | 기능적 검증 |
| 7️⃣ 구현 | Synthesis (gate-level netlist 생성) → Place & Route → Netlist,GDSII 생성 | Prover → Proof 생성 → On-chain 검증기(zkProof(verifiable output)) | 실제 실행 가능한 아티팩트 생성 |
| 8️⃣ 테스트 벡터 | Testbench에서 다양한 입력 케이스 검증 | MockProver input으로 다양한 케이스 테스트 | 테스트 벡터 생성 및 검증 |
module and_gate (
input wire a, b,
output wire y
);
assign y = a & b;
endmodule
-> vivado로 컴파일하면, synthesis -> netlist -> place & route -> 검증 순으로 진행
trait TutorialComposer<F: FieldExt> {
fn add_gate(...) {
// l⋅sl + r⋅sr − o⋅so = 0 형태의 제약 정의
}
}
-> 이걸 기반으로 MockProver로 테스트, 실제 Prover로 proof 생성
Advice column = 전선(wire)
Row = 한 시점(time step) 또는 gate 인스턴스
Fixed column = 전압을 항상 1로 고정한 신호선 (즉 selector 역할)
Selector = AND 게이트의 enable 핀이라고 보면 됨
assign_advice = 입력 값을 버퍼에 적재
enable_selector = 이 row에서만 연산 작동하도록 하는 컨트롤 신호
circuit 구조체 = Top module
https://www.youtube.com/watch?v=60lkR8DZKUA




To be countinued
1. 라이브러리 모아서 다른 편으로 연재
2. Circom vs Halo2 차이점 정리 후 연재(HDL vs zk 회로 언어)
3. 반도체와 Halo2 차이 정리 후 따로 연재
4. Halo2 + STARK 구조의 비교: STARK은 왜 HDL 스타일에 더 잘 맞는가?