Workspace IndexAlgorithms › Day 87

Commitments — Pedersen, KZG, FRI TODO

Algorithms · Day 87 / 100 · F. Cryptography & ZK (Day 82-96)

Concept

A commitment is a primitive for sealing a value so it can be revealed later, requiring binding (the sealed value can't be swapped out) and hiding (the seal alone reveals nothing about the value). A Pedersen commitment is built on the discrete-log assumption using two generators and a random blinding value; it achieves information-theoretic hiding and computational binding, and is additively homomorphic, so you can verify the sum of values by adding their commitments together. KZG is a polynomial commitment that uses pairings to make both the commitment and the evaluation proof at any point constant-size, but it needs a structured reference string (a trusted setup). FRI works via hash-based proximity testing against Reed-Solomon codes, needs no trusted setup, and has proof size that grows polylogarithmically, and because its assumptions are hash-based, it's favored from a post-quantum standpoint. Whether a setup is required, proof size, verification cost, and the type of assumption are the three axes that separate these approaches.

The cost structure of rollups and ZK systems, their data-availability design, and their trust assumptions all essentially come down to which commitment scheme is used, so without understanding this tradeoff you can't ground an architecture decision.

Code & Formula

# 커밋먼트 — Pedersen 커밋먼트를 모듈러 지수 연산으로 구현해 binding·hiding·덧셈 준동형을 시연.
# 이산로그 가정 기반 토이 그룹 (실제 EC 대신 소수체 위 지수 연산으로 개념만 재현, 교육용).

import secrets

P = 2**127 - 1        # 토이 소수 (실제로는 소수인지 별도 검증 필요 — 데모 목적)
G, H = 5, 7             # 서로 이산로그 관계를 모르는 두 "생성원" (토이 값)

def commit(value, blinding):
    return (pow(G, value, P) * pow(H, blinding, P)) % P

def open_commitment(commitment, value, blinding):
    return commit(value, blinding) == commitment

# --- hiding: 커밋먼트만 봐서는 값을 알 수 없다 ---
secret_value = 1000
blinding = secrets.randbelow(P)
c = commit(secret_value, blinding)
print("commitment (looks random, reveals nothing):", c)

# --- binding: 다른 값으로는 같은 커밋먼트를 열 수 없다 ---
print("opens correctly with real (value, blinding):", open_commitment(c, secret_value, blinding))
print("fails to open with a different value:", not open_commitment(c, secret_value + 1, blinding))

# --- 덧셈 준동형: 커밋먼트끼리 곱하면 값의 합에 대한 커밋먼트가 된다 ---
v1, b1 = 30, secrets.randbelow(P)
v2, b2 = 12, secrets.randbelow(P)
c1, c2 = commit(v1, b1), commit(v2, b2)

c_sum_direct = commit(v1 + v2, (b1 + b2) % P)
c_sum_from_commitments = (c1 * c2) % P

print()
print("commit(v1)*commit(v2) mod P:", c_sum_from_commitments)
print("commit(v1+v2, b1+b2) directly:", c_sum_direct)
print("additively homomorphic:", c_sum_from_commitments == c_sum_direct)
print("=> lets a verifier check sums (e.g. 'inputs balance outputs') without seeing v1, v2")

Exercise

Implement a Pedersen commitment with an elliptic-curve library and verify its homomorphism, then build a Merkle-tree commitment over the same values and tabulate commitment size, proof size, and verification time for comparison.

Practical Connection

When Verex compresses off-chain state or order batches onto the chain at settlement, which commitment it uses directly decides calldata/blob cost, on-chain verification gas, and the trust assumptions required.

If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/dev-100-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.


한국어

커밋먼트 TODO

Algorithms · Day 87 / 100 · F. 암호학·ZK (Day 82–96)

Pedersen·KZG·FRI

개념

커밋먼트는 값을 봉인해 공개하되 나중에 그 값을 밝힐 수 있게 하는 원시 도구이며, 봉인된 값을 바꿔치기할 수 없는 binding과 봉인만 봐서는 값을 알 수 없는 hiding을 요구한다. Pedersen 커밋먼트는 두 생성원과 무작위 블라인딩 값을 써서 이산로그 가정 위에 세워지며, 정보이론적으로 완벽한 hiding과 계산적 binding을 가지고 덧셈에 대해 준동형이라 값들의 합을 커밋먼트끼리 더해 검증할 수 있다. KZG는 다항식 커밋먼트로, 페어링을 이용해 커밋먼트와 임의 점에서의 평가 증명을 모두 상수 크기로 만들지만 구조화된 참조 문자열(trusted setup)이 필요하다. FRI는 해시와 리드-솔로몬 부호의 근접성 검사에 기반해 신뢰 셋업 없이 동작하고 증명 크기가 폴리로그로 커지지만, 가정이 해시 기반이라 양자 내성 관점에서 선호된다. 셋업 필요 여부, 증명 크기, 검증 비용, 가정의 종류가 세 방식을 가르는 축이다.

롤업과 ZK 시스템의 비용 구조, 데이터 가용성 설계, 신뢰 가정이 사실상 어떤 커밋먼트를 쓰느냐로 결정되기 때문에 이 트레이드오프를 모르면 아키텍처 선택 근거를 세울 수 없다.

코드 · 수식

# 커밋먼트 — Pedersen 커밋먼트를 모듈러 지수 연산으로 구현해 binding·hiding·덧셈 준동형을 시연.
# 이산로그 가정 기반 토이 그룹 (실제 EC 대신 소수체 위 지수 연산으로 개념만 재현, 교육용).

import secrets

P = 2**127 - 1        # 토이 소수 (실제로는 소수인지 별도 검증 필요 — 데모 목적)
G, H = 5, 7             # 서로 이산로그 관계를 모르는 두 "생성원" (토이 값)

def commit(value, blinding):
    return (pow(G, value, P) * pow(H, blinding, P)) % P

def open_commitment(commitment, value, blinding):
    return commit(value, blinding) == commitment

# --- hiding: 커밋먼트만 봐서는 값을 알 수 없다 ---
secret_value = 1000
blinding = secrets.randbelow(P)
c = commit(secret_value, blinding)
print("commitment (looks random, reveals nothing):", c)

# --- binding: 다른 값으로는 같은 커밋먼트를 열 수 없다 ---
print("opens correctly with real (value, blinding):", open_commitment(c, secret_value, blinding))
print("fails to open with a different value:", not open_commitment(c, secret_value + 1, blinding))

# --- 덧셈 준동형: 커밋먼트끼리 곱하면 값의 합에 대한 커밋먼트가 된다 ---
v1, b1 = 30, secrets.randbelow(P)
v2, b2 = 12, secrets.randbelow(P)
c1, c2 = commit(v1, b1), commit(v2, b2)

c_sum_direct = commit(v1 + v2, (b1 + b2) % P)
c_sum_from_commitments = (c1 * c2) % P

print()
print("commit(v1)*commit(v2) mod P:", c_sum_from_commitments)
print("commit(v1+v2, b1+b2) directly:", c_sum_direct)
print("additively homomorphic:", c_sum_from_commitments == c_sum_direct)
print("=> lets a verifier check sums (e.g. 'inputs balance outputs') without seeing v1, v2")

연습

타원곡선 라이브러리로 Pedersen 커밋먼트를 구현해 준동형성을 검증한 뒤, 같은 값을 머클 트리 커밋먼트로도 만들어 커밋 크기·증명 크기·검증 시간을 표로 비교하라.

실무 · Verex 연결

Verex가 정산 시 오프체인 상태나 주문 배치를 온체인에 압축해 올릴 때, 어떤 커밋먼트를 쓰느냐가 calldata/blob 비용과 온체인 검증 가스, 그리고 필요한 신뢰 가정을 직접 결정한다.

공부한 날 원본 커리큘럼(docs/knowledge/dev-100-curriculum.md)의 이 줄에 노트 링크와 ✅ 를 붙이면, 이 자리는 노트 본문으로 바로 이어집니다. 노트 없이 이 페이지에 바로 적어도 됩니다 — 다만 다시 생성하면 덮어쓰이므로, 남길 글은 docs/algorithms/ 의 마크다운으로 쓰는 편이 안전합니다.

← 86. 임계 서명·MPC·분산 키 생성(DKG)88. 다중정밀 산술(bignum) →