#circuit #input #axiom #compute #struct #sdk #traits

nightly axiom-sdk

用于编写 Axiom 计算电路的用户友好型 API

2 个版本

0.1.1 2024 年 3 月 20 日
0.1.0 2024 年 2 月 15 日
0.0.1 2024 年 2 月 14 日

#10 in #axiom

MIT 许可证

165KB
4K SLoC

axiom-sdk

用法

查看 ./examples/account_age.rs 以获取示例 Axiom 计算电路。要运行 account_age 电路

cargo run --example account_age -- --input data/account_age_input.json -k 12 -p <PROVIDER_URI> <CMD>

其中 PROVIDER_URI 是一个 JSON-RPC URL,而 CMDmockprovekeygenrun


lib.rs:

axiom-sdk

安装

要将我们的 Rust 电路 SDK 安装到 Cargo 项目中,请运行

cargo add axiom-sdk

概述

要使用 Rust SDK 实现 Axiom 电路,您需要

  • 指定一个由本地 Rust 类型以及 ethers-rs 类型(例如 u64AddressH256 等)组成的输入结构。结构名必须以 Input 结尾(例如 MyCircuitInput)。
  • 在您的输入结构上实现 AxiomComputeFn 特性

输入规范

您的输入结构可以包含原生Rust类型(例如 u64[usize; N] 等)和 ethers-rs 类型(例如 AddressH256 等),并且其名称必须以 Input 结尾(例如 MyCircuitInput)。如果它们实现了 RawInput 特性,则可以使用额外的类型(请参阅这里)。结构必须用 #[AxiomComputeInput] 属性注释,以便实现足够的电路特性。此属性还会生成一个新的结构,将 Input 替换为 CircuitInput(例如 AccountAgeInput -> AccountAgeCircuitInput),它具有指定结构体的所有字段,但使用 halo2-lib 类型在您的电路内部(如 AssignedValue<Fr>)。

以下是一个示例

#[AxiomComputeInput]
pub struct AccountAgeInput {
    pub addr: Address,
    pub claimed_block_number: u64,
}

计算函数规范

您必须在您的输入结构上实现 AxiomComputeFn。只有一个特例函数必须实现

fn compute(
    api: &mut AxiomAPI,
    assigned_inputs: AccountAgeCircuitInput<AssignedValue<Fr>>,
) -> Vec<AxiomResult>

其中应将 AccountAgeCircuitInput 替换为您派生的电路输入结构。

AxiomAPI 结构为您提供访问子查询调用函数的权限,以及一个 RlcCircuitBuilder 来指定您的电路。然后,您的计算函数应返回任何您希望传递到链上的值,在 Vec<AxiomResult> 中(AxiomResult 是一个枚举,可以是 HiLo<AssignedValue<Fr>>AssignedValue<Fr>,在这种情况下,它将为您转换为高-低)。

以下是一个示例

impl AxiomComputeFn for AccountAgeInput {
    fn compute(
        api: &mut AxiomAPI,
        assigned_inputs: AccountAgeCircuitInput<AssignedValue<Fr>>,
    ) -> Vec<AxiomResult> {
        let gate = GateChip::new();
        let zero = api.ctx().load_zero();
        let one = api.ctx().load_constant(Fr::one());
        let prev_block = gate.sub(api.ctx(), assigned_inputs.claimed_block_number, one);

        let account_prev_block = api.get_account(prev_block, assigned_inputs.addr);
        let prev_nonce = account_prev_block.call(AccountField::Nonce);
        let prev_nonce = api.from_hi_lo(prev_nonce);
        api.ctx().constrain_equal(&prev_nonce, &zero);

        let account = api.get_account(assigned_inputs.claimed_block_number, assigned_inputs.addr);
        let curr_nonce = account.call(AccountField::Nonce);
        let curr_nonce = api.from_hi_lo(curr_nonce);

        api.range.check_less_than(api.ctx(), zero, curr_nonce, 40);

        vec![
            assigned_inputs.addr.into(),
            assigned_inputs.claimed_block_number.into(),
        ]
    }
}

运行电路

要运行您的电路,创建一个 main 函数,并使用您的输入结构作为泛型参数调用 run_cli 函数

fn main() {
    env_logger::init();
    run_cli::<AccountAgeInput>();
}

main 函数将运行一个 CLI,允许您运行模拟证明、密钥生成和电路证明。CLI具有以下命令

Commands:
    mock    Run the mock prover
    keygen  Generate new proving & verifying keys
    prove   Generate a new proof
    run     Generate an Axiom compute query
    help    Print this message or the help of the given subcommand(s)

Options:
    -k, --degree <DEGREE>        To determine the size of your circuit (12..25)
    -p, --provider <PROVIDER>    JSON RPC provider URI
    -i, --input <INPUT_PATH>     JSON inputs to feed into your circuit
    -d, --data-path <DATA_PATH>  For saving build artifacts (optional)
    -c, --config <CONFIG>        For custom advanced usage only (optional)
    -h, --help                   Print help
    -V, --version                Print version

例如

cargo run --example account_age -- --input data/account_age_input.json -k 12 -p <PROVIDER_URI> <CMD>

其中 PROVIDER_URI 是一个 JSON-RPC URI,而 CMDmockprovekeygenrun

依赖关系

~36–52MB
~1M SLoC