4个版本
0.1.3 | 2023年3月30日 |
---|---|
0.1.2 | 2023年3月24日 |
0.1.1 | 2023年3月3日 |
0.1.0 | 2023年2月10日 |
27 在 #relation
1,012 每月下载次数
在 liminal-ark-relations 中使用
39KB
632 行
liminal-ark-relation-macro
该软件包提供了用于简洁定义SNARK关系的 snark_relation
进程宏。给定最小关系定义,此宏将生成创建和转换部分关系对象、公共输入序列化和电路生成的所有必需代码。
一般用法
#[snark_relation]
属性适用于模块。此类模块必须定义两个项目
- 关系对象:所有常量、公共和私有关系数据的集合。该结构必须使用
#[relation_object_definition]
属性定义。所有其他属性都将保留。 - 电路定义:电路形式。必须使用
#[circuit_definition]
属性来定义功能。签名可以是任意的:函数体将在ark_relations::r1cs::ConstraintSynthesizer
特质实现中使用。所有功能属性(如功能门控或linting)都保留,并在impl
级别添加。
提供这些输入后,宏将生成以下项目(在模块外部)。
- 三个新的公共结构体:
<R>WithoutInput
、<R>WithPublicInput
和<R>WithFullInput
,其中<R>
是关系对象结构的名称。第一个将只有常量作为其字段,第二个将另外包含公共输入,最后一个将包含所有数据。 - 每个结构体的
new(..)
构造函数。重要:构造函数参数的顺序是:所有常量,然后是公共输入,最后是私有输入。每个组中的顺序从关系对象定义继承。 - 字段的获取器。对于常量,签名是
fn <field>(&self) -> &<field_type>
。对于公共和私有输入,签名是fn <field>(&self) -> Result<&<field_type>, SynthesisError>
。所有结构体都有相同的获取器集合。当字段缺失时,返回SynthesisError::MissingAssignment
。 - 从
<R>WithFullInput
到<R>WithPublicInput
和从<R>WithPublicInput
到<R>WithoutInput
的转换。 - 为
<R>WithPublicInput
提供serialize_public_input(&self)
方法。 - 为
<R>WithoutInput
实现ConstraintSynthesizer
特质(带设置模式检查)。 - 为
<R>WithFullInput
实现ConstraintSynthesizer
特质。
#[snark_relation]
mod relation {
#[relation_object_definition]
struct SomeRelation {
#[constant]
a: CF,
#[public_input]
b: CF,
#[private_input]
c: CF,
}
#[circuit_definition]
fn generate_circuit() -> ark_relations::r1cs::Result<()> {
Ok(())
}
}
模块中存在的所有导入(use
项)将被复制并移至外部(与生成项一起)。
字段属性
字段可以具有额外的修饰符。常量和私有输入可以增强为
- 前端类型(例如:
#[private_input(frontend_type = "u32")]
)-这指定了构造函数中应该期望的类型。然后将从前端值创建项目类型(后端类型),并在以后使用。 - 前端值解析器(例如:
#[private_input(frontend_type = "u32", parse_with = "u32_to_CF")]
)-这是用于将前端值转换为构造函数中的后端类型的方法。除非指定,否则将使用.into()
。它不能在没有frontend_type
的情况下使用。
公共输入可以有一个额外的修饰符
- 序列化器(例如:
#[public_input(serialize_with = "flatten_sequence")]
)-序列化过程应产生Vec<CF>
(其中CF
是电路字段类型)。默认情况下,每个公共输入都将首先封装成一个单例向量(vec![input]
),然后,按顺序的结果将使用.concat()
进行展开。如果你的输入需要其他方式来适应(通常是展开),你可以传递你自定义的序列化器。
修饰符中的所有值(函数名称、类型)都必须以字符串字面量(在 ""
内)传递。
use ark_std::{One, Zero};
use snark_relation_proc_macro::snark_relation;
use crate::CircuitField;
fn parse_u16(x: u16) -> CircuitField {
CircuitField::from(x)
}
fn byte_to_bits<F: Zero + One + Copy>(byte: &u8) -> Vec<F> {
let mut bits = [F::zero(); 8];
for (idx, bit) in bits.iter_mut().enumerate() {
if (byte >> idx) & 1 == 1 {
*bit = F::one();
}
}
bits.to_vec()
}
#[snark_relation]
mod relation {
#[relation_object_definition]
struct SomeRelation {
#[constant]
a: u8,
#[public_input(frontend_type = "u16", parse_with = "parse_u16")]
b: CF,
#[private_input(frontend_type = "u32")]
c: u64,
#[public_input(serialize_with = "byte_to_bits")]
d: u8,
}
#[circuit_definition]
fn generate_circuit() -> ark_relations::r1cs::Result<()> {
Ok(())
}
}
依赖项
~2MB
~42K SLoC