作者:@Toni Wahrst?tter 翻譯: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 val) { // Snarkjs assembly code for proof verification… // … }
// _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 specifiedLogicHolder = _pubSignals[1]; require(specifiedLogicHolder == logicHoldingAccountHash, “Not 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]; signal input pathIndices[levels]; component secretHasher = SecretHasher(); secretHasher.secret <== secret; component hasher = CommitmentHasher(); hasher.logicHoldingAddress <== logicHoldingAddress; hasher.secret <== secretHasher.hashedSecret; hasher.nonce <== nonce; hasher.logicHoldingAddressHash === logicHoldingAddressHash; component tree = MerkleTreeChecker(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 證明可以用于風險低于資產支出的行動。例如,一個好的起點可能是允許用戶發起“提款請求”。如果邏輯持有合約的所有者沒有提出異議,用戶可以在一段時間后最終確定該請求。
這樣,邏輯持有合約的所有者仍然可以進行干預,盡管是以破壞隱私的方式,以防出現意外情況。
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。