1use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
4use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound};
5use scale_info::TypeInfo;
6use sp_core::{H160, H256, U256};
7use sp_runtime::RuntimeDebug;
8use sp_std::{boxed::Box, iter::repeat, prelude::*};
9
10use crate::config::{PUBKEY_SIZE, SIGNATURE_SIZE};
11
12#[cfg(feature = "std")]
13use serde::{Deserialize, Deserializer, Serialize, Serializer};
14
15#[cfg(feature = "std")]
16use crate::serde_utils::HexVisitor;
17
18use crate::ssz::{
19 hash_tree_root, SSZBeaconBlockHeader, SSZExecutionPayloadHeader, SSZForkData, SSZSigningData,
20 SSZSyncAggregate, SSZSyncCommittee,
21};
22use ssz_rs::SimpleSerializeError;
23
24pub use crate::bits::decompress_sync_committee_bits;
25
26use crate::bls::{prepare_g1_pubkeys, prepare_milagro_pubkey, BlsError};
27use milagro_bls::PublicKey as PublicKeyPrepared;
28
29pub type ValidatorIndex = u64;
30pub type ForkVersion = [u8; 4];
31
32#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
33pub struct ForkVersions {
34 pub genesis: Fork,
35 pub altair: Fork,
36 pub bellatrix: Fork,
37 pub capella: Fork,
38 pub deneb: Fork,
39 pub electra: Fork,
40}
41
42#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
43pub struct Fork {
44 pub version: [u8; 4],
45 pub epoch: u64,
46}
47
48#[derive(Copy, Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
49pub struct PublicKey(pub [u8; PUBKEY_SIZE]);
50
51impl Default for PublicKey {
52 fn default() -> Self {
53 PublicKey([0u8; PUBKEY_SIZE])
54 }
55}
56
57impl From<[u8; PUBKEY_SIZE]> for PublicKey {
58 fn from(v: [u8; PUBKEY_SIZE]) -> Self {
59 Self(v)
60 }
61}
62
63impl MaxEncodedLen for PublicKey {
64 fn max_encoded_len() -> usize {
65 PUBKEY_SIZE
66 }
67}
68
69#[cfg(feature = "std")]
70impl<'de> Deserialize<'de> for PublicKey {
71 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
72 where
73 D: Deserializer<'de>,
74 {
75 deserializer.deserialize_str(HexVisitor::<PUBKEY_SIZE>()).map(|v| v.into())
76 }
77}
78
79#[cfg(feature = "std")]
80impl Serialize for PublicKey {
81 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82 where
83 S: Serializer,
84 {
85 serializer.serialize_bytes(&self.0)
86 }
87}
88
89#[derive(Copy, Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
90pub struct Signature(pub [u8; SIGNATURE_SIZE]);
91
92impl Default for Signature {
93 fn default() -> Self {
94 Signature([0u8; SIGNATURE_SIZE])
95 }
96}
97
98impl From<[u8; SIGNATURE_SIZE]> for Signature {
99 fn from(v: [u8; SIGNATURE_SIZE]) -> Self {
100 Self(v)
101 }
102}
103
104#[cfg(feature = "std")]
105impl<'de> Deserialize<'de> for Signature {
106 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
107 where
108 D: Deserializer<'de>,
109 {
110 deserializer.deserialize_str(HexVisitor::<SIGNATURE_SIZE>()).map(|v| v.into())
111 }
112}
113
114#[derive(Copy, Clone, Default, Encode, Decode, TypeInfo, MaxEncodedLen)]
115pub struct FinalizedHeaderState {
116 pub beacon_block_root: H256,
117 pub beacon_slot: u64,
118}
119
120#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug)]
121pub struct ForkData {
122 pub current_version: [u8; 4],
124 pub genesis_validators_root: [u8; 32],
125}
126
127impl ForkData {
128 pub fn hash_tree_root(&self) -> Result<H256, SimpleSerializeError> {
129 hash_tree_root::<SSZForkData>(self.clone().into())
130 }
131}
132
133#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug)]
134pub struct SigningData {
135 pub object_root: H256,
136 pub domain: H256,
137}
138
139impl SigningData {
140 pub fn hash_tree_root(&self) -> Result<H256, SimpleSerializeError> {
141 hash_tree_root::<SSZSigningData>(self.clone().into())
142 }
143}
144
145#[derive(
147 Encode,
148 Decode,
149 DecodeWithMemTracking,
150 PartialEqNoBound,
151 CloneNoBound,
152 RuntimeDebugNoBound,
153 TypeInfo,
154 MaxEncodedLen,
155)]
156#[cfg_attr(
157 feature = "std",
158 derive(Serialize, Deserialize),
159 serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = ""))
160)]
161#[codec(mel_bound())]
162pub struct SyncCommittee<const COMMITTEE_SIZE: usize> {
163 #[cfg_attr(feature = "std", serde(with = "crate::serde_utils::arrays"))]
164 pub pubkeys: [PublicKey; COMMITTEE_SIZE],
165 pub aggregate_pubkey: PublicKey,
166}
167
168impl<const COMMITTEE_SIZE: usize> Default for SyncCommittee<COMMITTEE_SIZE> {
169 fn default() -> Self {
170 SyncCommittee {
171 pubkeys: [Default::default(); COMMITTEE_SIZE],
172 aggregate_pubkey: Default::default(),
173 }
174 }
175}
176
177impl<const COMMITTEE_SIZE: usize> SyncCommittee<COMMITTEE_SIZE> {
178 pub fn hash_tree_root(&self) -> Result<H256, SimpleSerializeError> {
179 hash_tree_root::<SSZSyncCommittee<COMMITTEE_SIZE>>(self.clone().into())
180 }
181}
182
183#[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)]
185pub struct SyncCommitteePrepared<const COMMITTEE_SIZE: usize> {
186 pub root: H256,
187 pub pubkeys: Box<[PublicKeyPrepared; COMMITTEE_SIZE]>,
188 pub aggregate_pubkey: PublicKeyPrepared,
189}
190
191impl<const COMMITTEE_SIZE: usize> Default for SyncCommitteePrepared<COMMITTEE_SIZE> {
192 fn default() -> Self {
193 let pubkeys: Vec<PublicKeyPrepared> =
194 repeat(PublicKeyPrepared::default()).take(COMMITTEE_SIZE).collect();
195 let pubkeys: Box<[PublicKeyPrepared; COMMITTEE_SIZE]> =
196 Box::new(pubkeys.try_into().map_err(|_| ()).expect("checked statically; qed"));
197
198 SyncCommitteePrepared {
199 root: H256::default(),
200 pubkeys,
201 aggregate_pubkey: PublicKeyPrepared::default(),
202 }
203 }
204}
205
206impl<const COMMITTEE_SIZE: usize> TryFrom<&SyncCommittee<COMMITTEE_SIZE>>
207 for SyncCommitteePrepared<COMMITTEE_SIZE>
208{
209 type Error = BlsError;
210
211 fn try_from(sync_committee: &SyncCommittee<COMMITTEE_SIZE>) -> Result<Self, Self::Error> {
212 let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys)?;
213 let sync_committee_root = sync_committee.hash_tree_root().expect("checked statically; qed");
214
215 Ok(SyncCommitteePrepared::<COMMITTEE_SIZE> {
216 pubkeys: g1_pubkeys.try_into().map_err(|_| ()).expect("checked statically; qed"),
217 aggregate_pubkey: prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?,
218 root: sync_committee_root,
219 })
220 }
221}
222
223#[derive(
226 Copy,
227 Clone,
228 Default,
229 Encode,
230 Decode,
231 DecodeWithMemTracking,
232 PartialEq,
233 RuntimeDebug,
234 TypeInfo,
235 MaxEncodedLen,
236)]
237#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
238pub struct BeaconHeader {
239 pub slot: u64,
242 pub proposer_index: ValidatorIndex,
244 pub parent_root: H256,
246 pub state_root: H256,
248 pub body_root: H256,
250}
251
252impl BeaconHeader {
253 pub fn hash_tree_root(&self) -> Result<H256, SimpleSerializeError> {
254 hash_tree_root::<SSZBeaconBlockHeader>((*self).into())
255 }
256}
257
258#[derive(
259 Encode,
260 Decode,
261 DecodeWithMemTracking,
262 CloneNoBound,
263 PartialEqNoBound,
264 RuntimeDebugNoBound,
265 TypeInfo,
266)]
267#[cfg_attr(
268 feature = "std",
269 derive(Deserialize),
270 serde(
271 try_from = "IntermediateSyncAggregate",
272 deny_unknown_fields,
273 bound(serialize = ""),
274 bound(deserialize = "")
275 )
276)]
277#[codec(mel_bound())]
278pub struct SyncAggregate<const COMMITTEE_SIZE: usize, const COMMITTEE_BITS_SIZE: usize> {
279 pub sync_committee_bits: [u8; COMMITTEE_BITS_SIZE],
280 pub sync_committee_signature: Signature,
281}
282
283impl<const COMMITTEE_SIZE: usize, const COMMITTEE_BITS_SIZE: usize> Default
284 for SyncAggregate<COMMITTEE_SIZE, COMMITTEE_BITS_SIZE>
285{
286 fn default() -> Self {
287 SyncAggregate {
288 sync_committee_bits: [0; COMMITTEE_BITS_SIZE],
289 sync_committee_signature: Default::default(),
290 }
291 }
292}
293
294impl<const COMMITTEE_SIZE: usize, const COMMITTEE_BITS_SIZE: usize>
295 SyncAggregate<COMMITTEE_SIZE, COMMITTEE_BITS_SIZE>
296{
297 pub fn hash_tree_root(&self) -> Result<H256, SimpleSerializeError> {
298 hash_tree_root::<SSZSyncAggregate<COMMITTEE_SIZE>>(self.clone().into())
299 }
300}
301
302#[cfg(feature = "std")]
304#[derive(Deserialize)]
305struct IntermediateSyncAggregate {
306 #[cfg_attr(feature = "std", serde(deserialize_with = "crate::serde_utils::from_hex_to_bytes"))]
307 pub sync_committee_bits: Vec<u8>,
308 pub sync_committee_signature: Signature,
309}
310
311#[cfg(feature = "std")]
312impl<const COMMITTEE_SIZE: usize, const COMMITTEE_BITS_SIZE: usize>
313 TryFrom<IntermediateSyncAggregate> for SyncAggregate<COMMITTEE_SIZE, COMMITTEE_BITS_SIZE>
314{
315 type Error = String;
316
317 fn try_from(other: IntermediateSyncAggregate) -> Result<Self, Self::Error> {
318 Ok(Self {
319 sync_committee_bits: other
320 .sync_committee_bits
321 .try_into()
322 .map_err(|_| "unexpected length".to_owned())?,
323 sync_committee_signature: other.sync_committee_signature,
324 })
325 }
326}
327
328#[derive(
331 Default,
332 Encode,
333 Decode,
334 DecodeWithMemTracking,
335 CloneNoBound,
336 PartialEqNoBound,
337 RuntimeDebugNoBound,
338 TypeInfo,
339)]
340#[cfg_attr(
341 feature = "std",
342 derive(Serialize, Deserialize),
343 serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = ""))
344)]
345#[codec(mel_bound())]
346pub struct ExecutionPayloadHeader {
347 pub parent_hash: H256,
348 pub fee_recipient: H160,
349 pub state_root: H256,
350 pub receipts_root: H256,
351 #[cfg_attr(feature = "std", serde(deserialize_with = "crate::serde_utils::from_hex_to_bytes"))]
352 pub logs_bloom: Vec<u8>,
353 pub prev_randao: H256,
354 pub block_number: u64,
355 pub gas_limit: u64,
356 pub gas_used: u64,
357 pub timestamp: u64,
358 #[cfg_attr(feature = "std", serde(deserialize_with = "crate::serde_utils::from_hex_to_bytes"))]
359 pub extra_data: Vec<u8>,
360 #[cfg_attr(feature = "std", serde(deserialize_with = "crate::serde_utils::from_int_to_u256"))]
361 pub base_fee_per_gas: U256,
362 pub block_hash: H256,
363 pub transactions_root: H256,
364 pub withdrawals_root: H256,
365}
366
367impl ExecutionPayloadHeader {
368 pub fn hash_tree_root(&self) -> Result<H256, SimpleSerializeError> {
369 hash_tree_root::<SSZExecutionPayloadHeader>(self.clone().try_into()?)
370 }
371}
372
373#[derive(
374 Default,
375 Encode,
376 Decode,
377 Copy,
378 Clone,
379 PartialEqNoBound,
380 RuntimeDebugNoBound,
381 TypeInfo,
382 MaxEncodedLen,
383)]
384pub struct CompactBeaconState {
385 #[codec(compact)]
386 pub slot: u64,
387 pub block_roots_root: H256,
388}
389
390#[derive(
392 Encode,
393 Decode,
394 DecodeWithMemTracking,
395 CloneNoBound,
396 PartialEqNoBound,
397 RuntimeDebugNoBound,
398 TypeInfo,
399)]
400#[cfg_attr(
401 feature = "std",
402 derive(Serialize, Deserialize),
403 serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = ""))
404)]
405#[codec(mel_bound())]
406pub enum VersionedExecutionPayloadHeader {
407 Capella(ExecutionPayloadHeader),
408 Deneb(deneb::ExecutionPayloadHeader),
409}
410
411impl VersionedExecutionPayloadHeader {
412 pub fn hash_tree_root(&self) -> Result<H256, SimpleSerializeError> {
413 match self {
414 VersionedExecutionPayloadHeader::Capella(execution_payload_header) =>
415 hash_tree_root::<SSZExecutionPayloadHeader>(
416 execution_payload_header.clone().try_into()?,
417 ),
418 VersionedExecutionPayloadHeader::Deneb(execution_payload_header) =>
419 hash_tree_root::<crate::ssz::deneb::SSZExecutionPayloadHeader>(
420 execution_payload_header.clone().try_into()?,
421 ),
422 }
423 }
424
425 pub fn block_hash(&self) -> H256 {
426 match self {
427 VersionedExecutionPayloadHeader::Capella(execution_payload_header) =>
428 execution_payload_header.block_hash,
429 VersionedExecutionPayloadHeader::Deneb(execution_payload_header) =>
430 execution_payload_header.block_hash,
431 }
432 }
433
434 pub fn block_number(&self) -> u64 {
435 match self {
436 VersionedExecutionPayloadHeader::Capella(execution_payload_header) =>
437 execution_payload_header.block_number,
438 VersionedExecutionPayloadHeader::Deneb(execution_payload_header) =>
439 execution_payload_header.block_number,
440 }
441 }
442
443 pub fn receipts_root(&self) -> H256 {
444 match self {
445 VersionedExecutionPayloadHeader::Capella(execution_payload_header) =>
446 execution_payload_header.receipts_root,
447 VersionedExecutionPayloadHeader::Deneb(execution_payload_header) =>
448 execution_payload_header.receipts_root,
449 }
450 }
451}
452
453#[derive(
454 Encode,
455 Decode,
456 DecodeWithMemTracking,
457 CloneNoBound,
458 PartialEqNoBound,
459 RuntimeDebugNoBound,
460 TypeInfo,
461)]
462#[cfg_attr(
463 feature = "std",
464 derive(serde::Deserialize),
465 serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = ""))
466)]
467pub struct ExecutionProof {
468 pub header: BeaconHeader,
470 pub ancestry_proof: Option<AncestryProof>,
472 pub execution_header: VersionedExecutionPayloadHeader,
474 pub execution_branch: Vec<H256>,
476}
477
478#[derive(
479 Encode,
480 Decode,
481 DecodeWithMemTracking,
482 CloneNoBound,
483 PartialEqNoBound,
484 RuntimeDebugNoBound,
485 TypeInfo,
486)]
487#[cfg_attr(
488 feature = "std",
489 derive(serde::Deserialize),
490 serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = ""))
491)]
492pub struct AncestryProof {
493 pub header_branch: Vec<H256>,
495 pub finalized_block_root: H256,
497}
498
499#[cfg(test)]
500mod tests {
501 use super::*;
502 use hex_literal::hex;
503
504 #[test]
505 pub fn test_hash_beacon_header1() {
506 let hash_root = BeaconHeader {
507 slot: 3,
508 proposer_index: 2,
509 parent_root: hex!("796ea53efb534eab7777809cc5ee2d84e7f25024b9d0c4d7e5bcaab657e4bdbd")
510 .into(),
511 state_root: hex!("ba3ff080912be5c9c158b2e962c1b39a91bc0615762ba6fa2ecacafa94e9ae0a")
512 .into(),
513 body_root: hex!("a18d7fcefbb74a177c959160e0ee89c23546482154e6831237710414465dcae5")
514 .into(),
515 }
516 .hash_tree_root();
517
518 assert!(hash_root.is_ok());
519 assert_eq!(
520 hash_root.unwrap(),
521 hex!("7d42595818709e805dd2fa710a2d2c1f62576ef1ab7273941ac9130fb94b91f7").into()
522 );
523 }
524
525 #[test]
526 pub fn test_hash_beacon_header2() {
527 let hash_root = BeaconHeader {
528 slot: 3476424,
529 proposer_index: 314905,
530 parent_root: hex!("c069d7b49cffd2b815b0fb8007eb9ca91202ea548df6f3db60000f29b2489f28")
531 .into(),
532 state_root: hex!("444d293e4533501ee508ad608783a7d677c3c566f001313e8a02ce08adf590a3")
533 .into(),
534 body_root: hex!("6508a0241047f21ba88f05d05b15534156ab6a6f8e029a9a5423da429834e04a")
535 .into(),
536 }
537 .hash_tree_root();
538
539 assert!(hash_root.is_ok());
540 assert_eq!(
541 hash_root.unwrap(),
542 hex!("0aa41166ff01e58e111ac8c42309a738ab453cf8d7285ed8477b1c484acb123e").into()
543 );
544 }
545
546 #[test]
547 pub fn test_hash_fork_data() {
548 let hash_root = ForkData {
549 current_version: hex!("83f38a34"),
550 genesis_validators_root: hex!(
551 "22370bbbb358800f5711a10ea9845284272d8493bed0348cab87b8ab1e127930"
552 ),
553 }
554 .hash_tree_root();
555
556 assert!(hash_root.is_ok());
557 assert_eq!(
558 hash_root.unwrap(),
559 hex!("57c12c4246bc7152b174b51920506bf943eff9c7ffa50b9533708e9cc1f680fc").into()
560 );
561 }
562
563 #[test]
564 pub fn test_hash_signing_data() {
565 let hash_root = SigningData {
566 object_root: hex!("63654cbe64fc07853f1198c165dd3d49c54fc53bc417989bbcc66da15f850c54")
567 .into(),
568 domain: hex!("037da907d1c3a03c0091b2254e1480d9b1783476e228ab29adaaa8f133e08f7a").into(),
569 }
570 .hash_tree_root();
571
572 assert!(hash_root.is_ok());
573 assert_eq!(
574 hash_root.unwrap(),
575 hex!("b9eb2caf2d691b183c2d57f322afe505c078cd08101324f61c3641714789a54e").into()
576 );
577 }
578
579 #[test]
580 pub fn test_hash_sync_aggregate() {
581 let hash_root = SyncAggregate::<512, 64>{
582 sync_committee_bits: hex!("cefffffefffffff767fffbedffffeffffeeffdffffdebffffff7f7dbdf7fffdffffbffcfffdff79dfffbbfefff2ffffff7ddeff7ffffc98ff7fbfffffffffff7"),
583 sync_committee_signature: hex!("8af1a8577bba419fe054ee49b16ed28e081dda6d3ba41651634685e890992a0b675e20f8d9f2ec137fe9eb50e838aa6117f9f5410e2e1024c4b4f0e098e55144843ce90b7acde52fe7b94f2a1037342c951dc59f501c92acf7ed944cb6d2b5f7").into(),
584 }.hash_tree_root();
585
586 assert!(hash_root.is_ok());
587 assert_eq!(
588 hash_root.unwrap(),
589 hex!("e6dcad4f60ce9ff8a587b110facbaf94721f06cd810b6d8bf6cffa641272808d").into()
590 );
591 }
592
593 #[test]
594 pub fn test_hash_execution_payload() {
595 let hash_root =
596 ExecutionPayloadHeader{
597 parent_hash: hex!("eadee5ab098dde64e9fd02ae5858064bad67064070679625b09f8d82dec183f7").into(),
598 fee_recipient: hex!("f97e180c050e5ab072211ad2c213eb5aee4df134").into(),
599 state_root: hex!("564fa064c2a324c2b5978d7fdfc5d4224d4f421a45388af1ed405a399c845dff").into(),
600 receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
601 logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").to_vec(),
602 prev_randao: hex!("6bf538bdfbdf1c96ff528726a40658a91d0bda0f1351448c4c4f3604db2a0ccf").into(),
603 block_number: 477434,
604 gas_limit: 8154925,
605 gas_used: 0,
606 timestamp: 1652816940,
607 extra_data: vec![],
608 base_fee_per_gas: U256::from(7_i16),
609 block_hash: hex!("cd8df91b4503adb8f2f1c7a4f60e07a1f1a2cbdfa2a95bceba581f3ff65c1968").into(),
610 transactions_root: hex!("7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1").into(),
611 withdrawals_root: hex!("28ba1834a3a7b657460ce79fa3a1d909ab8828fd557659d4d0554a9bdbc0ec30").into(),
612 }.hash_tree_root();
613 assert!(hash_root.is_ok());
614 }
615}
616
617#[derive(Encode, Decode, Copy, Clone, PartialEq, RuntimeDebug, TypeInfo)]
619pub enum Mode {
620 Active,
621 Blocked,
622}
623
624pub mod deneb {
625 use codec::{Decode, DecodeWithMemTracking, Encode};
626 use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound};
627 use scale_info::TypeInfo;
628 #[cfg(feature = "std")]
629 use serde::{Deserialize, Serialize};
630 use sp_core::{H160, H256, U256};
631 use sp_std::prelude::*;
632
633 #[derive(
636 Default,
637 Encode,
638 Decode,
639 DecodeWithMemTracking,
640 CloneNoBound,
641 PartialEqNoBound,
642 RuntimeDebugNoBound,
643 TypeInfo,
644 )]
645 #[cfg_attr(
646 feature = "std",
647 derive(Serialize, Deserialize),
648 serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = ""))
649 )]
650 #[codec(mel_bound())]
651 pub struct ExecutionPayloadHeader {
652 pub parent_hash: H256,
653 pub fee_recipient: H160,
654 pub state_root: H256,
655 pub receipts_root: H256,
656 #[cfg_attr(
657 feature = "std",
658 serde(deserialize_with = "crate::serde_utils::from_hex_to_bytes")
659 )]
660 pub logs_bloom: Vec<u8>,
661 pub prev_randao: H256,
662 pub block_number: u64,
663 pub gas_limit: u64,
664 pub gas_used: u64,
665 pub timestamp: u64,
666 #[cfg_attr(
667 feature = "std",
668 serde(deserialize_with = "crate::serde_utils::from_hex_to_bytes")
669 )]
670 pub extra_data: Vec<u8>,
671 #[cfg_attr(
672 feature = "std",
673 serde(deserialize_with = "crate::serde_utils::from_int_to_u256")
674 )]
675 pub base_fee_per_gas: U256,
676 pub block_hash: H256,
677 pub transactions_root: H256,
678 pub withdrawals_root: H256,
679 pub blob_gas_used: u64, pub excess_blob_gas: u64, }
682}