1use alloy_primitives::FixedBytes;
7use cairo_air::utils::VerificationOutput;
8
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22pub struct BankaiBlock {
23 pub block_number: u64,
25 pub beacon: BeaconClient,
27 pub execution: ExecutionClient,
29}
30
31#[derive(Debug, Clone)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36pub struct BeaconClient {
37 pub slot_number: u64,
39 pub header_root: FixedBytes<32>,
41 pub justified_height: u64,
43 pub finalized_height: u64,
45 pub num_signers: u64,
47 pub mmr_root_keccak: FixedBytes<32>,
49 pub mmr_root_poseidon: FixedBytes<32>,
51 pub current_committee_hash: FixedBytes<32>,
53 pub next_committee_hash: FixedBytes<32>,
55}
56
57#[derive(Debug, Clone)]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62pub struct ExecutionClient {
63 pub block_number: u64,
65 pub header_hash: FixedBytes<32>,
67 pub justified_height: u64,
69 pub finalized_height: u64,
71 pub mmr_root_keccak: FixedBytes<32>,
73 pub mmr_root_poseidon: FixedBytes<32>,
75}
76
77impl BankaiBlock {
78 pub fn from_verication_output(output: &VerificationOutput) -> Self {
79 let output = &output.output;
80
81 fn bytes32_from_limbs(low: &[u8], high: &[u8]) -> FixedBytes<32> {
82 let mut bytes = [0u8; 32];
83 bytes[0..16].copy_from_slice(high);
84 bytes[16..32].copy_from_slice(low);
85 FixedBytes::from(bytes)
86 }
87
88 Self {
89 block_number: output[0].try_into().unwrap(),
90 beacon: BeaconClient {
91 slot_number: output[1].try_into().unwrap(),
92 header_root: bytes32_from_limbs(
93 &output[2].to_bytes_be()[16..],
94 &output[3].to_bytes_be()[16..],
95 ),
96 justified_height: output[4].try_into().unwrap(),
97 finalized_height: output[5].try_into().unwrap(),
98 num_signers: output[6].try_into().unwrap(),
99 mmr_root_keccak: bytes32_from_limbs(
100 &output[7].to_bytes_be()[16..],
101 &output[8].to_bytes_be()[16..],
102 ),
103 mmr_root_poseidon: FixedBytes::from_slice(output[9].to_bytes_be().as_slice()),
104 current_committee_hash: bytes32_from_limbs(
105 &output[10].to_bytes_be()[16..],
106 &output[11].to_bytes_be()[16..],
107 ),
108 next_committee_hash: bytes32_from_limbs(
109 &output[12].to_bytes_be()[16..],
110 &output[13].to_bytes_be()[16..],
111 ),
112 },
113 execution: ExecutionClient {
114 block_number: output[14].try_into().unwrap(),
115 header_hash: bytes32_from_limbs(
116 &output[15].to_bytes_be()[16..],
117 &output[16].to_bytes_be()[16..],
118 ),
119 justified_height: output[17].try_into().unwrap(),
120 finalized_height: output[18].try_into().unwrap(),
121 mmr_root_keccak: bytes32_from_limbs(
122 &output[19].to_bytes_be()[16..],
123 &output[20].to_bytes_be()[16..],
124 ),
125 mmr_root_poseidon: FixedBytes::from_slice(output[21].to_bytes_be().as_slice()),
126 },
127 }
128 }
129}