diff --git a/CHANGELOG.md b/CHANGELOG.md index cc2c7651bb00..b7897867da55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning. -## [Unreleased](https://github.com/prysmaticlabs/prysm/compare/v5.1.2...HEAD) +## [Unreleased](https://github.com/prysmaticlabs/prysm/compare/v5.1.1...HEAD) ### Added @@ -30,8 +30,6 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve - Return false from HasBlock if the block is being synced. - Cleanup forkchoice on failed insertions. - Use read only validator for core processing to avoid unnecessary copying. -- Use ROBlock across block processing pipeline. -- Added missing Eth-Consensus-Version headers to GetBlockAttestationsV2 and GetAttesterSlashingsV2 endpoints. ### Deprecated @@ -45,30 +43,12 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve - Fixed mesh size by appending `gParams.Dhi = gossipSubDhi` - Fix skipping partial withdrawals count. -- wait for the async StreamEvent writer to exit before leaving the http handler, avoiding race condition panics [pr](https://github.com/prysmaticlabs/prysm/pull/14557) -- Certain deb files were returning a 404 which made building new docker images without an existing - cache impossible. This has been fixed with updates to rules_oci and bazel-lib. -- Fixed an issue where the length check between block body KZG commitments and the existing cache from the database was incompatible. +- recover from panics when writing the event stream [pr](https://github.com/prysmaticlabs/prysm/pull/14545) +- Return the correct light client payload proof. [PR](https://github.com/prysmaticlabs/prysm/pull/14565) +- Set fields of wrapped proto object in light client setters. [PR](https://github.com/prysmaticlabs/prysm/pull/14573) ### Security -## [v5.1.2](https://github.com/prysmaticlabs/prysm/compare/v5.1.1...v5.1.2) - 2024-10-16 - -This is a hotfix release with one change. - -Prysm v5.1.1 contains an updated implementation of the beacon api streaming events endpoint. This -new implementation contains a bug that can cause a panic in certain conditions. The issue is -difficult to reproduce reliably and we are still trying to determine the root cause, but in the -meantime we are issuing a patch that recovers from the panic to prevent the node from crashing. - -This only impacts the v5.1.1 release beacon api event stream endpoints. This endpoint is used by the -prysm REST mode validator (a feature which requires the validator to be configured to use the beacon -api intead of prysm's stock grpc endpoints) or accessory software that connects to the events api, -like https://github.com/ethpandaops/ethereum-metrics-exporter - -### Fixed - -- Recover from panics when writing the event stream [#14545](https://github.com/prysmaticlabs/prysm/pull/14545) ## [v5.1.1](https://github.com/prysmaticlabs/prysm/compare/v5.1.0...v5.1.1) - 2024-10-15 @@ -102,7 +82,6 @@ Updating to this release is recommended at your convenience. - fastssz version bump (better error messages). - SSE implementation that sheds stuck clients. [pr](https://github.com/prysmaticlabs/prysm/pull/14413) - Added GetPoolAttesterSlashingsV2 endpoint. -- Use engine API get-blobs for block subscriber to reduce block import latency and potentially reduce bandwidth. ### Changed diff --git a/beacon-chain/core/light-client/lightclient.go b/beacon-chain/core/light-client/lightclient.go index 7c60a163cf05..6a822012949b 100644 --- a/beacon-chain/core/light-client/lightclient.go +++ b/beacon-chain/core/light-client/lightclient.go @@ -169,7 +169,9 @@ func NewLightClientUpdateFromBeaconState( if err != nil { return nil, errors.Wrap(err, "could not get attested light client header") } - result.SetAttestedHeader(attestedLightClientHeader) + if err = result.SetAttestedHeader(attestedLightClientHeader); err != nil { + return nil, errors.Wrap(err, "could not set attested header") + } // if update_attested_period == update_signature_period if updateAttestedPeriod == updateSignaturePeriod { @@ -208,7 +210,9 @@ func NewLightClientUpdateFromBeaconState( if err != nil { return nil, errors.Wrap(err, "could not get finalized light client header") } - result.SetFinalizedHeader(finalizedLightClientHeader) + if err = result.SetFinalizedHeader(finalizedLightClientHeader); err != nil { + return nil, errors.Wrap(err, "could not set finalized header") + } } else { // assert attested_state.finalized_checkpoint.root == Bytes32() if !bytes.Equal(attestedState.FinalizedCheckpoint().Root, make([]byte, 32)) { diff --git a/consensus-types/interfaces/light_client.go b/consensus-types/interfaces/light_client.go index 994470c65a42..89ea81f07676 100644 --- a/consensus-types/interfaces/light_client.go +++ b/consensus-types/interfaces/light_client.go @@ -36,7 +36,7 @@ type LightClientUpdate interface { Proto() proto.Message Version() int AttestedHeader() LightClientHeader - SetAttestedHeader(header LightClientHeader) + SetAttestedHeader(header LightClientHeader) error NextSyncCommittee() *pb.SyncCommittee SetNextSyncCommittee(sc *pb.SyncCommittee) NextSyncCommitteeBranch() (LightClientSyncCommitteeBranch, error) @@ -44,7 +44,7 @@ type LightClientUpdate interface { NextSyncCommitteeBranchElectra() (LightClientSyncCommitteeBranchElectra, error) SetNextSyncCommitteeBranchElectra(branch [][]byte) error FinalizedHeader() LightClientHeader - SetFinalizedHeader(header LightClientHeader) + SetFinalizedHeader(header LightClientHeader) error FinalityBranch() LightClientFinalityBranch SetFinalityBranch(branch [][]byte) error SyncAggregate() *pb.SyncAggregate diff --git a/consensus-types/light-client/update.go b/consensus-types/light-client/update.go index 81ebf87f9c69..f6fb739d2996 100644 --- a/consensus-types/light-client/update.go +++ b/consensus-types/light-client/update.go @@ -30,6 +30,9 @@ func NewWrappedUpdate(m proto.Message) (interfaces.LightClientUpdate, error) { } } +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. type updateAltair struct { p *pb.LightClientUpdateAltair attestedHeader interfaces.LightClientHeader @@ -107,8 +110,19 @@ func (u *updateAltair) AttestedHeader() interfaces.LightClientHeader { return u.attestedHeader } -func (u *updateAltair) SetAttestedHeader(header interfaces.LightClientHeader) { +func (u *updateAltair) SetAttestedHeader(header interfaces.LightClientHeader) error { + if header.Version() != version.Altair { + return fmt.Errorf("header version %s is not %s", version.String(header.Version()), version.String(version.Altair)) + } u.attestedHeader = header + + proto, ok := header.Proto().(*pb.LightClientHeaderAltair) + if !ok { + return fmt.Errorf("header type %T is not %T", proto, &pb.LightClientHeaderAltair{}) + } + u.p.AttestedHeader = proto + + return nil } func (u *updateAltair) NextSyncCommittee() *pb.SyncCommittee { @@ -129,6 +143,9 @@ func (u *updateAltair) SetNextSyncCommitteeBranch(branch [][]byte) error { return err } u.nextSyncCommitteeBranch = b + + u.p.NextSyncCommitteeBranch = branch + return nil } @@ -144,8 +161,19 @@ func (u *updateAltair) FinalizedHeader() interfaces.LightClientHeader { return u.finalizedHeader } -func (u *updateAltair) SetFinalizedHeader(header interfaces.LightClientHeader) { +func (u *updateAltair) SetFinalizedHeader(header interfaces.LightClientHeader) error { + if header.Version() != version.Altair { + return fmt.Errorf("header version %s is not %s", version.String(header.Version()), version.String(version.Altair)) + } u.finalizedHeader = header + + proto, ok := header.Proto().(*pb.LightClientHeaderAltair) + if !ok { + return fmt.Errorf("header type %T is not %T", proto, &pb.LightClientHeaderAltair{}) + } + u.p.FinalizedHeader = proto + + return nil } func (u *updateAltair) FinalityBranch() interfaces.LightClientFinalityBranch { @@ -158,6 +186,9 @@ func (u *updateAltair) SetFinalityBranch(branch [][]byte) error { return err } u.finalityBranch = b + + u.p.FinalityBranch = branch + return nil } @@ -177,6 +208,9 @@ func (u *updateAltair) SetSignatureSlot(slot primitives.Slot) { u.p.SignatureSlot = slot } +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. type updateCapella struct { p *pb.LightClientUpdateCapella attestedHeader interfaces.LightClientHeader @@ -254,8 +288,19 @@ func (u *updateCapella) AttestedHeader() interfaces.LightClientHeader { return u.attestedHeader } -func (u *updateCapella) SetAttestedHeader(header interfaces.LightClientHeader) { +func (u *updateCapella) SetAttestedHeader(header interfaces.LightClientHeader) error { + if header.Version() != version.Capella { + return fmt.Errorf("header version %s is not %s", version.String(header.Version()), version.String(version.Capella)) + } u.attestedHeader = header + + proto, ok := header.Proto().(*pb.LightClientHeaderCapella) + if !ok { + return fmt.Errorf("header type %T is not %T", proto, &pb.LightClientHeaderCapella{}) + } + u.p.AttestedHeader = proto + + return nil } func (u *updateCapella) NextSyncCommittee() *pb.SyncCommittee { @@ -276,6 +321,9 @@ func (u *updateCapella) SetNextSyncCommitteeBranch(branch [][]byte) error { return err } u.nextSyncCommitteeBranch = b + + u.p.NextSyncCommitteeBranch = branch + return nil } @@ -291,8 +339,19 @@ func (u *updateCapella) FinalizedHeader() interfaces.LightClientHeader { return u.finalizedHeader } -func (u *updateCapella) SetFinalizedHeader(header interfaces.LightClientHeader) { +func (u *updateCapella) SetFinalizedHeader(header interfaces.LightClientHeader) error { + if header.Version() != version.Capella { + return fmt.Errorf("header version %s is not %s", version.String(header.Version()), version.String(version.Capella)) + } u.finalizedHeader = header + + proto, ok := header.Proto().(*pb.LightClientHeaderCapella) + if !ok { + return fmt.Errorf("header type %T is not %T", proto, &pb.LightClientHeaderCapella{}) + } + u.p.FinalizedHeader = proto + + return nil } func (u *updateCapella) FinalityBranch() interfaces.LightClientFinalityBranch { @@ -305,6 +364,9 @@ func (u *updateCapella) SetFinalityBranch(branch [][]byte) error { return err } u.finalityBranch = b + + u.p.FinalityBranch = branch + return nil } @@ -324,6 +386,9 @@ func (u *updateCapella) SetSignatureSlot(slot primitives.Slot) { u.p.SignatureSlot = slot } +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. type updateDeneb struct { p *pb.LightClientUpdateDeneb attestedHeader interfaces.LightClientHeader @@ -401,8 +466,19 @@ func (u *updateDeneb) AttestedHeader() interfaces.LightClientHeader { return u.attestedHeader } -func (u *updateDeneb) SetAttestedHeader(header interfaces.LightClientHeader) { +func (u *updateDeneb) SetAttestedHeader(header interfaces.LightClientHeader) error { + if header.Version() != version.Deneb { + return fmt.Errorf("header version %s is not %s", version.String(header.Version()), version.String(version.Deneb)) + } u.attestedHeader = header + + proto, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", proto, &pb.LightClientHeaderDeneb{}) + } + u.p.AttestedHeader = proto + + return nil } func (u *updateDeneb) NextSyncCommittee() *pb.SyncCommittee { @@ -423,6 +499,9 @@ func (u *updateDeneb) SetNextSyncCommitteeBranch(branch [][]byte) error { return err } u.nextSyncCommitteeBranch = b + + u.p.NextSyncCommitteeBranch = branch + return nil } @@ -438,8 +517,19 @@ func (u *updateDeneb) FinalizedHeader() interfaces.LightClientHeader { return u.finalizedHeader } -func (u *updateDeneb) SetFinalizedHeader(header interfaces.LightClientHeader) { +func (u *updateDeneb) SetFinalizedHeader(header interfaces.LightClientHeader) error { + if header.Version() != version.Deneb { + return fmt.Errorf("header version %s is not %s", version.String(header.Version()), version.String(version.Deneb)) + } u.finalizedHeader = header + + proto, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", proto, &pb.LightClientHeaderDeneb{}) + } + u.p.FinalizedHeader = proto + + return nil } func (u *updateDeneb) FinalityBranch() interfaces.LightClientFinalityBranch { @@ -452,6 +542,9 @@ func (u *updateDeneb) SetFinalityBranch(branch [][]byte) error { return err } u.finalityBranch = b + + u.p.FinalityBranch = branch + return nil } @@ -471,6 +564,9 @@ func (u *updateDeneb) SetSignatureSlot(slot primitives.Slot) { u.p.SignatureSlot = slot } +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. type updateElectra struct { p *pb.LightClientUpdateElectra attestedHeader interfaces.LightClientHeader @@ -548,8 +644,19 @@ func (u *updateElectra) AttestedHeader() interfaces.LightClientHeader { return u.attestedHeader } -func (u *updateElectra) SetAttestedHeader(header interfaces.LightClientHeader) { +func (u *updateElectra) SetAttestedHeader(header interfaces.LightClientHeader) error { + if header.Version() != version.Electra { + return fmt.Errorf("header version %s is not %s", version.String(header.Version()), version.String(version.Electra)) + } u.attestedHeader = header + + proto, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", proto, &pb.LightClientHeaderDeneb{}) + } + u.p.AttestedHeader = proto + + return nil } func (u *updateElectra) NextSyncCommittee() *pb.SyncCommittee { @@ -578,6 +685,9 @@ func (u *updateElectra) SetNextSyncCommitteeBranchElectra(branch [][]byte) error return err } u.nextSyncCommitteeBranch = b + + u.p.NextSyncCommitteeBranch = branch + return nil } @@ -585,8 +695,19 @@ func (u *updateElectra) FinalizedHeader() interfaces.LightClientHeader { return u.finalizedHeader } -func (u *updateElectra) SetFinalizedHeader(header interfaces.LightClientHeader) { +func (u *updateElectra) SetFinalizedHeader(header interfaces.LightClientHeader) error { + if header.Version() != version.Electra { + return fmt.Errorf("header version %s is not %s", version.String(header.Version()), version.String(version.Electra)) + } u.finalizedHeader = header + + proto, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", proto, &pb.LightClientHeaderDeneb{}) + } + u.p.FinalizedHeader = proto + + return nil } func (u *updateElectra) FinalityBranch() interfaces.LightClientFinalityBranch { @@ -599,6 +720,9 @@ func (u *updateElectra) SetFinalityBranch(branch [][]byte) error { return err } u.finalityBranch = b + + u.p.FinalityBranch = branch + return nil }