1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use std::sync::{Arc, Mutex};

use axiom_circuit::{
    axiom_codec::{special_values::HEADER_LOGS_BLOOM_FIELD_IDX_OFFSET, HiLo},
    axiom_eth::halo2_base::{AssignedValue, Context},
    subquery::{caller::SubqueryCaller, types::AssignedHeaderSubquery, HeaderField},
};
use ethers::providers::Http;

use crate::Fr;

/// Header subquery builder
pub struct Header<'a> {
    pub block_number: AssignedValue<Fr>,
    ctx: &'a mut Context<Fr>,
    caller: Arc<Mutex<SubqueryCaller<Http, Fr>>>,
}

pub(crate) fn get_header(
    ctx: &mut Context<Fr>,
    caller: Arc<Mutex<SubqueryCaller<Http, Fr>>>,
    block_number: AssignedValue<Fr>,
) -> Header {
    Header {
        block_number,
        ctx,
        caller,
    }
}

impl<'a> Header<'a> {
    /// Fetches the header subquery and returns the HiLo<AssignedValue<Fr>> result
    ///
    /// * `field` - The header field to fetch
    pub fn call(self, field: HeaderField) -> HiLo<AssignedValue<Fr>> {
        let field_constant = self.ctx.load_constant(Fr::from(field));
        let mut subquery_caller = self.caller.lock().unwrap();
        let subquery = AssignedHeaderSubquery {
            block_number: self.block_number,
            field_idx: field_constant,
        };
        subquery_caller.call(self.ctx, subquery)
    }

    /// Fetches the header logs bloom subquery and returns the HiLo<AssignedValue<Fr>> result
    ///
    /// * `logs_bloom_idx` - The logs bloom field index to fetch
    pub fn logs_bloom(self, logs_bloom_idx: usize) -> HiLo<AssignedValue<Fr>> {
        let mut subquery_caller = self.caller.lock().unwrap();
        if logs_bloom_idx >= 8 {
            panic!("logs_bloom_idx range is [0, 8)");
        }
        let field_idx = logs_bloom_idx + HEADER_LOGS_BLOOM_FIELD_IDX_OFFSET;
        let assigned_field_idx = self.ctx.load_constant(Fr::from(field_idx as u64));
        let subquery = AssignedHeaderSubquery {
            block_number: self.block_number,
            field_idx: assigned_field_idx,
        };
        subquery_caller.call(self.ctx, subquery)
    }
}