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

如何使用ark-circom Rust库传入数组类型输入信号?

在ark-circom中传入数组类型输入信号的问题

我需要用基于Rust的ark-circom库传入数组类型的输入信号,但文档里只有简单输入变量的示例,也没找到相关线上资源。多次尝试后确定问题出在数组in的传入方式上,求指导如何在ark-circom中使用数组。


复现错误的Circom代码

pragma circom 2.1.5;

include "node_modules/circomlib/circuits/poseidon.circom";

template Main() {
    component poseidon = Poseidon(2);
    signal input in[2];
    // signal input in1;
    signal output digest;
    poseidon.inputs[0] <== in[0];
    poseidon.inputs[1] <== in[1];
    digest <== poseidon.out;
}

component main = Main();

无法生成证明的Rust程序

fn main() {
    let current_dir = env::current_dir().unwrap();
    let main_js_path = current_dir.join("circuits/main_js/main.wasm");
    let main_r1cs_path = current_dir.join("circuits/main.r1cs");

    let cfg = CircomConfig::<Bn254>::new(main_js_path, main_r1cs_path).unwrap();

    let vec = vec![1, 2]; // Your vector of integers
    let s: String = vec.iter().map(|i| i.to_string()).collect();
    let big_int = BigInt::parse_bytes(s.as_bytes(), 10).unwrap();

    let mut builder = CircomBuilder::new(cfg);
    builder.push_input("in", big_int);
    let circom = builder.setup();

    let mut rng = rand::thread_rng();
    let params =
        Groth16::<Bn254>::generate_random_parameters_with_reduction(circom, &mut rng).unwrap();
    let circom = builder.build().unwrap();
    let inputs = circom.get_public_inputs().unwrap();
    let proof = Groth16::<Bn254>::prove(&params, circom, &mut rng).unwrap();

    // Check that the proof is valid
    let pvk = Groth16::<Bn254>::process_vk(&params.vk).unwrap();
    let verified = Groth16::<Bn254>::verify_with_processed_vk(&pvk, &inputs, &proof).unwrap();
    println!("Verified: {:?}", verified);
    println!("Inputs: {}", inputs[0]);

    assert!(verified);
}

错误日志

wasm path "/Users/root/Documents/cryptography/groth16_sui_rs/circuits/main_js/main.wasm" r1cs path "/Users/root/Documents/cryptography/groth16_sui_rs/circuits/main_js/main.wasm" Constraint trace requires enabling `ConstraintLayer` Constraint trace requires enabling `ConstraintLayer` Unsatisfied constraint: Some("0") thread 'main' panicked at /Users/root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ark-circom-0.1.0/src/circom/builder.rs:82:9: assertion failed: {
    use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem};
    let cs = ConstraintSystem::<E::ScalarField>::new_ref();
    circom.clone().generate_constraints(cs.clone()).unwrap();
    let is_satisfied = cs.is_satisfied().unwrap();
    if !is_satisfied {
            println!("Unsatisfied constraint: {:?}",
            cs.which_is_unsatisfied().unwrap());
        }
    is_satisfied } stack backtrace:    0: rust_begin_unwind
             at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:647:5 1: core::panicking::panic_fmt
             at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/panicking.rs:72:14 2: core::panicking::panic
             at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/panicking.rs:144:5 3: ark_circom::circom::builder::CircomBuilder<E>::build
             at /Users/root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ark-circom-0.1.0/src/circom/builder.rs:82:9 4: groth16_sui_rs::main
             at ./src/main.rs:49:18    5: core::ops::function::FnOnce::call_once
             at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/ops/function.rs:250:5 note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

解决方案

你的错误在于把数组元素拼接成单个大整数传入,这不符合ark-circom对数组输入的处理逻辑。正确的做法是为数组的每个索引单独指定输入:

修改后的Rust代码:

fn main() {
    use ark_bn254::Bn254;
    use ark_circom::{CircomBuilder, CircomConfig};
    use ark_groth16::Groth16;
    use num_bigint::BigInt;
    use std::env;
    use rand;

    let current_dir = env::current_dir().unwrap();
    let main_js_path = current_dir.join("circuits/main_js/main.wasm");
    let main_r1cs_path = current_dir.join("circuits/main.r1cs");

    let cfg = CircomConfig::<Bn254>::new(main_js_path, main_r1cs_path).unwrap();

    let vec = vec![1, 2];

    let mut builder = CircomBuilder::new(cfg);
    // 为数组的每个索引单独传入值
    builder.push_input("in[0]", BigInt::from(vec[0]));
    builder.push_input("in[1]", BigInt::from(vec[1]));
    
    let circom = builder.setup();

    let mut rng = rand::thread_rng();
    let params = Groth16::<Bn254>::generate_random_parameters_with_reduction(circom, &mut rng).unwrap();
    let circom = builder.build().unwrap();
    
    let inputs = circom.get_public_inputs().unwrap();
    let proof = Groth16::<Bn254>::prove(&params, circom, &mut rng).unwrap();

    // 验证证明有效性
    let pvk = Groth16::<Bn254>::process_vk(&params.vk).unwrap();
    let verified = Groth16::<Bn254>::verify_with_processed_vk(&pvk, &inputs, &proof).unwrap();
    
    println!("Verified: {:?}", verified);
    println!("Inputs: {:?}", inputs);

    assert!(verified);
}

关键说明

  • ark-circom处理数组输入时,需要通过数组名[索引]的形式逐个传入元素,而不是将数组拼接成单个值。
  • 确保每个数组元素的类型符合要求(这里用BigInt对应Circom的信号类型)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:12:16