openvm_pairing_circuit/pairing_chip/line/
evaluate_line.rs

1use std::{
2    cell::RefCell,
3    rc::Rc,
4    sync::{Arc, Mutex},
5};
6
7use openvm_algebra_circuit::Fp2;
8use openvm_circuit::{arch::VmChipWrapper, system::memory::OfflineMemory};
9use openvm_circuit_derive::InstructionExecutor;
10use openvm_circuit_primitives::var_range::{
11    SharedVariableRangeCheckerChip, VariableRangeCheckerBus,
12};
13use openvm_circuit_primitives_derive::{Chip, ChipUsageGetter};
14use openvm_mod_circuit_builder::{
15    ExprBuilder, ExprBuilderConfig, FieldExpr, FieldExpressionCoreChip,
16};
17use openvm_pairing_transpiler::PairingOpcode;
18use openvm_rv32_adapters::Rv32VecHeapTwoReadsAdapterChip;
19use openvm_stark_backend::p3_field::PrimeField32;
20
21// Input: UnevaluatedLine<Fp2>, (Fp, Fp)
22// Output: EvaluatedLine<Fp2>
23#[derive(Chip, ChipUsageGetter, InstructionExecutor)]
24pub struct EvaluateLineChip<
25    F: PrimeField32,
26    const INPUT_BLOCKS1: usize,
27    const INPUT_BLOCKS2: usize,
28    const OUTPUT_BLOCKS: usize,
29    const BLOCK_SIZE: usize,
30>(
31    pub  VmChipWrapper<
32        F,
33        Rv32VecHeapTwoReadsAdapterChip<
34            F,
35            INPUT_BLOCKS1,
36            INPUT_BLOCKS2,
37            OUTPUT_BLOCKS,
38            BLOCK_SIZE,
39            BLOCK_SIZE,
40        >,
41        FieldExpressionCoreChip,
42    >,
43);
44
45impl<
46        F: PrimeField32,
47        const INPUT_BLOCKS1: usize,
48        const INPUT_BLOCKS2: usize,
49        const OUTPUT_BLOCKS: usize,
50        const BLOCK_SIZE: usize,
51    > EvaluateLineChip<F, INPUT_BLOCKS1, INPUT_BLOCKS2, OUTPUT_BLOCKS, BLOCK_SIZE>
52{
53    pub fn new(
54        adapter: Rv32VecHeapTwoReadsAdapterChip<
55            F,
56            INPUT_BLOCKS1,
57            INPUT_BLOCKS2,
58            OUTPUT_BLOCKS,
59            BLOCK_SIZE,
60            BLOCK_SIZE,
61        >,
62        config: ExprBuilderConfig,
63        offset: usize,
64        range_checker: SharedVariableRangeCheckerChip,
65        offline_memory: Arc<Mutex<OfflineMemory<F>>>,
66    ) -> Self {
67        let expr = evaluate_line_expr(config, range_checker.bus());
68        let core = FieldExpressionCoreChip::new(
69            expr,
70            offset,
71            vec![PairingOpcode::EVALUATE_LINE as usize],
72            vec![],
73            range_checker,
74            "EvaluateLine",
75            false,
76        );
77        Self(VmChipWrapper::new(adapter, core, offline_memory))
78    }
79}
80
81pub fn evaluate_line_expr(
82    config: ExprBuilderConfig,
83    range_bus: VariableRangeCheckerBus,
84) -> FieldExpr {
85    config.check_valid();
86    let builder = ExprBuilder::new(config, range_bus.range_max_bits);
87    let builder = Rc::new(RefCell::new(builder));
88
89    let mut uneval_b = Fp2::new(builder.clone());
90    let mut uneval_c = Fp2::new(builder.clone());
91
92    let mut x_over_y = ExprBuilder::new_input(builder.clone());
93    let mut y_inv = ExprBuilder::new_input(builder.clone());
94
95    let mut b = uneval_b.scalar_mul(&mut x_over_y);
96    let mut c = uneval_c.scalar_mul(&mut y_inv);
97    b.save_output();
98    c.save_output();
99
100    let builder = builder.borrow().clone();
101    FieldExpr::new(builder, range_bus, false)
102}