定位电路不满足错误(UnSat)
第一步其实非常简单:在代码中捕获错误,并打印出reason字段——NovaError::UnSat { reason }这个结构体本身就带有可读性极强的失败归因,例如“constraint 47: a * b != c when a=0, b=5”。这种信息直接告诉你哪条约束被违反,比盲目调参高效十倍。
第二步,检查所有alloc_input调用是否与电路声明的变量数量严格一致。少一个inputize就会触发UnSat,多一个则会导致见证长度溢出。这类错误就像拼图缺少关键一块,系统会直接拒绝执行。
第三步,对边界值进行显式断言。例如在验证逻辑前插入assert!(x < 100),避免无符号整数回绕后违反约束条件。如果不这样做,reason字段只会显示“unsatisfied constraint”而无法定位具体是哪条约束。
修复证明验证失败(ProofVerifyError)
方法一:确认proof和vk使用同一套参数生成。如果使用NovaProver::new(circuit, params)生成proof,就必须用同一批params.verify_key()加载vk。混用不同批次的params会导致公钥校验直接拒绝,这个错误非常隐蔽,不易察觉。
方法二:检查proof序列化格式是否为bincode而非JSON。Nova底层验证器只接受紧凑二进制编码,传入JSON字符串会静默失败且不报具体错误码。许多开发者在这里栽了跟头,还误以为是算法问题。
【必须确保verify_key()调用发生在proof生成之后】——若提前缓存vk再生成proof,可能因参数缓存未刷新导致公钥与proof不匹配。这个顺序问题很容易被忽略,但恰恰是导致ProofVerifyError的高频原因。
处理输入与见证长度错误
遇到InvalidInputLength错误时,立即核对circuit.input_size()返回值与实际传入input数组长度,二者必须完全相等。差1都会触发校验拦截,而且报错信息往往很模糊,难以定位。
InvalidWitnessLength错误则需回溯到见证生成阶段。使用Circuit::synthesize生成witness后,必须用witness.len()对比circuit.witness_size(),不等说明alloc_cell或constrain_equal调用漏写或重复。这一步操作很简单,直接打印出witness数组长度就能快速定位问题。
