原文
pERC20: Privacy-Native Fungible Token Standard (Draft) — JiangXb-son (2026-06-04)
著者: _pERC20Labs · 種類: Standards Track (Ethereum Request for Comments (ERC)) · 作成日: 2026-06-03
簡易要約
プライバシーネイティブな代替可能トークン (fungible tokens) のための標準インターフェース。
概要
以下の標準は、EVM上のスマートコントラクト内でプライバシーネイティブな代替可能トークンのための標準APIの実装を可能にする。この標準は、残高と送金量がデフォルトでプライベートであるトークンを、公開検証可能なtotalSupplyを維持しつつ、送金、ミント、バーンするための基本的な機能を提供する。トークンは、発行時から暗号化されたUTXOノート(Groth16証明、Orchardスタイルのモデル)として存在する。各pERC20アセットは、アセットコントラクトによって維持されるコンプライアンス凍結ルート (compliance frozen root) にバインドされなければならず、これによりブラックリストに登録されたノートは使用できなくなる。
この標準はEthereum Request for Comments (ERC)-20とバイナリ互換性がない。公開のbalanceOfやapprove / allowanceは存在しない。代わりに、同等のプライバシーインターフェースであるIPERC20を定義する。
この提案はEIP(Ethereum 改善提案)-8182を補完するものである。EIP(Ethereum 改善提案)-8182はETHおよび互換性のあるEthereum Request for Comments (ERC)-20アセットのプライベート送金レイヤーを対象としているが、pERC20はアセットレベルでプライバシーネイティブなトークン標準インターフェースを定義する。
動機
イーサリアムは、プロトコル層でのネイティブなプライバシーにますます注力している。いくつかのEIP(Ethereum 改善提案)はすでに、FOCIL (強制オンチェーンインクルージョンリスト) (EIP(Ethereum 改善提案)-7805)、EIP-8141 frame transaction (EIP(Ethereum 改善提案)-8141)、EIP-8250 Keyed Nonces (EIP(Ethereum 改善提案)-8250)、EIP(Ethereum 改善提案)-8272 (Recent Roots) を含む、補完的な構成要素を提案している。これらの提案がまとめて採用されれば、イーサリアムはベースレイヤーでトラストレスで検閲耐性のあるプライベートトランザクションをサポートできるようになり、エコシステムは公開トークンに対してEthereum Request for Comments (ERC)-20が果たすのと同じ標準化の役割を持つプライバシーネイティブな代替可能トークン標準を必要とするだろう。
この文書は、そのギャップを埋めるためにpERC20を提案する。これは、OrchardスタイルのZK-UTXOモデルモデル(Groth16証明、Zcash Orchardプロトコルを応用)に基づいて構築された、EVM上のプライバシーネイティブな代替可能アセットのための標準インターフェースである。対照的に、Ethereum Request for Comments (ERC)-20は残高と送金を完全にオンチェーンで公開し、保有者の分布、取引相手、および金額を明らかにする。pERC20は、以下の目標を持つノートベースのUTXOモデルモデルを採用する。
- デフォルトでのプライバシー: アセットは発行時からプライベートであり、公開からシールドへの変換ステップは不要。
- UTXOレベルのプライバシー: アカウント残高はパターン分析の対象とならず、匿名化セットは同種のノートから形成される。
- 検証可能な正直性:
totalSupplyは公開されており、見えないインフレを防ぐ。 - 組み込みのコンプライアンス: プロトコル層は、規制上の措置可能性要件を満たすために特定のノートを凍結できる。
- EVMデプロイ可能性: 標準インターフェースにより、ウォレット、インデクサー、およびサービスによる統一された統合が可能になる。
仕様
この文書におけるキーワードMUST、MUST NOT、SHOULD、およびMAYは、RFC 2119に記述されている通りに解釈される。
用語
| 用語 | 意味 |
|---|---|
| note | 値(トークン量)と受信者情報を含む暗号化されたUTXOモデル |
| commitment / cmx | ノートコミットメント(Merkleツリーのリーフ、x座標) |
| nullifier / nf | ノートを使用する際に公開される1回限りの公開マーカー。二重使用を防ぎ、IDとリンクできない |
| anchor | 使用時に参照される過去のMerkleルート |
| perc1 address | pERC20を受信するためのプライバシーアドレス(Orchardキー導出)。この仕様内で定義される(別途の補完EIP(Ethereum 改善提案)なし) |
| cmxFrozenRoot / rt_frozen | コンプライアンスブラックリストのSparse Merkle Treeのルート。公開回路入力 |
| binding signature | オペレーションの値の保存を証明するSchnorr署名 |
| spend-auth signature | ノートを使用する権限を証明するSchnorr署名 |
| bundle | 1つ以上の行動(各行動 = オプションの消費 + 1つの出力)からなる単一のオペレーション |
データ構造
以下の仕様はSolidity 0.8.20(またはそれ以降)の構文を使用する。
PrivacyCall
IPERC20メソッドのプロダクト層コールペイロード。
struct PrivacyCall {
bytes actions; // = abi.encode(BundleAction[])
uint256[3] bindingSig; // [Rx, Ry, s] Baby JubJub Schnorr binding signature
}
BundleAction
IEndpointCoreの実装層アクション。
struct BundleAction {
bytes32 cmx; // output note commitment
bytes encCiphertext; // recipient ciphertext; length MUST match the note encryption format (see below)
bytes outCiphertext; // sender self-recovery ciphertext; length MUST match the OVK encryption format (see below)
bytes32 epk; // ephemeral public key
bytes32 nfOld; // nullifier of the consumed input note
bytes32 anchor; // historical root used by the consumed input note
bytes proof; // Groth16 proof = abi.encode(pA, pB, pC)
uint256[8] pubFields; // public inputs; [7] MUST == cmxFrozenRoot
uint256[3] spendAuthSig; // spend authorization signature for the consumed input note
}
ノート暗号文形式: この標準は、特定のノートプレーンテキストのレイアウトをバイトレベルの不変条件に埋め込んでいないが、実装は1つを固定し、それを文書化しなければならない。参照実装は、Zcash Protocol Specification §7.5 Action Description Encoding and Consensusで定義されているOrchardスタイルのフィールドサイズを使用する。
encCiphertext= 580バイト:epkと受信者の受信ビューイングキー (IVK) から導出されたキーでノートプレーンテキストを暗号化したChaCha20-Poly1305暗号文(564バイトのプレーンテキスト + 16バイトのPoly1305タグ。プレーンテキストフィールドには、ダイバーシファイア/送信キーエンコーディング、value、rseed、および512バイトのメモが含まれる)。outCiphertext= 80バイト: 送信キーとエフェメラル秘密鍵から形成されたバイト文字列を、送信者の送信ビューイングキー (OVK) で暗号化したChaCha20-Poly1305暗号文。送信済みノートのリカバリに使用される(64バイトのプレーンテキスト + 16バイトのPoly1305タグ)。
ノート暗号化レイアウト(異なる暗号、異なるプレーンテキストスキーマ、異なるメモサイズ)を変更する実装は、サイレントに長さを変更するのではなく、このEIP(Ethereum 改善提案)の別のバリアントを公開しなければならない。
pubFieldsの順序は [anchor, cv_net_x, cv_net_y, nf_old, rk_x, rk_y, cmx, rt_frozen] でなければならない。
このレイアウトは、Zcash Protocol Specification §4.18.4 Action Statement (Orchard)におけるOrchard Actionの主要入力(anchor、純値コミットメントcv_net、nf_old、ランダム化キーrk、出力コミットメントcmx)から導出されている。pERC20は、コンプライアンスと統一された検証パスのために、2つの意図的な変更を加えている。
rt_frozenがenable_spend/enable_outputを置き換える: スロット[7]は各アクションをアセットのコンプライアンスブラックリストSMTルート(IPERC20.cmxFrozenRoot())にバインドする。回路は、そのルートの下で消費されたノートコミットメントが非メンバーであることを証明する。- ミント/送金/バーンに対する単一のアクション形状: ダミー入力のミントと実際の消費は同じ公開フィールドレイアウトを共有する。有効化フラグは個別の公開入力として公開されない(回路内で処理される)。
オンチェーン実装は、これらの8つのフィールドをActionPubHash(Poseidonスポンジ)を介して単一のGroth16公開シグナルpub_hashに圧縮しなければならず、この圧縮関数は回路のPubHashAction()と一致しなければならない。
pubFieldsの各要素は、正規のフィールド要素(実装の検証者が使用するSNARK curveの**scalar field modulus** Frよりも厳密に小さい)でなければならない。そうでない場合、コールはリバートしなければならない(PubFieldOutOfRange)。この制約がないと、ActionPubHashはハッシュ化前にフィールドのモジュロで入力を削減するが、SNARK curve検証者は最終的なpub_hashのみをチェックする。攻撃者はnf + Frを提出して同じpub_hashと証明を生成できるが、異なるnullifierセットキーにマッピングされ、同じノートの二重使用が可能になる。
IPERC20
実装は成功時にtrueを返し、失敗時にリバートしなければならない。boolの戻り値はEthereum Request for Comments (ERC)-20の呼び出し規約互換性のために保持されている。
name
トークンの名前を返す。例: "MyPrivateToken"。
function name() external view returns (string memory)
symbol
トークンのシンボルを返す。例: "pHIX"。
function symbol() external view returns (uint8)
decimals
トークンが使用する小数点以下の桁数を返す。例: 8は、トークン量を100000000で割ってユーザー表現を得ることを意味する。
function decimals() external view returns (uint8)
totalSupply
総トークン供給量(累積ミントから累積バーンを引いたもの)を返す。この値は公開されており、オンチェーンで検証可能でなければならない。
function totalSupply() external view returns (uint256)
issuer
この標準の下でミントを許可されたアドレスを返す。
function issuer() external view returns (address)
cmxFrozenRoot
現在のコンプライアンス凍結ルート(IPERC20標準メソッド)を返す。
function cmxFrozenRoot() external view returns (uint256)
setFrozenRoot
オフチェーンのブラックリストSMTを再構築した後、コンプライアンス凍結ルートを更新する。adminに制限しなければならない。
function setFrozenRoot(uint256 newRoot) external
transfer
一連のノートを受益者にプライベートに送金する(ノート→ノート)、値の保存を伴う。
実装は、valueBalance == 0で基盤となるバンドルロジックを実行しなければならない(_executeBundleなどの内部実行パスを介して)。
実装は成功時にtrueを返さなければならない。失敗はリバートによって表現しなければならない。
実装はEthereum Request for Comments (ERC)-20のTransfer(from, to, value)イベントを発行してはならない。ノートごとの可視性はNoteAdded / NoteConfirmedによって提供される(IEndpointCoreを参照)。
送信者、受信者のID、および送金量はプライベートのままでなければならない。
値変更操作は、制御されたmint / burn / transferを通じてのみ公開しなければならない。コア実行パスは公開呼び出し可能であってはならない。これにより、呼び出し元が供給会計を迂回するためにvalueBalanceの方向を選択できないようにする(以下の供給不変条件を参照)。
function transfer(PrivacyCall calldata call) external returns (bool success)
mint
額面amountの新しいノートを作成する。totalSupplyはamountだけ増加する。
実装は、amount < ℓ(SUBGROUP_ORDER)を検証しなければならない。これにより、バインディングスカラーamount mod ℓが宣言された量(AmountTooLarge)と等しくなる。
実装は、valueBalanceの下位255ビットがamountと等しいことを検証しなければならない(amount binding)。
実装は、transferおよびburnと同じアンカー / nullifier / spend-auth検証パスを通じてミントアクションを実行しなければならない(オンチェーンでの出力のみのブランチなし。nfOld == 0センチネルなし)。回路は、ミントアクションの消費された入力ノートがv = 0を保持するように制約しなければならない。これにより、アクションは純流入セマンティクスを示す。これは回路レベルの不変条件であり、オンチェーンで直接チェック可能ではない。
承認: mintは発行者(onlyIssuer)に制限しなければならない。
実装は、後のバージョンでミント承認を緩和することができる(ブロックウィンドウ、キャップ、許可リスト、PoW、ステーキング)が、totalSupplyは公開で累積され続けなければならない。
受信者のIDはプライベートでなければならない。amountは公開である。
function mint(uint256 amount, PrivacyCall calldata call) external
burn
ノートを消費して値を破壊する。totalSupplyはamountだけ減少する。外部アセットはリリースされない。
実装は、amount < 2^255(符号ビットが設定されていない)およびamount < ℓ(SUBGROUP_ORDER、AmountTooLarge)を検証しなければならない。
実装は、valueBalance == amount(bit255 = 0)で実行しなければならない。
実装は、totalSupply >= amountを検証しなければならない。そうでない場合、リバートする。
承認: 任意の保有者は自身のノートをバーンすることができる(対応する消費承認が必要)。
バーナーのIDはプライベートでなければならない。amountは公開である。
function burn(uint256 amount, PrivacyCall calldata call) external
イベント
Mint
新しいトークンがミントされたときにトリガーしなければならない。
event Mint(address indexed issuer, uint256 amount)
Burn
トークンがバーンされたときにトリガーしなければならない。
event Burn(uint256 amount)
FrozenRootUpdated
コンプライアンス凍結ルートが変更されたときにトリガーしなければならない。
event FrozenRootUpdated(uint256 oldRoot, uint256 newRoot)
Perc20Created
新しいpERC20アセットコントラクトがデプロイされたときに一度発行しなければならない(通常はアセットコンストラクタ内で)。
ファクトリデプロイパターンは推奨されるが、必須ではない。アセットコントラクトがPerc20Created(または同等のコンストラクタ時メタデータ)を発行する限り、スタンドアロンデプロイメントは準拠している。ファクトリコントラクトは規範的な標準の一部ではない。参照実装は、発見可能性と共有検証者配線のためにファクトリコントラクト(例: PERC20Factory)を提供することができる。
event Perc20Created(
address indexed pool,
address indexed issuer,
string name,
string symbol,
uint8 decimals
)
インデクサーとウォレットは、新しいアセットを登録するためにこのイベントをリッスンすべきである。ファクトリが使用される場合でも、イベントはデプロイされたアセットコントラクトから発信しなければならない(ファクトリラッパーからのみではない)。これにより、スタンドアロンデプロイメントとファクトリバックアップデプロイメントが同じ観測可能なメタデータを生成する。
注: この標準は意図的にEthereum Request for Comments (ERC)-20のTransferまたはApprovalイベントを定義しない。From/toは常に隠されたノートであり、送金量はプライベートであるため、Transferを発行することは誤解を招く可能性がある。供給量の変更はMint / Burnを通じて観測可能であり、ノートごとの詳細はNoteAdded / NoteConfirmedによって伝達される。
コンプライアンス凍結ルート
コンプライアンス凍結ルートは**IPERC20**の一部である(個別のコンプライアンスモジュールではない)。
function cmxFrozenRoot() external view returns (uint256)
function setFrozenRoot(uint256 newRoot) external // onlyAdmin
event FrozenRootUpdated(uint256 oldRoot, uint256 newRoot)
- 各アクションの
pubFields[7]は現在のcmxFrozenRoot()と等しくなければならない。そうでない場合、リバートする(BadFrozenRoot)。 - 回路は、消費されたノートのコミットメントが
cmxFrozenRootをルートとするブラックリストSMTのメンバーではないことを証明しなければならない(非メンバーシップ証明)。 - 完全なブラックリストSMT構造はオフチェーンで維持され、ルートのみがオンチェーンに保存される。
setFrozenRootはadmin(デプロイメントとadmin設定に応じて、発行者または専任のコンプライアンス担当者)に制限しなければならず、マルチシグ / タイムロックを使用すべきである。各変更は監査可能性のためにFrozenRootUpdatedを発行しなければならない。- ノートを凍結するには: オフチェーンで、その
cmxをブラックリストSMTに挿入し、新しいルートを計算し、setFrozenRoot(newRoot)を呼び出す。凍結を解除するには、削除して再度setFrozenRootを呼び出す。 - 初期の
cmxFrozenRoot == 0は空のブラックリスト(デフォルトで許可)を示す。
IEndpointCore
基盤となるノートステートマシンは以下を公開しなければならない。
interface IEndpointCore {
function cmxRoot() external view returns (bytes32);
function isValidAnchor(bytes32 root) external view returns (bool);
event NoteAdded(
bytes32 indexed cmx,
bytes encCiphertext,
bytes outCiphertext,
bytes32 epk,
bytes32 nfOld,
bytes32 cvNetX
);
event NoteConfirmed(bytes32 indexed cmx, bytes32 newRoot, uint256 position);
event BundleExecuted(uint256 valueBalance, uint256 amount, bytes32 recipientMeta);
}
cmxRoot(): 最新のコミットメントツリーのルート。ウォレットとインデクサーはイベントからツリーを再構築し、この値と比較することができる。isValidAnchor(root):rootがこのコントラクトのコミットメントツリーによって発行されたことがあるかどうか。ウォレットはトランザクションを送信する前にこれを呼び出して、証明アンカーを検証すべきである。
実装は以下をしなければならない。
- 内部のnullifierセットを介して二重使用を防ぐ。同じ
nfは二度使用されてはならない。NullifierメンバーシップはIEndpointCoreの公開ビュー関数として必須ではない。 isValidAnchorを介してクエリ可能な履歴ルートを持つ、追記専用のMerkleコミットメントツリーを維持する。- バインディング署名を介して値の保存を検証し、spend-auth署名を介して消費承認を検証する。バインディング署名検証は、状態変更(ツリー挿入、nullifierマーク、イベント発行)の前に完了しなければならない。
- 重複する
cmx(DuplicateCommitment)およびゼロコミットメントcmx == 0(ZeroCommitment)を拒否する。 - バインディング / spend-auth署名点
RがSNARK curveとペアリングされた署名曲線(参照実装はBaby JubJubを使用)上にあり、正規のフィールド座標(< Fr)を持つことを検証する。 - 各アクションの
pubFields[7] == IPERC20.cmxFrozenRoot()(コンプライアンスバインディング)を検証する。 - 空の
BundleAction[]配列を拒否し、コールあたりのアクション数に上限を設けるしなければならない(maxActions)。上限は有限で設定可能な正の整数でなければならない。証明検証のガスを予測可能に保つために、妥当な上限は10〜50の範囲である。
実装は、すべての特権的な設定変更(検証者ローテーション、管理者移譲、maxActions)に対してイベントを発行すべきである。管理者移譲は、ゼロアドレス禁止の2段階フロー(transferAdmin + acceptAdmin)を使用すべきである。
供給不変条件
totalSupply会計を持つアセットコントラクト(例: PERC20)は、値の変更を制御されたmint / burn / transferを通じてのみ公開しなければならない。コア実行パス(例: _executeBundle)は公開呼び出し可能であってはならない。そうでない場合、誰でもtotalSupplyを増やさずに未計上の値を注入できてしまう。
NoteAddedはoutCiphertext(80バイトの送信者自己回復暗号文)とcvNetX(= pubFields[1])を運ばなければならない。これにより、送信ビューイングキー (OVK) を持つウォレットは、calldataを解析せずにログから送信済みノートをスキャンできる。
値残高エンコーディング
valueBalance (uint256) の符号ビットエンコーディングは以下に従わなければならない。
| 操作 | エンコーディング | バインディングスカラー |
|---|---|---|
| transfer | 0 | 0 (保存) |
| burn | bit255 = 0, 下位ビット = v | v (+v 流出) |
| mint | bit255 = 1, 下位ビット = v | ℓ − v (−v 流入) |
理論的根拠
ノートモデルとERC-20セマンティクス
- アカウント残高ではなくUTXOモデルノート: アカウント活動パターンの漏洩を防ぐ。同種のノートはより強力な匿名化セットを提供する。
- バイナリ互換性のないEthereum Request for Comments (ERC)-20セマンティクス: 公開残高の欠如を正直に反映しつつ、エコシステムの認知コストを低減する。バイナリEthereum Request for Comments (ERC)-20互換性は残高の公開を強制し、設計目標と矛盾する。
- 公開
totalSupply: 高価なレンジ証明なしで「見えないインフレなし」を検証するための最小限の透明性トレードオフ。 - ミントはダミー入力(
v=0)を使用し、バーン/送金と同じ検証パスを共有: ミントの純流入セマンティクスを維持しつつ、単一のアクション検証フローを維持する。回路の増分は単一の追加公開入力rt_frozenに収束する。
SaplingではなくOrchard
Orchardが選ばれたのは、そのアクション回路が単一の証明内で任意の数の入力と出力を柔軟にサポートするためである。pERC20バンドルは、複数の消費と出力を1つのトランザクションに結合できる。Saplingの固定された1入力/2出力のアクション形状では、人工的な分割、高いリレーヤーコスト、およびマルチノート送金におけるUXの低下を強いられるだろう。
Halo2 / PLONKではなくGroth16
EVMにおけるGroth16 proofsの検証コストは、同等のセキュリティレベルで一般的なHalo2またはPLONK検証者よりも低い。ペアリングベースのGroth16 proofsチェッカーはオンチェーンでよく理解されている。VKサイズと検証者バイトコードは、アクションごとのガスを予測可能に保ちつつ、アセットごとのデプロイメントにとって実用的である。
回路内のコンプライアンスルート (cmxFrozenRoot)
コンプライアンスブラックリストは、cmxFrozenRootをルートとする**cmx(ノートコミットメント)のセットである。ユーザーが消費する際、オンチェーンアクションは消費されたノートのcmxではなく、nfOld(nullifier)を公開する。オンチェーンでは、nfからcmxへの直接的でプライバシーを保護するマッピングは存在しない**ため、コントラクトはプライバシーを侵害することなく「このnullifierは凍結されたコミットメントに紐付けられているか?」を安価にチェックできない。
したがって、制約は回路内で強制される。証明者は、消費されたノートのコミットメントがpubFields[7] == cmxFrozenRoot()をルートとするブラックリストSMTのメンバーではないことを示す。チェーンはSMTルートのみを保存およびバインドし、メンバーシップロジックはZK内に留まる。これは明示的なトレードオフである。コンプライアンスは識別された特定のノートに対して厳密に保証されるが、回路とcmxFrozenRootを更新する管理者を信頼する必要がある。
エコシステム統合 (非規範的)
このセクションは情報提供を目的としており、追加のプロトコル要件を導入するものではない。
pERC20は、より広範なプライバシー送金インフラストラクチャを補完することを意図している。考えられるエコシステムパスの1つは次のとおりである。
- 既存の公開アセット(DeFi関連アセットを含む)は、EIP(Ethereum 改善提案)-8182などのインフラストラクチャを通じてプライベート送金パスを獲得する。
- プライバシーネイティブなアセットとノートが、新しいアプリケーション設計の第一級のプリミティブとなる。
- プライバシーを周辺的なラッパーとして扱うのではなく、プライバシーネイティブな状態に直接基づいて新しいプロトコルカテゴリが構築される(例えば、プライバシー保護型取引所、貸付、または構造化決済フロー)。
この提案は、ブリッジ構築、リレーヤー経済学、プライベートメムプール/ネットワークの仮定、またはプライベートオラクル設計を標準化するものではない。その範囲は、プライバシーネイティブな代替可能アセットのトークンインターフェースのセマンティクスと不変条件に限定される。
後方互換性
pERC20はEthereum Request for Comments (ERC)-20のbalanceOf、approve、allowance、またはtransferFrom(from, to, amount)を実装しないため、既存のEthereum Request for Comments (ERC)-20ツールで直接使用することはできない。
| Ethereum Request for Comments (ERC)-20 | pERC20 | 注記 |
|---|---|---|
| name / symbol / decimals | 同じ | 公開メタデータ |
| totalSupply | totalSupply | 公開 |
| balanceOf(addr) | なし | 残高はプライベート。保有者はIVK/FVKを介してスキャン |
| transfer(to, amount) → bool | transfer(PrivacyCall) → bool | 当事者と金額はプライベート。戻り値の規約は維持 |
| transferFrom / approve / allowance | なし | 承認する公開残高なし。ビューイングキーを介した委任 |
| mint (拡張) | mint(amount, PrivacyCall) | 発行者のみ |
| burn (拡張) | burn(amount, PrivacyCall) | 任意の保有者 |
| Transfer / Approval イベント | Transferは省略。ノートごとはNoteAdded / NoteConfirmedを介して。供給量はMint / Burnを介して | IDはリンク不可 |
公開DeFiとの相互運用性は、オプションのbridgeOut(pERC20 → 公開Ethereum Request for Comments (ERC)-20ツイン)を介して達成されることができる。この場合、プライバシーは出口で終了する(この標準では必須ではない)。
参照実装
参照実装はpERC20_リポジトリで利用可能。
contracts/ptoken/PERC20.sol— 規範的なアセットコントラクト(IPERC20参照)
PERC20はOrchardVerifier(IEndpointCore)を継承し、完全な参照実装からのGroth16検証者、Merkleコミットメントツリー、および暗号ライブラリに依存する。
セキュリティに関する考慮事項
- 二重使用保護: nullifierセットと回路内の正しい
nf導出に依存する。一度nullifierが使用済みとマークされると、ノートは再度使用可能であってはならない。pubFieldsのフィールド範囲チェック(< Fr)は二重使用保護の前提条件である。そうでない場合、nf + Frは同じ証明を再利用できるが、nullifierセットを迂回する(上記のデータ構造を参照)。 - 供給不変条件:
totalSupply会計を持つアセットコントラクトは、値の変更をmint/burn/transferを通じてのみ公開しなければならない。コア実行パスは公開呼び出し可能であってはならない。そうでない場合、誰でもtotalSupplyを増やさずに未計上の値を注入できてしまう。 - 値の保存: バインディング署名とNUMSジェネレーター(
log_{G_RANDOM}(G_VALUE)は不明)に依存する。amountとvalueBalanceの一貫性は、下位255ビットを比較することで強制される。署名点Rは曲線とフィールドの検証を受けなければならない。 - リプレイ保護: sighashドメイン分離は
chainId、コントラクトアドレス、およびすべてのnf/cmx値をバインドし、クロスチェーン、クロスコントラクト、クロスバンドルのリプレイを防ぐ。 - アンカーの有効性:
isValidAnchorは永続的なセットを使用するため、古い証明アンカーは有効なままだが、生成されたことのないルートの偽造を防がなければならない。 - コンプライアンス権限のリスク:
admin(発行者 / コンプライアンス担当者)はsetFrozenRootを介してノートを凍結できる。これは高価値の攻撃対象であり、信頼された役割である。マルチシグ / タイムロックを使用すべきである。FrozenRootUpdatedログは公開すべきである。デプロイメントでは、通常、コンプライアンスとアセット管理の両方を構築時に同じadminに割り当てる。分離が必要な実装は、adminを独立したコンプライアンスマルチシグに転送すべきである。 - 管理者権限:
setGroth16Verifier、transferAdmin+acceptAdmin、およびsetMaxActionsは検証ロジックとパラメータを変更できる。ガバナンスによって制約されるべきである(マルチシグ + タイムロック)。検証者をローテーションする際、新しい検証者のActionPubHashは回路と一致しなければならない。2段階の管理者移譲は偶発的なロックアウトを防ぐ。
プライバシーに関する考慮事項
- 受信者の匿名性: 操作はリレーヤーを介して送信すべきである。これにより、送信者のEOAが隠される。直接自己送信すると、EOAが操作にリンクされる。
- 金額の可視性:
mint/burnのamountとtotalSupplyは公開される。送金量はプライベートである。 - 匿名化セット: V1はアセットごとのプールを使用する。新しいアセットは匿名化セットが小さい。クロスアセットの共有匿名性(共有ツリー +
asset_id)は、回路の変更を必要とする将来の機能強化である。 - コンプライアンス vs. プライバシー:
cmxFrozenRootメカニズムは識別された特定のノートを凍結できるが、(a)cmxの特定には通常、ビューイングキーの開示またはオフチェーンのインテリジェンスが必要であり、(b) ターゲットノートが凍結前に送金された場合、値は新しいcmxに移動し、再識別が必要となる。強制的なコンプライアンスルートは明示的な設計選択である。実装は、トラストレス性を近似するためにcmxFrozenRoot == 0(空のブラックリスト = デフォルトで許可)を維持することができる。
8件の投稿 - 2名の参加者