原文作者:@Toni Wahrstätter
發布日期:2023 年9月12日
譯:DeBox研究院
前言
Vitalik 建議使用zk-SNARKs 將交易邏輯帳戶與持有資產的帳戶分開。這樣可以改善隱私,使用者體驗和一鍵式社交恢復。以太坊研究員Toni Wahrstätter 對此錢包原型進行詳細解析,涵蓋工作流程和優勢。
非常感謝Matt就該主題進行了精彩的討論,並開發了這個工具來解析每個合約並將其放入稀疏的Merkle 樹中,該樹無需在patricia 樹上進行zk 證明,從而簡化了原型設計。另外,感謝Vitalik的大力投入。
由於多種原因,管理多個帳戶可能具有挑戰性,包括社交恢復、隱私、L2 和整體使用者體驗問題。使用隱形位址會使事情變得更加複雜,因為每次互動都需要一個新帳戶。 Vitalik建議使用zk-SNARKs 將交易邏輯帳戶與持有資產的帳戶分開。這可以改善隱私、使用者體驗和一鍵社交恢復。
對於以下內容,建議先查看Vitalik 的「三個轉變」貼文以了解一些背景知識。
簡而言之,我們試圖實現的目標是:
在不損害隱私的情況下一站式社交恢復。
一、傳統的方法
一個簡單但會損害隱私的實作如下:
- 使用者向資產持有帳戶提供簽名和一些意圖/命令。
- 資產持有帳戶將簽名轉發給邏輯持有帳戶。
- 邏輯持有帳戶從簽章中匯出公鑰,並將其與它儲存的公鑰進行比較。
- 如果驗證通過,邏輯帳戶將通知資產持有帳戶繼續操作。
- 資產持有帳戶執行用戶的命令。
缺點是,這將邏輯帳戶和資產持有帳戶公開聯繫起來,從而損害了隱私。
二、使用ZK-SNARK
透過使用zk-SNARK,用戶可以證明他們有權支出,而無需透露邏輯持有帳戶和資產持有帳戶之間的聯繫。
工作流程如下圖所示:
1. 使用者在本地建造一棵Merkle 樹並識別包含其合約的葉子。
1.1. Merkle 樹基本上包含按日期或名稱排序的每個現有合約的slot0 和slot1 值。
1.2. 每個使用者都可以根據最近的狀態在本地建立Merkle 樹。
2. 使用者建構一個zk 證明,證明知道邏輯持有帳戶中的秘密。稍後再詳細證明。
3. 用戶將zk-proof 發送到資產持有帳戶。
4. 資產持有帳戶驗證證明,確認以下內容:
4.1使用者知道邏輯在哪裡。
4.2 使用者知道一個秘密值,在雜湊後對應到儲存在邏輯持有帳戶中的值。
4.3使用者可以重建在規範鏈中維護的帳戶狀態默克爾樹根(例如預編譯)
4.4使用正確的隨機數(用於切換邏輯持有帳戶中的金鑰)。
本質上,用戶可以說:“我擁有邏輯持有帳戶的可證明的權限來執行此操作,並且我知道該邏輯帳戶的位置。”
優點
- 使用者體驗:一個私鑰或一個多重簽名設定可以控制多個帳戶,即使它們位於不同的L2 上。
- 恢復:透過一次合約更新可以更輕鬆地恢復帳戶。
- 隱私:各個帳戶之間沒有公共連結。
- 相容性:這有助於普及帳戶抽象化(AA)錢包和其他功能。
此外,透過在邏輯和資產持有合約之間添加另一個(聚合器)合約,可以在一次交易中提供不同資產持有帳戶的多個證明,從而幾乎可以像UTXO 一樣對待帳戶。聚合器將能夠取得多個zk 證明並將其轉發到各自的資產持有帳戶進行驗證。當然,這樣的聚合器可以在各個資產持有帳戶之間建立連結——包括隱私。
值得注意的是,使用SNARK(因此依賴其安全性)和完全不使用SNARK(因此錯過了良好的隱私屬性)之間不一定是二選一。一種折中方案可以是使用SNARK 證明在邏輯持有合約中打開一個時間窗口,然後短暫延遲,之後邏輯持有合約的所有者可以更改slot0 值,而不是要求SNARK 證明來進行支出,從而改變消費邏輯。合約的目前擁有者可以使用時間視窗開啟先前的延遲來阻止憑證更新。
技術細節
zk-SNARK 設定包含私有元素:
- 用於驗證的金鑰。
- 邏輯持有帳戶地址為資產持有帳戶所指向的地址。
- Merkle 分支來辨識特定的狀態值。
- 允許密鑰輪換同時使舊密鑰無效的隨機數。明文邏輯持有合約地址和秘密等私有元素不公開,而是用於私下連結邏輯持有帳戶和資產持有帳戶。透過產生整個狀態的證明,不需要中央機構來建立梅克爾樹來提交證明。
1.邏輯持有帳戶
邏輯持有帳戶的原型可能如下所示:
pragma solidity >=0.7.0 <0.9.0;
contract LogicHoldingAccount is Ownable { uint256 public slot0 = 0x1234; // hashed secret uint256 public nonce = 0; // keep track of key changes address public owner;
function updateOwner(uint256 newValue) public onlyOwner { nonce += 1; slot0 = newValue; }}
- slot0:最初保存雜湊值的公共變數。只有所有者知道哈希的原像。
- nonce:追蹤所有者資訊更新次數的計數器。這確保舊密鑰變得無效。
- updateOwner(uint256 newValue):更新值並增加隨機數的函數。
該合約追蹤所有者目前的支出邏輯(slot0) 並允許透過該updateOwner函數進行更新。
2、帳戶持有帳戶
pragma solidity >=0.7.0 <0.9.0;
contract AssetHoldingAccount { uint256 public logicHoldingAccountHash = 1234...;
// Scalar field size, Base field size, Verification Key data, etc. // ...
function verifyProof( uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[2] calldata _pubSignals) public view returns (bool valific) { Snarkjs assemation ... // ... }
// _pubSignals[0] - the root of the contract-slot0||nonce Merkle tree // _pubSignals[1] - the hased logic-holder address function execute( address payable to, uint256 amount, uint[2] calldata _pA, uint [2][2] calldata _pB, uint[2] calldata _pC, uint[2] calldata _pubSignals) public { contractRootPrecompile.getRoot(block.number) uint256 specLogicHolder = _pubSignals[1]; require(wint256 specLogicHolder = _pubSignals[1]; require(spectiveicHolder allowed");
bool validProof = verifyProof(_pA, _pB, _pC, _pubSignals) == true; if (validProof) { (bool success,) = to.call{value:amount}(""); require(success); } } }
receive() external payable {}}
資產持有帳戶儲存ETH等資產,並允許用戶提交提款證明。透過驗證是否specifiedLogicHolder匹配logicHoldingAccountHash,所有者可以確保資產持有合約僅接受來自授權邏輯持有合約的證明,而不是任何任意合約。
在構造證明時作為私人訊號提供的秘密確保只有包含支出邏輯的帳戶的所有者才能從資產持有帳戶存取資金。
3、電路
以下電路是使用circom開發的,完整的程式碼可以在這裡找到。
pragma circom 2.0.2;
include "./modules/merkleTree.circom";include "./modules/commitmentHasher.circom";
template Main(levels) { signal input root; signal input logicHoldingAddressHash; signal input logicHoldingAddress; signal input secret; signal input nonce; signal input pathElements[levels]; <== secret; component hasher = CommitmentHasher(); hasher.logicHoldingAddress <== logicHoldingAddress; hasher.secret <== secretHasher.hashedSecret; hasher.nonce <== nonce; (levels); tree.leaf <== hasher.commitment; tree.root <== root; for (var i = 0; i < levels; i++) { tree.pathElements[i] <== pathElements[i]; tree.pathIndices[i] <== pathIndices[i]; }}
component main {public [root,logicHoldingAddressHash]} = Main(N);
該電路共有7 個訊號,其中2 個是公開的,即Merkle 樹根和邏輯持有帳戶的雜湊地址(在編碼到資產持有合約之前必須進行雜湊處理,以防止觀察者對帳戶進行聚類別)基於相同的邏輯持有者帳戶)。
結論
在使用者必須管理多個帳戶的世界中,對一站式社交恢復功能的需求變得越來越重要。 Zk-SNARK 可用於實現邏輯/資產分離的錢包,使用戶能夠使用帳戶A 的「邏輯」從帳戶B 進行支出,而無需在兩者之間建立連結。作為第一步,SNARK 證明可以用於風險低於資產支出的行動。例如,一個好的起點可能是允許使用者發起「提款請求」。如果邏輯持有合約的所有者沒有提出異議,用戶可以在一段時間後最終確定該請求。
這樣,邏輯持有合約的所有者仍然可以進行幹預,儘管是以破壞隱私的方式,以防出現意外情況。