axiom_query/components/results/
types.rs1use std::{any::Any, marker::PhantomData};
2
3use anyhow::Result;
4use axiom_codec::{
5 types::{
6 field_elements::{AnySubqueryResult, FlattenedSubqueryResult},
7 native::{SubqueryResult, SubqueryType},
8 },
9 HiLo,
10};
11use axiom_eth::{
12 halo2_base::{
13 gates::{GateInstructions, RangeChip},
14 AssignedValue,
15 },
16 impl_flatten_conversion,
17 rlc::{chip::RlcChip, circuit::builder::RlcContextPair},
18 utils::{
19 build_utils::dummy::DummyFrom,
20 component::{
21 circuit::CoreBuilderInput,
22 promise_loader::{
23 flatten_witness_to_rlc,
24 multi::{ComponentTypeList, RlcAdapter},
25 },
26 types::{Flatten, LogicalEmpty},
27 utils::into_key,
28 ComponentType, ComponentTypeId, LogicalResult, PromiseCallWitness,
29 TypelessLogicalInput,
30 },
31 encode_h256_to_hilo,
32 },
33};
34use ethers_core::types::H256;
35use itertools::Itertools;
36use serde::{Deserialize, Serialize};
37
38use crate::{components::results::circuit::SubqueryDependencies, Field, RawField};
39
40use super::{
41 circuit::CoreParamsResultRoot,
42 table::{join::GroupedSubqueryResults, SubqueryResultsTable},
43};
44
45pub struct ComponentTypeResultsRoot<F: Field>(PhantomData<F>);
47
48#[derive(Clone, Debug, Serialize, Deserialize)]
52pub struct CircuitInputResultsRootShard<F: RawField> {
53 pub subqueries: SubqueryResultsTable<F>,
57 pub num_subqueries: F,
59}
60
61impl<F: Field> DummyFrom<CoreParamsResultRoot> for CircuitInputResultsRootShard<F> {
62 fn dummy_from(core_params: CoreParamsResultRoot) -> Self {
63 let subqueries = SubqueryResultsTable {
64 rows: vec![FlattenedSubqueryResult::default(); core_params.capacity],
65 };
66 Self { subqueries, num_subqueries: F::ZERO }
67 }
68}
69
70#[derive(Clone, Debug, Default, Serialize, Deserialize, Hash)]
73#[serde(rename_all = "camelCase")]
74pub struct LogicOutputResultsRoot {
75 pub results: Vec<SubqueryResult>,
76 pub subquery_hashes: Vec<H256>,
77 pub num_subqueries: usize,
78}
79
80#[derive(Clone, Debug, Default, Serialize, Deserialize)]
83pub struct CircuitOutputResultsRoot<F: RawField> {
84 pub results: SubqueryResultsTable<F>,
85 pub subquery_hashes: Vec<HiLo<F>>,
86 pub num_subqueries: usize,
87}
88
89impl<F: RawField> CircuitOutputResultsRoot<F> {
90 pub fn resize_with_first(&mut self, new_len: usize) {
92 self.results.rows.resize(new_len, self.results.rows[0]);
93 self.subquery_hashes.resize(new_len, self.subquery_hashes[0]);
94 }
95}
96
97const NUM_BITS_PER_FE: [usize; 2] = [9999, 9999];
100#[derive(Debug, Clone, PartialEq, Eq, Hash)]
101pub struct LogicalPublicInstanceResultsRoot<T> {
102 pub results_root_poseidon: T,
103 pub commit_subquery_hashes: T,
104}
105
106impl<F: Field> ComponentType<F> for ComponentTypeResultsRoot<F> {
109 type InputValue = LogicalEmpty<F>;
110 type InputWitness = LogicalEmpty<AssignedValue<F>>;
111 type OutputValue = LogicalEmpty<F>;
112 type OutputWitness = LogicalEmpty<AssignedValue<F>>;
113 type LogicalInput = LogicalEmpty<F>;
114
115 fn get_type_id() -> ComponentTypeId {
116 "axiom-query:ComponentTypeResultsRoot".to_string()
117 }
118
119 fn logical_result_to_virtual_rows_impl(
120 _ins: &LogicalResult<F, Self>,
121 ) -> Vec<(Self::InputValue, Self::OutputValue)> {
122 unreachable!()
123 }
124 fn logical_input_to_virtual_rows_impl(_li: &Self::LogicalInput) -> Vec<Self::InputValue> {
125 unreachable!()
126 }
127}
128
129impl LogicOutputResultsRoot {
130 pub fn new(
131 results: Vec<SubqueryResult>,
132 subquery_hashes: Vec<H256>,
133 num_subqueries: usize,
134 ) -> Self {
135 assert_eq!(results.len(), subquery_hashes.len());
136 Self { results, subquery_hashes, num_subqueries }
137 }
138}
139
140impl<F: Field> TryFrom<LogicOutputResultsRoot> for CircuitOutputResultsRoot<F> {
141 type Error = std::io::Error;
142 fn try_from(output: LogicOutputResultsRoot) -> Result<Self, Self::Error> {
143 let LogicOutputResultsRoot { results, subquery_hashes, num_subqueries } = output;
144 let rows = results
145 .into_iter()
146 .map(FlattenedSubqueryResult::<F>::try_from)
147 .collect::<Result<Vec<_>, _>>()?;
148 let results = SubqueryResultsTable { rows };
149 let subquery_hashes = subquery_hashes
150 .into_iter()
151 .map(|subquery_hash| encode_h256_to_hilo(&subquery_hash))
152 .collect();
153 Ok(Self { results, subquery_hashes, num_subqueries })
154 }
155}
156
157impl<T: Copy> TryFrom<Vec<T>> for LogicalPublicInstanceResultsRoot<T> {
159 type Error = anyhow::Error;
160
161 fn try_from(value: Vec<T>) -> anyhow::Result<Self> {
162 let [results_root_poseidon, commit_subquery_hashes] =
163 value.try_into().map_err(|_| anyhow::anyhow!("invalid length"))?;
164 Ok(Self { results_root_poseidon, commit_subquery_hashes })
165 }
166}
167impl<T: Copy> LogicalPublicInstanceResultsRoot<T> {
168 pub fn flatten(&self) -> [T; 2] {
169 [self.results_root_poseidon, self.commit_subquery_hashes]
170 }
171}
172impl_flatten_conversion!(LogicalPublicInstanceResultsRoot, NUM_BITS_PER_FE);
173
174pub struct RlcAdapterResultsRoot<F>(PhantomData<F>);
178impl<F: Field> RlcAdapter<F> for RlcAdapterResultsRoot<F> {
179 fn to_rlc(
180 ctx_pair: RlcContextPair<F>,
181 gate: &impl GateInstructions<F>,
182 rlc: &RlcChip<F>,
183 component_type_id: &ComponentTypeId,
184 io_pairs: &[(Flatten<AssignedValue<F>>, Flatten<AssignedValue<F>>)],
185 ) -> Vec<AssignedValue<F>> {
186 let subquery_type = component_type_id_to_subquery_type::<F>(component_type_id).unwrap();
187
188 let subqueries = GroupedSubqueryResults {
189 subquery_type,
190 results: io_pairs
191 .iter()
192 .map(|(i, o)| AnySubqueryResult {
193 subquery: i.fields.clone(),
194 value: o.fields.clone(),
195 })
196 .collect_vec(),
197 };
198 subqueries.into_rlc(ctx_pair, gate, rlc).concat()
199 }
200}
201
202pub struct VirtualComponentType<F: Field>(PhantomData<F>);
204
205impl<F: Field> ComponentType<F> for VirtualComponentType<F> {
206 type InputValue = FlattenedSubqueryResult<F>;
207 type InputWitness = FlattenedSubqueryResult<AssignedValue<F>>;
208 type OutputValue = LogicalEmpty<F>;
209 type OutputWitness = LogicalEmpty<AssignedValue<F>>;
210 type LogicalInput = LogicalEmpty<F>;
211
212 fn get_type_id() -> ComponentTypeId {
213 "axiom-query:VirtualComponentTypeResultsRoot".to_string()
214 }
215
216 fn logical_result_to_virtual_rows_impl(
217 _ins: &LogicalResult<F, Self>,
218 ) -> Vec<(Self::InputValue, Self::OutputValue)> {
219 unreachable!()
220 }
221 fn logical_input_to_virtual_rows_impl(_li: &Self::LogicalInput) -> Vec<Self::InputValue> {
222 unreachable!()
223 }
224}
225
226#[derive(Clone, Copy, Debug)]
227pub struct SubqueryResultCall<F: Field>(pub FlattenedSubqueryResult<AssignedValue<F>>);
228
229impl<F: Field> PromiseCallWitness<F> for SubqueryResultCall<F> {
230 fn get_component_type_id(&self) -> ComponentTypeId {
231 VirtualComponentType::<F>::get_type_id()
232 }
233 fn get_capacity(&self) -> usize {
234 0
236 }
237 fn to_rlc(
238 &self,
239 (_, rlc_ctx): RlcContextPair<F>,
240 _range_chip: &RangeChip<F>,
241 rlc_chip: &RlcChip<F>,
242 ) -> AssignedValue<F> {
243 flatten_witness_to_rlc(rlc_ctx, rlc_chip, &self.0.into())
244 }
245 fn to_typeless_logical_input(&self) -> TypelessLogicalInput {
246 let f_a: Flatten<AssignedValue<F>> = self.0.into();
247 let f_v: Flatten<F> = f_a.into();
248 let l_v: FlattenedSubqueryResult<F> = f_v.try_into().unwrap();
249 into_key(l_v)
250 }
251 fn get_mock_output(&self) -> Flatten<F> {
252 let output_val: <VirtualComponentType<F> as ComponentType<F>>::OutputValue =
253 Default::default();
254 output_val.into()
255 }
256 fn as_any(&self) -> &dyn Any {
257 self
258 }
259}
260
261pub fn component_type_id_to_subquery_type<F: Field>(
265 type_id: &ComponentTypeId,
266) -> Option<SubqueryType> {
267 let type_ids = SubqueryDependencies::<F>::get_component_type_ids();
269 type_ids
270 .iter()
271 .position(|id| id == type_id)
272 .map(|i| SubqueryType::try_from(i as u16 + 1).unwrap())
273}