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

Circom实现新加坡NRIC校验器遇非二次约束错误求解决方案

新加坡NRIC校验Circom电路错误解决方法

问题描述

我需要用Circom编写新加坡NRIC的校验电路,NRIC的结构与校验规则如下:

NRIC结构

  • 前缀:枚举值为S、T、G、F、M
  • 后缀:单个校验字母
  • 中间7位数字

校验步骤

  1. 将7位数字依次乘以权重[2,7,6,5,4,3,2],计算乘积之和
  2. 若前缀为T或G,总和加4
  3. 将总和对11取余,得到0-10之间的余数
  4. 根据前缀分组映射余数到对应字母:
    • S/T/M组:余数0→J、1→Z、2→I、3→H、4→G、5→F、6→E、7→D、8→C、9→B、10→A
    • F/G组:余数0→X、1→W、2→U、3→T、4→R、5→Q、6→P、7→N、8→M、9→L、10→K
  5. 映射结果与后缀匹配则校验通过

编写的Circom代码及编译错误如下:

pragma circom 2.1.5;

template NRICValidator() {
  signal input prefix; // 1 or 2
  signal input suffix; // 3 or 4
  signal input digits[7];
  var sumWithOffset;
  var weights[5] = [2, 7, 6, 5, 4, 3, 2];
  var checkDigits[11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  var offset = 4;

  var weightedSum = digits[0]*weights[0] + digits[1]*weights[1] + digits[2]*weights[2] + digits[3]*weights[3] + digits[4]*weights[4] + digits[5]*weights[5] + digits[6]*weights[6];
  if (prefix == 1 && prefix == 2) { // T or G
    var sumWithOffset = weightedSum + offset;
  } else {
    var sumWithOffset = weightedSum; // S or F
  }
  
  signal output valid;
  sumWithOffset %= 11; // <=== a number between 0 to 10
  valid <== (checkDigits[sumWithOffset] == suffix); // <=== Error: Non-quadratic constraint was detected statically, using unknown index will cause the constraint to be non-quadratic
}

component main = NRICValidator();

编译错误:

error[T20462]: Typing error found
   ┌─ "main.circom":21:14
   │
21 │   valid <== (checkDigits[sumWithOffset] == suffix); // <=== Error: Non-quadratic constraint was detected statically, using unknown index will cause the constraint to be non-quadratic
   │              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Non-quadratic constraint was detected statically, using unknown index will cause the constraint to be non-quadratic

previous errors were found

错误原因

  1. 非二次约束问题:Circom仅支持二次及以下的算术约束,用动态计算的sumWithOffset(编译时未知值)作为数组索引属于非线性操作,违反约束规则。
  2. 逻辑错误:原代码中prefix ==1 && prefix ==2永远为假,应该用||判断前缀是否属于T/G组。
  3. 变量类型错误:weightedSum和sumWithOffset用var定义会被视为编译期常量,但实际依赖输入信号,需要改为signal类型存储。

解决方案

将动态数组索引的操作转化为遍历所有可能余数的条件约束,确保所有逻辑都符合Circom的二次约束要求,同时修正逻辑错误:

修正后的代码

pragma circom 2.1.5;

template NRICValidator() {
  // 前缀编码规则:
  // 1=S, 2=T, 3=F, 4=G, 5=M
  signal input prefix;
  // 后缀编码:按对应组的映射转为数字(如S/T组J=0、Z=1...A=10;F/G组X=0...K=10)
  signal input suffix;
  signal input digits[7];
  
  var weights[7] = [2, 7, 6, 5, 4, 3, 2];
  var offset = 4;

  // 计算加权和(用signal存储,依赖输入信号的计算不能用var)
  signal weightedSum;
  weightedSum <== digits[0]*weights[0] + digits[1]*weights[1] + digits[2]*weights[2] + 
                  digits[3]*weights[3] + digits[4]*weights[4] + digits[5]*weights[5] + digits[6]*weights[6];

  // 计算加偏移后的总和:前缀为T(2)或G(4)时加4
  signal sumWithOffset;
  sumWithOffset <== weightedSum + ((prefix == 2 || prefix == 4) ? offset : 0);

  // 计算余数并约束范围在0-10之间
  signal remainder;
  remainder <== sumWithOffset - 11 * floor(sumWithOffset / 11);
  // 额外约束确保余数是0-10中的一个值
  signal remRangeCheck;
  remRangeCheck <== remainder * (remainder-1)*(remainder-2)*(remainder-3)*(remainder-4)*
                    (remainder-5)*(remainder-6)*(remainder-7)*(remainder-8)*(remainder-9)*(remainder-10);
  remRangeCheck === 0;

  // 定义两组余数到后缀编码的映射
  var mapST[11] = [0,1,2,3,4,5,6,7,8,9,10]; // S/T/M组:J,Z,I,H,G,F,E,D,C,B,A
  var mapFG[11] = [0,1,2,3,4,5,6,7,8,9,10]; // F/G组:X,W,U,T,R,Q,P,N,M,L,K

  signal output valid;
  valid <== 0;

  // 遍历所有可能的余数,验证后缀是否匹配对应组的映射
  for (var i=0; i<11; i++) {
    // 当余数为i时,检查前缀组和后缀是否匹配
    var matchST = (remainder == i) && (prefix ==1 || prefix ==2 || prefix ==5) && (suffix == mapST[i]);
    var matchFG = (remainder == i) && (prefix ==3 || prefix ==4) && (suffix == mapFG[i]);
    valid <== valid + matchST + matchFG;
  }

  // 确保valid只能是0或1(避免多个条件同时满足的异常情况)
  valid * (valid - 1) === 0;
}

component main = NRICValidator();

关键修正点

  • 将依赖输入信号的计算从var改为signal,确保符合Circom的信号约束规则。
  • 用遍历+条件判断替代动态数组索引,所有条件均为二次约束,符合Circom要求。
  • 增加余数范围约束,确保余数只能是0-10之间的整数。
  • 修正前缀判断逻辑,正确区分需要加偏移的分组。
  • 最后约束valid只能为0或1,避免出现无效值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:15:31