@@ -5,6 +5,7 @@ use ssz::{Decode, DecodeError, Encode};
55use ssz_types:: { typenum:: U128 , VariableList } ;
66
77use crate :: {
8+ consensus:: historical_summaries:: { HistoricalSummaries , HistoricalSummariesWithProofElectra } ,
89 light_client:: {
910 bootstrap:: { LightClientBootstrapDeneb , LightClientBootstrapElectra } ,
1011 finality_update:: { LightClientFinalityUpdateDeneb , LightClientFinalityUpdateElectra } ,
@@ -14,7 +15,7 @@ use crate::{
1415 types:: {
1516 consensus:: {
1617 fork:: { ForkDigest , ForkName } ,
17- historical_summaries:: HistoricalSummariesWithProof ,
18+ historical_summaries:: HistoricalSummariesWithProofDeneb ,
1819 light_client:: {
1920 bootstrap:: {
2021 LightClientBootstrap , LightClientBootstrapBellatrix ,
@@ -477,57 +478,116 @@ impl Encode for ForkVersionedLightClientFinalityUpdate {
477478
478479/// A wrapper type including a `ForkName` and `HistoricalSummariesWithProof`
479480#[ derive( Clone , Debug , PartialEq ) ]
480- pub struct ForkVersionedHistoricalSummariesWithProof {
481- pub fork_name : ForkName ,
482- pub historical_summaries_with_proof : HistoricalSummariesWithProof ,
481+ pub enum ForkVersionedHistoricalSummariesWithProof {
482+ Deneb ( HistoricalSummariesWithProofDeneb ) ,
483+ Electra ( HistoricalSummariesWithProofElectra ) ,
483484}
484485
485486impl ForkVersionedHistoricalSummariesWithProof {
486- pub fn encode ( & self ) -> Vec < u8 > {
487- let fork_digest = self . fork_name . as_fork_digest ( ) ;
488-
489- let mut data = fork_digest. to_vec ( ) ;
490- data. extend ( self . historical_summaries_with_proof . as_ssz_bytes ( ) ) ;
491- data
487+ pub fn epoch ( & self ) -> u64 {
488+ match self {
489+ Self :: Deneb ( historical_summaries_with_proof) => historical_summaries_with_proof. epoch ,
490+ Self :: Electra ( historical_summaries_with_proof) => historical_summaries_with_proof. epoch ,
491+ }
492492 }
493493
494- pub fn decode ( buf : & [ u8 ] ) -> Result < Self , DecodeError > {
495- let fork_digest = ForkDigest :: try_from ( & buf[ 0 ..4 ] ) . map_err ( |err| {
496- DecodeError :: BytesInvalid ( format ! ( "Unable to decode fork digest: {err:?}" ) )
497- } ) ?;
498- let fork_name = ForkName :: try_from ( fork_digest) . map_err ( |_| {
499- DecodeError :: BytesInvalid ( format ! ( "Unable to decode fork name: {fork_digest:?}" ) )
500- } ) ?;
501- let summaries_with_proof = HistoricalSummariesWithProof :: from_ssz_bytes ( & buf[ 4 ..] ) ?;
494+ pub fn fork_name ( & self ) -> ForkName {
495+ match self {
496+ Self :: Deneb ( _) => ForkName :: Deneb ,
497+ Self :: Electra ( _) => ForkName :: Electra ,
498+ }
499+ }
500+ }
502501
503- Ok ( Self {
504- fork_name,
505- historical_summaries_with_proof : summaries_with_proof,
506- } )
502+ impl From < ForkVersionedHistoricalSummariesWithProof > for HistoricalSummaries {
503+ fn from ( historical_summaries_with_proof : ForkVersionedHistoricalSummariesWithProof ) -> Self {
504+ match historical_summaries_with_proof {
505+ ForkVersionedHistoricalSummariesWithProof :: Deneb ( historical_summaries_with_proof) => {
506+ historical_summaries_with_proof. historical_summaries
507+ }
508+ ForkVersionedHistoricalSummariesWithProof :: Electra ( historical_summaries_with_proof) => {
509+ historical_summaries_with_proof. historical_summaries
510+ }
511+ }
507512 }
508513}
509514
510- impl Decode for ForkVersionedHistoricalSummariesWithProof {
515+ impl Encode for ForkVersionedHistoricalSummariesWithProof {
511516 fn is_ssz_fixed_len ( ) -> bool {
512517 false
513518 }
514519
515- fn from_ssz_bytes ( bytes : & [ u8 ] ) -> Result < Self , DecodeError > {
516- Self :: decode ( bytes)
520+ fn ssz_append ( & self , buf : & mut Vec < u8 > ) {
521+ self . fork_name ( ) . as_fork_digest ( ) . ssz_append ( buf) ;
522+ match self {
523+ Self :: Deneb ( historical_summaries_with_proof) => {
524+ historical_summaries_with_proof. ssz_append ( buf)
525+ }
526+ Self :: Electra ( historical_summaries_with_proof) => {
527+ historical_summaries_with_proof. ssz_append ( buf)
528+ }
529+ }
530+ }
531+
532+ fn ssz_fixed_len ( ) -> usize {
533+ ssz:: BYTES_PER_LENGTH_OFFSET
534+ }
535+
536+ fn ssz_bytes_len ( & self ) -> usize {
537+ let fork_digest_len = self . fork_name ( ) . as_fork_digest ( ) . ssz_bytes_len ( ) ;
538+ let historical_summaries_with_proof_len = match self {
539+ Self :: Deneb ( historical_summaries_with_proof) => {
540+ historical_summaries_with_proof. ssz_bytes_len ( )
541+ }
542+ Self :: Electra ( historical_summaries_with_proof) => {
543+ historical_summaries_with_proof. ssz_bytes_len ( )
544+ }
545+ } ;
546+ fork_digest_len + historical_summaries_with_proof_len
517547 }
518548}
519549
520- impl Encode for ForkVersionedHistoricalSummariesWithProof {
550+ impl Decode for ForkVersionedHistoricalSummariesWithProof {
521551 fn is_ssz_fixed_len ( ) -> bool {
522552 false
523553 }
524554
525- fn ssz_append ( & self , buf : & mut Vec < u8 > ) {
526- buf . extend_from_slice ( & self . encode ( ) ) ;
555+ fn ssz_fixed_len ( ) -> usize {
556+ ssz :: BYTES_PER_LENGTH_OFFSET
527557 }
528558
529- fn ssz_bytes_len ( & self ) -> usize {
530- self . encode ( ) . len ( )
559+ fn from_ssz_bytes ( bytes : & [ u8 ] ) -> Result < Self , DecodeError > {
560+ let fork_digest_len = <ForkDigest as Decode >:: ssz_fixed_len ( ) ;
561+ let Some ( ( fork_digest_bytes, historical_summaries_with_proof_bytes) ) =
562+ bytes. split_at_checked ( fork_digest_len)
563+ else {
564+ return Err ( DecodeError :: InvalidByteLength {
565+ len : bytes. len ( ) ,
566+ expected : fork_digest_len,
567+ } ) ;
568+ } ;
569+
570+ let fork_digest = ForkDigest :: from_ssz_bytes ( fork_digest_bytes) ?;
571+ let fork_name = match ForkName :: try_from ( fork_digest) {
572+ Ok ( fork_name) => fork_name,
573+ Err ( err) => return Err ( DecodeError :: BytesInvalid ( err. to_string ( ) ) ) ,
574+ } ;
575+
576+ match fork_name {
577+ ForkName :: Bellatrix | ForkName :: Capella => Err ( DecodeError :: BytesInvalid ( format ! (
578+ "HistoricalSummariesWithProof not supported for fork digest: {fork_digest:?}"
579+ ) ) ) ,
580+ ForkName :: Deneb => Ok ( Self :: Deneb (
581+ HistoricalSummariesWithProofDeneb :: from_ssz_bytes (
582+ historical_summaries_with_proof_bytes,
583+ ) ?,
584+ ) ) ,
585+ ForkName :: Electra => Ok ( Self :: Electra (
586+ HistoricalSummariesWithProofElectra :: from_ssz_bytes (
587+ historical_summaries_with_proof_bytes,
588+ ) ?,
589+ ) ) ,
590+ }
531591 }
532592}
533593
@@ -710,11 +770,15 @@ mod test {
710770
711771 match & beacon_content {
712772 BeaconContentValue :: HistoricalSummariesWithProof ( content) => {
713- assert_eq ! (
714- expected_epoch,
715- content. historical_summaries_with_proof. epoch
716- ) ;
717- assert_eq ! ( ForkName :: Deneb , content. fork_name) ;
773+ assert_eq ! ( ForkName :: Deneb , content. fork_name( ) ) ;
774+
775+ let ForkVersionedHistoricalSummariesWithProof :: Deneb (
776+ historical_summaries_with_proof,
777+ ) = content
778+ else {
779+ panic ! ( "Expected Deneb historical summaries, actual: {content:?}" ) ;
780+ } ;
781+ assert_eq ! ( expected_epoch, historical_summaries_with_proof. epoch) ;
718782 }
719783 _ => panic ! ( "Invalid beacon content type!" ) ,
720784 }
0 commit comments