Skip to main content

espresso_types/v0/impls/
chain_config.rs

1use alloy::primitives::U256;
2use espresso_utils::{
3    impl_serde_from_string_or_integer, impl_to_fixed_bytes, ser::FromStringOrInteger,
4};
5
6use super::parse_size;
7use crate::{BlockSize, ChainId};
8
9impl_serde_from_string_or_integer!(ChainId);
10impl_to_fixed_bytes!(ChainId, U256);
11
12impl FromStringOrInteger for ChainId {
13    type Binary = ethers_core::types::U256;
14    type Integer = u64;
15
16    fn from_binary(b: Self::Binary) -> anyhow::Result<Self> {
17        Ok(Self(U256::from_limbs(b.0)))
18    }
19
20    fn from_integer(i: Self::Integer) -> anyhow::Result<Self> {
21        Ok(i.into())
22    }
23
24    fn from_string(s: String) -> anyhow::Result<Self> {
25        if let Some(stripped) = s.strip_prefix("0x") {
26            Ok(Self(U256::from_str_radix(stripped, 16)?))
27        } else {
28            Ok(Self(U256::from_str_radix(&s, 10)?))
29        }
30    }
31
32    fn to_binary(&self) -> anyhow::Result<Self::Binary> {
33        Ok(ethers_core::types::U256(self.0.into_limbs()))
34    }
35
36    fn to_string(&self) -> anyhow::Result<String> {
37        Ok(format!("{self}"))
38    }
39}
40
41impl From<u64> for ChainId {
42    fn from(id: u64) -> Self {
43        Self(U256::from(id))
44    }
45}
46
47impl_serde_from_string_or_integer!(BlockSize);
48
49impl FromStringOrInteger for BlockSize {
50    type Binary = u64;
51    type Integer = u64;
52
53    fn from_binary(b: Self::Binary) -> anyhow::Result<Self> {
54        Ok(Self(b))
55    }
56
57    fn from_integer(i: Self::Integer) -> anyhow::Result<Self> {
58        Ok(Self(i))
59    }
60
61    fn from_string(s: String) -> anyhow::Result<Self> {
62        Ok(parse_size(&s)?.into())
63    }
64
65    fn to_binary(&self) -> anyhow::Result<Self::Binary> {
66        Ok(self.0)
67    }
68
69    fn to_string(&self) -> anyhow::Result<String> {
70        Ok(format!("{self}"))
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use crate::v0_3::{ChainConfig, ResolvableChainConfig};
78
79    #[test]
80    fn decaf_chain_id_value() {
81        use crate::v0_1::DECAF_CHAIN_ID;
82        assert_eq!(DECAF_CHAIN_ID, ChainId(U256::from(0xdecafu64)));
83        assert_ne!(DECAF_CHAIN_ID, ChainConfig::default().chain_id);
84    }
85
86    #[test]
87    fn test_chainid_serde_json_as_decimal() {
88        let id = ChainId::from(123);
89        let serialized = serde_json::to_string(&id).unwrap();
90
91        // The value is serialized as a decimal string.
92        assert_eq!(serialized, "\"123\"");
93
94        // Deserialization produces the original value
95        let deserialized: ChainId = serde_json::from_str(&serialized).unwrap();
96        assert_eq!(deserialized, id);
97    }
98
99    #[test]
100    fn test_chainid_serde_json_from_hex() {
101        // For backwards compatibility, chain ID can also be deserialized from a 0x-prefixed hex
102        // string.
103        let id: ChainId = serde_json::from_str("\"0x123\"").unwrap();
104        assert_eq!(id, ChainId::from(0x123));
105    }
106
107    #[test]
108    fn test_chainid_serde_json_from_number() {
109        // For convenience, chain ID can also be deserialized from a decimal number.
110        let id: ChainId = serde_json::from_str("123").unwrap();
111        assert_eq!(id, ChainId::from(123));
112    }
113
114    #[test]
115    fn test_chainid_serde_bincode_unchanged() {
116        // For non-human-readable formats, ChainId just serializes as the underlying U256.
117        // note: for backward compat, it has to be the same as ethers' U256 instead of alloy's
118        let n = ethers_core::types::U256::from(123);
119        let id = ChainId(U256::from(123));
120        assert_eq!(
121            bincode::serialize(&n).unwrap(),
122            bincode::serialize(&id).unwrap(),
123        );
124    }
125
126    #[test]
127    fn test_block_size_serde_json_as_decimal() {
128        let size = BlockSize::from(123);
129        let serialized = serde_json::to_string(&size).unwrap();
130
131        // The value is serialized as a decimal string.
132        assert_eq!(serialized, "\"123\"");
133
134        // Deserialization produces the original value
135        let deserialized: BlockSize = serde_json::from_str(&serialized).unwrap();
136        assert_eq!(deserialized, size);
137    }
138
139    #[test]
140    fn test_block_size_serde_json_from_number() {
141        // For backwards compatibility, block size can also be deserialized from a decimal number.
142        let size: BlockSize = serde_json::from_str("123").unwrap();
143        assert_eq!(size, BlockSize::from(123));
144    }
145
146    #[test]
147    fn test_block_size_serde_bincode_unchanged() {
148        // For non-human-readable formats, BlockSize just serializes as the underlying u64.
149        let n = 123u64;
150        let size = BlockSize(n);
151        assert_eq!(
152            bincode::serialize(&n).unwrap(),
153            bincode::serialize(&size).unwrap(),
154        );
155    }
156
157    #[test]
158    fn test_chain_config_equality() {
159        let chain_config = ChainConfig::default();
160        assert_eq!(chain_config, chain_config.clone());
161        let ChainConfig {
162            chain_id,
163            max_block_size,
164            ..
165        } = chain_config;
166        let other_config = ChainConfig {
167            chain_id,
168            max_block_size,
169            base_fee: 1.into(),
170            ..Default::default()
171        };
172        assert!(chain_config != other_config);
173    }
174
175    #[test]
176    fn test_resolve_chain_config() {
177        let chain_config = ChainConfig::default();
178        let resolvable: ResolvableChainConfig = chain_config.into();
179        assert_eq!(chain_config, resolvable.resolve().unwrap());
180    }
181}