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 证明可以用于风险低于资产支出的行动。例如,一个好的起点可能是允许用户发起“提款请求”。如果逻辑持有合约的所有者没有提出异议,用户可以在一段时间后最终确定该请求。 这样,逻辑持有合约的所有者仍然可以进行干预,尽管是以破坏隐私的方式,以防出现意外情况。 来源:金色财经lg...