alloy_rpc_types_beacon/
sidecar.rs1use crate::header::Header;
2use alloy_eips::eip4844::{
3 deserialize_blob, deserialize_blobs, Blob, BlobTransactionSidecar, Bytes48,
4};
5use alloy_primitives::B256;
6use serde::{Deserialize, Serialize};
7use serde_with::{serde_as, DisplayFromStr};
8use std::vec::IntoIter;
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, derive_more::IntoIterator)]
14pub struct BeaconBlobBundle {
15 pub data: Vec<BlobData>,
17}
18
19impl BeaconBlobBundle {
20 pub const fn new(data: Vec<BlobData>) -> Self {
22 Self { data }
23 }
24
25 pub const fn len(&self) -> usize {
27 self.data.len()
28 }
29
30 pub const fn is_empty(&self) -> bool {
32 self.data.is_empty()
33 }
34
35 pub fn get_blob(&self, index: u64) -> Option<&BlobData> {
37 self.data.iter().find(|blob| blob.index == index)
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, derive_more::IntoIterator)]
43pub struct GetBlobsResponse {
44 #[serde(default)]
47 pub execution_optimistic: bool,
48 #[serde(default)]
52 pub finalized: bool,
53 #[serde(deserialize_with = "deserialize_blobs")]
55 #[into_iterator]
56 pub data: Vec<Blob>,
57}
58
59#[derive(Debug, Clone)]
61pub struct SidecarIterator {
62 pub iter: IntoIter<BlobData>,
64}
65
66impl Iterator for SidecarIterator {
67 type Item = BlobData;
68
69 fn next(&mut self) -> Option<Self::Item> {
70 self.iter.next()
71 }
72}
73
74impl SidecarIterator {
75 pub fn new(bundle: BeaconBlobBundle) -> Self {
77 Self { iter: bundle.into_iter() }
78 }
79
80 pub fn next_sidecar(&mut self, num_hashes: usize) -> Option<BlobTransactionSidecar> {
82 let mut blobs = Vec::with_capacity(num_hashes);
83 let mut commitments = Vec::with_capacity(num_hashes);
84 let mut proofs = Vec::with_capacity(num_hashes);
85 for _ in 0..num_hashes {
86 let next = self.next()?;
87 blobs.push(*next.blob);
88 commitments.push(next.kzg_commitment);
89 proofs.push(next.kzg_proof);
90 }
91 Some(BlobTransactionSidecar { blobs, commitments, proofs })
92 }
93}
94
95#[serde_as]
97#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
98pub struct BlobData {
99 #[serde_as(as = "DisplayFromStr")]
101 pub index: u64,
102 #[serde(deserialize_with = "deserialize_blob")]
103 pub blob: Box<Blob>,
105 pub kzg_commitment: Bytes48,
107 pub kzg_proof: Bytes48,
109 pub signed_block_header: Header,
111 pub kzg_commitment_inclusion_proof: Vec<B256>,
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use similar_asserts::assert_eq;
119
120 #[test]
122 fn serde_sidecar_bundle() {
123 let s = include_str!("examples/sidecar.json");
124 let resp: BeaconBlobBundle = serde_json::from_str(s).unwrap();
125 let json: serde_json::Value = serde_json::from_str(s).unwrap();
126 assert_eq!(json, serde_json::to_value(resp.clone()).unwrap());
127 assert_eq!(6, resp.data.len());
128 }
129}