openvm_ecc_circuit/weierstrass_chip/add_ne/
mod.rs1use std::{
2 cell::RefCell,
3 ops::{Deref, DerefMut},
4 rc::Rc,
5};
6
7use openvm_algebra_circuit::fields::{get_field_type, FieldType};
8use openvm_circuit::{
9 arch::*,
10 system::memory::{offline_checker::MemoryBridge, SharedMemoryHelper},
11};
12use openvm_circuit_primitives::{
13 bitwise_op_lookup::{BitwiseOperationLookupBus, SharedBitwiseOperationLookupChip},
14 var_range::{SharedVariableRangeCheckerChip, VariableRangeCheckerBus},
15};
16use openvm_ecc_transpiler::Rv32WeierstrassOpcode;
17use openvm_instructions::riscv::RV32_CELL_BITS;
18use openvm_mod_circuit_builder::{
19 ExprBuilder, ExprBuilderConfig, FieldExpr, FieldExpressionCoreAir, FieldExpressionExecutor,
20 FieldExpressionFiller,
21};
22use openvm_rv32_adapters::{
23 Rv32VecHeapAdapterAir, Rv32VecHeapAdapterExecutor, Rv32VecHeapAdapterFiller,
24};
25
26use super::{WeierstrassAir, WeierstrassChip};
27
28mod execution;
29
30pub fn ec_add_ne_expr(
33 config: ExprBuilderConfig, range_bus: VariableRangeCheckerBus,
35) -> FieldExpr {
36 config.check_valid();
37 let builder = ExprBuilder::new(config, range_bus.range_max_bits);
38 let builder = Rc::new(RefCell::new(builder));
39
40 let x1 = ExprBuilder::new_input(builder.clone());
41 let y1 = ExprBuilder::new_input(builder.clone());
42 let x2 = ExprBuilder::new_input(builder.clone());
43 let y2 = ExprBuilder::new_input(builder.clone());
44 let mut lambda = (y2 - y1.clone()) / (x2.clone() - x1.clone());
45 let mut x3 = lambda.square() - x1.clone() - x2;
46 x3.save_output();
47 let mut y3 = lambda * (x1 - x3.clone()) - y1;
48 y3.save_output();
49
50 let builder = (*builder).borrow().clone();
51 FieldExpr::new(builder, range_bus, true)
52}
53
54#[derive(Clone)]
60pub struct EcAddNeExecutor<const BLOCKS: usize, const BLOCK_SIZE: usize> {
61 pub(crate) inner: FieldExpressionExecutor<
62 Rv32VecHeapAdapterExecutor<2, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
63 >,
64 pub(crate) cached_field_type: Option<FieldType>,
65}
66
67impl<const BLOCKS: usize, const BLOCK_SIZE: usize> EcAddNeExecutor<BLOCKS, BLOCK_SIZE> {
68 pub fn new(
69 inner: FieldExpressionExecutor<
70 Rv32VecHeapAdapterExecutor<2, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
71 >,
72 ) -> Self {
73 let cached_field_type = get_field_type(&inner.expr.prime);
74 Self {
75 inner,
76 cached_field_type,
77 }
78 }
79}
80
81impl<const BLOCKS: usize, const BLOCK_SIZE: usize> Deref for EcAddNeExecutor<BLOCKS, BLOCK_SIZE> {
82 type Target = FieldExpressionExecutor<
83 Rv32VecHeapAdapterExecutor<2, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
84 >;
85
86 fn deref(&self) -> &Self::Target {
87 &self.inner
88 }
89}
90
91impl<const BLOCKS: usize, const BLOCK_SIZE: usize> DerefMut
92 for EcAddNeExecutor<BLOCKS, BLOCK_SIZE>
93{
94 fn deref_mut(&mut self) -> &mut Self::Target {
95 &mut self.inner
96 }
97}
98
99fn gen_base_expr(
100 config: ExprBuilderConfig,
101 range_checker_bus: VariableRangeCheckerBus,
102) -> (FieldExpr, Vec<usize>) {
103 let expr = ec_add_ne_expr(config, range_checker_bus);
104
105 let local_opcode_idx = vec![
106 Rv32WeierstrassOpcode::EC_ADD_NE as usize,
107 Rv32WeierstrassOpcode::SETUP_EC_ADD_NE as usize,
108 ];
109
110 (expr, local_opcode_idx)
111}
112
113pub fn get_ec_addne_air<const BLOCKS: usize, const BLOCK_SIZE: usize>(
114 exec_bridge: ExecutionBridge,
115 mem_bridge: MemoryBridge,
116 config: ExprBuilderConfig,
117 range_checker_bus: VariableRangeCheckerBus,
118 bitwise_lookup_bus: BitwiseOperationLookupBus,
119 pointer_max_bits: usize,
120 offset: usize,
121) -> WeierstrassAir<2, BLOCKS, BLOCK_SIZE> {
122 let (expr, local_opcode_idx) = gen_base_expr(config, range_checker_bus);
123 WeierstrassAir::new(
124 Rv32VecHeapAdapterAir::new(
125 exec_bridge,
126 mem_bridge,
127 bitwise_lookup_bus,
128 pointer_max_bits,
129 ),
130 FieldExpressionCoreAir::new(expr.clone(), offset, local_opcode_idx.clone(), vec![]),
131 )
132}
133
134pub fn get_ec_addne_executor<const BLOCKS: usize, const BLOCK_SIZE: usize>(
135 config: ExprBuilderConfig,
136 range_checker_bus: VariableRangeCheckerBus,
137 pointer_max_bits: usize,
138 offset: usize,
139) -> EcAddNeExecutor<BLOCKS, BLOCK_SIZE> {
140 let (expr, local_opcode_idx) = gen_base_expr(config, range_checker_bus);
141 EcAddNeExecutor::new(FieldExpressionExecutor::new(
142 Rv32VecHeapAdapterExecutor::new(pointer_max_bits),
143 expr,
144 offset,
145 local_opcode_idx,
146 vec![],
147 "EcAddNe",
148 ))
149}
150
151pub fn get_ec_addne_chip<F, const BLOCKS: usize, const BLOCK_SIZE: usize>(
152 config: ExprBuilderConfig,
153 mem_helper: SharedMemoryHelper<F>,
154 range_checker: SharedVariableRangeCheckerChip,
155 bitwise_lookup_chip: SharedBitwiseOperationLookupChip<RV32_CELL_BITS>,
156 pointer_max_bits: usize,
157) -> WeierstrassChip<F, 2, BLOCKS, BLOCK_SIZE> {
158 let (expr, local_opcode_idx) = gen_base_expr(config, range_checker.bus());
159 WeierstrassChip::new(
160 FieldExpressionFiller::new(
161 Rv32VecHeapAdapterFiller::new(pointer_max_bits, bitwise_lookup_chip),
162 expr,
163 local_opcode_idx,
164 vec![],
165 range_checker,
166 false,
167 ),
168 mem_helper,
169 )
170}