奇妙な交渉の問題に遭遇したことをお話しします
こんな状況を想像してください:企業のエネルギー購入者が、水素供給者が最低3,000 MWhの認定グリーンクレジットを保有していることを確認する必要があり、それがなければ調達契約を結べないのです。まあ、公平な話です。供給者はクレジットを持っています。取引を望んでいます。だから彼らは実際の在庫数を共有します
そして、それをすると、部屋の中で何かが変わります
今や買い手はサプライヤーが8,500 MWhの電力を手元に持っていることを知っています。突然、買い手はそのサプライヤーがどれほど絶望的であるかを非常に明確に理解するようになりますではない。力関係が変わりました。サプライヤーの取引条件はすぐに悪化し、彼らには何もできません。なぜなら、彼らはすでに自分の手を示したからです。
この問題について考え続けていた。そして、それは実際には交渉の問題ではなく、情報アーキテクチャの問題だと気づいた。供給業者は「はい、資格がある」と言いながら、「そしてこれは正確にどれだけ持っているか」と言わずに伝える方法が必要だった。
それがH2Ledgerで作ったものだ。:グリーン水素クレジットのための分散型マーケットプレイスで、供給者はスマートコントラクトに対してactualAmount >= thresholdを証明でき、完全な暗号学的確実性で、実際の番号がどこにも表示されることなく。ブロックチェーン上でも、証明書中でも、中継中でも、どこにも。
このツールはゼロ知識証明と呼ばれています。 こちらがどのように機能するか、コードの見た目、正直に言って、何か違う方法を取りたかったかを示します
さて本題に入る前に:ゼロ知識証明とは一体何ですか?
これは聞こえるほど恐ろしくないと約束します。
こんな風に考えてみてください。友人があなたに、安全室の組み合わせを知っていることを証明するのを挑発するが、あなたは数字を大声で言わないで拒否する。ゼロ知識証明は本質的に、その挑発を勝ち取ることを許す数学的プロトコルです。あなたは他の当事者に、その声明が真であることを確信させ、その背後にある秘密を明らかにすることなく。
より正確には、三つのことが成り立っている必要があります:
- 完全性: 真実を言っている場合、そして正しい秘密を持っている場合、常に有効な証明を生成できます.
- 安全性: 嘘をついている場合、有効な証明を偽造できません。数学は不正を計算的に実行不可能にします.
- ゼロ知識: 証明を確認している人はそれだけしか学びません その声明が真であれ偽であれ。他の何も漏れない。
H2Ledgerでは、その声明はactualAmount >= thresholdです。秘密(「証人」と呼ばれるもの)はactualAmountです。そして、証明を確認している方は人間ではなく、EVM互換ブロックチェーン上に座っているSolidityスマートコントラクトです。
信頼は不要。仲介者は必要ありません。ただ数学だけです。
本当の問題点:グリーンハイドロゲンクレジット市場はある種の災害だ
いいえ、「災害」という言葉は強いですが、現在の状況は本当に不安定です
今、ハイドロゲンクレジット市場は以下のものを扱っています:
- 紙ベースの認証チェーン にブロックチェーン上のアンカーがないもの。同じ認証されたクレジットは、異なる交渉を通じて複数の買い手に静かに提示できる。誰も共有された帳簿を持っていないので、それを見つけることはできない。
- 分断された登録システム が、互換性のない規制枠組みの下で動作しており、連携がない。ドイツの買い手とチリのサプライヤーは、全く異なる認証基準で作業しており、そのギャップを検証する方法がないかもしれない。
- 透明性と不透明性の間で強制的な選択を迫られる。 あなたのクレジット残高を公開ブロックチェーンに置くと、すべての競合他社がリアルタイムであなたの在庫を見ることができる。ブロックチェーン外に持っていれば、信頼できない決済機構がない。あなたは毒を選ぶしかない。
ゼロ知識証明は、あなたがそのバランスを完全に外れることを許す。決済のために共有帳簿を得と に基づく人物のプライバシー。両方同時に。
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上で3つの楕円曲線群要素を出力します。
π_a, π_b, π_c
これらの三つの要素は証拠です。シリアライズされると、常に正確に256バイトになります。どのような証人データが含まれていても。この固定されたサイズは実際には非常に便利です:ガスコストは予測可能で、ABIエンコーディングはクリーンで、ストレージは問題になりません。
通常のラップトップで証明の生成には約1~2秒かかり、すべてオフチェーンで行われます。ブロックチェーンは計算を見ません;出力だけを見ます。
スマートコントラクト:実際に意味のあるアクセス制御
onlyOwner の罠
最初から避けたかったパターンがあります。
多くの契約システムは単一onlyOwner は各特権操作の修飾子です。シンプルです。動作します。単一のアクターシステムでは、おそらく問題ありません。
しかし、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;
}
}
結果として、一つのアドレスが二つの役割を持つことはできません。買い手は証明書を提出できません。プロデューサーは注文を作成できません。ロール割り当て自体は管理者キーによって制限され、これは学習セクションで正直に取り上げる残りの中央集権化ポイントです。onlyRole 修飾子は組み合わせ可能なので、新しい関数タイプに拡張するには1行のコードが必要です。
注文の作成
たった 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検証が行われる場所です。サプライヤーが証明書を提出すると、契約は意図的に最も安い順から最も高い順に5つのチェックを実行します:
- ロールチェック: 呼び出し元は登録された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。これが冗長に見えるかもしれませんが、重要な仕事をしています。これがなければ、サプライヤーは有効な証明を生成することで 提出__JHSNS_SEG_f144cd4d_116__異なるしきいち (例えば、1,000 MWhで、彼らは簡単に達成できる) と組み合わせ、それに合わせて3,000 MWhを必要とする注文を組み合わせます。証明自体はペアリングチェックを通過します、なぜならです1,000 MWh の有効な証明。この結びつきチェックだけが置き換えを検出し、それを拒否する。
パフォーマンスの数値:これは実際にどのくらいのコストですか?
| メトリック | 値 |
|---|---|
| 証明サイズ | 256 バイト(常に固定) |
| 証明生成時間 | 1 から 2 秒(オフチェーン) |
| 検証者デプロイガス | ~2,850,000(一度限り) |
| 証明ごとの検証ガス | ~289,096 |
| Ethereum L1 でのコスト(30 Gwei) | 証明ごとに約 $0.87 |
| アリブリムやオプティミズムにおけるコスト | ~証明書あたり0.01ドル |
企業の調達取引において個々の契約が数百万ドルになる場合、L1での検証あたり0.87ドルは完全に現実的です。より高い頻度に近づくものについては、L2が明らかな道です
正解したことと、違う方法でやるべきことを
いいこと
分離Verifier.sol から GreenHydrogenMarketplace.sol が適切な建築的選択でした。検証器はビジネスロジックを持たない状態無しの暗号学的な primitive です。それを隔離することで、他のすべてから独立して監査することができます。小さい表面、クリーンな監査範囲.
安いから高価な順番に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の追加の制約が加わり、証明生成時間はおそらく2倍になる。どちらも実用的な限界内であり、システムを意味深くより便利にするだろう.
自分で実行してみよう
コードを触りたい場合は:
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













