验证zkVerify是否支持worldId的零知识证明

从worldId的资料查看用的是SnarkJS的Groth16,而zkVerify也支持它,因此技术上应该是无缝支持的。
下面将进行验证worldId的proof信息是否可以提交至zkVerify。
tips:验证结果为:可以。

1. 接口约束

zkVerify的验证proofdata接口参数分别为vkey、proof和publicSignals。

2. 参数包装

需要在主网上找一条官方验证通过的交易去解析参数。示例采用的交易信息为https://polygonscan.com/tx/0x5b4faca67d37537575f34ffc9ca9d15cec2f9126b19cdc1c1375c895130a4eaf

2.1 Vkey

合约地址:https://vscode.blockscan.com/137/0xa6d85F3b3bE6Ff6DC52C3aaBe9A35d0ce252b79F

通过阅读代码VerificationKey memory vk = _getVerificationKey(30- 16);
找到对应的vkey信息如下:

{
  "protocol": "groth16",
  "curve": "bn128",
  "nPublic": 1,
  "vk_alpha_1": [
    "20491192805390485299153009773594534940189261866228447918068658471970481763042",
    "9383485363053290200918347156157836566562967994039712273449902621266178545958",
    "1"
  ],
  "vk_beta_2": [
    [
      "6375614351688725206403948262868962793625744043794305715222011528459656738731",
      "4252822878758300859123897981450591353533073413197771768651442665752259397132"
    ],
    [
      "10505242626370262277552901082094356697409835680220590971873171140371331206856",
      "21847035105528745403288232691147584728191162732299865338377159692350059136679"
    ],
    [
      "1",
      "0"
    ]
  ],
  "vk_gamma_2": [
    [
      "10857046999023057135944570762232829481370756359578518086990519993285655852781",
      "11559732032986387107991004021392285783925812861821192530917403151452391805634"
    ],
    [
      "8495653923123431417604973247489272438418190587263600148770280649306958101930",
      "4082367875863433681332203403145435568316851327593401208105741076214120093531"
    ],
    [
      "1",
      "0"
    ]
  ],
  "vk_delta_2": [
    [
      "15028154694713144242204861571552635520290993855826554325002991692907421516918",
      "10202326166286888893675634318107715186834588694714750762952081034135561546271"
    ],
    [
      "12766289885372833812620582632847872978085960777075662988932200910695848591357",
      "18486039841380105976272577521609866666900576498507352937328726490052296469859"
    ],
    [
      "1",
      "0"
    ]
  ],
  "IC": [
    [
      "1452272927738590248356371174422184656932731110936062990115610832462181634644",
      "3608050114233210789542189629343107890943266759827387991788718454179833288695",
      "1"
    ],
    [
      "14798240452388909327945424685903532333765637883272751382037716636327236955001",
      "10773894897711848209682368488916121016695006898681985691467605219098835500201",
      "1"
    ],
    [
      "17204267933132009093604099819536245144503489322639121825381131096467570698650",
      "7704298975420304156332734115679983371345754866278811368869074990486717531131",
      "1"
    ],
    [
      "8060465662017324080560848316478407038163145149983639907596180500095598669247",
      "20475082166427284188002500222093571716651248980245637602667562336751029856573",
      "1"
    ],
    [
      "7457566682692308112726332096733260585025339741083447785327706250123165087868",
      "11904519443874922292602150685069370036383697877657723976244907400392778002614",
      "1"
    ]
  ]
}

注:vk_alpha_1、vk_beta_2、vk_gamma_2的参数都一样,从vk_delta_2开始参数有改变。

2.2 Proof

同理根据上述的交易解析proof信息,包装后如下:

{
    "pi_a": ["13854976072665683512875694823770713602187820700695689350251461484190678622777", "18799557382530648175973455419041717287155809457433735733081423863845533167035", "1"],
    "pi_b": [
        ["21631033507770131063075234997873571580206312087443135082188407010890735573826","17284477071273727205307884885925514362528638567837502733476872336658245826667" ],
        ["21416090582919078253993061506868758708760849320693132617130552343228640816224","4331438738399797206841210679865661753887605911103646249109166935177875981680"],
        ["1", "0"]
    ],
    "pi_c": ["6963197242267745453228534041057111262015907874139826882645803706173800617723", "21228315632900969810255945810651892392785324416813648206706599893327301572674", "1"],
    "protocol": "groth16",
    "curve": "bn128"
}

2.3 PublicSignals

同理根据上述的交易解析inputs信息,包装后如下:

["3061226360032517472274638926888854265068926881234476762304931412247737246919","6728982073551526785722952266936853582119478438086215932478760190917718952680","37938388892362834151584770384290207919364301626797345218722464515205243407","327931312179528553812809153503804462984186837247941235923454264438475220876"]

注:publicSignals的顺序与上述交易的入参顺序不一样,需要与合约方法“verifyProof”里的vk.IC的构造逻辑保持一致。

3. 验证proof data

向zkVerify发起验证proof data的交易。示例的代码如下:

import { zkVerifySession, Library, CurveType, ZkVerifyEvents } from "zkverifyjs";

import dotenv from 'dotenv';
dotenv.config();

import fs from "fs";
const proof = JSON.parse(fs.readFileSync("./data/proof.json"));
const publicInputs = JSON.parse(fs.readFileSync("./data/public.json"));
const key = JSON.parse(fs.readFileSync("./data/main.groth16.vkey.json"));

async function main() {
    // Required code
    const session = await zkVerifySession.start().Volta().withAccount(process.env.SEED_PHRASE);

    let statement, aggregationId;

    session.subscribe([
        {
            event: ZkVerifyEvents.NewAggregationReceipt,
            callback: async (eventData) => {
                console.log("New aggregation receipt:", eventData);
                if (aggregationId == parseInt(eventData.data.aggregationId.replace(/,/g, ''))) {
                    let statementpath = await session.getAggregateStatementPath(
                        eventData.blockHash,
                        parseInt(eventData.data.domainId),
                        parseInt(eventData.data.aggregationId.replace(/,/g, '')),
                        statement
                    );
                    console.log("Statement path:", statementpath);
                    const statementproof = {
                        ...statementpath,
                        domainId: parseInt(eventData.data.domainId),
                        aggregationId: parseInt(eventData.data.aggregationId.replace(/,/g, '')),
                    };
                    fs.writeFileSync("aggregation.json", JSON.stringify(statementproof));
                }
            },
            options: { domainId: 0 },
        },
    ]);

    const { events } = await session.verify()
        .groth16({ library: Library.snarkjs, curve: CurveType.bn128 })
        .execute({
            proofData: {
                vk: key,
                proof: proof,
                publicSignals: publicInputs
            }, domainId: 0
        });

    events.on(ZkVerifyEvents.IncludedInBlock, (eventData) => {
        console.log("Included in block", eventData);
        aggregationId = eventData.aggregationId;
        statement = eventData.statement;
    })
}
main();

交易成功后的日志如下:

D:/Work/Research/zkVerify/proof-submission-worldID> node ./index.js
2025-06-17 10:27:31        API/INIT: RPC methods not decorated: chainHead_v1_body, chainHead_v1_call, chainHead_v1_continue, chainHead_v1_follow, chainHead_v1_header, chainHead_v1_stopOperation, chainHead_v1_storage, chainHead_v1_unfollow, chainHead_v1_unpin, chainSpec_v1_chainName, chainSpec_v1_genesisHash, chainSpec_v1_properties, ismp_queryChallengePeriod, ismp_queryChildTrieProof, ismp_queryConsensusState, ismp_queryEvents, ismp_queryEventsWithMetadata, ismp_queryRequests, ismp_queryResponses, ismp_queryStateMachineLatestHeight, ismp_queryStateMachineUpdateTime, ismp_queryStateProof, transactionWatch_v1_submitAndWatch, transactionWatch_v1_unwatch, transaction_v1_broadcast, transaction_v1_stop
Included in block {
  blockHash: '0x5619b52eb9b9bac6199520f42dcd333087580bd7da84db19979957a7766c37bf',
  status: 'inBlock',
  txHash: '0x2a2157ddbe5a5742b3fc2864c804324ad29a0f0871e1d075b3690812c2292bda',
  proofType: 'groth16',
  domainId: 0,
  aggregationId: 27507,
  statement: '0x97d53e32a3f539654455a9dac10a2a1823d004a057cb60f5455db6781f90eebf',
  extrinsicIndex: 3,
  feeInfo: {
    payer: 'xpfFJrquqVjbFTDpQVxfkZcsAxs56Jpkuo3WEotHV36sm3nS3',
    actualFee: '24468241160000000',
    tip: '0',
    paysFee: 'Yes'
  },
  weightInfo: { refTime: '4893646934', proofSize: '177995' },
  txClass: 'Normal'
}
New aggregation receipt: {
  event: 'newAggregationReceipt',
  blockHash: '0x85a383ab7f9df13bc8e06612dea035095440864aad828c790f4dc389b65aa449',
  data: {
    domainId: '0',
    aggregationId: '27,506',
    receipt: '0x73d3bf8085e6d851c7f00c618a824afca45f33941f15422a7d2402654d9df03d'
  },
  phase: { applyExtrinsic: 2 }
}
New aggregation receipt: {
  event: 'newAggregationReceipt',
  blockHash: '0x77a5a0a0640bd04bdd719781cd4efe92f035b91b1ccec4de6fc40e89fd0c75a1',
  data: {
    domainId: '0',
    aggregationId: '27,507',
    receipt: '0xfd7c070309aa730f83ef20b7580a5ae1e90341cad2390badb424cff923fdfb30'
  },
  phase: { applyExtrinsic: 2 }
}
Statement path: {
  root: '0xfd7c070309aa730f83ef20b7580a5ae1e90341cad2390badb424cff923fdfb30',
  proof: [
    '0x7b1eaacc3f921a3a3d00188b353a2b6021ea32bfac4599323f2f0aff642a8c3b',
    '0xf7ed833f00e43a1e7b6c5809810cc19fca218d0f7eaf0522b224c3f2cb967f54'
  ],
  numberOfLeaves: 4,
  leafIndex: 1,
  leaf: '0x97d53e32a3f539654455a9dac10a2a1823d004a057cb60f5455db6781f90eebf'
}
New aggregation receipt: {
  event: 'newAggregationReceipt',
  blockHash: '0x05eb5d39a3c2fd16fb18b68e9485e59c3abc167eb29879e3ad7dc21cd848315a',
  data: {
    domainId: '0',
    aggregationId: '27,508',
    receipt: '0x9c1d397094b6aa6a59e8d85f86c2206fa971707cba2f539529327672944329c5'
  },
  phase: { applyExtrinsic: 2 }
}

交易hash:https://zkverify-testnet.subscan.io/extrinsic/1141735-3

4. 注意点

  1. 包装时需要交换参数顺序
    带有["1", "0"]标识的参数,都需要根据zkverify的规则,将两个参数的位置进行互换。
  2. 交易失败是的异常处理
  • Error: settlementGroth16Pallet.InvalidVerificationKey: Provided an invalid verification key.
    答:注意参数vk_delta_2的顺序
  • Error: settlementGroth16Pallet.InvalidProofData: Provided data has not valid proof.
    答:注意参数pi_b的顺序
  • Error: settlementGroth16Pallet.InvalidInput: Provided data has not valid public inputs.
    答:注意“verifyProof”里的vk.IC的构造顺序

版权声明:
作者:ht
链接:https://www.techfm.club/p/217065.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>