axiom_codec/decoder/
native.rs

1use std::io::{self, Read, Result};
2
3use axiom_eth::halo2curves::bn256::G1Affine;
4use byteorder::{BigEndian, ReadBytesExt};
5use ethers_core::types::Bytes;
6
7use crate::{
8    constants::MAX_SOLIDITY_MAPPING_KEYS,
9    types::native::{
10        AccountSubquery, AnySubquery, AxiomV2ComputeSnark, HeaderSubquery, ReceiptSubquery,
11        SolidityNestedMappingSubquery, StorageSubquery, Subquery, SubqueryType, TxSubquery,
12    },
13    utils::reader::{read_address, read_curve_compressed, read_h256, read_u256},
14};
15
16impl TryFrom<Subquery> for AnySubquery {
17    type Error = io::Error;
18
19    fn try_from(subquery: Subquery) -> Result<Self> {
20        let mut reader = &subquery.encoded_subquery_data[..];
21        let subquery_type = subquery.subquery_type;
22        Ok(match subquery_type {
23            SubqueryType::Null => AnySubquery::Null,
24            SubqueryType::Header => AnySubquery::Header(decode_header_subquery(&mut reader)?),
25            SubqueryType::Account => AnySubquery::Account(decode_account_subquery(&mut reader)?),
26            SubqueryType::Storage => AnySubquery::Storage(decode_storage_subquery(&mut reader)?),
27            SubqueryType::Transaction => AnySubquery::Transaction(decode_tx_subquery(&mut reader)?),
28            SubqueryType::Receipt => AnySubquery::Receipt(decode_receipt_subquery(&mut reader)?),
29            SubqueryType::SolidityNestedMapping => AnySubquery::SolidityNestedMapping(
30                decode_solidity_nested_mapping_subquery(&mut reader)?,
31            ),
32        })
33    }
34}
35
36impl TryFrom<u16> for SubqueryType {
37    type Error = io::Error;
38    fn try_from(value: u16) -> Result<Self> {
39        match value {
40            0 => Ok(Self::Null),
41            1 => Ok(Self::Header),
42            2 => Ok(Self::Account),
43            3 => Ok(Self::Storage),
44            4 => Ok(Self::Transaction),
45            5 => Ok(Self::Receipt),
46            6 => Ok(Self::SolidityNestedMapping),
47            // 7 => Ok(Self::BeaconValidator),
48            _ => Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid SubqueryType")),
49        }
50    }
51}
52
53/// Decoder from `compute_proof` in bytes into `AxiomV2ComputeSnark`.
54/// `reader` should be a reader on `compute_proof` in `AxiomV2ComputeQuery`.
55pub fn decode_compute_snark(
56    mut reader: impl Read,
57    result_len: u16,
58    is_aggregation: bool,
59) -> Result<AxiomV2ComputeSnark> {
60    let kzg_accumulator = if is_aggregation {
61        let lhs = read_curve_compressed::<G1Affine>(&mut reader)?;
62        let rhs = read_curve_compressed::<G1Affine>(&mut reader)?;
63        Some((lhs, rhs))
64    } else {
65        read_h256(&mut reader)?;
66        read_h256(&mut reader)?;
67        None
68    };
69    let mut compute_results = Vec::with_capacity(result_len as usize);
70    for _ in 0..result_len {
71        compute_results.push(read_h256(&mut reader)?);
72    }
73    let mut proof_transcript = vec![];
74    reader.read_to_end(&mut proof_transcript)?;
75    Ok(AxiomV2ComputeSnark { kzg_accumulator, compute_results, proof_transcript })
76}
77
78pub fn decode_subquery(mut reader: impl Read) -> Result<AnySubquery> {
79    let subquery_type = reader.read_u16::<BigEndian>()?;
80    let subquery_type = subquery_type.try_into()?;
81    let mut buf = vec![];
82    reader.read_to_end(&mut buf)?;
83    let encoded_subquery_data = Bytes::from(buf);
84    let subquery = Subquery { subquery_type, encoded_subquery_data };
85    subquery.try_into()
86}
87
88pub fn decode_header_subquery(mut reader: impl Read) -> Result<HeaderSubquery> {
89    let block_number = reader.read_u32::<BigEndian>()?;
90    let field_idx = reader.read_u32::<BigEndian>()?;
91    Ok(HeaderSubquery { block_number, field_idx })
92}
93
94pub fn decode_account_subquery(mut reader: impl Read) -> Result<AccountSubquery> {
95    let block_number = reader.read_u32::<BigEndian>()?;
96    let addr = read_address(&mut reader)?;
97    let field_idx = reader.read_u32::<BigEndian>()?;
98    Ok(AccountSubquery { block_number, addr, field_idx })
99}
100
101pub fn decode_storage_subquery(mut reader: impl Read) -> Result<StorageSubquery> {
102    let block_number = reader.read_u32::<BigEndian>()?;
103    let addr = read_address(&mut reader)?;
104    let slot = read_u256(&mut reader)?;
105    Ok(StorageSubquery { block_number, addr, slot })
106}
107
108pub fn decode_tx_subquery(mut reader: impl Read) -> Result<TxSubquery> {
109    let block_number = reader.read_u32::<BigEndian>()?;
110    let tx_idx = reader.read_u16::<BigEndian>()?;
111    let field_or_calldata_idx = reader.read_u32::<BigEndian>()?;
112    Ok(TxSubquery { block_number, tx_idx, field_or_calldata_idx })
113}
114
115pub fn decode_receipt_subquery(mut reader: impl Read) -> Result<ReceiptSubquery> {
116    let block_number = reader.read_u32::<BigEndian>()?;
117    let tx_idx = reader.read_u16::<BigEndian>()?;
118    let field_or_log_idx = reader.read_u32::<BigEndian>()?;
119    let topic_or_data_or_address_idx = reader.read_u32::<BigEndian>()?;
120    let event_schema = read_h256(&mut reader)?;
121    Ok(ReceiptSubquery {
122        block_number,
123        tx_idx,
124        field_or_log_idx,
125        topic_or_data_or_address_idx,
126        event_schema,
127    })
128}
129
130pub fn decode_solidity_nested_mapping_subquery(
131    mut reader: impl Read,
132) -> Result<SolidityNestedMappingSubquery> {
133    let block_number = reader.read_u32::<BigEndian>()?;
134    let addr = read_address(&mut reader)?;
135    let mapping_slot = read_u256(&mut reader)?;
136    let mapping_depth = reader.read_u8()?;
137    if mapping_depth as usize > MAX_SOLIDITY_MAPPING_KEYS {
138        return Err(io::Error::new(
139            io::ErrorKind::InvalidData,
140            format!(
141                "SolidityNestedMappingSubquery mapping_depth {} exceeds MAX_SOLIDITY_MAPPING_KEYS {}",
142                mapping_depth, MAX_SOLIDITY_MAPPING_KEYS
143            ),
144        ));
145    }
146    let mut keys = Vec::with_capacity(mapping_depth as usize);
147    for _ in 0..mapping_depth {
148        keys.push(read_h256(&mut reader)?);
149    }
150    Ok(SolidityNestedMappingSubquery { block_number, addr, mapping_slot, mapping_depth, keys })
151}