alloy_eips/eip4844/
utils.rs1#[cfg(feature = "kzg")]
7use crate::eip4844::Blob;
8use crate::eip4844::{FIELD_ELEMENT_BYTES_USIZE, USABLE_BITS_PER_FIELD_ELEMENT};
9
10pub const fn fits_in_fe(data: &[u8]) -> bool {
12 const FIELD_ELEMENT_BYTES_USIZE_PLUS_ONE: usize = FIELD_ELEMENT_BYTES_USIZE + 1;
13
14 match data.len() {
15 FIELD_ELEMENT_BYTES_USIZE_PLUS_ONE.. => false,
16 FIELD_ELEMENT_BYTES_USIZE => data[0] & 0b1100_0000 == 0, _ => true,
18 }
19}
20
21pub const fn minimum_fe_for_bytes(bytes: usize) -> usize {
24 (bytes * 8).div_ceil(USABLE_BITS_PER_FIELD_ELEMENT)
25}
26
27pub const fn minimum_fe(data: &[u8]) -> usize {
29 minimum_fe_for_bytes(data.len())
30}
31
32#[cfg(feature = "kzg")]
36pub fn bytes_to_blob<B: AsRef<[u8]>>(blob: B) -> Result<Blob, c_kzg::Error> {
37 let b_ref = blob.as_ref();
38 Blob::try_from(b_ref).map_err(|_| {
39 c_kzg::Error::InvalidBytesLength(format!(
41 "Invalid byte length. Expected {} got {}",
42 crate::eip4844::BYTES_PER_BLOB,
43 b_ref.len(),
44 ))
45 })
46}
47
48#[cfg(feature = "kzg")]
52pub fn hex_to_blob<B: AsRef<str>>(blob: B) -> Result<Blob, c_kzg::Error> {
53 let b_ref = blob.as_ref();
54 alloy_primitives::hex::decode(b_ref)
55 .map_err(|e| c_kzg::Error::InvalidHexFormat(format!("Failed to decode hex: {}", e)))
56 .and_then(bytes_to_blob)
57}
58
59#[derive(Clone, Copy, Debug)]
61pub struct WholeFe<'a>(&'a [u8]);
62
63impl<'a> WholeFe<'a> {
64 pub(crate) const fn new_unchecked(data: &'a [u8]) -> Self {
65 Self(data)
66 }
67
68 pub const fn new(data: &'a [u8]) -> Option<Self> {
71 if data.len() == FIELD_ELEMENT_BYTES_USIZE && fits_in_fe(data) {
72 Some(Self::new_unchecked(data))
73 } else {
74 None
75 }
76 }
77}
78
79impl AsRef<[u8]> for WholeFe<'_> {
80 fn as_ref(&self) -> &[u8] {
81 self.0
82 }
83}
84
85#[cfg(test)]
86mod test {
87 use crate::eip4844::{FIELD_ELEMENTS_PER_BLOB, USABLE_BYTES_PER_BLOB};
88
89 use super::*;
90 #[test]
91 fn calc_required_fe() {
92 assert_eq!(minimum_fe(&[0u8; 32]), 2);
93 assert_eq!(minimum_fe(&[0u8; 31]), 1);
94 assert_eq!(minimum_fe(&[0u8; 33]), 2);
95 assert_eq!(minimum_fe(&[0u8; 64]), 3);
96 assert_eq!(minimum_fe(&[0u8; 65]), 3);
97 assert_eq!(minimum_fe_for_bytes(USABLE_BYTES_PER_BLOB), FIELD_ELEMENTS_PER_BLOB as usize);
98 }
99
100 #[test]
101 fn calc_is_valid_field_element() {
102 assert!(fits_in_fe(&[0u8; 32]));
103 assert!(!fits_in_fe(&[0u8; 33]));
104
105 assert!(WholeFe::new(&[0u8; 32]).is_some());
106 assert!(WholeFe::new(&[0u8; 33]).is_none());
107 assert!(WholeFe::new(&[0u8; 31]).is_none());
108 }
109}