저희가 엇갈린 이상한 협상 문제에 대해 말씀드리게요.
이런 상황을 상상해 보세요: 기업 에너지 구매자는 수소 공급자가 구매 계약을 체결하기 전에 최소 3,000 MWh의 인증된 녹색 크레딧을 보유하고 있는지 확인해야 합니다. 충분히 합리적입니다. 공급자는 크레딧을 가지고 있습니다. 그들은 계약을 원합니다. 그래서 그들은 실제 재고 수를 공유합니다.
그리고 그렇게 하자마자, 방 안에서 무언가 변화가 일어납니다.
이제 구매자는 공급업체가 8,500 MWh를 가지고 있다는 것을 알고 있습니다. 갑자기 구매자는 공급업체가 얼마나 절박한지에 대해 매우 명확한 그림을 가지게 되었습니다 아니. 이점이 이동했습니다. 공급업체의 거래 조건은 앞으로 더 나빠질 것입니다. 그들은 아무것도 할 수 없습니다. 이미 그들의 카드를 드러낸 것입니다.
이 문제에 대해 계속 생각했다. 그리고 그것이 정말 협상 문제가 아니라는 것을 깨달았다. 그것은 정보 아키텍처 문제였다. 공급자는 "네, 저는 자격이 있어요"라고 말하면서도 "그리고 정확히 얼마나 많은 것을 가지고 있나요"라고 말하지 않는 방법이 필요했다.
그것이 바로 H2Ledger로 만들었던 것이다.는 녹색 수소 크레딧을 위한 분산형 시장으로, 공급자가 스마트 계약에 actualAmount >= threshold를 증명할 수 있으며, 실제 숫자가 결코 어디에도 나타나지 않고 완전한 암호화적 확신을 가지고 있습니다. 블록체인에도, 증명에도, 전송 중에도 없습니다. 어디에도 없습니다.
이것을 가능하게 하는 도구는 ゼロ지식 증명이라고 합니다 저희가 어떻게 작동하는지, 코드가 어떤지, 그리고 솔직히 말해서 내가 다르게 하고 싶었던 점을 보여드리게요.
시작하기 전에: Zero-Knowledge Proof이란 정말로 뭘까요?
저는 이것이 들리는 것만큼 두려운 것이 아니라고 약속드립니다.
이렇게 생각해 보세요. 친구가 보안 장치의 조합을 알고 있다는 것을 증명해 달라고 도전해 주지만, 당신은 숫자를 높이 외치지 않겠다고 거절한다고 상상해 보세요. 절대 지식 증명은本质上 말 그대로 당신이 도전을 이기도록 허락하는 수학적 프로토콜입니다. 당신은 다른 당사자에게 어떤 주장이 참인지 증명하면서 그 이면의 비밀을 드러내지 않습니다.
더 정확히 말하자면, 세 가지 사항이 성립해야 합니다.
- 완전성: 진실을 말하고 올바른 비밀을 가지고 있으면 항상 유효한 증명을 제공할 수 있습니다.
- 안정성: 거짓을 말하면 유효한 증명을 가짜로 만들 수 없습니다. 수학적으로 해킹을 컴퓨터적으로 불가능하게 만듭니다.
- 영지식: 증명을 확인하는 사람은 오직 참인지 거짓인지 여부. 다른 어떤 정보도 유출되지 않습니다.
H2Ledger에서는 해당 선언이 actualAmount >= threshold입니다. 비밀(“증인”이라고 불립니다)은 actualAmount입니다. 그리고 증명을 확인하는 당사자는 사람이 아니라, EVM 호환 체인 위에 위치한 Solidity 스마트 계약입니다.
신뢰가 필요 없습니다. 중개인도 필요 없습니다. 오직 수학만이 필요합니다.
진짜 문제는: 녹색 수소 자격 증명 시장은 꽤나 재앙 같다
물론, "재앙"이라는 단어는 강한 표현이지만. 현재 상황은 정말로 취약하다.
현재 수소 자격 증명 시장은 다음과 같은 문제를 다루고 있다.
- 지면 기반의 인증 체인에 on-chain anchor가 없는 경우. 동일한 인증된 신용을 여러 구매자에게 다른 협상을 통해 조용히 제시할 수 있습니다. 누구도 공유된 레지스트리를 사용하여 이를 포착할 수 없습니다.
- 독립된 레지스트리 호환되지 않는 규제 프레임워크 하에 작동 중이며 상호운용성이 없습니다. 독일의 구매자와 칠레의 공급자는 완전히 다른 인증 표준을 사용하여 작업할 수 있으며, 그 간격을 확인할 방법이 없습니다.
- 투명성과 불투명성 사이의 강제 선택.크레딧 잔액을 공개 블록체인에 올리고 모든 경쟁사가 실시간으로 재고를 볼 수 있습니다. 차단체인(Off-chain)으로 두면 신뢰 없는 결제 메커니즘이 없습니다. 당신은 독을 고르아야 합니다.
영지식 증명(Zero-knowledge proofs)은 당신이 그 횡단보트에서 완전히 벗어날 수 있게 합니다. 당신은 결제를 위한 공유 원장(Shared ledger)을 얻습니다 그리고 기밀성을 위한 기반이 되는 인물들에 대한 보호. 동시에.
H2Ledger가 실제로 어떻게 작동하는지: 삼층 구조의 그림
고수준으로 볼 때, 시스템에는 서로 소통하는 세 개의 층이 있습니다:
[ Supplier (off-chain) ]
|
| Private: actualAmount (stays here, never transmitted)
v
[ Circom Circuit + Groth16 Prover ]
|
| Outputs: proof.json (256 bytes) + public.json (threshold only)
v
[ GreenHydrogenMarketplace.sol ]
|
| Delegates the heavy cryptographic check to:
v
[ Verifier.sol ] --> true / false
공급업체의 실제 재고 수치는 그들의 기계를 벗어나지 않습니다. 차단체인(온체인)에 이동하는 것은 256바이트 증명과 공개 임계값입니다. 스마트 계약은 증명을 확인하고, 그것이 유효한지 확인한 다음 주문 상태를 완료된 것으로 전환합니다. 이것이 전체 정산 흐름입니다.
ZK Circuit: 마법이 지루해지는 곳 (좋은 의미로)
회로는 ZK 증명 시스템이 평가하는 프로그램입니다. 저는 제 것을Circom 2.0는本质上 산술 제약 조건의 시스템으로 계산을 표현하기 위한 도메인 특화 언어입니다. 여기는 핵심 템플릿입니다:
template ThresholdVerification(n) {
signal input actualAmount; // Private: never leaves the prover's machine
signal input threshold; // Public: the buyer's stated minimum
signal output isValid; // 1 if actualAmount >= threshold, else 0
// Uses LessThan from circomlib to prove:
// NOT (actualAmount < threshold) = (actualAmount >= threshold)
}
이것을 컴파일하면, 128 개의 R1CS 제약 조건을 193 개의 와이어에 걸쳐 생성합니다. 그 제약 조건들이 실제로 하는 일은 다음과 같습니다:
- 64개는
actualAmount와threshold를 64비트 이진 표현으로 분해합니다. - 다른 64개는 비트마다 비교기를 구현하여 어떤 숫자가 더 큰지 결정합니다.
64비트 선택에 대한 간단한 메모: 기업 시장의 수소 용량은 백만 MWh 단위로 측정됩니다. 64비트 필드는 2^64까지의 값을 저장할 수 있어, 당신이 언제든 거래할 수 있는 모든 것보다 약 2^40의 여유 공간을 제공합니다. 실질적인 한계 문제는 없습니다.
Groth16 증명기는 이 회로, 증거, 그리고 설정식에서 가져온 증명 키를 사용하여 BN254에서 세 개의 타원 곡선 그룹 요소를 출력합니다:
π_a, π_b, π_c
이 세 가지 요소은증거입니다. 시리얼라이즈되면 항상 정확히 256 바이트가 나옵니다. 증거에 무엇이 포함되든 관계없이. 이 고정된 크기는 실제로 유용합니다: 가스 비용은 예측 가능하며, ABI 인코딩은 깨끗하며, 저장 공간은 문제가 아닙니다.
증명 생성은 일반적인 노트북에서 약 1에서 2초가 걸리며, 모든 것이 오프체인에서 발생합니다. 블록체인은 컴퓨팅을 볼 수 없습니다; 그저 출력만 본 것입니다.
스마트 계약: 실제로 의미가 있는 접근 제어
The onlyOwner 함정
시작부터 피하고 싶었던 패턴이 있습니다.
많은 계약 시스템은 기본적으로 단일onlyOwner 모든 특권 작업에 대한 modifier입니다. 간단합니다. 작동합니다. 그리고 단일 작성자 시스템에서는 아마도 괜찮습니다.
하지만 H2Ledger에는 완전히 다른 신뢰 가정을 가진 세 가지 구별되는 작성자 유형이 있습니다.생산자 (크레딧을 보유한 공급자), 구매자 (구매 입찰 주문을 게시하는 회사) 및 검증 에이전트 (오프체인에서 기존의 인증의 합법성을 증명하는 자격을 갖춘 당사자들). 모든 세 가지를 단일 소유자 주소를 통해 필터링하면 전체 시스템의 무신뢰성 기반 원칙과 근본적으로 배치되는 단일 통제 지점이 생성됩니다.
그래서 나는 역할 기반 접근 계층을 대신 구축했습니다. 각 주소는 네 가지 상태 중 하나에 할당됩니다: NONE, PRODUCER, VERIFIER_AGENT, 또는BUYER 모든 민감한 기능은 다른任何事情运行之前检查调用者的角色.
pragma solidity ^0.8.0;
import "./Verifier.sol";
contract GreenHydrogenMarketplace {
Verifier verifier;
enum Role { NONE, PRODUCER, VERIFIER_AGENT, BUYER }
mapping(address => Role) private roles;
address public admin;
modifier onlyRole(Role _required) {
require(roles[msg.sender] == _required, "Access denied: insufficient role");
_;
}
modifier onlyAdmin() {
require(msg.sender == admin, "Access denied: not admin");
_;
}
constructor(address _verifier) {
verifier = Verifier(_verifier);
admin = msg.sender;
}
function assignRole(address _account, Role _role) external onlyAdmin {
roles[_account] = _role;
}
}
결과: 주소는 두 가지 역할을 동시에 수행할 수 없습니다. 구매자는 증명서를 제출할 수 없습니다. 생산자는 주문을 만들 수 없습니다. 역할 할당 자체는 관리자 키로 보호되어 있으며, 이는 아래 학습 섹션에서 솔직하게 다룰 남은 중앙 집중화 지점입니다. TheonlyRole modifier는 조합 가능하므로 새로운 함수 유형으로 확장하는 데 한 줄이 듭니다.
주문 생성
BUYER 주소만 구매 주문을 생성할 수 있습니다. 주문이 생성되면 임계값은 변경할 수 없습니다. 마지막 부분을 강조하고 싶습니다. 그것이 생각보다 더 중요하기 때문입니다.
구매자가 공급업체가 이미 증명서를 생성한 후 임계값을 낮출 수 있다면, 공급업체는 원래 기준을 충족했을 때 적법하게 자격을 갖춘 공급업체를 역사적으로 자격을 박탈할 수 있습니다. 생성 시 임계값을 잠그면 그런 조작을 완전히 방지할 수 있습니다.
struct ProcurementOrder {
address buyer;
address supplier;
uint256 threshold;
bool fulfilled;
}
mapping(uint256 => ProcurementOrder) public orders;
uint256 public nextOrderId;
function createOrder(address _supplier, uint256 _threshold)
external
onlyRole(Role.BUYER)
returns (uint256 orderId)
{
orderId = nextOrderId++;
orders[orderId] = ProcurementOrder({
buyer: msg.sender,
supplier: _supplier,
threshold: _threshold,
fulfilled: false
});
}
증명서 제출: 저렴한 검사를 먼저, 비싼 검사를 나중에
실제 ZK 검증이 이곳에서 일어납니다. 공급자가 증명을 제출할 때, 계약은 의도된 순서대로 가장 저렴한 순서부터 가장 비싼 순서까지 다섯 가지 검사를 실행합니다.
- 역할 검사: 호출자가 등록된 PRODUCER인가요? (modifier, ~200 gas)
- 공급자 신원: 이것이 이 주문과 연결된 구체적인 공급자인가요? (SLOAD, ~2,100 gas)
- 재방지: 이 주문은 이미 완료되었나요? (SLOAD, ~2,100 가스)
- 임계값 결합: 공공 신호가 저장된 임계값과 일치하나요? (비교, ~200 가스)
- 페어링 확인: ZK 증명이 암호학적으로 유효한가요? (~285,000 가스)
비싼 쌍계산이 마지막에 실행됩니다. 더 저렴한 경비 중 하나가 그것보다 먼저 실패하면 호출자가 파괴된 거래에 285k 가스를 쓰는 것을 피할 수 있습니다.
function submitThresholdProof(
uint256 orderId,
uint[2] calldata _pA,
uint[2][2] calldata _pB,
uint[2] calldata _pC,
uint[1] calldata _pubSignals
) external onlyRole(Role.PRODUCER) {
ProcurementOrder storage order = orders[orderId];
require(msg.sender == order.supplier, "Caller is not the designated supplier");
require(!order.fulfilled, "Order already fulfilled");
require(_pubSignals[0] == order.threshold, "Public signal does not match order threshold");
require(
verifier.verifyProof(_pA, _pB, _pC, _pubSignals),
"ZK proof verification failed"
);
order.fulfilled = true;
// Downstream: emit event, trigger escrow release, etc.
}
여기서 한 검사는 추가적인 주의를值得 합니다: _pubSignals[0] == order.threshold. 이것은 중복처럼 보일 수 있지만 중요한 작업을 하고 있습니다. 그것이 없다면 공급자는 유효한 증명을 제출할 수 있지만,다른임계점(예를 들어 1,000 MWh, 이를 쉽게 만족시키는)과 3,000 MWh를 요구하는 주문을 짝지어야 합니다. 증명 자체는 짝지어서 확인을 통과할 것입니다, 그래서입니다1,000 MWh에 대한 유효한 증거. 오직 이 바인딩 체크만 대체를 포착하고 거부합니다.
성능 숫자: 이게 정말로 얼마나 비쌀까요?
| 미터릭 | 값 |
|---|---|
| 증명 크기 | 256 바이트 (고정됨) |
| 증명 생성 시간 | 1에서 2초 (오프체인) |
| 검증자 배포 가스 | ~2,850,000 (한 번에) |
| 증명당 검증 가스 | ~289,096 |
| 30 Gwei에서의 이더리움 L1 비용 | ~$0.87 per proof |
| 아리브럼 또는 옵티밋의 비용 | ~$0.01 per proof |
개별 계약이 수백만 달러인 기업 구매 거래에서 L1당 $0.87의 검증 비용은 전혀 합리적입니다. 더 높은 빈도에 가까워지는 모든 사항에서 L2가 명백한 경로입니다.
제가 올바르게 이해한 점과 다르게 할 점
좋은 부분
분리Verifier.sol은 GreenHydrogenMarketplace.sol에서 옳은 건축적 결정이었다. 검증기는 비즈니스 로직이 없는 무상태 암호화 원시형이다. 이를 분리하는 것은 다른 모든 것과 독립적으로 감사할 수 있음을 의미한다. 더 작은 표면, 더 깨끗한 감사 범위.
저렴에서 비싼 순서는submitThresholdProof도 테스트 중에 효과를 보였습니다. 잘못된 입력에 대한 실패 제출은 쌍을 맞추는 확인이 먼저 실행될 경우보다 일관되게 저렴했습니다.
성실한 후회
신뢰할 수 있는 설정이 제가 해결되지 않은 가장 큰 책임입니다. Groth16은 증명 및 검증 키를 생성하기 위해 한 번의 MPC 의식이 필요합니다. PoC는 연구 환경에는 적합한 시뮬레이티드 의식을 사용하지만, 생산 환경에서는 해당 의식에 참여한 모든 참가자가 자신의 "독성 폐기물" (그들의 기여에서 비롯된 비밀 무작위성)을 유지하면, 그들은 영원히 거짓 주장에 대한 유효한 증명을 생성할 수 있습니다. 생산 배포는 검증 가능한 대규모 MPC 의식과 검증 가능한 트랜스크립트를 필요로 하거나, PLONK 또는 Halo2와 같은 설정 투명한 증명 시스템으로 이전해야 합니다. 이 경우에는 전혀 신뢰 설정이 필요하지 않습니다.
관리자 키는 제가 완전히 해결하지 못한 신뢰의 병목 현상입니다. 현재, 단일 주소가 전체 마켓플레이스의 역할 할당을 통제하고 있습니다. 그것은 중앙 집중화 위험입니다. 다음 버전에서는 관리자 역할이 첫 날부터 Gnosis Safe 멀티시그로 전환되어야 하며, 역할 할당 작업에 타임락을 설정하여 참여자들이 어떤 변경 사항도 사전에 알릴 수 있어야 합니다.
가스비는 더 낮아질 수 있습니다. Verifier.sol에서의 BN254 쌍결합 작업은 Ethereum의 EIP-197 사전컴파일을 크게 활용할 수 있습니다. 생성된 검증자가 EVM 해석기에서 계산하는 대신 이를 통해 올바르게 라우팅하면 검증 비용이 30에서 40퍼센트까지 감소합니다. 생산 배포 전에 신중하게 측정하는 것이 가치가 있습니다.
이 회로는 오직 한 가지 사실을 증명합니다. 실제 구매 계약은 단순히 수량만큼만 신경 쓰지 않습니다. 순도 등급, 인증 날짜, 원산국; 이 모두가 중요합니다. 회로를 복합 검사(volume >= min_vol AND purity >= min_purity AND date >= cutoff)로 확장하면 약 256개의 추가 제약 조건이 추가되고 증명 생성 시간이 두 배가 될 수 있습니다. 두 가지 모두 실용적인 한계 내에 있으며, 시스템을 의미 있게 더 유용하게 만들 것입니다.
Run It Yourself
코드를 수정하고 싶다면:
git clone <your-repo-url>
cd h2ledger-poc
npm install
npm run verify
# Expected: OK
# (verifies the included proof where actualAmount=5000 >= threshold=3000)
그리고 직접 회로 통계를 보려면:
snarkjs r1cs info circuits/credit_proof.r1cs
# Curve: bn-128
# Constraints: 128
# Wires: 193
# Private Inputs: 1
# Public Inputs: 1
이 패턴이 수소를 넘어서는 중요성은 무엇인가
이 프로젝트를 만들면서 계속 돌아오는 점은 이것입니다: H2Ledger는 정말 수소 프로젝트가 아닙니다. 일반적인 패턴의 데모입니다.
누군가가 숫자가 임계값을 만족한다는 것을 증명해야 하지만, 그 숫자를 공개하는 것이 비용이 드는 모든 시장은 이 아키텍처의 후보입니다. 신용 평가. 보험 수리. 공급망 공급자 자격. 급여 준수 감사. 회로는 변하지만, 패턴은 그렇지 않습니다.
조작 증명은 추상적인 용어로 많이 이야기되지만, 여기서 보고 싶었던 것은 Circom, SnarkJS와 몇백 줄의 Solidity로 몇 주 안에 실제로 무언가를 만들 수 있다는 것입니다. 도구는 정말로 사용 가능합니다. 수학은 마술이 필요 없습니다; 올바르게 연결되면 됩니다.
비슷한 접근 방식으로 무언가를 만들거나, 내가 수정해야 할 점을 발견하시면 정말 기뻐서 듣고 싶어요.
H2Ledger는 연구용 개념 증명입니다 (v0.1.0). 증명 시스템: Groth16 (BN254). 회로: 128 제약 조건, 193 와이어. 질문이나 협력: nioomeee@gmail.com













