axiom_eth/utils/
hilo.rs

1use std::io::{Error, ErrorKind, Result};
2
3use ethers_core::types::H256;
4use halo2_base::{AssignedValue, Context};
5use serde::{Deserialize, Serialize};
6use zkevm_hashes::util::{eth_types::Field, word::Word};
7
8use crate::impl_flatten_conversion;
9
10use super::encode_h256_to_hilo;
11
12/// Stored as [lo, hi], just like Word2
13#[derive(Clone, Copy, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
14pub struct HiLo<T>([T; 2]);
15
16impl<T> HiLo<T> {
17    /// Create a new [HiLo] from a `[lo, hi]` array.
18    pub fn from_lo_hi([lo, hi]: [T; 2]) -> Self {
19        Self([lo, hi])
20    }
21    /// Create a new [HiLo] from a `[hi, lo]` array.
22    pub fn from_hi_lo([hi, lo]: [T; 2]) -> Self {
23        Self([lo, hi])
24    }
25    pub fn hi(&self) -> T
26    where
27        T: Copy,
28    {
29        self.0[1]
30    }
31    pub fn lo(&self) -> T
32    where
33        T: Copy,
34    {
35        self.0[0]
36    }
37    pub fn hi_lo(&self) -> [T; 2]
38    where
39        T: Copy,
40    {
41        [self.hi(), self.lo()]
42    }
43    pub fn flatten(&self) -> [T; 2]
44    where
45        T: Copy,
46    {
47        self.hi_lo()
48    }
49}
50
51impl<F: Field> HiLo<F> {
52    pub fn assign(&self, ctx: &mut Context<F>) -> HiLo<AssignedValue<F>> {
53        HiLo(self.0.map(|x| ctx.load_witness(x)))
54    }
55}
56
57impl<T: Clone> From<Word<T>> for HiLo<T> {
58    fn from(word: Word<T>) -> Self {
59        Self::from_hi_lo([word.hi(), word.lo()])
60    }
61}
62
63impl<T: Clone> From<HiLo<T>> for Word<T> {
64    fn from(lohi: HiLo<T>) -> Self {
65        Word::new(lohi.0)
66    }
67}
68
69impl<F: Field> From<H256> for HiLo<F> {
70    fn from(value: H256) -> Self {
71        encode_h256_to_hilo(&value)
72    }
73}
74
75impl<T> TryFrom<Vec<T>> for HiLo<T> {
76    type Error = Error;
77
78    fn try_from(value: Vec<T>) -> Result<Self> {
79        let [hi, lo] = value
80            .try_into()
81            .map_err(|_| Error::new(ErrorKind::InvalidInput, "invalid array length"))?;
82        Ok(Self::from_hi_lo([hi, lo]))
83    }
84}
85
86/// We will only flatten HiLo to uint128 words.
87pub const BITS_PER_FE_HILO: [usize; 2] = [128, 128];
88impl_flatten_conversion!(HiLo, BITS_PER_FE_HILO);
89
90impl<T: std::fmt::Debug> std::fmt::Debug for HiLo<T> {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        f.debug_tuple("HiLo").field(&self.0[1]).field(&self.0[0]).finish()
93    }
94}