1use std::io;
2
3use ethers_core::types::{Bytes, H256};
4
5use crate::{
6 constants::*,
7 types::field_elements::*,
8 types::native::*,
9 utils::native::{encode_addr_to_field, encode_h256_to_hilo, encode_u256_to_hilo},
10 Field,
11};
12
13pub const NUM_FE_HEADER: usize = 2;
14pub const NUM_FE_ACCOUNT: usize = 3;
15pub const NUM_FE_STORAGE: usize = 4;
16pub const NUM_FE_TX: usize = 3;
17pub const NUM_FE_RECEIPT: usize = 6;
18pub const NUM_FE_SOLIDITY_NESTED_MAPPING: usize =
19 NUM_FE_SOLIDITY_NESTED_MAPPING_WITHOUT_KEYS + MAX_SOLIDITY_MAPPING_KEYS * 2;
20pub const NUM_FE_SOLIDITY_NESTED_MAPPING_WITHOUT_KEYS: usize = 5;
21pub const NUM_FE_SOLIDITY_NESTED_MAPPING_MIN: usize = 7; pub const NUM_FE_ANY: [usize; NUM_SUBQUERY_TYPES] = [
23 0,
24 NUM_FE_HEADER,
25 NUM_FE_ACCOUNT,
26 NUM_FE_STORAGE,
27 NUM_FE_TX,
28 NUM_FE_RECEIPT,
29 NUM_FE_SOLIDITY_NESTED_MAPPING,
30];
31
32pub const FIELD_SOLIDITY_NESTED_MAPPING_DEPTH_IDX: usize = 4;
34pub const FIELD_ENCODED_SOLIDITY_NESTED_MAPPING_DEPTH_IDX: usize =
36 FIELD_SOLIDITY_NESTED_MAPPING_DEPTH_IDX + 1;
37
38pub const BYTES_PER_FE_HEADER: [usize; NUM_FE_HEADER] = [4, 4];
42pub const BITS_PER_FE_HEADER: [usize; NUM_FE_HEADER] = [32, 32];
43pub const BYTES_PER_FE_ACCOUNT: [usize; NUM_FE_ACCOUNT] = [4, 20, 4];
44pub const BITS_PER_FE_ACCOUNT: [usize; NUM_FE_ACCOUNT] = [32, 160, 32];
45pub const BYTES_PER_FE_STORAGE: [usize; NUM_FE_STORAGE] = [4, 20, 16, 16];
46pub const BITS_PER_FE_STORAGE: [usize; NUM_FE_STORAGE] = [32, 160, 128, 128];
47pub const BYTES_PER_FE_TX: [usize; NUM_FE_TX] = [4, 2, 4];
48pub const BITS_PER_FE_TX: [usize; NUM_FE_TX] = [32, 16, 32];
49pub const BYTES_PER_FE_RECEIPT: [usize; NUM_FE_RECEIPT] = [4, 2, 4, 4, 16, 16];
50pub const BITS_PER_FE_RECEIPT: [usize; NUM_FE_RECEIPT] = [32, 16, 32, 32, 128, 128];
51pub const BYTES_PER_FE_SOLIDITY_NESTED_MAPPING: [usize; NUM_FE_SOLIDITY_NESTED_MAPPING] =
52 bytes_per_fe_solidity_nested_mapping();
53pub const BITS_PER_FE_SOLIDITY_NESTED_MAPPING: [usize; NUM_FE_SOLIDITY_NESTED_MAPPING] =
54 bits_per_fe_solidity_nested_mapping();
55pub const BYTES_PER_FE_ANY: [&[usize]; NUM_SUBQUERY_TYPES] = [
56 &[],
57 &BYTES_PER_FE_HEADER,
58 &BYTES_PER_FE_ACCOUNT,
59 &BYTES_PER_FE_STORAGE,
60 &BYTES_PER_FE_TX,
61 &BYTES_PER_FE_RECEIPT,
62 &BYTES_PER_FE_SOLIDITY_NESTED_MAPPING,
63];
64pub const BYTES_PER_FE_SUBQUERY_OUTPUT: usize = 16;
65
66pub const BITS_PER_FE_SUBQUERY_RESULT: [usize; SUBQUERY_RESULT_LEN] = [128; SUBQUERY_RESULT_LEN];
67pub const SUBQUERY_OUTPUT_BYTES: usize = MAX_SUBQUERY_OUTPUTS * BYTES_PER_FE_SUBQUERY_OUTPUT;
68
69const fn bytes_per_fe_solidity_nested_mapping() -> [usize; NUM_FE_SOLIDITY_NESTED_MAPPING] {
70 let mut bytes_per = [16; MAX_SUBQUERY_INPUTS];
71 bytes_per[0] = 4;
72 bytes_per[1] = 20;
73 bytes_per[2] = 16;
74 bytes_per[3] = 16;
75 bytes_per[4] = 1;
76 bytes_per
77}
78const fn bits_per_fe_solidity_nested_mapping() -> [usize; NUM_FE_SOLIDITY_NESTED_MAPPING] {
79 let mut bits_per = [128; MAX_SUBQUERY_INPUTS];
80 bits_per[0] = 32;
81 bits_per[1] = 160;
82 bits_per[2] = 128;
83 bits_per[3] = 128;
84 bits_per[4] = 8;
85 bits_per
86}
87
88pub const BITS_PER_FE_SUBQUERY_OUTPUT: usize = BYTES_PER_FE_SUBQUERY_OUTPUT * 8;
89
90impl<F: Field> From<H256> for SubqueryOutput<F> {
91 fn from(value: H256) -> Self {
92 let mut output = [F::ZERO; MAX_SUBQUERY_OUTPUTS];
93 let hilo = encode_h256_to_hilo(&value);
94 output[0] = hilo.hi();
95 output[1] = hilo.lo();
96 Self(output)
97 }
98}
99
100impl<F: Field> TryFrom<Bytes> for SubqueryOutput<F> {
101 type Error = io::Error;
102 fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
103 if bytes.len() != 32 {
104 Err(io::Error::new(io::ErrorKind::InvalidData, "result length is not 32"))
105 } else {
106 let result = H256::from_slice(&bytes[..]);
107 let hilo = encode_h256_to_hilo(&result);
108 let mut result = [F::ZERO; MAX_SUBQUERY_OUTPUTS];
109 result[0] = hilo.hi();
110 result[1] = hilo.lo();
111 Ok(Self(result))
112 }
113 }
114}
115
116impl<F: Field> TryFrom<SubqueryResult> for FlattenedSubqueryResult<F> {
117 type Error = io::Error;
118 fn try_from(result: SubqueryResult) -> Result<Self, Self::Error> {
119 let result: FieldSubqueryResult<F> = result.try_into()?;
120 Ok(result.into())
121 }
122}
123
124impl<F: Field> TryFrom<SubqueryResult> for FieldSubqueryResult<F> {
125 type Error = io::Error;
126 fn try_from(result: SubqueryResult) -> Result<Self, Self::Error> {
127 let subquery = result.subquery.try_into()?;
128 let value = result.value.try_into()?;
129 Ok(FieldSubqueryResult { subquery, value })
130 }
131}
132
133impl<F: Field> TryFrom<Subquery> for FieldSubquery<F> {
134 type Error = io::Error;
135 fn try_from(subquery: Subquery) -> Result<Self, Self::Error> {
136 let subquery = AnySubquery::try_from(subquery)?;
137 Ok(subquery.into())
138 }
139}
140
141impl<F: Field> From<AnySubquery> for FieldSubquery<F> {
142 fn from(subquery: AnySubquery) -> Self {
143 match subquery {
144 AnySubquery::Null => FieldSubquery {
145 subquery_type: SubqueryType::Null,
146 encoded_subquery_data: Default::default(),
147 },
148 AnySubquery::Header(subquery) => FieldHeaderSubquery::from(subquery).into(),
149 AnySubquery::Account(subquery) => FieldAccountSubquery::from(subquery).into(),
150 AnySubquery::Storage(subquery) => FieldStorageSubquery::from(subquery).into(),
151 AnySubquery::Transaction(subquery) => FieldTxSubquery::from(subquery).into(),
152 AnySubquery::Receipt(subquery) => FieldReceiptSubquery::from(subquery).into(),
153 AnySubquery::SolidityNestedMapping(subquery) => {
154 FieldSolidityNestedMappingSubquery::from(subquery).into()
155 }
156 }
157 }
158}
159
160impl<F: Field> From<HeaderSubquery> for FieldHeaderSubquery<F> {
161 fn from(subquery: HeaderSubquery) -> Self {
162 Self {
163 block_number: F::from(subquery.block_number as u64),
164 field_idx: F::from(subquery.field_idx as u64),
165 }
166 }
167}
168
169impl<T> FieldHeaderSubquery<T> {
170 pub fn flatten(self) -> [T; NUM_FE_HEADER] {
171 [self.block_number, self.field_idx]
172 }
173}
174
175impl<F: Field> From<FieldHeaderSubquery<F>> for FieldSubquery<F> {
176 fn from(subquery: FieldHeaderSubquery<F>) -> Self {
177 let mut encoded_subquery_data = [F::ZERO; MAX_SUBQUERY_INPUTS];
178 encoded_subquery_data[..NUM_FE_HEADER].copy_from_slice(&subquery.flatten());
179 Self { subquery_type: SubqueryType::Header, encoded_subquery_data }
180 }
181}
182
183impl<F: Field> From<AccountSubquery> for FieldAccountSubquery<F> {
184 fn from(subquery: AccountSubquery) -> Self {
185 Self {
186 block_number: F::from(subquery.block_number as u64),
187 addr: encode_addr_to_field(&subquery.addr),
188 field_idx: F::from(subquery.field_idx as u64),
189 }
190 }
191}
192
193impl<T> FieldAccountSubquery<T> {
194 pub fn flatten(self) -> [T; NUM_FE_ACCOUNT] {
195 [self.block_number, self.addr, self.field_idx]
196 }
197}
198
199impl<F: Field> From<FieldAccountSubquery<F>> for FieldSubquery<F> {
200 fn from(value: FieldAccountSubquery<F>) -> Self {
201 let mut encoded_subquery_data = [F::ZERO; MAX_SUBQUERY_INPUTS];
202 encoded_subquery_data[..NUM_FE_ACCOUNT].copy_from_slice(&value.flatten());
203 Self { subquery_type: SubqueryType::Account, encoded_subquery_data }
204 }
205}
206
207impl<F: Field> From<StorageSubquery> for FieldStorageSubquery<F> {
208 fn from(subquery: StorageSubquery) -> Self {
209 Self {
210 block_number: F::from(subquery.block_number as u64),
211 addr: encode_addr_to_field(&subquery.addr),
212 slot: encode_u256_to_hilo(&subquery.slot),
213 }
214 }
215}
216
217impl<T: Copy> FieldStorageSubquery<T> {
218 pub fn flatten(self) -> [T; NUM_FE_STORAGE] {
219 [self.block_number, self.addr, self.slot.hi(), self.slot.lo()]
220 }
221}
222
223impl<F: Field> From<FieldStorageSubquery<F>> for FieldSubquery<F> {
224 fn from(value: FieldStorageSubquery<F>) -> Self {
225 let mut encoded_subquery_data = [F::ZERO; MAX_SUBQUERY_INPUTS];
226 encoded_subquery_data[..NUM_FE_STORAGE].copy_from_slice(&value.flatten());
227 Self { subquery_type: SubqueryType::Storage, encoded_subquery_data }
228 }
229}
230
231impl<F: Field> From<TxSubquery> for FieldTxSubquery<F> {
232 fn from(subquery: TxSubquery) -> Self {
233 Self {
234 block_number: F::from(subquery.block_number as u64),
235 tx_idx: F::from(subquery.tx_idx as u64),
236 field_or_calldata_idx: F::from(subquery.field_or_calldata_idx as u64),
237 }
238 }
239}
240
241impl<T> FieldTxSubquery<T> {
242 pub fn flatten(self) -> [T; NUM_FE_TX] {
243 [self.block_number, self.tx_idx, self.field_or_calldata_idx]
244 }
245}
246
247impl<F: Field> From<FieldTxSubquery<F>> for FieldSubquery<F> {
248 fn from(value: FieldTxSubquery<F>) -> Self {
249 let mut encoded_subquery_data = [F::ZERO; MAX_SUBQUERY_INPUTS];
250 encoded_subquery_data[..NUM_FE_TX].copy_from_slice(&value.flatten());
251 Self { subquery_type: SubqueryType::Transaction, encoded_subquery_data }
252 }
253}
254
255impl<F: Field> From<ReceiptSubquery> for FieldReceiptSubquery<F> {
256 fn from(subquery: ReceiptSubquery) -> Self {
257 Self {
258 block_number: F::from(subquery.block_number as u64),
259 tx_idx: F::from(subquery.tx_idx as u64),
260 field_or_log_idx: F::from(subquery.field_or_log_idx as u64),
261 topic_or_data_or_address_idx: F::from(subquery.topic_or_data_or_address_idx as u64),
262 event_schema: encode_h256_to_hilo(&subquery.event_schema),
263 }
264 }
265}
266
267impl<T: Copy> FieldReceiptSubquery<T> {
268 pub fn flatten(self) -> [T; NUM_FE_RECEIPT] {
269 [
270 self.block_number,
271 self.tx_idx,
272 self.field_or_log_idx,
273 self.topic_or_data_or_address_idx,
274 self.event_schema.hi(),
275 self.event_schema.lo(),
276 ]
277 }
278}
279
280impl<F: Field> From<FieldReceiptSubquery<F>> for FieldSubquery<F> {
281 fn from(value: FieldReceiptSubquery<F>) -> Self {
282 let mut encoded_subquery_data = [F::ZERO; MAX_SUBQUERY_INPUTS];
283 encoded_subquery_data[..NUM_FE_RECEIPT].copy_from_slice(&value.flatten());
284 Self { subquery_type: SubqueryType::Receipt, encoded_subquery_data }
285 }
286}
287
288impl<F: Field> From<SolidityNestedMappingSubquery> for FieldSolidityNestedMappingSubquery<F> {
289 fn from(mut subquery: SolidityNestedMappingSubquery) -> Self {
290 assert!(subquery.keys.len() <= MAX_SOLIDITY_MAPPING_KEYS);
291 subquery.keys.resize(MAX_SOLIDITY_MAPPING_KEYS, H256::zero());
292
293 Self {
294 block_number: F::from(subquery.block_number as u64),
295 addr: encode_addr_to_field(&subquery.addr),
296 mapping_slot: encode_u256_to_hilo(&subquery.mapping_slot),
297 mapping_depth: F::from(subquery.mapping_depth as u64),
298 keys: subquery
299 .keys
300 .iter()
301 .map(|k| encode_h256_to_hilo(k))
302 .collect::<Vec<_>>()
303 .try_into()
304 .unwrap(),
305 }
306 }
307}
308
309impl<T: Copy> FieldSolidityNestedMappingSubquery<T> {
310 pub fn flatten(self) -> [T; NUM_FE_SOLIDITY_NESTED_MAPPING] {
311 assert_eq!(5 + self.keys.len() * 2, NUM_FE_SOLIDITY_NESTED_MAPPING);
312 let mut result = [self.block_number; NUM_FE_SOLIDITY_NESTED_MAPPING]; result[0] = self.block_number;
314 result[1] = self.addr;
315 result[2] = self.mapping_slot.hi();
316 result[3] = self.mapping_slot.lo();
317 result[4] = self.mapping_depth;
318 for (i, key) in self.keys.iter().enumerate() {
319 result[5 + i * 2] = key.hi();
320 result[5 + i * 2 + 1] = key.lo();
321 }
322 result
323 }
324}
325
326impl<F: Field> From<FieldSolidityNestedMappingSubquery<F>> for FieldSubquery<F> {
327 fn from(value: FieldSolidityNestedMappingSubquery<F>) -> Self {
328 let mut encoded_subquery_data = [F::ZERO; MAX_SUBQUERY_INPUTS];
329 encoded_subquery_data[..NUM_FE_SOLIDITY_NESTED_MAPPING].copy_from_slice(&value.flatten());
330 Self { subquery_type: SubqueryType::SolidityNestedMapping, encoded_subquery_data }
331 }
332}