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

如何在gnark中实现对可正负明文整数的>=0校验?

在Gnark中实现整数>=0的校验逻辑

由于Gnark仅处理无符号有限域整数,原明文负数会被模域阶p转换为p - |x|形式的大正数,无法直接用常规比较判断原数是否非负。同时api.Select的第一个参数必须是布尔变量(仅0或1),这是触发assertIsBoolean错误的原因。以下是适配Gnark的解决方案:

核心思路

域阶p是一个大奇数,原明文正数在无符号域中直接等于自身,且必然小于p/2;原明文负数模p后的值为p - |x|,必然大于p/2。因此可以通过判断变量与p/2的大小关系,反向推导原数是否非负。

具体实现代码

首先获取当前曲线的域阶并计算其一半:

import (
    "math/big"
    "github.com/consensys/gnark/frontend"
)

func YourCircuit(api frontend.API) error {
    // 定义变量(假设已声明val, postcheck, bitpostcheck为[10]frontend.Variable)
    val := [10]frontend.Variable{/* 初始化输入 */}
    var postcheck [10]frontend.Variable
    var bitpostcheck [10]frontend.Variable

    // 获取当前电路使用的有限域阶
    p := api.Compiler().Field().Params().Fr.Modulus()
    // 计算域阶的一半(p为奇数,直接整除2即可)
    pDiv2 := new(big.Int).Div(p, big.NewInt(2))
    pDiv2Var := frontend.Variable(pDiv2)

    for i := 0; i < 10; i++ {
        // api.Cmp(a, b)返回1当a >= b,返回0当a < b
        // 原正数在域中 < p/2,所以cmpResult为0;原负数模后 >= p/2,cmpResult为1
        cmpResult := api.Cmp(val[i], pDiv2Var)
        // 取反得到isNonNegative:1表示原数>=0,0表示原数<0
        isNonNegative := api.Sub(1, cmpResult)

        // 使用布尔变量作为Select的条件参数,符合Gnark要求
        postcheck[i] = api.Select(isNonNegative, val[i], frontend.Variable(0))
        // bitpostcheck直接复用isNonNegative即可,无需重复Select
        bitpostcheck[i] = isNonNegative
    }

    return nil
}

关键说明

  • 确保输入的原整数绝对值不超过p/2:这是该逻辑成立的前提,若原数绝对值超过p/2,负数模p后可能小于p/2,导致判断错误。ZK电路设计中通常会通过约束限制输入范围,避免这种情况。
  • isNonNegative是严格布尔变量:通过api.Sub(1, api.Cmp(...))得到的结果只能是0或1,完全符合api.Select对条件参数的要求,不会触发assertIsBoolean错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 02:22:34