You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Circomlib中简单MiMCSponge哈希断言失败问题排查

MiMCSponge哈希电路与JS计算结果不一致的排查方向

问题场景

我基于circom和circomlib搭建了一个MiMCSponge哈希电路,配置为2输入、220轮运算、1输出。在前端用circomlibjs计算哈希值后填入input.json,执行witness生成脚本时触发o===hasher.outs[0]断言失败。已确认电路和JS实现都使用220轮运算,求其他可能导致结果不一致的原因。

电路代码

template sponge_test() {
    signal input l;
    signal input r;
    signal input o;

    // instantiate - 2 inputs 220 rounds of hashing and 1 output
    component hasher = MiMCSponge(2, 220, 1);

    // signals in hasher
    hasher.ins[0] <== l;
    hasher.ins[1] <== r;

    // addition constant
    hasher.k <== 0;

    o === hasher.outs[0];

}

component main = sponge_test();

JS前端代码

import { buildMimcSponge } from 'circomlibjs';
    
function toHexString(byteArray) {
  return Array.from(byteArray, function(byte) {
    return ('0' + (byte & 0xFF).toString(16)).slice(-2);
  }).join('')
}

export async function getProof(message) {
  var hasher = await buildMimcSponge();
  var h = hasher.multiHash([BigInt("0x3"), BigInt("0x4")]);

  // returns byte array
  console.log(h);
  // back to hexstring
  console.log(toHexString(h));
}

input.json内容

{
    "l": "0x3",
    "r": "0x4",
    "o": "0x690f48aba976f2786371b7fa3e941df623e96329e0570dc610f59b7fcfa94723"
}

执行脚本

# Compile the circuit
circom ${CIRCUIT}.circom --r1cs --wasm --sym --c

# Generate the witness.wtns
node ${CIRCUIT}_js/generate_witness.js ${CIRCUIT}_js/${CIRCUIT}.wasm input.json ${CIRCUIT}_js/witness.wtns

可能的排查方向

1. MiMCSponge加法常量k不匹配

电路中明确设置hasher.k <== 0,但circomlibjs的buildMimcSponge默认使用预设加法常量(而非0)。两边k值不一致会导致每轮运算的中间结果全部偏差,最终哈希值必然不同。

验证方法:JS初始化hasher时手动指定k=0,与电路保持一致:

var hasher = await buildMimcSponge({ k: 0, nRounds: 220 });

2. 字节序转换错误

JS端multiHash返回的Uint8Array字节数组,你的toHexString直接按原顺序转十六进制,但circom中的信号数值以大端字节序存储,若Uint8Array是小端输出,会导致最终十六进制字符串顺序反转,哈希值错误。

验证方法:反转字节数组后再转十六进制:

function toHexString(byteArray) {
  return Array.from(byteArray.reverse(), function(byte) {
    return ('0' + (byte & 0xFF).toString(16)).slice(-2);
  }).join('')
}

或用Buffer简化处理:

console.log(Buffer.from(h).reverse().toString('hex'));

3. 版本不兼容问题

circom、circomlib、circomlibjs的版本差异可能导致MiMCSponge的实现细节(如轮常数生成、模运算逻辑)不一致。比如circom 3.x与2.x编译逻辑有变化,或circomlibjs新版本调整了默认参数。

验证方法:检查三方版本是否匹配:

  • 查看项目package.json中circomlibjs版本
  • 执行circom --version查看circom版本
  • 确保circomlib与circomlibjs版本适配

4. 输入/输出模运算差异

circom中的signal会自动模上电路使用的素数(如BabyJubJub素数21888242871839275222246405745257275088548364400416034343698204186575808495617),若JS端multiHash未做相同模运算,会导致结果偏差(虽当前输入值较小,但逻辑上仍需对齐)。

验证方法:JS端手动对输入做模素数处理:

const FIELD_PRIME = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
var h = hasher.multiHash([BigInt("0x3") % FIELD_PRIME, BigInt("0x4") % FIELD_PRIME]);

5. 输出取法不一致

电路取hasher.outs[0]作为结果,需确认JS端multiHash返回值是否对应该输出。部分场景下,multiHash可能返回多个输出的拼接结果,而非单个指定输出。

验证方法:查看circomlibjs中multiHash的实现,确认返回值为单个输出的字节数组,而非多输出组合。


内容的提问来源于stack exchange,提问作者TIZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 11:03:26