mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
17 Commits
fix-comput
...
v5.1.1-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fa6d3bd9d | ||
|
|
56f0eb1437 | ||
|
|
7fc5c714a1 | ||
|
|
cfbfccb203 | ||
|
|
884b663455 | ||
|
|
0f1d16c599 | ||
|
|
c11e3392d4 | ||
|
|
f498463843 | ||
|
|
cf4ffc97e2 | ||
|
|
3824e8a463 | ||
|
|
21ca4e008f | ||
|
|
6af44a1466 | ||
|
|
2e29164582 | ||
|
|
6d499bc9fc | ||
|
|
7786cb5684 | ||
|
|
003b70c34b | ||
|
|
71edf96c7d |
17
CHANGELOG.md
17
CHANGELOG.md
@@ -13,12 +13,20 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
|
||||
- Light client support: Implement `ComputeFieldRootsForBlockBody`.
|
||||
- Light client support: Add light client database changes.
|
||||
- Light client support: Implement capella and deneb changes.
|
||||
- Light client support: Implement `BlockToLightClientHeaderXXX` functions upto Deneb
|
||||
- Light client support: Implement `BlockToLightClientHeader` function.
|
||||
- Light client support: Consensus types.
|
||||
- GetBeaconStateV2: add Electra case.
|
||||
- Implement [consensus-specs/3875](https://github.com/ethereum/consensus-specs/pull/3875)
|
||||
- Tests to ensure sepolia config matches the official upstream yaml
|
||||
- HTTP endpoint for PublishBlobs
|
||||
- GetBlockV2, GetBlindedBlock, ProduceBlockV2, ProduceBlockV3: add Electra case.
|
||||
- Add Electra support and tests for light client functions
|
||||
- fastssz version bump (better error messages).
|
||||
- SSE implementation that sheds stuck clients. [pr](https://github.com/prysmaticlabs/prysm/pull/14413)
|
||||
|
||||
### Changed
|
||||
|
||||
- Electra: Updated interop genesis generator to support Electra.
|
||||
- `getLocalPayload` has been refactored to enable work in ePBS branch.
|
||||
- `TestNodeServer_GetPeer` and `TestNodeServer_ListPeers` test flakes resolved by iterating the whole peer list to find
|
||||
a match rather than taking the first peer in the map.
|
||||
@@ -39,7 +47,11 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
|
||||
- Updated k8s-io/client-go to v0.30.4 and k8s-io/apimachinery to v0.30.4
|
||||
- Migrated tracing library from opencensus to opentelemetry for both the beacon node and validator.
|
||||
- Refactored light client code to make it more readable and make future PRs easier.
|
||||
- Update light client helper functions to reference `dev` branch of CL specs
|
||||
- Updated Libp2p Dependencies to allow prysm to use gossipsub v1.2 .
|
||||
- Updated Sepolia bootnodes.
|
||||
- Make committee aware packing the default by deprecating `--enable-committee-aware-packing`.
|
||||
- Moved `ConvertKzgCommitmentToVersionedHash` to the `primitives` package.
|
||||
|
||||
### Deprecated
|
||||
- `--disable-grpc-gateway` flag is deprecated due to grpc gateway removal.
|
||||
@@ -64,7 +76,10 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
|
||||
- Core: Fixed slash processing causing extra hashing.
|
||||
- Core: Fixed extra allocations when processing slashings.
|
||||
- remove unneeded container in blob sidecar ssz response
|
||||
- Light client support: create finalized header based on finalizedBlock's version, not attestedBlock.
|
||||
- Light client support: fix light client attested header execution fields' wrong version bug.
|
||||
- Testing: added custom matcher for better push settings testing.
|
||||
- Registered `GetDepositSnapshot` Beacon API endpoint.
|
||||
|
||||
### Security
|
||||
|
||||
|
||||
16
WORKSPACE
16
WORKSPACE
@@ -342,6 +342,22 @@ filegroup(
|
||||
url = "https://github.com/eth-clients/holesky/archive/874c199423ccd180607320c38cbaca05d9a1573a.tar.gz", # 2024-06-18
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "sepolia_testnet",
|
||||
build_file_content = """
|
||||
filegroup(
|
||||
name = "configs",
|
||||
srcs = [
|
||||
"metadata/config.yaml",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-cY/UgpCcYEhQf7JefD65FI8tn/A+rAvKhcm2/qiVdqY=",
|
||||
strip_prefix = "sepolia-f2c219a93c4491cee3d90c18f2f8e82aed850eab",
|
||||
url = "https://github.com/eth-clients/sepolia/archive/f2c219a93c4491cee3d90c18f2f8e82aed850eab.tar.gz", # 2024-09-19
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "com_google_protobuf",
|
||||
sha256 = "9bd87b8280ef720d3240514f884e56a712f2218f0d693b48050c836028940a42",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package api
|
||||
|
||||
import "net/http"
|
||||
|
||||
const (
|
||||
VersionHeader = "Eth-Consensus-Version"
|
||||
ExecutionPayloadBlindedHeader = "Eth-Execution-Payload-Blinded"
|
||||
@@ -10,3 +12,9 @@ const (
|
||||
EventStreamMediaType = "text/event-stream"
|
||||
KeepAlive = "keep-alive"
|
||||
)
|
||||
|
||||
// SetSSEHeaders sets the headers needed for a server-sent event response.
|
||||
func SetSSEHeaders(w http.ResponseWriter) {
|
||||
w.Header().Set("Content-Type", EventStreamMediaType)
|
||||
w.Header().Set("Connection", KeepAlive)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ go_library(
|
||||
srcs = [
|
||||
"block.go",
|
||||
"conversions.go",
|
||||
"conversions_blob.go",
|
||||
"conversions_block.go",
|
||||
"conversions_lightclient.go",
|
||||
"conversions_state.go",
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -1508,3 +1509,37 @@ func PendingConsolidationsFromConsensus(cs []*eth.PendingConsolidation) []*Pendi
|
||||
}
|
||||
return consolidations
|
||||
}
|
||||
|
||||
func HeadEventFromV1(event *ethv1.EventHead) *HeadEvent {
|
||||
return &HeadEvent{
|
||||
Slot: fmt.Sprintf("%d", event.Slot),
|
||||
Block: hexutil.Encode(event.Block),
|
||||
State: hexutil.Encode(event.State),
|
||||
EpochTransition: event.EpochTransition,
|
||||
ExecutionOptimistic: event.ExecutionOptimistic,
|
||||
PreviousDutyDependentRoot: hexutil.Encode(event.PreviousDutyDependentRoot),
|
||||
CurrentDutyDependentRoot: hexutil.Encode(event.CurrentDutyDependentRoot),
|
||||
}
|
||||
}
|
||||
|
||||
func FinalizedCheckpointEventFromV1(event *ethv1.EventFinalizedCheckpoint) *FinalizedCheckpointEvent {
|
||||
return &FinalizedCheckpointEvent{
|
||||
Block: hexutil.Encode(event.Block),
|
||||
State: hexutil.Encode(event.State),
|
||||
Epoch: fmt.Sprintf("%d", event.Epoch),
|
||||
ExecutionOptimistic: event.ExecutionOptimistic,
|
||||
}
|
||||
}
|
||||
|
||||
func EventChainReorgFromV1(event *ethv1.EventChainReorg) *ChainReorgEvent {
|
||||
return &ChainReorgEvent{
|
||||
Slot: fmt.Sprintf("%d", event.Slot),
|
||||
Depth: fmt.Sprintf("%d", event.Depth),
|
||||
OldHeadBlock: hexutil.Encode(event.OldHeadBlock),
|
||||
NewHeadBlock: hexutil.Encode(event.NewHeadBlock),
|
||||
OldHeadState: hexutil.Encode(event.OldHeadState),
|
||||
NewHeadState: hexutil.Encode(event.NewHeadState),
|
||||
Epoch: fmt.Sprintf("%d", event.Epoch),
|
||||
ExecutionOptimistic: event.ExecutionOptimistic,
|
||||
}
|
||||
}
|
||||
|
||||
61
api/server/structs/conversions_blob.go
Normal file
61
api/server/structs/conversions_blob.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package structs
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func (sc *Sidecar) ToConsensus() (*eth.BlobSidecar, error) {
|
||||
if sc == nil {
|
||||
return nil, errNilValue
|
||||
}
|
||||
|
||||
index, err := strconv.ParseUint(sc.Index, 10, 64)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Index")
|
||||
}
|
||||
|
||||
blob, err := bytesutil.DecodeHexWithLength(sc.Blob, 131072)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Blob")
|
||||
}
|
||||
|
||||
kzgCommitment, err := bytesutil.DecodeHexWithLength(sc.KzgCommitment, 48)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "KzgCommitment")
|
||||
}
|
||||
|
||||
kzgProof, err := bytesutil.DecodeHexWithLength(sc.KzgProof, 48)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "KzgProof")
|
||||
}
|
||||
|
||||
header, err := sc.SignedBeaconBlockHeader.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "SignedBeaconBlockHeader")
|
||||
}
|
||||
|
||||
// decode the commitment inclusion proof
|
||||
var commitmentInclusionProof [][]byte
|
||||
for _, proof := range sc.CommitmentInclusionProof {
|
||||
proofBytes, err := bytesutil.DecodeHexWithLength(proof, 32)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "CommitmentInclusionProof")
|
||||
}
|
||||
commitmentInclusionProof = append(commitmentInclusionProof, proofBytes)
|
||||
}
|
||||
|
||||
bsc := ð.BlobSidecar{
|
||||
Index: index,
|
||||
Blob: blob,
|
||||
KzgCommitment: kzgCommitment,
|
||||
KzgProof: kzgProof,
|
||||
SignedBlockHeader: header,
|
||||
CommitmentInclusionProof: commitmentInclusionProof,
|
||||
}
|
||||
|
||||
return bsc, nil
|
||||
}
|
||||
@@ -20,6 +20,9 @@ import (
|
||||
var ErrUnsupportedConversion = errors.New("Could not determine api struct type to use for value")
|
||||
|
||||
func (h *SignedBeaconBlockHeader) ToConsensus() (*eth.SignedBeaconBlockHeader, error) {
|
||||
if h == nil {
|
||||
return nil, errNilValue
|
||||
}
|
||||
msg, err := h.Message.ToConsensus()
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Message")
|
||||
@@ -36,6 +39,9 @@ func (h *SignedBeaconBlockHeader) ToConsensus() (*eth.SignedBeaconBlockHeader, e
|
||||
}
|
||||
|
||||
func (h *BeaconBlockHeader) ToConsensus() (*eth.BeaconBlockHeader, error) {
|
||||
if h == nil {
|
||||
return nil, errNilValue
|
||||
}
|
||||
s, err := strconv.ParseUint(h.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return nil, server.NewDecodeError(err, "Slot")
|
||||
@@ -2548,6 +2554,8 @@ func SignedBeaconBlockMessageJsoner(block interfaces.ReadOnlySignedBeaconBlock)
|
||||
return SignedBlindedBeaconBlockDenebFromConsensus(pbStruct)
|
||||
case *eth.SignedBeaconBlockDeneb:
|
||||
return SignedBeaconBlockDenebFromConsensus(pbStruct)
|
||||
case *eth.SignedBlindedBeaconBlockElectra:
|
||||
return SignedBlindedBeaconBlockElectraFromConsensus(pbStruct)
|
||||
case *eth.SignedBeaconBlockElectra:
|
||||
return SignedBeaconBlockElectraFromConsensus(pbStruct)
|
||||
default:
|
||||
|
||||
@@ -84,6 +84,11 @@ func syncAggregateToJSON(input *v1.SyncAggregate) *SyncAggregate {
|
||||
}
|
||||
|
||||
func lightClientHeaderContainerToJSON(container *v2.LightClientHeaderContainer) (json.RawMessage, error) {
|
||||
// In the case that a finalizedHeader is nil.
|
||||
if container == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
beacon, err := container.GetBeacon()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get beacon block header")
|
||||
|
||||
@@ -12,3 +12,12 @@ type Sidecar struct {
|
||||
KzgProof string `json:"kzg_proof"`
|
||||
CommitmentInclusionProof []string `json:"kzg_commitment_inclusion_proof"`
|
||||
}
|
||||
|
||||
type BlobSidecars struct {
|
||||
Sidecars []*Sidecar `json:"sidecars"`
|
||||
}
|
||||
|
||||
type PublishBlobsRequest struct {
|
||||
BlobSidecars *BlobSidecars `json:"blob_sidecars"`
|
||||
BlockRoot string `json:"block_root"`
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"feed.go",
|
||||
"interface.go",
|
||||
"subscription.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/async/event",
|
||||
|
||||
@@ -22,3 +22,4 @@ import (
|
||||
|
||||
// Feed is a re-export of the go-ethereum event feed.
|
||||
type Feed = geth_event.Feed
|
||||
type Subscription = geth_event.Subscription
|
||||
|
||||
8
async/event/interface.go
Normal file
8
async/event/interface.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package event
|
||||
|
||||
// SubscriberSender is an abstract representation of an *event.Feed
|
||||
// to use in describing types that accept or return an *event.Feed.
|
||||
type SubscriberSender interface {
|
||||
Subscribe(channel interface{}) Subscription
|
||||
Send(value interface{}) (nsent int)
|
||||
}
|
||||
@@ -28,25 +28,6 @@ import (
|
||||
// request backoff time.
|
||||
const waitQuotient = 10
|
||||
|
||||
// Subscription represents a stream of events. The carrier of the events is typically a
|
||||
// channel, but isn't part of the interface.
|
||||
//
|
||||
// Subscriptions can fail while established. Failures are reported through an error
|
||||
// channel. It receives a value if there is an issue with the subscription (e.g. the
|
||||
// network connection delivering the events has been closed). Only one value will ever be
|
||||
// sent.
|
||||
//
|
||||
// The error channel is closed when the subscription ends successfully (i.e. when the
|
||||
// source of events is closed). It is also closed when Unsubscribe is called.
|
||||
//
|
||||
// The Unsubscribe method cancels the sending of events. You must call Unsubscribe in all
|
||||
// cases to ensure that resources related to the subscription are released. It can be
|
||||
// called any number of times.
|
||||
type Subscription interface {
|
||||
Err() <-chan error // returns the error channel
|
||||
Unsubscribe() // cancels sending of events, closing the error channel
|
||||
}
|
||||
|
||||
// NewSubscription runs a producer function as a subscription in a new goroutine. The
|
||||
// channel given to the producer is closed when Unsubscribe is called. If fn returns an
|
||||
// error, it is sent on the subscription's error channel.
|
||||
|
||||
@@ -2,7 +2,6 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@@ -28,8 +27,6 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const blobCommitmentVersionKZG uint8 = 0x01
|
||||
|
||||
var defaultLatestValidHash = bytesutil.PadTo([]byte{0xff}, 32)
|
||||
|
||||
// notifyForkchoiceUpdate signals execution engine the fork choice updates. Execution engine should:
|
||||
@@ -402,13 +399,7 @@ func kzgCommitmentsToVersionedHashes(body interfaces.ReadOnlyBeaconBlockBody) ([
|
||||
|
||||
versionedHashes := make([]common.Hash, len(commitments))
|
||||
for i, commitment := range commitments {
|
||||
versionedHashes[i] = ConvertKzgCommitmentToVersionedHash(commitment)
|
||||
versionedHashes[i] = primitives.ConvertKzgCommitmentToVersionedHash(commitment)
|
||||
}
|
||||
return versionedHashes, nil
|
||||
}
|
||||
|
||||
func ConvertKzgCommitmentToVersionedHash(commitment []byte) common.Hash {
|
||||
versionedHash := sha256.Sum256(commitment)
|
||||
versionedHash[0] = blobCommitmentVersionKZG
|
||||
return versionedHash
|
||||
}
|
||||
|
||||
@@ -162,6 +162,10 @@ func (s *Service) sendLightClientFinalityUpdate(ctx context.Context, signed inte
|
||||
postState state.BeaconState) (int, error) {
|
||||
// Get attested state
|
||||
attestedRoot := signed.Block().ParentRoot()
|
||||
attestedBlock, err := s.cfg.BeaconDB.Block(ctx, attestedRoot)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not get attested block")
|
||||
}
|
||||
attestedState, err := s.cfg.StateGen.StateByRoot(ctx, attestedRoot)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not get attested state")
|
||||
@@ -183,6 +187,7 @@ func (s *Service) sendLightClientFinalityUpdate(ctx context.Context, signed inte
|
||||
postState,
|
||||
signed,
|
||||
attestedState,
|
||||
attestedBlock,
|
||||
finalizedBlock,
|
||||
)
|
||||
|
||||
@@ -208,6 +213,10 @@ func (s *Service) sendLightClientOptimisticUpdate(ctx context.Context, signed in
|
||||
postState state.BeaconState) (int, error) {
|
||||
// Get attested state
|
||||
attestedRoot := signed.Block().ParentRoot()
|
||||
attestedBlock, err := s.cfg.BeaconDB.Block(ctx, attestedRoot)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not get attested block")
|
||||
}
|
||||
attestedState, err := s.cfg.StateGen.StateByRoot(ctx, attestedRoot)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not get attested state")
|
||||
@@ -218,6 +227,7 @@ func (s *Service) sendLightClientOptimisticUpdate(ctx context.Context, signed in
|
||||
postState,
|
||||
signed,
|
||||
attestedState,
|
||||
attestedBlock,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -32,7 +32,7 @@ type mockBeaconNode struct {
|
||||
}
|
||||
|
||||
// StateFeed mocks the same method in the beacon node.
|
||||
func (mbn *mockBeaconNode) StateFeed() *event.Feed {
|
||||
func (mbn *mockBeaconNode) StateFeed() event.SubscriberSender {
|
||||
mbn.mu.Lock()
|
||||
defer mbn.mu.Unlock()
|
||||
if mbn.stateFeed == nil {
|
||||
|
||||
@@ -98,6 +98,44 @@ func (s *ChainService) BlockNotifier() blockfeed.Notifier {
|
||||
return s.blockNotifier
|
||||
}
|
||||
|
||||
type EventFeedWrapper struct {
|
||||
feed *event.Feed
|
||||
subscribed chan struct{} // this channel is closed once a subscription is made
|
||||
}
|
||||
|
||||
func (w *EventFeedWrapper) Subscribe(channel interface{}) event.Subscription {
|
||||
select {
|
||||
case <-w.subscribed:
|
||||
break // already closed
|
||||
default:
|
||||
close(w.subscribed)
|
||||
}
|
||||
return w.feed.Subscribe(channel)
|
||||
}
|
||||
|
||||
func (w *EventFeedWrapper) Send(value interface{}) int {
|
||||
return w.feed.Send(value)
|
||||
}
|
||||
|
||||
// WaitForSubscription allows test to wait for the feed to have a subscription before beginning to send events.
|
||||
func (w *EventFeedWrapper) WaitForSubscription(ctx context.Context) error {
|
||||
select {
|
||||
case <-w.subscribed:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
var _ event.SubscriberSender = &EventFeedWrapper{}
|
||||
|
||||
func NewEventFeedWrapper() *EventFeedWrapper {
|
||||
return &EventFeedWrapper{
|
||||
feed: new(event.Feed),
|
||||
subscribed: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// MockBlockNotifier mocks the block notifier.
|
||||
type MockBlockNotifier struct {
|
||||
feed *event.Feed
|
||||
@@ -131,7 +169,7 @@ func (msn *MockStateNotifier) ReceivedEvents() []*feed.Event {
|
||||
}
|
||||
|
||||
// StateFeed returns a state feed.
|
||||
func (msn *MockStateNotifier) StateFeed() *event.Feed {
|
||||
func (msn *MockStateNotifier) StateFeed() event.SubscriberSender {
|
||||
msn.feedLock.Lock()
|
||||
defer msn.feedLock.Unlock()
|
||||
|
||||
@@ -159,6 +197,23 @@ func (msn *MockStateNotifier) StateFeed() *event.Feed {
|
||||
return msn.feed
|
||||
}
|
||||
|
||||
// NewSimpleStateNotifier makes a state feed without the custom mock feed machinery.
|
||||
func NewSimpleStateNotifier() *MockStateNotifier {
|
||||
return &MockStateNotifier{feed: new(event.Feed)}
|
||||
}
|
||||
|
||||
type SimpleNotifier struct {
|
||||
Feed event.SubscriberSender
|
||||
}
|
||||
|
||||
func (n *SimpleNotifier) StateFeed() event.SubscriberSender {
|
||||
return n.Feed
|
||||
}
|
||||
|
||||
func (n *SimpleNotifier) OperationFeed() event.SubscriberSender {
|
||||
return n.Feed
|
||||
}
|
||||
|
||||
// OperationNotifier mocks the same method in the chain service.
|
||||
func (s *ChainService) OperationNotifier() opfeed.Notifier {
|
||||
if s.opNotifier == nil {
|
||||
@@ -173,7 +228,7 @@ type MockOperationNotifier struct {
|
||||
}
|
||||
|
||||
// OperationFeed returns an operation feed.
|
||||
func (mon *MockOperationNotifier) OperationFeed() *event.Feed {
|
||||
func (mon *MockOperationNotifier) OperationFeed() event.SubscriberSender {
|
||||
if mon.feed == nil {
|
||||
mon.feed = new(event.Feed)
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@ import "github.com/prysmaticlabs/prysm/v5/async/event"
|
||||
|
||||
// Notifier interface defines the methods of the service that provides beacon block operation updates to consumers.
|
||||
type Notifier interface {
|
||||
OperationFeed() *event.Feed
|
||||
OperationFeed() event.SubscriberSender
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@ import "github.com/prysmaticlabs/prysm/v5/async/event"
|
||||
|
||||
// Notifier interface defines the methods of the service that provides state updates to consumers.
|
||||
type Notifier interface {
|
||||
StateFeed() *event.Feed
|
||||
StateFeed() event.SubscriberSender
|
||||
}
|
||||
|
||||
@@ -12,12 +12,10 @@ go_library(
|
||||
"//consensus-types:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/eth/v2:go_default_library",
|
||||
"//proto/migration:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
@@ -29,11 +27,13 @@ go_test(
|
||||
srcs = ["lightclient_test.go"],
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//consensus-types:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -13,15 +13,11 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/v5/proto/migration"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,16 +25,6 @@ const (
|
||||
executionBranchNumOfLeaves = 4
|
||||
)
|
||||
|
||||
// createLightClientFinalityUpdate - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_finality_update
|
||||
// def create_light_client_finality_update(update: LightClientUpdate) -> LightClientFinalityUpdate:
|
||||
//
|
||||
// return LightClientFinalityUpdate(
|
||||
// attested_header=update.attested_header,
|
||||
// finalized_header=update.finalized_header,
|
||||
// finality_branch=update.finality_branch,
|
||||
// sync_aggregate=update.sync_aggregate,
|
||||
// signature_slot=update.signature_slot,
|
||||
// )
|
||||
func createLightClientFinalityUpdate(update *ethpbv2.LightClientUpdate) *ethpbv2.LightClientFinalityUpdate {
|
||||
finalityUpdate := ðpbv2.LightClientFinalityUpdate{
|
||||
AttestedHeader: update.AttestedHeader,
|
||||
@@ -51,14 +37,6 @@ func createLightClientFinalityUpdate(update *ethpbv2.LightClientUpdate) *ethpbv2
|
||||
return finalityUpdate
|
||||
}
|
||||
|
||||
// createLightClientOptimisticUpdate - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_optimistic_update
|
||||
// def create_light_client_optimistic_update(update: LightClientUpdate) -> LightClientOptimisticUpdate:
|
||||
//
|
||||
// return LightClientOptimisticUpdate(
|
||||
// attested_header=update.attested_header,
|
||||
// sync_aggregate=update.sync_aggregate,
|
||||
// signature_slot=update.signature_slot,
|
||||
// )
|
||||
func createLightClientOptimisticUpdate(update *ethpbv2.LightClientUpdate) *ethpbv2.LightClientOptimisticUpdate {
|
||||
optimisticUpdate := ðpbv2.LightClientOptimisticUpdate{
|
||||
AttestedHeader: update.AttestedHeader,
|
||||
@@ -74,9 +52,10 @@ func NewLightClientFinalityUpdateFromBeaconState(
|
||||
state state.BeaconState,
|
||||
block interfaces.ReadOnlySignedBeaconBlock,
|
||||
attestedState state.BeaconState,
|
||||
attestedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
finalizedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
) (*ethpbv2.LightClientFinalityUpdate, error) {
|
||||
update, err := NewLightClientUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock)
|
||||
update, err := NewLightClientUpdateFromBeaconState(ctx, state, block, attestedState, attestedBlock, finalizedBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -89,8 +68,9 @@ func NewLightClientOptimisticUpdateFromBeaconState(
|
||||
state state.BeaconState,
|
||||
block interfaces.ReadOnlySignedBeaconBlock,
|
||||
attestedState state.BeaconState,
|
||||
attestedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
) (*ethpbv2.LightClientOptimisticUpdate, error) {
|
||||
update, err := NewLightClientUpdateFromBeaconState(ctx, state, block, attestedState, nil)
|
||||
update, err := NewLightClientUpdateFromBeaconState(ctx, state, block, attestedState, attestedBlock, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,68 +78,12 @@ func NewLightClientOptimisticUpdateFromBeaconState(
|
||||
return createLightClientOptimisticUpdate(update), nil
|
||||
}
|
||||
|
||||
// NewLightClientUpdateFromBeaconState implements https://github.com/ethereum/consensus-specs/blob/d70dcd9926a4bbe987f1b4e65c3e05bd029fcfb8/specs/altair/light-client/full-node.md#create_light_client_update
|
||||
// def create_light_client_update(state: BeaconState,
|
||||
//
|
||||
// block: SignedBeaconBlock,
|
||||
// attested_state: BeaconState,
|
||||
// finalized_block: Optional[SignedBeaconBlock]) -> LightClientUpdate:
|
||||
// assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH
|
||||
// assert sum(block.message.body.sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS
|
||||
//
|
||||
// assert state.slot == state.latest_block_header.slot
|
||||
// header = state.latest_block_header.copy()
|
||||
// header.state_root = hash_tree_root(state)
|
||||
// assert hash_tree_root(header) == hash_tree_root(block.message)
|
||||
// update_signature_period = compute_sync_committee_period(compute_epoch_at_slot(block.message.slot))
|
||||
//
|
||||
// assert attested_state.slot == attested_state.latest_block_header.slot
|
||||
// attested_header = attested_state.latest_block_header.copy()
|
||||
// attested_header.state_root = hash_tree_root(attested_state)
|
||||
// assert hash_tree_root(attested_header) == block.message.parent_root
|
||||
// update_attested_period = compute_sync_committee_period(compute_epoch_at_slot(attested_header.slot))
|
||||
//
|
||||
// # `next_sync_committee` is only useful if the message is signed by the current sync committee
|
||||
// if update_attested_period == update_signature_period:
|
||||
// next_sync_committee = attested_state.next_sync_committee
|
||||
// next_sync_committee_branch = compute_merkle_proof_for_state(attested_state, NEXT_SYNC_COMMITTEE_INDEX)
|
||||
// else:
|
||||
// next_sync_committee = SyncCommittee()
|
||||
// next_sync_committee_branch = [Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))]
|
||||
//
|
||||
// # Indicate finality whenever possible
|
||||
// if finalized_block is not None:
|
||||
// if finalized_block.message.slot != GENESIS_SLOT:
|
||||
// finalized_header = BeaconBlockHeader(
|
||||
// slot=finalized_block.message.slot,
|
||||
// proposer_index=finalized_block.message.proposer_index,
|
||||
// parent_root=finalized_block.message.parent_root,
|
||||
// state_root=finalized_block.message.state_root,
|
||||
// body_root=hash_tree_root(finalized_block.message.body),
|
||||
// )
|
||||
// assert hash_tree_root(finalized_header) == attested_state.finalized_checkpoint.root
|
||||
// else:
|
||||
// assert attested_state.finalized_checkpoint.root == Bytes32()
|
||||
// finalized_header = BeaconBlockHeader()
|
||||
// finality_branch = compute_merkle_proof_for_state(attested_state, FINALIZED_ROOT_INDEX)
|
||||
// else:
|
||||
// finalized_header = BeaconBlockHeader()
|
||||
// finality_branch = [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))]
|
||||
//
|
||||
// return LightClientUpdate(
|
||||
// attested_header=attested_header,
|
||||
// next_sync_committee=next_sync_committee,
|
||||
// next_sync_committee_branch=next_sync_committee_branch,
|
||||
// finalized_header=finalized_header,
|
||||
// finality_branch=finality_branch,
|
||||
// sync_aggregate=block.message.body.sync_aggregate,
|
||||
// signature_slot=block.message.slot,
|
||||
// )
|
||||
func NewLightClientUpdateFromBeaconState(
|
||||
ctx context.Context,
|
||||
state state.BeaconState,
|
||||
block interfaces.ReadOnlySignedBeaconBlock,
|
||||
attestedState state.BeaconState,
|
||||
attestedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
finalizedBlock interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientUpdate, error) {
|
||||
// assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH
|
||||
attestedEpoch := slots.ToEpoch(attestedState.Slot())
|
||||
@@ -223,73 +147,30 @@ func NewLightClientUpdateFromBeaconState(
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get attested header root")
|
||||
}
|
||||
if attestedHeaderRoot != block.Block().ParentRoot() {
|
||||
return nil, fmt.Errorf("attested header root %#x not equal to block parent root %#x", attestedHeaderRoot, block.Block().ParentRoot())
|
||||
attestedBlockRoot, err := attestedBlock.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get attested block root")
|
||||
}
|
||||
// assert hash_tree_root(attested_header) == hash_tree_root(attested_block.message) == block.message.parent_root
|
||||
if attestedHeaderRoot != block.Block().ParentRoot() || attestedHeaderRoot != attestedBlockRoot {
|
||||
return nil, fmt.Errorf("attested header root %#x not equal to block parent root %#x or attested block root %#x", attestedHeaderRoot, block.Block().ParentRoot(), attestedBlockRoot)
|
||||
}
|
||||
|
||||
// update_attested_period = compute_sync_committee_period(compute_epoch_at_slot(attested_header.slot))
|
||||
updateAttestedPeriod := slots.SyncCommitteePeriod(slots.ToEpoch(attestedHeader.Slot))
|
||||
// update_attested_period = compute_sync_committee_period_at_slot(attested_block.message.slot)
|
||||
updateAttestedPeriod := slots.SyncCommitteePeriod(slots.ToEpoch(attestedBlock.Block().Slot()))
|
||||
|
||||
// update = LightClientUpdate()
|
||||
result, err := createDefaultLightClientUpdate(block.Block().Version())
|
||||
result, err := createDefaultLightClientUpdate()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create default light client update")
|
||||
}
|
||||
|
||||
// update.attested_header = block_to_light_client_header(attested_block)
|
||||
blockHeader := ðpbv1.BeaconBlockHeader{
|
||||
Slot: attestedHeader.Slot,
|
||||
ProposerIndex: attestedHeader.ProposerIndex,
|
||||
ParentRoot: attestedHeader.ParentRoot,
|
||||
StateRoot: attestedHeader.StateRoot,
|
||||
BodyRoot: attestedHeader.BodyRoot,
|
||||
}
|
||||
switch block.Block().Version() {
|
||||
case version.Altair, version.Bellatrix:
|
||||
result.AttestedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderAltair{
|
||||
HeaderAltair: ðpbv2.LightClientHeader{Beacon: blockHeader},
|
||||
},
|
||||
}
|
||||
case version.Capella:
|
||||
executionPayloadHeader, err := getExecutionPayloadHeaderCapella(block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload header")
|
||||
}
|
||||
executionPayloadProof, err := blocks.PayloadProof(ctx, block.Block())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload proof")
|
||||
}
|
||||
result.AttestedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderCapella{
|
||||
HeaderCapella: ðpbv2.LightClientHeaderCapella{
|
||||
Beacon: blockHeader,
|
||||
Execution: executionPayloadHeader,
|
||||
ExecutionBranch: executionPayloadProof,
|
||||
},
|
||||
},
|
||||
}
|
||||
case version.Deneb:
|
||||
executionPayloadHeader, err := getExecutionPayloadHeaderDeneb(block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload header")
|
||||
}
|
||||
executionPayloadProof, err := blocks.PayloadProof(ctx, block.Block())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload proof")
|
||||
}
|
||||
result.AttestedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderDeneb{
|
||||
HeaderDeneb: ðpbv2.LightClientHeaderDeneb{
|
||||
Beacon: blockHeader,
|
||||
Execution: executionPayloadHeader,
|
||||
ExecutionBranch: executionPayloadProof,
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported block version %s", version.String(block.Block().Version()))
|
||||
attestedLightClientHeader, err := BlockToLightClientHeader(attestedBlock)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get attested light client header")
|
||||
}
|
||||
result.AttestedHeader = attestedLightClientHeader
|
||||
|
||||
// if update_attested_period == update_signature_period
|
||||
if updateAttestedPeriod == updateSignaturePeriod {
|
||||
@@ -319,70 +200,11 @@ func NewLightClientUpdateFromBeaconState(
|
||||
// if finalized_block.message.slot != GENESIS_SLOT
|
||||
if finalizedBlock.Block().Slot() != 0 {
|
||||
// update.finalized_header = block_to_light_client_header(finalized_block)
|
||||
v1alpha1FinalizedHeader, err := finalizedBlock.Header()
|
||||
finalizedLightClientHeader, err := BlockToLightClientHeader(finalizedBlock)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get finalized header")
|
||||
}
|
||||
finalizedHeader := migration.V1Alpha1SignedHeaderToV1(v1alpha1FinalizedHeader).GetMessage()
|
||||
finalizedHeaderRoot, err := finalizedHeader.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get finalized header root")
|
||||
}
|
||||
switch block.Block().Version() {
|
||||
case version.Altair, version.Bellatrix:
|
||||
result.FinalizedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderAltair{
|
||||
HeaderAltair: ðpbv2.LightClientHeader{Beacon: finalizedHeader},
|
||||
},
|
||||
}
|
||||
case version.Capella:
|
||||
executionPayloadHeader, err := getExecutionPayloadHeaderCapella(finalizedBlock)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload header")
|
||||
}
|
||||
executionPayloadProof, err := blocks.PayloadProof(ctx, finalizedBlock.Block())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload proof")
|
||||
}
|
||||
result.FinalizedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderCapella{
|
||||
HeaderCapella: ðpbv2.LightClientHeaderCapella{
|
||||
Beacon: finalizedHeader,
|
||||
Execution: executionPayloadHeader,
|
||||
ExecutionBranch: executionPayloadProof,
|
||||
},
|
||||
},
|
||||
}
|
||||
case version.Deneb:
|
||||
executionPayloadHeader, err := getExecutionPayloadHeaderDeneb(finalizedBlock)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload header")
|
||||
}
|
||||
executionPayloadProof, err := blocks.PayloadProof(ctx, finalizedBlock.Block())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload proof")
|
||||
}
|
||||
result.FinalizedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderDeneb{
|
||||
HeaderDeneb: ðpbv2.LightClientHeaderDeneb{
|
||||
Beacon: finalizedHeader,
|
||||
Execution: executionPayloadHeader,
|
||||
ExecutionBranch: executionPayloadProof,
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported block version %s", version.String(block.Block().Version()))
|
||||
}
|
||||
|
||||
// assert hash_tree_root(update.finalized_header.beacon) == attested_state.finalized_checkpoint.root
|
||||
if finalizedHeaderRoot != bytesutil.ToBytes32(attestedState.FinalizedCheckpoint().Root) {
|
||||
return nil, fmt.Errorf(
|
||||
"finalized header root %#x not equal to attested finalized checkpoint root %#x",
|
||||
finalizedHeaderRoot,
|
||||
bytesutil.ToBytes32(attestedState.FinalizedCheckpoint().Root),
|
||||
)
|
||||
return nil, errors.Wrap(err, "could not get finalized light client header")
|
||||
}
|
||||
result.FinalizedHeader = finalizedLightClientHeader
|
||||
} else {
|
||||
// assert attested_state.finalized_checkpoint.root == Bytes32()
|
||||
if !bytes.Equal(attestedState.FinalizedCheckpoint().Root, make([]byte, 32)) {
|
||||
@@ -411,7 +233,7 @@ func NewLightClientUpdateFromBeaconState(
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func createDefaultLightClientUpdate(v int) (*ethpbv2.LightClientUpdate, error) {
|
||||
func createDefaultLightClientUpdate() (*ethpbv2.LightClientUpdate, error) {
|
||||
syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize
|
||||
pubKeys := make([][]byte, syncCommitteeSize)
|
||||
for i := uint64(0); i < syncCommitteeSize; i++ {
|
||||
@@ -421,218 +243,26 @@ func createDefaultLightClientUpdate(v int) (*ethpbv2.LightClientUpdate, error) {
|
||||
Pubkeys: pubKeys,
|
||||
AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength),
|
||||
}
|
||||
nextSyncCommitteeBranch := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth)
|
||||
for i := 0; i < fieldparams.NextSyncCommitteeBranchDepth; i++ {
|
||||
nextSyncCommitteeBranch := make([][]byte, fieldparams.SyncCommitteeBranchDepth)
|
||||
for i := 0; i < fieldparams.SyncCommitteeBranchDepth; i++ {
|
||||
nextSyncCommitteeBranch[i] = make([]byte, fieldparams.RootLength)
|
||||
}
|
||||
executionBranch := make([][]byte, executionBranchNumOfLeaves)
|
||||
for i := 0; i < executionBranchNumOfLeaves; i++ {
|
||||
executionBranch[i] = make([]byte, 32)
|
||||
}
|
||||
finalizedBlockHeader := ðpbv1.BeaconBlockHeader{
|
||||
Slot: 0,
|
||||
ProposerIndex: 0,
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
BodyRoot: make([]byte, 32),
|
||||
}
|
||||
finalityBranch := make([][]byte, FinalityBranchNumOfLeaves)
|
||||
for i := 0; i < FinalityBranchNumOfLeaves; i++ {
|
||||
finalityBranch[i] = make([]byte, 32)
|
||||
}
|
||||
|
||||
var finalizedHeader *ethpbv2.LightClientHeaderContainer
|
||||
switch v {
|
||||
case version.Altair, version.Bellatrix:
|
||||
finalizedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderAltair{
|
||||
HeaderAltair: ðpbv2.LightClientHeader{
|
||||
Beacon: finalizedBlockHeader,
|
||||
},
|
||||
},
|
||||
}
|
||||
case version.Capella:
|
||||
finalizedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderCapella{
|
||||
HeaderCapella: ðpbv2.LightClientHeaderCapella{
|
||||
Beacon: finalizedBlockHeader,
|
||||
Execution: createEmptyExecutionPayloadHeaderCapella(),
|
||||
ExecutionBranch: executionBranch,
|
||||
},
|
||||
},
|
||||
}
|
||||
case version.Deneb:
|
||||
finalizedHeader = ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderDeneb{
|
||||
HeaderDeneb: ðpbv2.LightClientHeaderDeneb{
|
||||
Beacon: finalizedBlockHeader,
|
||||
Execution: createEmptyExecutionPayloadHeaderDeneb(),
|
||||
ExecutionBranch: executionBranch,
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported block version %s", version.String(v))
|
||||
}
|
||||
|
||||
return ðpbv2.LightClientUpdate{
|
||||
NextSyncCommittee: nextSyncCommittee,
|
||||
NextSyncCommitteeBranch: nextSyncCommitteeBranch,
|
||||
FinalizedHeader: finalizedHeader,
|
||||
FinalityBranch: finalityBranch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createEmptyExecutionPayloadHeaderCapella() *enginev1.ExecutionPayloadHeaderCapella {
|
||||
return &enginev1.ExecutionPayloadHeaderCapella{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, 32),
|
||||
ReceiptsRoot: make([]byte, 32),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, 32),
|
||||
BlockNumber: 0,
|
||||
GasLimit: 0,
|
||||
GasUsed: 0,
|
||||
Timestamp: 0,
|
||||
ExtraData: make([]byte, 32),
|
||||
BaseFeePerGas: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
TransactionsRoot: make([]byte, 32),
|
||||
WithdrawalsRoot: make([]byte, 32),
|
||||
}
|
||||
}
|
||||
|
||||
func createEmptyExecutionPayloadHeaderDeneb() *enginev1.ExecutionPayloadHeaderDeneb {
|
||||
return &enginev1.ExecutionPayloadHeaderDeneb{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, 32),
|
||||
ReceiptsRoot: make([]byte, 32),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, 32),
|
||||
BlockNumber: 0,
|
||||
GasLimit: 0,
|
||||
GasUsed: 0,
|
||||
Timestamp: 0,
|
||||
ExtraData: make([]byte, 32),
|
||||
BaseFeePerGas: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
TransactionsRoot: make([]byte, 32),
|
||||
WithdrawalsRoot: make([]byte, 32),
|
||||
}
|
||||
}
|
||||
|
||||
func getExecutionPayloadHeaderCapella(block interfaces.ReadOnlySignedBeaconBlock) (*enginev1.ExecutionPayloadHeaderCapella, error) {
|
||||
payloadInterface, err := block.Block().Body().Execution()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution data")
|
||||
}
|
||||
transactionsRoot, err := payloadInterface.TransactionsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
transactions, err := payloadInterface.Transactions()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions")
|
||||
}
|
||||
transactionsRootArray, err := ssz.TransactionsRoot(transactions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions root")
|
||||
}
|
||||
transactionsRoot = transactionsRootArray[:]
|
||||
} else if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions root")
|
||||
}
|
||||
withdrawalsRoot, err := payloadInterface.WithdrawalsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
withdrawals, err := payloadInterface.Withdrawals()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals")
|
||||
}
|
||||
withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||
}
|
||||
withdrawalsRoot = withdrawalsRootArray[:]
|
||||
} else if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||
}
|
||||
|
||||
execution := &enginev1.ExecutionPayloadHeaderCapella{
|
||||
ParentHash: payloadInterface.ParentHash(),
|
||||
FeeRecipient: payloadInterface.FeeRecipient(),
|
||||
StateRoot: payloadInterface.StateRoot(),
|
||||
ReceiptsRoot: payloadInterface.ReceiptsRoot(),
|
||||
LogsBloom: payloadInterface.LogsBloom(),
|
||||
PrevRandao: payloadInterface.PrevRandao(),
|
||||
BlockNumber: payloadInterface.BlockNumber(),
|
||||
GasLimit: payloadInterface.GasLimit(),
|
||||
GasUsed: payloadInterface.GasUsed(),
|
||||
Timestamp: payloadInterface.Timestamp(),
|
||||
ExtraData: payloadInterface.ExtraData(),
|
||||
BaseFeePerGas: payloadInterface.BaseFeePerGas(),
|
||||
BlockHash: payloadInterface.BlockHash(),
|
||||
TransactionsRoot: transactionsRoot,
|
||||
WithdrawalsRoot: withdrawalsRoot,
|
||||
}
|
||||
|
||||
return execution, nil
|
||||
}
|
||||
|
||||
func getExecutionPayloadHeaderDeneb(block interfaces.ReadOnlySignedBeaconBlock) (*enginev1.ExecutionPayloadHeaderDeneb, error) {
|
||||
payloadInterface, err := block.Block().Body().Execution()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution data")
|
||||
}
|
||||
transactionsRoot, err := payloadInterface.TransactionsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
transactions, err := payloadInterface.Transactions()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions")
|
||||
}
|
||||
transactionsRootArray, err := ssz.TransactionsRoot(transactions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions root")
|
||||
}
|
||||
transactionsRoot = transactionsRootArray[:]
|
||||
} else if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions root")
|
||||
}
|
||||
withdrawalsRoot, err := payloadInterface.WithdrawalsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
withdrawals, err := payloadInterface.Withdrawals()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals")
|
||||
}
|
||||
withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||
}
|
||||
withdrawalsRoot = withdrawalsRootArray[:]
|
||||
} else if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||
}
|
||||
|
||||
execution := &enginev1.ExecutionPayloadHeaderDeneb{
|
||||
ParentHash: payloadInterface.ParentHash(),
|
||||
FeeRecipient: payloadInterface.FeeRecipient(),
|
||||
StateRoot: payloadInterface.StateRoot(),
|
||||
ReceiptsRoot: payloadInterface.ReceiptsRoot(),
|
||||
LogsBloom: payloadInterface.LogsBloom(),
|
||||
PrevRandao: payloadInterface.PrevRandao(),
|
||||
BlockNumber: payloadInterface.BlockNumber(),
|
||||
GasLimit: payloadInterface.GasLimit(),
|
||||
GasUsed: payloadInterface.GasUsed(),
|
||||
Timestamp: payloadInterface.Timestamp(),
|
||||
ExtraData: payloadInterface.ExtraData(),
|
||||
BaseFeePerGas: payloadInterface.BaseFeePerGas(),
|
||||
BlockHash: payloadInterface.BlockHash(),
|
||||
TransactionsRoot: transactionsRoot,
|
||||
WithdrawalsRoot: withdrawalsRoot,
|
||||
}
|
||||
|
||||
return execution, nil
|
||||
}
|
||||
|
||||
func ComputeTransactionsRoot(payload interfaces.ExecutionData) ([]byte, error) {
|
||||
transactionsRoot, err := payload.TransactionsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
@@ -669,8 +299,45 @@ func ComputeWithdrawalsRoot(payload interfaces.ExecutionData) ([]byte, error) {
|
||||
return withdrawalsRoot, nil
|
||||
}
|
||||
|
||||
func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeader, error) {
|
||||
if block.Version() != version.Altair {
|
||||
func BlockToLightClientHeader(block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeaderContainer, error) {
|
||||
switch block.Version() {
|
||||
case version.Altair, version.Bellatrix:
|
||||
altairHeader, err := blockToLightClientHeaderAltair(block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get header")
|
||||
}
|
||||
return ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderAltair{
|
||||
HeaderAltair: altairHeader,
|
||||
},
|
||||
}, nil
|
||||
case version.Capella:
|
||||
capellaHeader, err := blockToLightClientHeaderCapella(context.Background(), block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get capella header")
|
||||
}
|
||||
return ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderCapella{
|
||||
HeaderCapella: capellaHeader,
|
||||
},
|
||||
}, nil
|
||||
case version.Deneb, version.Electra:
|
||||
denebHeader, err := blockToLightClientHeaderDeneb(context.Background(), block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get header")
|
||||
}
|
||||
return ðpbv2.LightClientHeaderContainer{
|
||||
Header: ðpbv2.LightClientHeaderContainer_HeaderDeneb{
|
||||
HeaderDeneb: denebHeader,
|
||||
},
|
||||
}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported block version %s", version.String(block.Version()))
|
||||
}
|
||||
}
|
||||
|
||||
func blockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeader, error) {
|
||||
if block.Version() < version.Altair {
|
||||
return nil, fmt.Errorf("block version is %s instead of Altair", version.String(block.Version()))
|
||||
}
|
||||
|
||||
@@ -692,8 +359,8 @@ func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeaderCapella, error) {
|
||||
if block.Version() != version.Capella {
|
||||
func blockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeaderCapella, error) {
|
||||
if block.Version() < version.Capella {
|
||||
return nil, fmt.Errorf("block version is %s instead of Capella", version.String(block.Version()))
|
||||
}
|
||||
|
||||
@@ -754,9 +421,9 @@ func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadO
|
||||
}, nil
|
||||
}
|
||||
|
||||
func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeaderDeneb, error) {
|
||||
if block.Version() != version.Deneb {
|
||||
return nil, fmt.Errorf("block version is %s instead of Deneb", version.String(block.Version()))
|
||||
func blockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeaderDeneb, error) {
|
||||
if block.Version() < version.Deneb {
|
||||
return nil, fmt.Errorf("block version is %s instead of Deneb/Electra", version.String(block.Version()))
|
||||
}
|
||||
|
||||
payload, err := block.Block().Body().Execution()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -73,7 +73,7 @@ type goodNotifier struct {
|
||||
MockStateFeed *event.Feed
|
||||
}
|
||||
|
||||
func (g *goodNotifier) StateFeed() *event.Feed {
|
||||
func (g *goodNotifier) StateFeed() event.SubscriberSender {
|
||||
if g.MockStateFeed == nil {
|
||||
g.MockStateFeed = new(event.Feed)
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ func initSyncWaiter(ctx context.Context, complete chan struct{}) func() error {
|
||||
}
|
||||
|
||||
// StateFeed implements statefeed.Notifier.
|
||||
func (b *BeaconNode) StateFeed() *event.Feed {
|
||||
func (b *BeaconNode) StateFeed() event.SubscriberSender {
|
||||
return b.stateFeed
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ func (b *BeaconNode) BlockFeed() *event.Feed {
|
||||
}
|
||||
|
||||
// OperationFeed implements opfeed.Notifier.
|
||||
func (b *BeaconNode) OperationFeed() *event.Feed {
|
||||
func (b *BeaconNode) OperationFeed() event.SubscriberSender {
|
||||
return b.opFeed
|
||||
}
|
||||
|
||||
|
||||
@@ -89,5 +89,6 @@ go_test(
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@org_golang_x_exp//maps:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -773,6 +773,15 @@ func (s *Service) beaconEndpoints(
|
||||
handler: server.GetValidatorBalances,
|
||||
methods: []string{http.MethodGet, http.MethodPost},
|
||||
},
|
||||
{
|
||||
template: "/eth/v1/beacon/deposit_snapshot",
|
||||
name: namespace + ".GetDepositSnapshot",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
handler: server.GetDepositSnapshot,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -942,6 +951,8 @@ func (s *Service) prysmBeaconEndpoints(
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
||||
CoreService: coreService,
|
||||
Broadcaster: s.cfg.Broadcaster,
|
||||
BlobReceiver: s.cfg.BlobReceiver,
|
||||
}
|
||||
|
||||
const namespace = "prysm.beacon"
|
||||
@@ -992,6 +1003,16 @@ func (s *Service) prysmBeaconEndpoints(
|
||||
handler: server.GetChainHead,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
template: "/prysm/v1/beacon/blobs",
|
||||
name: namespace + ".PublishBlobs",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
},
|
||||
handler: server.PublishBlobs,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@ package rpc
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
func Test_endpoints(t *testing.T) {
|
||||
@@ -31,7 +33,6 @@ func Test_endpoints(t *testing.T) {
|
||||
"/eth/v2/beacon/blinded_blocks": {http.MethodPost},
|
||||
"/eth/v1/beacon/blocks": {http.MethodPost},
|
||||
"/eth/v2/beacon/blocks": {http.MethodPost},
|
||||
"/eth/v1/beacon/blocks/{block_id}": {http.MethodGet},
|
||||
"/eth/v2/beacon/blocks/{block_id}": {http.MethodGet},
|
||||
"/eth/v1/beacon/blocks/{block_id}/root": {http.MethodGet},
|
||||
"/eth/v1/beacon/blocks/{block_id}/attestations": {http.MethodGet},
|
||||
@@ -69,7 +70,6 @@ func Test_endpoints(t *testing.T) {
|
||||
}
|
||||
|
||||
debugRoutes := map[string][]string{
|
||||
"/eth/v1/debug/beacon/states/{state_id}": {http.MethodGet},
|
||||
"/eth/v2/debug/beacon/states/{state_id}": {http.MethodGet},
|
||||
"/eth/v2/debug/beacon/heads": {http.MethodGet},
|
||||
"/eth/v1/debug/fork_choice": {http.MethodGet},
|
||||
@@ -115,6 +115,7 @@ func Test_endpoints(t *testing.T) {
|
||||
"/eth/v1/beacon/states/{state_id}/validator_count": {http.MethodGet},
|
||||
"/prysm/v1/beacon/states/{state_id}/validator_count": {http.MethodGet},
|
||||
"/prysm/v1/beacon/chain_head": {http.MethodGet},
|
||||
"/prysm/v1/beacon/blobs": {http.MethodPost},
|
||||
}
|
||||
|
||||
prysmNodeRoutes := map[string][]string{
|
||||
@@ -133,22 +134,18 @@ func Test_endpoints(t *testing.T) {
|
||||
|
||||
s := &Service{cfg: &Config{}}
|
||||
|
||||
routesMap := combineMaps(beaconRoutes, builderRoutes, configRoutes, debugRoutes, eventsRoutes, nodeRoutes, validatorRoutes, rewardsRoutes, lightClientRoutes, blobRoutes, prysmValidatorRoutes, prysmNodeRoutes, prysmBeaconRoutes)
|
||||
actual := s.endpoints(true, nil, nil, nil, nil, nil, nil)
|
||||
for _, e := range actual {
|
||||
methods, ok := routesMap[e.template]
|
||||
assert.Equal(t, true, ok, "endpoint "+e.template+" not found")
|
||||
if ok {
|
||||
for _, em := range e.methods {
|
||||
methodFound := false
|
||||
for _, m := range methods {
|
||||
if m == em {
|
||||
methodFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.Equal(t, true, methodFound, "method "+em+" for endpoint "+e.template+" not found")
|
||||
}
|
||||
endpoints := s.endpoints(true, nil, nil, nil, nil, nil, nil)
|
||||
actualRoutes := make(map[string][]string, len(endpoints))
|
||||
for _, e := range endpoints {
|
||||
if _, ok := actualRoutes[e.template]; ok {
|
||||
actualRoutes[e.template] = append(actualRoutes[e.template], e.methods...)
|
||||
} else {
|
||||
actualRoutes[e.template] = e.methods
|
||||
}
|
||||
}
|
||||
expectedRoutes := combineMaps(beaconRoutes, builderRoutes, configRoutes, debugRoutes, eventsRoutes, nodeRoutes, validatorRoutes, rewardsRoutes, lightClientRoutes, blobRoutes, prysmValidatorRoutes, prysmNodeRoutes, prysmBeaconRoutes)
|
||||
|
||||
assert.Equal(t, true, maps.EqualFunc(expectedRoutes, actualRoutes, func(actualMethods []string, expectedMethods []string) bool {
|
||||
return slices.Equal(expectedMethods, actualMethods)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1512,10 +1512,6 @@ func (s *Server) GetDepositSnapshot(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.GetDepositSnapshot")
|
||||
defer span.End()
|
||||
|
||||
if s.BeaconDB == nil {
|
||||
httputil.HandleError(w, "Could not retrieve beaconDB", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
eth1data, err := s.BeaconDB.ExecutionChainData(ctx)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not retrieve execution chain data: "+err.Error(), http.StatusInternalServerError)
|
||||
@@ -1527,7 +1523,7 @@ func (s *Server) GetDepositSnapshot(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
snapshot := eth1data.DepositSnapshot
|
||||
if snapshot == nil || len(snapshot.Finalized) == 0 {
|
||||
httputil.HandleError(w, "No Finalized Snapshot Available", http.StatusNotFound)
|
||||
httputil.HandleError(w, "No finalized snapshot available", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if len(snapshot.Finalized) > depositsnapshot.DepositContractDepth {
|
||||
|
||||
@@ -268,6 +268,38 @@ func TestGetBlockV2(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, blk, b)
|
||||
})
|
||||
t.Run("electra", func(t *testing.T) {
|
||||
b := util.NewBeaconBlockElectra()
|
||||
b.Block.Slot = 123
|
||||
sb, err := blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
mockBlockFetcher := &testutil.MockBlocker{BlockToReturn: sb}
|
||||
mockChainService := &chainMock.ChainService{
|
||||
FinalizedRoots: map[[32]byte]bool{},
|
||||
}
|
||||
s := &Server{
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
Blocker: mockBlockFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil)
|
||||
request.SetPathValue("block_id", "head")
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetBlockV2(writer, request)
|
||||
require.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &structs.GetBlockV2Response{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, version.String(version.Electra), resp.Version)
|
||||
sbb := &structs.SignedBeaconBlockElectra{Message: &structs.BeaconBlockElectra{}}
|
||||
require.NoError(t, json.Unmarshal(resp.Data.Message, sbb.Message))
|
||||
sbb.Signature = resp.Data.Signature
|
||||
blk, err := sbb.ToConsensus()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, blk, b)
|
||||
})
|
||||
t.Run("execution optimistic", func(t *testing.T) {
|
||||
b := util.NewBeaconBlockBellatrix()
|
||||
sb, err := blocks.NewSignedBeaconBlock(b)
|
||||
@@ -461,7 +493,29 @@ func TestGetBlockSSZV2(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, sszExpected, writer.Body.Bytes())
|
||||
})
|
||||
t.Run("electra", func(t *testing.T) {
|
||||
b := util.NewBeaconBlockElectra()
|
||||
b.Block.Slot = 123
|
||||
sb, err := blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := &Server{
|
||||
Blocker: &testutil.MockBlocker{BlockToReturn: sb},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil)
|
||||
request.SetPathValue("block_id", "head")
|
||||
request.Header.Set("Accept", api.OctetStreamMediaType)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetBlockV2(writer, request)
|
||||
require.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, version.String(version.Electra), writer.Header().Get(api.VersionHeader))
|
||||
sszExpected, err := b.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, sszExpected, writer.Body.Bytes())
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetBlockAttestations(t *testing.T) {
|
||||
@@ -759,6 +813,35 @@ func TestGetBlindedBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, blk, b)
|
||||
})
|
||||
t.Run("electra", func(t *testing.T) {
|
||||
b := util.NewBlindedBeaconBlockElectra()
|
||||
sb, err := blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
|
||||
mockChainService := &chainMock.ChainService{}
|
||||
s := &Server{
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
Blocker: &testutil.MockBlocker{BlockToReturn: sb},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil)
|
||||
request.SetPathValue("block_id", "head")
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetBlindedBlock(writer, request)
|
||||
require.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &structs.GetBlockV2Response{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, version.String(version.Electra), resp.Version)
|
||||
sbb := &structs.SignedBlindedBeaconBlockElectra{Message: &structs.BlindedBeaconBlockElectra{}}
|
||||
require.NoError(t, json.Unmarshal(resp.Data.Message, sbb.Message))
|
||||
sbb.Signature = resp.Data.Signature
|
||||
blk, err := sbb.ToConsensus()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, blk, b)
|
||||
})
|
||||
t.Run("execution optimistic", func(t *testing.T) {
|
||||
b := util.NewBlindedBeaconBlockBellatrix()
|
||||
sb, err := blocks.NewSignedBeaconBlock(b)
|
||||
|
||||
@@ -20,6 +20,7 @@ go_library(
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//monitoring/tracing/trace:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
@@ -29,12 +30,16 @@ go_library(
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["events_test.go"],
|
||||
srcs = [
|
||||
"events_test.go",
|
||||
"http_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
@@ -49,9 +54,9 @@ go_test(
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_r3labs_sse_v2//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
time2 "time"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation"
|
||||
statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time"
|
||||
chaintime "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
|
||||
@@ -26,9 +28,13 @@ import (
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const DefaultEventFeedDepth = 1000
|
||||
|
||||
const (
|
||||
InvalidTopic = "__invalid__"
|
||||
// HeadTopic represents a new chain head event topic.
|
||||
HeadTopic = "head"
|
||||
// BlockTopic represents a new produced block event topic.
|
||||
@@ -59,25 +65,83 @@ const (
|
||||
LightClientOptimisticUpdateTopic = "light_client_optimistic_update"
|
||||
)
|
||||
|
||||
const topicDataMismatch = "Event data type %T does not correspond to event topic %s"
|
||||
var (
|
||||
errInvalidTopicName = errors.New("invalid topic name")
|
||||
errNoValidTopics = errors.New("no valid topics specified")
|
||||
errSlowReader = errors.New("client failed to read fast enough to keep outgoing buffer below threshold")
|
||||
errNotRequested = errors.New("event not requested by client")
|
||||
errUnhandledEventData = errors.New("unable to represent event data in the event stream")
|
||||
)
|
||||
|
||||
const chanBuffer = 1000
|
||||
// StreamingResponseWriter defines a type that can be used by the eventStreamer.
|
||||
// This must be an http.ResponseWriter that supports flushing and hijacking.
|
||||
type StreamingResponseWriter interface {
|
||||
http.ResponseWriter
|
||||
http.Flusher
|
||||
}
|
||||
|
||||
var casesHandled = map[string]bool{
|
||||
HeadTopic: true,
|
||||
BlockTopic: true,
|
||||
AttestationTopic: true,
|
||||
VoluntaryExitTopic: true,
|
||||
FinalizedCheckpointTopic: true,
|
||||
ChainReorgTopic: true,
|
||||
SyncCommitteeContributionTopic: true,
|
||||
BLSToExecutionChangeTopic: true,
|
||||
PayloadAttributesTopic: true,
|
||||
BlobSidecarTopic: true,
|
||||
ProposerSlashingTopic: true,
|
||||
AttesterSlashingTopic: true,
|
||||
LightClientFinalityUpdateTopic: true,
|
||||
LightClientOptimisticUpdateTopic: true,
|
||||
// The eventStreamer uses lazyReaders to defer serialization until the moment the value is ready to be written to the client.
|
||||
type lazyReader func() io.Reader
|
||||
|
||||
var opsFeedEventTopics = map[feed.EventType]string{
|
||||
operation.AggregatedAttReceived: AttestationTopic,
|
||||
operation.UnaggregatedAttReceived: AttestationTopic,
|
||||
operation.ExitReceived: VoluntaryExitTopic,
|
||||
operation.SyncCommitteeContributionReceived: SyncCommitteeContributionTopic,
|
||||
operation.BLSToExecutionChangeReceived: BLSToExecutionChangeTopic,
|
||||
operation.BlobSidecarReceived: BlobSidecarTopic,
|
||||
operation.AttesterSlashingReceived: AttesterSlashingTopic,
|
||||
operation.ProposerSlashingReceived: ProposerSlashingTopic,
|
||||
}
|
||||
|
||||
var stateFeedEventTopics = map[feed.EventType]string{
|
||||
statefeed.NewHead: HeadTopic,
|
||||
statefeed.MissedSlot: PayloadAttributesTopic,
|
||||
statefeed.FinalizedCheckpoint: FinalizedCheckpointTopic,
|
||||
statefeed.LightClientFinalityUpdate: LightClientFinalityUpdateTopic,
|
||||
statefeed.LightClientOptimisticUpdate: LightClientOptimisticUpdateTopic,
|
||||
statefeed.Reorg: ChainReorgTopic,
|
||||
statefeed.BlockProcessed: BlockTopic,
|
||||
}
|
||||
|
||||
var topicsForStateFeed = topicsForFeed(stateFeedEventTopics)
|
||||
var topicsForOpsFeed = topicsForFeed(opsFeedEventTopics)
|
||||
|
||||
func topicsForFeed(em map[feed.EventType]string) map[string]bool {
|
||||
topics := make(map[string]bool, len(em))
|
||||
for _, topic := range em {
|
||||
topics[topic] = true
|
||||
}
|
||||
return topics
|
||||
}
|
||||
|
||||
type topicRequest struct {
|
||||
topics map[string]bool
|
||||
needStateFeed bool
|
||||
needOpsFeed bool
|
||||
}
|
||||
|
||||
func (req *topicRequest) requested(topic string) bool {
|
||||
return req.topics[topic]
|
||||
}
|
||||
|
||||
func newTopicRequest(topics []string) (*topicRequest, error) {
|
||||
req := &topicRequest{topics: make(map[string]bool)}
|
||||
for _, name := range topics {
|
||||
if topicsForStateFeed[name] {
|
||||
req.needStateFeed = true
|
||||
} else if topicsForOpsFeed[name] {
|
||||
req.needOpsFeed = true
|
||||
} else {
|
||||
return nil, errors.Wrapf(errInvalidTopicName, name)
|
||||
}
|
||||
req.topics[name] = true
|
||||
}
|
||||
if len(req.topics) == 0 || (!req.needStateFeed && !req.needOpsFeed) {
|
||||
return nil, errNoValidTopics
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// StreamEvents provides an endpoint to subscribe to the beacon node Server-Sent-Events stream.
|
||||
@@ -88,326 +152,412 @@ func (s *Server) StreamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "events.StreamEvents")
|
||||
defer span.End()
|
||||
|
||||
flusher, ok := w.(http.Flusher)
|
||||
topics, err := newTopicRequest(r.URL.Query()["topics"])
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
sw, ok := w.(StreamingResponseWriter)
|
||||
if !ok {
|
||||
httputil.HandleError(w, "Streaming unsupported!", http.StatusInternalServerError)
|
||||
msg := "beacon node misconfiguration: http stack may not support required response handling features, like flushing"
|
||||
httputil.HandleError(w, msg, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
topics := r.URL.Query()["topics"]
|
||||
if len(topics) == 0 {
|
||||
httputil.HandleError(w, "No topics specified to subscribe to", http.StatusBadRequest)
|
||||
return
|
||||
depth := s.EventFeedDepth
|
||||
if depth == 0 {
|
||||
depth = DefaultEventFeedDepth
|
||||
}
|
||||
topicsMap := make(map[string]bool)
|
||||
for _, topic := range topics {
|
||||
if _, ok := casesHandled[topic]; !ok {
|
||||
httputil.HandleError(w, fmt.Sprintf("Invalid topic: %s", topic), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
topicsMap[topic] = true
|
||||
}
|
||||
|
||||
// Subscribe to event feeds from information received in the beacon node runtime.
|
||||
opsChan := make(chan *feed.Event, chanBuffer)
|
||||
opsSub := s.OperationNotifier.OperationFeed().Subscribe(opsChan)
|
||||
stateChan := make(chan *feed.Event, chanBuffer)
|
||||
stateSub := s.StateNotifier.StateFeed().Subscribe(stateChan)
|
||||
defer opsSub.Unsubscribe()
|
||||
defer stateSub.Unsubscribe()
|
||||
|
||||
// Set up SSE response headers
|
||||
w.Header().Set("Content-Type", api.EventStreamMediaType)
|
||||
w.Header().Set("Connection", api.KeepAlive)
|
||||
|
||||
// Handle each event received and context cancellation.
|
||||
// We send a keepalive dummy message immediately to prevent clients
|
||||
// stalling while waiting for the first response chunk.
|
||||
// After that we send a keepalive dummy message every SECONDS_PER_SLOT
|
||||
// to prevent anyone (e.g. proxy servers) from closing connections.
|
||||
if err := sendKeepalive(w, flusher); err != nil {
|
||||
es, err := newEventStreamer(depth, s.KeepAliveInterval)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
keepaliveTicker := time2.NewTicker(time2.Duration(params.BeaconConfig().SecondsPerSlot) * time2.Second)
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
api.SetSSEHeaders(sw)
|
||||
go es.outboxWriteLoop(ctx, cancel, sw)
|
||||
if err := es.recvEventLoop(ctx, cancel, topics, s); err != nil {
|
||||
log.WithError(err).Debug("Shutting down StreamEvents handler.")
|
||||
}
|
||||
}
|
||||
|
||||
func newEventStreamer(buffSize int, ka time.Duration) (*eventStreamer, error) {
|
||||
if ka == 0 {
|
||||
ka = time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second
|
||||
}
|
||||
return &eventStreamer{
|
||||
outbox: make(chan lazyReader, buffSize),
|
||||
keepAlive: ka,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type eventStreamer struct {
|
||||
outbox chan lazyReader
|
||||
keepAlive time.Duration
|
||||
}
|
||||
|
||||
func (es *eventStreamer) recvEventLoop(ctx context.Context, cancel context.CancelFunc, req *topicRequest, s *Server) error {
|
||||
eventsChan := make(chan *feed.Event, len(es.outbox))
|
||||
if req.needOpsFeed {
|
||||
opsSub := s.OperationNotifier.OperationFeed().Subscribe(eventsChan)
|
||||
defer opsSub.Unsubscribe()
|
||||
}
|
||||
if req.needStateFeed {
|
||||
stateSub := s.StateNotifier.StateFeed().Subscribe(eventsChan)
|
||||
defer stateSub.Unsubscribe()
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case event := <-opsChan:
|
||||
if err := handleBlockOperationEvents(w, flusher, topicsMap, event); err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
case event := <-stateChan:
|
||||
if err := s.handleStateEvents(ctx, w, flusher, topicsMap, event); err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
case <-keepaliveTicker.C:
|
||||
if err := sendKeepalive(w, flusher); err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case event := <-eventsChan:
|
||||
lr, err := s.lazyReaderForEvent(ctx, event, req)
|
||||
if err != nil {
|
||||
if !errors.Is(err, errNotRequested) {
|
||||
log.WithField("event_type", fmt.Sprintf("%v", event.Data)).WithError(err).Error("StreamEvents API endpoint received an event it was unable to handle.")
|
||||
}
|
||||
continue
|
||||
}
|
||||
// If the client can't keep up, the outbox will eventually completely fill, at which
|
||||
// safeWrite will error, and we'll hit the below return statement, at which point the deferred
|
||||
// Unsuscribe calls will be made and the event feed will stop writing to this channel.
|
||||
// Since the outbox and event stream channels are separately buffered, the event subscription
|
||||
// channel should stay relatively empty, which gives this loop time to unsubscribe
|
||||
// and cleanup before the event stream channel fills and disrupts other readers.
|
||||
if err := es.safeWrite(ctx, lr); err != nil {
|
||||
cancel()
|
||||
// note: we could hijack the connection and close it here. Does that cause issues? What are the benefits?
|
||||
// A benefit of hijack and close is that it may force an error on the remote end, however just closing the context of the
|
||||
// http handler may be sufficient to cause the remote http response reader to close.
|
||||
if errors.Is(err, errSlowReader) {
|
||||
log.WithError(err).Warn("Client is unable to keep up with event stream, shutting down.")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (es *eventStreamer) safeWrite(ctx context.Context, rf func() io.Reader) error {
|
||||
if rf == nil {
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case es.outbox <- rf:
|
||||
return nil
|
||||
default:
|
||||
// If this is the case, the select case to write to the outbox could not proceed, meaning the outbox is full.
|
||||
// If a reader can't keep up with the stream, we shut them down.
|
||||
return errSlowReader
|
||||
}
|
||||
}
|
||||
|
||||
// newlineReader is used to write keep-alives to the client.
|
||||
// keep-alives in the sse protocol are a single ':' colon followed by 2 newlines.
|
||||
func newlineReader() io.Reader {
|
||||
return bytes.NewBufferString(":\n\n")
|
||||
}
|
||||
|
||||
// outboxWriteLoop runs in a separate goroutine. Its job is to write the values in the outbox to
|
||||
// the client as fast as the client can read them.
|
||||
func (es *eventStreamer) outboxWriteLoop(ctx context.Context, cancel context.CancelFunc, w StreamingResponseWriter) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
log.WithError(err).Debug("Event streamer shutting down due to error.")
|
||||
}
|
||||
}()
|
||||
defer cancel()
|
||||
// Write a keepalive at the start to test the connection and simplify test setup.
|
||||
if err = es.writeOutbox(ctx, w, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
kaT := time.NewTimer(es.keepAlive)
|
||||
// Ensure the keepalive timer is stopped and drained if it has fired.
|
||||
defer func() {
|
||||
if !kaT.Stop() {
|
||||
<-kaT.C
|
||||
}
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
return
|
||||
case <-kaT.C:
|
||||
if err = es.writeOutbox(ctx, w, nil); err != nil {
|
||||
return
|
||||
}
|
||||
// In this case the timer doesn't need to be Stopped before the Reset call after the select statement,
|
||||
// because the timer has already fired.
|
||||
case lr := <-es.outbox:
|
||||
if err = es.writeOutbox(ctx, w, lr); err != nil {
|
||||
return
|
||||
}
|
||||
// We don't know if the timer fired concurrently to this case being ready, so we need to check the return
|
||||
// of Stop and drain the timer channel if it fired. We won't need to do this in go 1.23.
|
||||
if !kaT.Stop() {
|
||||
<-kaT.C
|
||||
}
|
||||
}
|
||||
kaT.Reset(es.keepAlive)
|
||||
}
|
||||
}
|
||||
|
||||
func (es *eventStreamer) writeOutbox(ctx context.Context, w StreamingResponseWriter, first lazyReader) error {
|
||||
needKeepAlive := true
|
||||
if first != nil {
|
||||
if _, err := io.Copy(w, first()); err != nil {
|
||||
return err
|
||||
}
|
||||
needKeepAlive = false
|
||||
}
|
||||
// While the first event was being read by the client, further events may be queued in the outbox.
|
||||
// We can drain them right away rather than go back out to the outer select statement, where the keepAlive timer
|
||||
// may have fired, triggering an unnecessary extra keep-alive write and flush.
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case rf := <-es.outbox:
|
||||
if _, err := io.Copy(w, rf()); err != nil {
|
||||
return err
|
||||
}
|
||||
needKeepAlive = false
|
||||
default:
|
||||
if needKeepAlive {
|
||||
if _, err := io.Copy(w, newlineReader()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
w.Flush()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleBlockOperationEvents(w http.ResponseWriter, flusher http.Flusher, requestedTopics map[string]bool, event *feed.Event) error {
|
||||
switch event.Type {
|
||||
case operation.AggregatedAttReceived:
|
||||
if _, ok := requestedTopics[AttestationTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
attData, ok := event.Data.(*operation.AggregatedAttReceivedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, AttestationTopic)
|
||||
}
|
||||
att := structs.AttFromConsensus(attData.Attestation.Aggregate)
|
||||
return send(w, flusher, AttestationTopic, att)
|
||||
case operation.UnaggregatedAttReceived:
|
||||
if _, ok := requestedTopics[AttestationTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
attData, ok := event.Data.(*operation.UnAggregatedAttReceivedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, AttestationTopic)
|
||||
}
|
||||
a, ok := attData.Attestation.(*eth.Attestation)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, AttestationTopic)
|
||||
}
|
||||
att := structs.AttFromConsensus(a)
|
||||
return send(w, flusher, AttestationTopic, att)
|
||||
case operation.ExitReceived:
|
||||
if _, ok := requestedTopics[VoluntaryExitTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
exitData, ok := event.Data.(*operation.ExitReceivedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, VoluntaryExitTopic)
|
||||
}
|
||||
exit := structs.SignedExitFromConsensus(exitData.Exit)
|
||||
return send(w, flusher, VoluntaryExitTopic, exit)
|
||||
case operation.SyncCommitteeContributionReceived:
|
||||
if _, ok := requestedTopics[SyncCommitteeContributionTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
contributionData, ok := event.Data.(*operation.SyncCommitteeContributionReceivedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, SyncCommitteeContributionTopic)
|
||||
}
|
||||
contribution := structs.SignedContributionAndProofFromConsensus(contributionData.Contribution)
|
||||
return send(w, flusher, SyncCommitteeContributionTopic, contribution)
|
||||
case operation.BLSToExecutionChangeReceived:
|
||||
if _, ok := requestedTopics[BLSToExecutionChangeTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
changeData, ok := event.Data.(*operation.BLSToExecutionChangeReceivedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, BLSToExecutionChangeTopic)
|
||||
}
|
||||
return send(w, flusher, BLSToExecutionChangeTopic, structs.SignedBLSChangeFromConsensus(changeData.Change))
|
||||
case operation.BlobSidecarReceived:
|
||||
if _, ok := requestedTopics[BlobSidecarTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
blobData, ok := event.Data.(*operation.BlobSidecarReceivedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, BlobSidecarTopic)
|
||||
}
|
||||
versionedHash := blockchain.ConvertKzgCommitmentToVersionedHash(blobData.Blob.KzgCommitment)
|
||||
blobEvent := &structs.BlobSidecarEvent{
|
||||
BlockRoot: hexutil.Encode(blobData.Blob.BlockRootSlice()),
|
||||
Index: fmt.Sprintf("%d", blobData.Blob.Index),
|
||||
Slot: fmt.Sprintf("%d", blobData.Blob.Slot()),
|
||||
VersionedHash: versionedHash.String(),
|
||||
KzgCommitment: hexutil.Encode(blobData.Blob.KzgCommitment),
|
||||
}
|
||||
return send(w, flusher, BlobSidecarTopic, blobEvent)
|
||||
case operation.AttesterSlashingReceived:
|
||||
if _, ok := requestedTopics[AttesterSlashingTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
attesterSlashingData, ok := event.Data.(*operation.AttesterSlashingReceivedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, AttesterSlashingTopic)
|
||||
}
|
||||
slashing, ok := attesterSlashingData.AttesterSlashing.(*eth.AttesterSlashing)
|
||||
if ok {
|
||||
return send(w, flusher, AttesterSlashingTopic, structs.AttesterSlashingFromConsensus(slashing))
|
||||
}
|
||||
// TODO: extend to Electra
|
||||
case operation.ProposerSlashingReceived:
|
||||
if _, ok := requestedTopics[ProposerSlashingTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
proposerSlashingData, ok := event.Data.(*operation.ProposerSlashingReceivedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, ProposerSlashingTopic)
|
||||
}
|
||||
return send(w, flusher, ProposerSlashingTopic, structs.ProposerSlashingFromConsensus(proposerSlashingData.ProposerSlashing))
|
||||
func jsonMarshalReader(name string, v any) io.Reader {
|
||||
d, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("type_name", fmt.Sprintf("%T", v)).Error("Could not marshal event data.")
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
return bytes.NewBufferString("event: " + name + "\ndata: " + string(d) + "\n\n")
|
||||
}
|
||||
|
||||
func (s *Server) handleStateEvents(ctx context.Context, w http.ResponseWriter, flusher http.Flusher, requestedTopics map[string]bool, event *feed.Event) error {
|
||||
switch event.Type {
|
||||
case statefeed.NewHead:
|
||||
if _, ok := requestedTopics[HeadTopic]; ok {
|
||||
headData, ok := event.Data.(*ethpb.EventHead)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, HeadTopic)
|
||||
}
|
||||
head := &structs.HeadEvent{
|
||||
Slot: fmt.Sprintf("%d", headData.Slot),
|
||||
Block: hexutil.Encode(headData.Block),
|
||||
State: hexutil.Encode(headData.State),
|
||||
EpochTransition: headData.EpochTransition,
|
||||
ExecutionOptimistic: headData.ExecutionOptimistic,
|
||||
PreviousDutyDependentRoot: hexutil.Encode(headData.PreviousDutyDependentRoot),
|
||||
CurrentDutyDependentRoot: hexutil.Encode(headData.CurrentDutyDependentRoot),
|
||||
}
|
||||
return send(w, flusher, HeadTopic, head)
|
||||
func topicForEvent(event *feed.Event) string {
|
||||
switch event.Data.(type) {
|
||||
case *operation.AggregatedAttReceivedData:
|
||||
return AttestationTopic
|
||||
case *operation.UnAggregatedAttReceivedData:
|
||||
return AttestationTopic
|
||||
case *operation.ExitReceivedData:
|
||||
return VoluntaryExitTopic
|
||||
case *operation.SyncCommitteeContributionReceivedData:
|
||||
return SyncCommitteeContributionTopic
|
||||
case *operation.BLSToExecutionChangeReceivedData:
|
||||
return BLSToExecutionChangeTopic
|
||||
case *operation.BlobSidecarReceivedData:
|
||||
return BlobSidecarTopic
|
||||
case *operation.AttesterSlashingReceivedData:
|
||||
return AttesterSlashingTopic
|
||||
case *operation.ProposerSlashingReceivedData:
|
||||
return ProposerSlashingTopic
|
||||
case *ethpb.EventHead:
|
||||
return HeadTopic
|
||||
case *ethpb.EventFinalizedCheckpoint:
|
||||
return FinalizedCheckpointTopic
|
||||
case *ethpbv2.LightClientFinalityUpdateWithVersion:
|
||||
return LightClientFinalityUpdateTopic
|
||||
case *ethpbv2.LightClientOptimisticUpdateWithVersion:
|
||||
return LightClientOptimisticUpdateTopic
|
||||
case *ethpb.EventChainReorg:
|
||||
return ChainReorgTopic
|
||||
case *statefeed.BlockProcessedData:
|
||||
return BlockTopic
|
||||
default:
|
||||
if event.Type == statefeed.MissedSlot {
|
||||
return PayloadAttributesTopic
|
||||
}
|
||||
if _, ok := requestedTopics[PayloadAttributesTopic]; ok {
|
||||
return s.sendPayloadAttributes(ctx, w, flusher)
|
||||
}
|
||||
case statefeed.MissedSlot:
|
||||
if _, ok := requestedTopics[PayloadAttributesTopic]; ok {
|
||||
return s.sendPayloadAttributes(ctx, w, flusher)
|
||||
}
|
||||
case statefeed.FinalizedCheckpoint:
|
||||
if _, ok := requestedTopics[FinalizedCheckpointTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
checkpointData, ok := event.Data.(*ethpb.EventFinalizedCheckpoint)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, FinalizedCheckpointTopic)
|
||||
}
|
||||
checkpoint := &structs.FinalizedCheckpointEvent{
|
||||
Block: hexutil.Encode(checkpointData.Block),
|
||||
State: hexutil.Encode(checkpointData.State),
|
||||
Epoch: fmt.Sprintf("%d", checkpointData.Epoch),
|
||||
ExecutionOptimistic: checkpointData.ExecutionOptimistic,
|
||||
}
|
||||
return send(w, flusher, FinalizedCheckpointTopic, checkpoint)
|
||||
case statefeed.LightClientFinalityUpdate:
|
||||
if _, ok := requestedTopics[LightClientFinalityUpdateTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
updateData, ok := event.Data.(*ethpbv2.LightClientFinalityUpdateWithVersion)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, LightClientFinalityUpdateTopic)
|
||||
}
|
||||
update, err := structs.LightClientFinalityUpdateFromConsensus(updateData.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateEvent := &structs.LightClientFinalityUpdateEvent{
|
||||
Version: version.String(int(updateData.Version)),
|
||||
Data: update,
|
||||
}
|
||||
return send(w, flusher, LightClientFinalityUpdateTopic, updateEvent)
|
||||
case statefeed.LightClientOptimisticUpdate:
|
||||
if _, ok := requestedTopics[LightClientOptimisticUpdateTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
updateData, ok := event.Data.(*ethpbv2.LightClientOptimisticUpdateWithVersion)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, LightClientOptimisticUpdateTopic)
|
||||
}
|
||||
update, err := structs.LightClientOptimisticUpdateFromConsensus(updateData.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateEvent := &structs.LightClientOptimisticUpdateEvent{
|
||||
Version: version.String(int(updateData.Version)),
|
||||
Data: update,
|
||||
}
|
||||
return send(w, flusher, LightClientOptimisticUpdateTopic, updateEvent)
|
||||
case statefeed.Reorg:
|
||||
if _, ok := requestedTopics[ChainReorgTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
reorgData, ok := event.Data.(*ethpb.EventChainReorg)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, ChainReorgTopic)
|
||||
}
|
||||
reorg := &structs.ChainReorgEvent{
|
||||
Slot: fmt.Sprintf("%d", reorgData.Slot),
|
||||
Depth: fmt.Sprintf("%d", reorgData.Depth),
|
||||
OldHeadBlock: hexutil.Encode(reorgData.OldHeadBlock),
|
||||
NewHeadBlock: hexutil.Encode(reorgData.NewHeadBlock),
|
||||
OldHeadState: hexutil.Encode(reorgData.OldHeadState),
|
||||
NewHeadState: hexutil.Encode(reorgData.NewHeadState),
|
||||
Epoch: fmt.Sprintf("%d", reorgData.Epoch),
|
||||
ExecutionOptimistic: reorgData.ExecutionOptimistic,
|
||||
}
|
||||
return send(w, flusher, ChainReorgTopic, reorg)
|
||||
case statefeed.BlockProcessed:
|
||||
if _, ok := requestedTopics[BlockTopic]; !ok {
|
||||
return nil
|
||||
}
|
||||
blkData, ok := event.Data.(*statefeed.BlockProcessedData)
|
||||
if !ok {
|
||||
return write(w, flusher, topicDataMismatch, event.Data, BlockTopic)
|
||||
}
|
||||
blockRoot, err := blkData.SignedBlock.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get block root: "+err.Error())
|
||||
}
|
||||
blk := &structs.BlockEvent{
|
||||
Slot: fmt.Sprintf("%d", blkData.Slot),
|
||||
Block: hexutil.Encode(blockRoot[:]),
|
||||
ExecutionOptimistic: blkData.Optimistic,
|
||||
}
|
||||
return send(w, flusher, BlockTopic, blk)
|
||||
return InvalidTopic
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) lazyReaderForEvent(ctx context.Context, event *feed.Event, topics *topicRequest) (lazyReader, error) {
|
||||
eventName := topicForEvent(event)
|
||||
if !topics.requested(eventName) {
|
||||
return nil, errNotRequested
|
||||
}
|
||||
if eventName == PayloadAttributesTopic {
|
||||
return s.currentPayloadAttributes(ctx)
|
||||
}
|
||||
if event == nil || event.Data == nil {
|
||||
return nil, errors.New("event or event data is nil")
|
||||
}
|
||||
switch v := event.Data.(type) {
|
||||
case *ethpb.EventHead:
|
||||
// The head event is a special case because, if the client requested the payload attributes topic,
|
||||
// we send two event messages in reaction; the head event and the payload attributes.
|
||||
headReader := func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.HeadEventFromV1(v))
|
||||
}
|
||||
// Don't do the expensive attr lookup unless the client requested it.
|
||||
if !topics.requested(PayloadAttributesTopic) {
|
||||
return headReader, nil
|
||||
}
|
||||
// Since payload attributes could change before the outbox is written, we need to do a blocking operation to
|
||||
// get the current payload attributes right here.
|
||||
attrReader, err := s.currentPayloadAttributes(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get payload attributes for head event")
|
||||
}
|
||||
return func() io.Reader {
|
||||
return io.MultiReader(headReader(), attrReader())
|
||||
}, nil
|
||||
case *operation.AggregatedAttReceivedData:
|
||||
return func() io.Reader {
|
||||
att := structs.AttFromConsensus(v.Attestation.Aggregate)
|
||||
return jsonMarshalReader(eventName, att)
|
||||
}, nil
|
||||
case *operation.UnAggregatedAttReceivedData:
|
||||
att, ok := v.Attestation.(*eth.Attestation)
|
||||
if !ok {
|
||||
return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .Attestation field of UnAggregatedAttReceivedData", v.Attestation)
|
||||
}
|
||||
return func() io.Reader {
|
||||
att := structs.AttFromConsensus(att)
|
||||
return jsonMarshalReader(eventName, att)
|
||||
}, nil
|
||||
case *operation.ExitReceivedData:
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.SignedExitFromConsensus(v.Exit))
|
||||
}, nil
|
||||
case *operation.SyncCommitteeContributionReceivedData:
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.SignedContributionAndProofFromConsensus(v.Contribution))
|
||||
}, nil
|
||||
case *operation.BLSToExecutionChangeReceivedData:
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.SignedBLSChangeFromConsensus(v.Change))
|
||||
}, nil
|
||||
case *operation.BlobSidecarReceivedData:
|
||||
return func() io.Reader {
|
||||
versionedHash := primitives.ConvertKzgCommitmentToVersionedHash(v.Blob.KzgCommitment)
|
||||
return jsonMarshalReader(eventName, &structs.BlobSidecarEvent{
|
||||
BlockRoot: hexutil.Encode(v.Blob.BlockRootSlice()),
|
||||
Index: fmt.Sprintf("%d", v.Blob.Index),
|
||||
Slot: fmt.Sprintf("%d", v.Blob.Slot()),
|
||||
VersionedHash: versionedHash.String(),
|
||||
KzgCommitment: hexutil.Encode(v.Blob.KzgCommitment),
|
||||
})
|
||||
}, nil
|
||||
case *operation.AttesterSlashingReceivedData:
|
||||
slashing, ok := v.AttesterSlashing.(*eth.AttesterSlashing)
|
||||
if !ok {
|
||||
return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .AttesterSlashing field of AttesterSlashingReceivedData", v.AttesterSlashing)
|
||||
}
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.AttesterSlashingFromConsensus(slashing))
|
||||
}, nil
|
||||
case *operation.ProposerSlashingReceivedData:
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.ProposerSlashingFromConsensus(v.ProposerSlashing))
|
||||
}, nil
|
||||
case *ethpb.EventFinalizedCheckpoint:
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.FinalizedCheckpointEventFromV1(v))
|
||||
}, nil
|
||||
case *ethpbv2.LightClientFinalityUpdateWithVersion:
|
||||
cv, err := structs.LightClientFinalityUpdateFromConsensus(v.Data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "LightClientFinalityUpdateWithVersion event conversion failure")
|
||||
}
|
||||
ev := &structs.LightClientFinalityUpdateEvent{
|
||||
Version: version.String(int(v.Version)),
|
||||
Data: cv,
|
||||
}
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, ev)
|
||||
}, nil
|
||||
case *ethpbv2.LightClientOptimisticUpdateWithVersion:
|
||||
cv, err := structs.LightClientOptimisticUpdateFromConsensus(v.Data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "LightClientOptimisticUpdateWithVersion event conversion failure")
|
||||
}
|
||||
ev := &structs.LightClientOptimisticUpdateEvent{
|
||||
Version: version.String(int(v.Version)),
|
||||
Data: cv,
|
||||
}
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, ev)
|
||||
}, nil
|
||||
case *ethpb.EventChainReorg:
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(eventName, structs.EventChainReorgFromV1(v))
|
||||
}, nil
|
||||
case *statefeed.BlockProcessedData:
|
||||
blockRoot, err := v.SignedBlock.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute block root for BlockProcessedData state feed event")
|
||||
}
|
||||
return func() io.Reader {
|
||||
blk := &structs.BlockEvent{
|
||||
Slot: fmt.Sprintf("%d", v.Slot),
|
||||
Block: hexutil.Encode(blockRoot[:]),
|
||||
ExecutionOptimistic: v.Optimistic,
|
||||
}
|
||||
return jsonMarshalReader(eventName, blk)
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.Wrapf(errUnhandledEventData, "event data type %T unsupported", v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This event stream is intended to be used by builders and relays.
|
||||
// Parent fields are based on state at N_{current_slot}, while the rest of fields are based on state of N_{current_slot + 1}
|
||||
func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWriter, flusher http.Flusher) error {
|
||||
func (s *Server) currentPayloadAttributes(ctx context.Context) (lazyReader, error) {
|
||||
headRoot, err := s.HeadFetcher.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head root: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head root")
|
||||
}
|
||||
st, err := s.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head state: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head state")
|
||||
}
|
||||
// advance the head state
|
||||
headState, err := transition.ProcessSlotsIfPossible(ctx, st, s.ChainInfoFetcher.CurrentSlot()+1)
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not advance head state: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not advance head state")
|
||||
}
|
||||
|
||||
headBlock, err := s.HeadFetcher.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head block: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head block")
|
||||
}
|
||||
|
||||
headPayload, err := headBlock.Block().Body().Execution()
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get execution payload: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get execution payload")
|
||||
}
|
||||
|
||||
t, err := slots.ToTime(headState.GenesisTime(), headState.Slot())
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head state slot time: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head state slot time")
|
||||
}
|
||||
|
||||
prevRando, err := helpers.RandaoMix(headState, time.CurrentEpoch(headState))
|
||||
prevRando, err := helpers.RandaoMix(headState, chaintime.CurrentEpoch(headState))
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head state randao mix: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head state randao mix")
|
||||
}
|
||||
|
||||
proposerIndex, err := helpers.BeaconProposerIndex(ctx, headState)
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head state proposer index: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head state proposer index")
|
||||
}
|
||||
feeRecipient := params.BeaconConfig().DefaultFeeRecipient.Bytes()
|
||||
tValidator, exists := s.TrackedValidatorsCache.Validator(proposerIndex)
|
||||
@@ -425,7 +575,7 @@ func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWrite
|
||||
case version.Capella:
|
||||
withdrawals, _, err := headState.ExpectedWithdrawals()
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head state expected withdrawals: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head state expected withdrawals")
|
||||
}
|
||||
attributes = &structs.PayloadAttributesV2{
|
||||
Timestamp: fmt.Sprintf("%d", t.Unix()),
|
||||
@@ -436,11 +586,11 @@ func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWrite
|
||||
case version.Deneb, version.Electra:
|
||||
withdrawals, _, err := headState.ExpectedWithdrawals()
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head state expected withdrawals: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head state expected withdrawals")
|
||||
}
|
||||
parentRoot, err := headBlock.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head block root: "+err.Error())
|
||||
return nil, errors.Wrap(err, "could not get head block root")
|
||||
}
|
||||
attributes = &structs.PayloadAttributesV3{
|
||||
Timestamp: fmt.Sprintf("%d", t.Unix()),
|
||||
@@ -450,12 +600,12 @@ func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWrite
|
||||
ParentBeaconBlockRoot: hexutil.Encode(parentRoot[:]),
|
||||
}
|
||||
default:
|
||||
return write(w, flusher, "Payload version %s is not supported", version.String(headState.Version()))
|
||||
return nil, errors.Wrapf(err, "Payload version %s is not supported", version.String(headState.Version()))
|
||||
}
|
||||
|
||||
attributesBytes, err := json.Marshal(attributes)
|
||||
if err != nil {
|
||||
return write(w, flusher, err.Error())
|
||||
return nil, errors.Wrap(err, "errors marshaling payload attributes to json")
|
||||
}
|
||||
eventData := structs.PayloadAttributesEventData{
|
||||
ProposerIndex: fmt.Sprintf("%d", proposerIndex),
|
||||
@@ -467,31 +617,12 @@ func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWrite
|
||||
}
|
||||
eventDataBytes, err := json.Marshal(eventData)
|
||||
if err != nil {
|
||||
return write(w, flusher, err.Error())
|
||||
return nil, errors.Wrap(err, "errors marshaling payload attributes event data to json")
|
||||
}
|
||||
return send(w, flusher, PayloadAttributesTopic, &structs.PayloadAttributesEvent{
|
||||
Version: version.String(headState.Version()),
|
||||
Data: eventDataBytes,
|
||||
})
|
||||
}
|
||||
|
||||
func send(w http.ResponseWriter, flusher http.Flusher, name string, data interface{}) error {
|
||||
j, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not marshal event to JSON: "+err.Error())
|
||||
}
|
||||
return write(w, flusher, "event: %s\ndata: %s\n\n", name, string(j))
|
||||
}
|
||||
|
||||
func sendKeepalive(w http.ResponseWriter, flusher http.Flusher) error {
|
||||
return write(w, flusher, ":\n\n")
|
||||
}
|
||||
|
||||
func write(w http.ResponseWriter, flusher http.Flusher, format string, a ...any) error {
|
||||
_, err := fmt.Fprintf(w, format, a...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not write to response writer")
|
||||
}
|
||||
flusher.Flush()
|
||||
return nil
|
||||
return func() io.Reader {
|
||||
return jsonMarshalReader(PayloadAttributesTopic, &structs.PayloadAttributesEvent{
|
||||
Version: version.String(headState.Version()),
|
||||
Data: eventDataBytes,
|
||||
})
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
@@ -23,56 +24,99 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
sse "github.com/r3labs/sse/v2"
|
||||
)
|
||||
|
||||
type flushableResponseRecorder struct {
|
||||
*httptest.ResponseRecorder
|
||||
flushed bool
|
||||
func requireAllEventsReceived(t *testing.T, stn, opn *mockChain.EventFeedWrapper, events []*feed.Event, req *topicRequest, s *Server, w *StreamingResponseWriterRecorder) {
|
||||
// maxBufferSize param copied from sse lib client code
|
||||
sseR := sse.NewEventStreamReader(w.Body(), 1<<24)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
expected := make(map[string]bool)
|
||||
for i := range events {
|
||||
ev := events[i]
|
||||
// serialize the event the same way the server will so that we can compare expectation to results.
|
||||
top := topicForEvent(ev)
|
||||
eb, err := s.lazyReaderForEvent(context.Background(), ev, req)
|
||||
require.NoError(t, err)
|
||||
exb, err := io.ReadAll(eb())
|
||||
require.NoError(t, err)
|
||||
exs := string(exb[0 : len(exb)-2]) // remove trailing double newline
|
||||
|
||||
if topicsForOpsFeed[top] {
|
||||
if err := opn.WaitForSubscription(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Send the event on the feed.
|
||||
s.OperationNotifier.OperationFeed().Send(ev)
|
||||
} else {
|
||||
if err := stn.WaitForSubscription(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Send the event on the feed.
|
||||
s.StateNotifier.StateFeed().Send(ev)
|
||||
}
|
||||
expected[exs] = true
|
||||
}
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for {
|
||||
ev, err := sseR.ReadEvent()
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
str := string(ev)
|
||||
delete(expected, str)
|
||||
if len(expected) == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case <-done:
|
||||
break
|
||||
case <-ctx.Done():
|
||||
t.Fatalf("context canceled / timed out waiting for events, err=%v", ctx.Err())
|
||||
}
|
||||
require.Equal(t, 0, len(expected), "expected events not seen")
|
||||
}
|
||||
|
||||
func (f *flushableResponseRecorder) Flush() {
|
||||
f.flushed = true
|
||||
func (tr *topicRequest) testHttpRequest(_ *testing.T) *http.Request {
|
||||
tq := make([]string, 0, len(tr.topics))
|
||||
for topic := range tr.topics {
|
||||
tq = append(tq, "topics="+topic)
|
||||
}
|
||||
return httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/events?%s", strings.Join(tq, "&")), nil)
|
||||
}
|
||||
|
||||
func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
t.Run("operations", func(t *testing.T) {
|
||||
s := &Server{
|
||||
StateNotifier: &mockChain.MockStateNotifier{},
|
||||
OperationNotifier: &mockChain.MockOperationNotifier{},
|
||||
}
|
||||
func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) {
|
||||
topics, err := newTopicRequest([]string{
|
||||
AttestationTopic,
|
||||
VoluntaryExitTopic,
|
||||
SyncCommitteeContributionTopic,
|
||||
BLSToExecutionChangeTopic,
|
||||
BlobSidecarTopic,
|
||||
AttesterSlashingTopic,
|
||||
ProposerSlashingTopic,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
ro, err := blocks.NewROBlob(util.HydrateBlobSidecar(ð.BlobSidecar{}))
|
||||
require.NoError(t, err)
|
||||
vblob := blocks.NewVerifiedROBlob(ro)
|
||||
|
||||
topics := []string{
|
||||
AttestationTopic,
|
||||
VoluntaryExitTopic,
|
||||
SyncCommitteeContributionTopic,
|
||||
BLSToExecutionChangeTopic,
|
||||
BlobSidecarTopic,
|
||||
AttesterSlashingTopic,
|
||||
ProposerSlashingTopic,
|
||||
}
|
||||
for i, topic := range topics {
|
||||
topics[i] = "topics=" + topic
|
||||
}
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/events?%s", strings.Join(topics, "&")), nil)
|
||||
w := &flushableResponseRecorder{
|
||||
ResponseRecorder: httptest.NewRecorder(),
|
||||
}
|
||||
|
||||
go func() {
|
||||
s.StreamEvents(w, request)
|
||||
}()
|
||||
// wait for initiation of StreamEvents
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
return topics, []*feed.Event{
|
||||
&feed.Event{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: util.HydrateAttestation(ð.Attestation{}),
|
||||
},
|
||||
})
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
},
|
||||
&feed.Event{
|
||||
Type: operation.AggregatedAttReceived,
|
||||
Data: &operation.AggregatedAttReceivedData{
|
||||
Attestation: ð.AggregateAttestationAndProof{
|
||||
@@ -81,8 +125,8 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
SelectionProof: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
})
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
},
|
||||
&feed.Event{
|
||||
Type: operation.ExitReceived,
|
||||
Data: &operation.ExitReceivedData{
|
||||
Exit: ð.SignedVoluntaryExit{
|
||||
@@ -93,8 +137,8 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
})
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
},
|
||||
&feed.Event{
|
||||
Type: operation.SyncCommitteeContributionReceived,
|
||||
Data: &operation.SyncCommitteeContributionReceivedData{
|
||||
Contribution: ð.SignedContributionAndProof{
|
||||
@@ -112,8 +156,8 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
})
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
},
|
||||
&feed.Event{
|
||||
Type: operation.BLSToExecutionChangeReceived,
|
||||
Data: &operation.BLSToExecutionChangeReceivedData{
|
||||
Change: ð.SignedBLSToExecutionChange{
|
||||
@@ -125,18 +169,14 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
})
|
||||
ro, err := blocks.NewROBlob(util.HydrateBlobSidecar(ð.BlobSidecar{}))
|
||||
require.NoError(t, err)
|
||||
vblob := blocks.NewVerifiedROBlob(ro)
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
},
|
||||
&feed.Event{
|
||||
Type: operation.BlobSidecarReceived,
|
||||
Data: &operation.BlobSidecarReceivedData{
|
||||
Blob: &vblob,
|
||||
},
|
||||
})
|
||||
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
},
|
||||
&feed.Event{
|
||||
Type: operation.AttesterSlashingReceived,
|
||||
Data: &operation.AttesterSlashingReceivedData{
|
||||
AttesterSlashing: ð.AttesterSlashing{
|
||||
@@ -168,9 +208,8 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
s.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
},
|
||||
&feed.Event{
|
||||
Type: operation.ProposerSlashingReceived,
|
||||
Data: &operation.ProposerSlashingReceivedData{
|
||||
ProposerSlashing: ð.ProposerSlashing{
|
||||
@@ -192,100 +231,107 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
request.Context().Done()
|
||||
func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
t.Run("operations", func(t *testing.T) {
|
||||
stn := mockChain.NewEventFeedWrapper()
|
||||
opn := mockChain.NewEventFeedWrapper()
|
||||
s := &Server{
|
||||
StateNotifier: &mockChain.SimpleNotifier{Feed: stn},
|
||||
OperationNotifier: &mockChain.SimpleNotifier{Feed: opn},
|
||||
}
|
||||
|
||||
resp := w.Result()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, body)
|
||||
assert.Equal(t, operationsResult, string(body))
|
||||
topics, events := operationEventsFixtures(t)
|
||||
request := topics.testHttpRequest(t)
|
||||
w := NewStreamingResponseWriterRecorder()
|
||||
|
||||
go func() {
|
||||
s.StreamEvents(w, request)
|
||||
}()
|
||||
|
||||
requireAllEventsReceived(t, stn, opn, events, topics, s, w)
|
||||
})
|
||||
t.Run("state", func(t *testing.T) {
|
||||
stn := mockChain.NewEventFeedWrapper()
|
||||
opn := mockChain.NewEventFeedWrapper()
|
||||
s := &Server{
|
||||
StateNotifier: &mockChain.MockStateNotifier{},
|
||||
OperationNotifier: &mockChain.MockOperationNotifier{},
|
||||
StateNotifier: &mockChain.SimpleNotifier{Feed: stn},
|
||||
OperationNotifier: &mockChain.SimpleNotifier{Feed: opn},
|
||||
}
|
||||
|
||||
topics := []string{HeadTopic, FinalizedCheckpointTopic, ChainReorgTopic, BlockTopic}
|
||||
for i, topic := range topics {
|
||||
topics[i] = "topics=" + topic
|
||||
}
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/events?%s", strings.Join(topics, "&")), nil)
|
||||
w := &flushableResponseRecorder{
|
||||
ResponseRecorder: httptest.NewRecorder(),
|
||||
topics, err := newTopicRequest([]string{
|
||||
HeadTopic,
|
||||
FinalizedCheckpointTopic,
|
||||
ChainReorgTopic,
|
||||
BlockTopic,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
request := topics.testHttpRequest(t)
|
||||
w := NewStreamingResponseWriterRecorder()
|
||||
|
||||
b, err := blocks.NewSignedBeaconBlock(util.HydrateSignedBeaconBlock(ð.SignedBeaconBlock{}))
|
||||
require.NoError(t, err)
|
||||
events := []*feed.Event{
|
||||
&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: 0,
|
||||
BlockRoot: [32]byte{},
|
||||
SignedBlock: b,
|
||||
Verified: true,
|
||||
Optimistic: false,
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
Type: statefeed.NewHead,
|
||||
Data: ðpb.EventHead{
|
||||
Slot: 0,
|
||||
Block: make([]byte, 32),
|
||||
State: make([]byte, 32),
|
||||
EpochTransition: true,
|
||||
PreviousDutyDependentRoot: make([]byte, 32),
|
||||
CurrentDutyDependentRoot: make([]byte, 32),
|
||||
ExecutionOptimistic: false,
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
Type: statefeed.Reorg,
|
||||
Data: ðpb.EventChainReorg{
|
||||
Slot: 0,
|
||||
Depth: 0,
|
||||
OldHeadBlock: make([]byte, 32),
|
||||
NewHeadBlock: make([]byte, 32),
|
||||
OldHeadState: make([]byte, 32),
|
||||
NewHeadState: make([]byte, 32),
|
||||
Epoch: 0,
|
||||
ExecutionOptimistic: false,
|
||||
},
|
||||
},
|
||||
&feed.Event{
|
||||
Type: statefeed.FinalizedCheckpoint,
|
||||
Data: ðpb.EventFinalizedCheckpoint{
|
||||
Block: make([]byte, 32),
|
||||
State: make([]byte, 32),
|
||||
Epoch: 0,
|
||||
ExecutionOptimistic: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
go func() {
|
||||
s.StreamEvents(w, request)
|
||||
}()
|
||||
// wait for initiation of StreamEvents
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
s.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.NewHead,
|
||||
Data: ðpb.EventHead{
|
||||
Slot: 0,
|
||||
Block: make([]byte, 32),
|
||||
State: make([]byte, 32),
|
||||
EpochTransition: true,
|
||||
PreviousDutyDependentRoot: make([]byte, 32),
|
||||
CurrentDutyDependentRoot: make([]byte, 32),
|
||||
ExecutionOptimistic: false,
|
||||
},
|
||||
})
|
||||
s.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.FinalizedCheckpoint,
|
||||
Data: ðpb.EventFinalizedCheckpoint{
|
||||
Block: make([]byte, 32),
|
||||
State: make([]byte, 32),
|
||||
Epoch: 0,
|
||||
ExecutionOptimistic: false,
|
||||
},
|
||||
})
|
||||
s.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Reorg,
|
||||
Data: ðpb.EventChainReorg{
|
||||
Slot: 0,
|
||||
Depth: 0,
|
||||
OldHeadBlock: make([]byte, 32),
|
||||
NewHeadBlock: make([]byte, 32),
|
||||
OldHeadState: make([]byte, 32),
|
||||
NewHeadState: make([]byte, 32),
|
||||
Epoch: 0,
|
||||
ExecutionOptimistic: false,
|
||||
},
|
||||
})
|
||||
b, err := blocks.NewSignedBeaconBlock(util.HydrateSignedBeaconBlock(ð.SignedBeaconBlock{}))
|
||||
require.NoError(t, err)
|
||||
s.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: 0,
|
||||
BlockRoot: [32]byte{},
|
||||
SignedBlock: b,
|
||||
Verified: true,
|
||||
Optimistic: false,
|
||||
},
|
||||
})
|
||||
|
||||
// wait for feed
|
||||
time.Sleep(1 * time.Second)
|
||||
request.Context().Done()
|
||||
|
||||
resp := w.Result()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, body)
|
||||
assert.Equal(t, stateResult, string(body))
|
||||
requireAllEventsReceived(t, stn, opn, events, topics, s, w)
|
||||
})
|
||||
t.Run("payload attributes", func(t *testing.T) {
|
||||
type testCase struct {
|
||||
name string
|
||||
getState func() state.BeaconState
|
||||
getBlock func() interfaces.SignedBeaconBlock
|
||||
expected string
|
||||
SetTrackedValidatorsCache func(*cache.TrackedValidatorsCache)
|
||||
}
|
||||
testCases := []testCase{
|
||||
@@ -301,7 +347,6 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
},
|
||||
expected: payloadAttributesBellatrixResult,
|
||||
},
|
||||
{
|
||||
name: "capella",
|
||||
@@ -315,7 +360,6 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
},
|
||||
expected: payloadAttributesCapellaResult,
|
||||
},
|
||||
{
|
||||
name: "deneb",
|
||||
@@ -329,7 +373,6 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
},
|
||||
expected: payloadAttributesDenebResult,
|
||||
},
|
||||
{
|
||||
name: "electra",
|
||||
@@ -343,7 +386,6 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
return b
|
||||
},
|
||||
expected: payloadAttributesElectraResultWithTVC,
|
||||
SetTrackedValidatorsCache: func(c *cache.TrackedValidatorsCache) {
|
||||
c.Set(cache.TrackedValidator{
|
||||
Active: true,
|
||||
@@ -368,9 +410,11 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
Slot: ¤tSlot,
|
||||
}
|
||||
|
||||
stn := mockChain.NewEventFeedWrapper()
|
||||
opn := mockChain.NewEventFeedWrapper()
|
||||
s := &Server{
|
||||
StateNotifier: &mockChain.MockStateNotifier{},
|
||||
OperationNotifier: &mockChain.MockOperationNotifier{},
|
||||
StateNotifier: &mockChain.SimpleNotifier{Feed: stn},
|
||||
OperationNotifier: &mockChain.SimpleNotifier{Feed: opn},
|
||||
HeadFetcher: mockChainService,
|
||||
ChainInfoFetcher: mockChainService,
|
||||
TrackedValidatorsCache: cache.NewTrackedValidatorsCache(),
|
||||
@@ -378,100 +422,76 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
|
||||
if tc.SetTrackedValidatorsCache != nil {
|
||||
tc.SetTrackedValidatorsCache(s.TrackedValidatorsCache)
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/events?topics=%s", PayloadAttributesTopic), nil)
|
||||
w := &flushableResponseRecorder{
|
||||
ResponseRecorder: httptest.NewRecorder(),
|
||||
}
|
||||
topics, err := newTopicRequest([]string{PayloadAttributesTopic})
|
||||
require.NoError(t, err)
|
||||
request := topics.testHttpRequest(t)
|
||||
w := NewStreamingResponseWriterRecorder()
|
||||
events := []*feed.Event{&feed.Event{Type: statefeed.MissedSlot}}
|
||||
|
||||
go func() {
|
||||
s.StreamEvents(w, request)
|
||||
}()
|
||||
// wait for initiation of StreamEvents
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
s.StateNotifier.StateFeed().Send(&feed.Event{Type: statefeed.MissedSlot})
|
||||
|
||||
// wait for feed
|
||||
time.Sleep(1 * time.Second)
|
||||
request.Context().Done()
|
||||
|
||||
resp := w.Result()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, body)
|
||||
assert.Equal(t, tc.expected, string(body), "wrong result for "+tc.name)
|
||||
requireAllEventsReceived(t, stn, opn, events, topics, s, w)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const operationsResult = `:
|
||||
func TestStuckReader(t *testing.T) {
|
||||
topics, events := operationEventsFixtures(t)
|
||||
require.Equal(t, 8, len(events))
|
||||
// set eventFeedDepth to a number lower than the events we intend to send to force the server to drop the reader.
|
||||
stn := mockChain.NewEventFeedWrapper()
|
||||
opn := mockChain.NewEventFeedWrapper()
|
||||
s := &Server{
|
||||
StateNotifier: &mockChain.SimpleNotifier{Feed: stn},
|
||||
OperationNotifier: &mockChain.SimpleNotifier{Feed: opn},
|
||||
EventFeedDepth: len(events) - 1,
|
||||
}
|
||||
|
||||
event: attestation
|
||||
data: {"aggregation_bits":"0x00","data":{"slot":"0","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"target":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
eventsWritten := make(chan struct{})
|
||||
go func() {
|
||||
for i := range events {
|
||||
ev := events[i]
|
||||
top := topicForEvent(ev)
|
||||
if topicsForOpsFeed[top] {
|
||||
err := opn.WaitForSubscription(ctx)
|
||||
require.NoError(t, err)
|
||||
s.OperationNotifier.OperationFeed().Send(ev)
|
||||
} else {
|
||||
err := stn.WaitForSubscription(ctx)
|
||||
require.NoError(t, err)
|
||||
s.StateNotifier.StateFeed().Send(ev)
|
||||
}
|
||||
}
|
||||
close(eventsWritten)
|
||||
}()
|
||||
|
||||
event: attestation
|
||||
data: {"aggregation_bits":"0x00","data":{"slot":"0","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"target":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}
|
||||
request := topics.testHttpRequest(t)
|
||||
w := NewStreamingResponseWriterRecorder()
|
||||
|
||||
event: voluntary_exit
|
||||
data: {"message":{"epoch":"0","validator_index":"0"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}
|
||||
handlerFinished := make(chan struct{})
|
||||
go func() {
|
||||
s.StreamEvents(w, request)
|
||||
close(handlerFinished)
|
||||
}()
|
||||
|
||||
event: contribution_and_proof
|
||||
data: {"message":{"aggregator_index":"0","contribution":{"slot":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","subcommittee_index":"0","aggregation_bits":"0x00000000000000000000000000000000","signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"selection_proof":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}
|
||||
// Make sure that the stream writer shut down when the reader failed to clear the write buffer.
|
||||
select {
|
||||
case <-handlerFinished:
|
||||
// We expect the stream handler to max out the queue buffer and exit gracefully.
|
||||
return
|
||||
case <-ctx.Done():
|
||||
t.Fatalf("context canceled / timed out waiting for handler completion, err=%v", ctx.Err())
|
||||
}
|
||||
|
||||
event: bls_to_execution_change
|
||||
data: {"message":{"validator_index":"0","from_bls_pubkey":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","to_execution_address":"0x0000000000000000000000000000000000000000"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}
|
||||
|
||||
event: blob_sidecar
|
||||
data: {"block_root":"0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c","index":"0","slot":"0","kzg_commitment":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","versioned_hash":"0x01b0761f87b081d5cf10757ccc89f12be355c70e2e29df288b65b30710dcbcd1"}
|
||||
|
||||
event: attester_slashing
|
||||
data: {"attestation_1":{"attesting_indices":["0","1"],"data":{"slot":"0","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"target":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"attestation_2":{"attesting_indices":["0","1"],"data":{"slot":"0","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"target":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}}
|
||||
|
||||
event: proposer_slashing
|
||||
data: {"signed_header_1":{"message":{"slot":"0","proposer_index":"0","parent_root":"0x0000000000000000000000000000000000000000000000000000000000000000","state_root":"0x0000000000000000000000000000000000000000000000000000000000000000","body_root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"signed_header_2":{"message":{"slot":"0","proposer_index":"0","parent_root":"0x0000000000000000000000000000000000000000000000000000000000000000","state_root":"0x0000000000000000000000000000000000000000000000000000000000000000","body_root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}}
|
||||
|
||||
`
|
||||
|
||||
const stateResult = `:
|
||||
|
||||
event: head
|
||||
data: {"slot":"0","block":"0x0000000000000000000000000000000000000000000000000000000000000000","state":"0x0000000000000000000000000000000000000000000000000000000000000000","epoch_transition":true,"execution_optimistic":false,"previous_duty_dependent_root":"0x0000000000000000000000000000000000000000000000000000000000000000","current_duty_dependent_root":"0x0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
|
||||
event: finalized_checkpoint
|
||||
data: {"block":"0x0000000000000000000000000000000000000000000000000000000000000000","state":"0x0000000000000000000000000000000000000000000000000000000000000000","epoch":"0","execution_optimistic":false}
|
||||
|
||||
event: chain_reorg
|
||||
data: {"slot":"0","depth":"0","old_head_block":"0x0000000000000000000000000000000000000000000000000000000000000000","old_head_state":"0x0000000000000000000000000000000000000000000000000000000000000000","new_head_block":"0x0000000000000000000000000000000000000000000000000000000000000000","new_head_state":"0x0000000000000000000000000000000000000000000000000000000000000000","epoch":"0","execution_optimistic":false}
|
||||
|
||||
event: block
|
||||
data: {"slot":"0","block":"0xeade62f0457b2fdf48e7d3fc4b60736688286be7c7a3ac4c9a16a5e0600bd9e4","execution_optimistic":false}
|
||||
|
||||
`
|
||||
|
||||
const payloadAttributesBellatrixResult = `:
|
||||
|
||||
event: payload_attributes
|
||||
data: {"version":"bellatrix","data":{"proposer_index":"0","proposal_slot":"1","parent_block_number":"0","parent_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","parent_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","payload_attributes":{"timestamp":"12","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","suggested_fee_recipient":"0x0000000000000000000000000000000000000000"}}}
|
||||
|
||||
`
|
||||
|
||||
const payloadAttributesCapellaResult = `:
|
||||
|
||||
event: payload_attributes
|
||||
data: {"version":"capella","data":{"proposer_index":"0","proposal_slot":"1","parent_block_number":"0","parent_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","parent_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","payload_attributes":{"timestamp":"12","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","suggested_fee_recipient":"0x0000000000000000000000000000000000000000","withdrawals":[]}}}
|
||||
|
||||
`
|
||||
|
||||
const payloadAttributesDenebResult = `:
|
||||
|
||||
event: payload_attributes
|
||||
data: {"version":"deneb","data":{"proposer_index":"0","proposal_slot":"1","parent_block_number":"0","parent_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","parent_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","payload_attributes":{"timestamp":"12","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","suggested_fee_recipient":"0x0000000000000000000000000000000000000000","withdrawals":[],"parent_beacon_block_root":"0xbef96cb938fd48b2403d3e662664325abb0102ed12737cbb80d717520e50cf4a"}}}
|
||||
|
||||
`
|
||||
|
||||
const payloadAttributesElectraResultWithTVC = `:
|
||||
|
||||
event: payload_attributes
|
||||
data: {"version":"electra","data":{"proposer_index":"0","proposal_slot":"1","parent_block_number":"0","parent_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","parent_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","payload_attributes":{"timestamp":"12","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","suggested_fee_recipient":"0xd2dbd02e4efe087d7d195de828b9dd25f19a89c9","withdrawals":[],"parent_beacon_block_root":"0xf2110e448638f41cb34514ecdbb49c055536cd5f715f1cb259d1287bb900853e"}}}
|
||||
|
||||
`
|
||||
// Also make sure all the events were written.
|
||||
select {
|
||||
case <-eventsWritten:
|
||||
// We expect the stream handler to max out the queue buffer and exit gracefully.
|
||||
return
|
||||
case <-ctx.Done():
|
||||
t.Fatalf("context canceled / timed out waiting to write all events, err=%v", ctx.Err())
|
||||
}
|
||||
}
|
||||
|
||||
75
beacon-chain/rpc/eth/events/http_test.go
Normal file
75
beacon-chain/rpc/eth/events/http_test.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
type StreamingResponseWriterRecorder struct {
|
||||
http.ResponseWriter
|
||||
r io.Reader
|
||||
w io.Writer
|
||||
statusWritten *int
|
||||
status chan int
|
||||
bodyRecording []byte
|
||||
flushed bool
|
||||
}
|
||||
|
||||
func (w *StreamingResponseWriterRecorder) StatusChan() chan int {
|
||||
return w.status
|
||||
}
|
||||
|
||||
func NewStreamingResponseWriterRecorder() *StreamingResponseWriterRecorder {
|
||||
r, w := io.Pipe()
|
||||
return &StreamingResponseWriterRecorder{
|
||||
ResponseWriter: httptest.NewRecorder(),
|
||||
r: r,
|
||||
w: w,
|
||||
status: make(chan int, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// Write implements http.ResponseWriter.
|
||||
func (w *StreamingResponseWriterRecorder) Write(data []byte) (int, error) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
n, err := w.w.Write(data)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return w.ResponseWriter.Write(data)
|
||||
}
|
||||
|
||||
// WriteHeader implements http.ResponseWriter.
|
||||
func (w *StreamingResponseWriterRecorder) WriteHeader(statusCode int) {
|
||||
if w.statusWritten != nil {
|
||||
return
|
||||
}
|
||||
w.statusWritten = &statusCode
|
||||
w.status <- statusCode
|
||||
w.ResponseWriter.WriteHeader(statusCode)
|
||||
}
|
||||
|
||||
func (w *StreamingResponseWriterRecorder) Body() io.Reader {
|
||||
return w.r
|
||||
}
|
||||
|
||||
func (w *StreamingResponseWriterRecorder) RequireStatus(t *testing.T, status int) {
|
||||
if w.statusWritten == nil {
|
||||
t.Fatal("WriteHeader was not called")
|
||||
}
|
||||
require.Equal(t, status, *w.statusWritten)
|
||||
}
|
||||
|
||||
func (w *StreamingResponseWriterRecorder) Flush() {
|
||||
fw, ok := w.ResponseWriter.(http.Flusher)
|
||||
if ok {
|
||||
fw.Flush()
|
||||
}
|
||||
w.flushed = true
|
||||
}
|
||||
|
||||
var _ http.ResponseWriter = &StreamingResponseWriterRecorder{}
|
||||
@@ -4,6 +4,8 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache"
|
||||
opfeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation"
|
||||
@@ -18,4 +20,6 @@ type Server struct {
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||
TrackedValidatorsCache *cache.TrackedValidatorsCache
|
||||
KeepAliveInterval time.Duration
|
||||
EventFeedDepth int
|
||||
}
|
||||
|
||||
@@ -20,14 +20,12 @@ go_library(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//monitoring/tracing/trace:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//proto/eth/v2:go_default_library",
|
||||
"//proto/migration:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
@@ -55,7 +53,6 @@ go_test(
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/eth/v2:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
|
||||
@@ -47,7 +47,7 @@ func (s *Server) GetLightClientBootstrap(w http.ResponseWriter, req *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
bootstrap, err := createLightClientBootstrap(ctx, state, blk.Block())
|
||||
bootstrap, err := createLightClientBootstrap(ctx, state, blk)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "could not get light client bootstrap: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
@@ -204,6 +204,7 @@ func (s *Server) GetLightClientUpdatesByRange(w http.ResponseWriter, req *http.R
|
||||
state,
|
||||
block,
|
||||
attestedState,
|
||||
attestedBlock,
|
||||
finalizedBlock,
|
||||
)
|
||||
|
||||
@@ -267,7 +268,7 @@ func (s *Server) GetLightClientFinalityUpdate(w http.ResponseWriter, req *http.R
|
||||
return
|
||||
}
|
||||
|
||||
update, err := newLightClientFinalityUpdateFromBeaconState(ctx, st, block, attestedState, finalizedBlock)
|
||||
update, err := newLightClientFinalityUpdateFromBeaconState(ctx, st, block, attestedState, attestedBlock, finalizedBlock)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not get light client finality update: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
@@ -312,7 +313,7 @@ func (s *Server) GetLightClientOptimisticUpdate(w http.ResponseWriter, req *http
|
||||
return
|
||||
}
|
||||
|
||||
update, err := newLightClientOptimisticUpdateFromBeaconState(ctx, st, block, attestedState)
|
||||
update, err := newLightClientOptimisticUpdateFromBeaconState(ctx, st, block, attestedState, attestedBlock)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not get light client optimistic update: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
@@ -19,49 +20,29 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
)
|
||||
|
||||
func TestLightClientHandler_GetLightClientBootstrap_Altair(t *testing.T) {
|
||||
helpers.ClearCache()
|
||||
slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1)
|
||||
l := util.NewTestLightClient(t).SetupTestAltair()
|
||||
|
||||
b := util.NewBeaconBlockAltair()
|
||||
b.Block.StateRoot = bytesutil.PadTo([]byte("foo"), 32)
|
||||
b.Block.Slot = slot
|
||||
|
||||
signedBlock, err := blocks.NewSignedBeaconBlock(b)
|
||||
|
||||
require.NoError(t, err)
|
||||
header, err := signedBlock.Header()
|
||||
slot := l.State.Slot()
|
||||
stateRoot, err := l.State.HashTreeRoot(l.Ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
bs, err := util.NewBeaconStateAltair(func(state *ethpb.BeaconStateAltair) error {
|
||||
state.BlockRoots[0] = r[:]
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, bs.SetSlot(slot))
|
||||
require.NoError(t, bs.SetLatestBlockHeader(header.Header))
|
||||
|
||||
mockBlocker := &testutil.MockBlocker{BlockToReturn: signedBlock}
|
||||
mockBlocker := &testutil.MockBlocker{BlockToReturn: l.Block}
|
||||
mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot}
|
||||
s := &Server{
|
||||
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{
|
||||
slot: bs,
|
||||
slot: l.State,
|
||||
}},
|
||||
Blocker: mockBlocker,
|
||||
HeadFetcher: mockChainService,
|
||||
}
|
||||
request := httptest.NewRequest("GET", "http://foo.com/", nil)
|
||||
request.SetPathValue("block_root", hexutil.Encode(r[:]))
|
||||
request.SetPathValue("block_root", hexutil.Encode(stateRoot[:]))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
@@ -74,47 +55,35 @@ func TestLightClientHandler_GetLightClientBootstrap_Altair(t *testing.T) {
|
||||
err = json.Unmarshal(resp.Data.Header, &respHeader)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "altair", resp.Version)
|
||||
require.Equal(t, hexutil.Encode(header.Header.BodyRoot), respHeader.Beacon.BodyRoot)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
blockHeader, err := l.Block.Header()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot)
|
||||
require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot)
|
||||
|
||||
require.NotNil(t, resp.Data.CurrentSyncCommittee)
|
||||
require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch)
|
||||
|
||||
}
|
||||
|
||||
func TestLightClientHandler_GetLightClientBootstrap_Capella(t *testing.T) {
|
||||
helpers.ClearCache()
|
||||
slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1)
|
||||
l := util.NewTestLightClient(t).SetupTestCapella(false) // result is same for true and false
|
||||
|
||||
b := util.NewBeaconBlockCapella()
|
||||
b.Block.StateRoot = bytesutil.PadTo([]byte("foo"), 32)
|
||||
b.Block.Slot = slot
|
||||
|
||||
signedBlock, err := blocks.NewSignedBeaconBlock(b)
|
||||
|
||||
require.NoError(t, err)
|
||||
header, err := signedBlock.Header()
|
||||
slot := l.State.Slot()
|
||||
stateRoot, err := l.State.HashTreeRoot(l.Ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
bs, err := util.NewBeaconStateCapella(func(state *ethpb.BeaconStateCapella) error {
|
||||
state.BlockRoots[0] = r[:]
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, bs.SetSlot(slot))
|
||||
require.NoError(t, bs.SetLatestBlockHeader(header.Header))
|
||||
|
||||
mockBlocker := &testutil.MockBlocker{BlockToReturn: signedBlock}
|
||||
mockBlocker := &testutil.MockBlocker{BlockToReturn: l.Block}
|
||||
mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot}
|
||||
s := &Server{
|
||||
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{
|
||||
slot: bs,
|
||||
slot: l.State,
|
||||
}},
|
||||
Blocker: mockBlocker,
|
||||
HeadFetcher: mockChainService,
|
||||
}
|
||||
request := httptest.NewRequest("GET", "http://foo.com/", nil)
|
||||
request.SetPathValue("block_root", hexutil.Encode(r[:]))
|
||||
request.SetPathValue("block_root", hexutil.Encode(stateRoot[:]))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
@@ -123,51 +92,38 @@ func TestLightClientHandler_GetLightClientBootstrap_Capella(t *testing.T) {
|
||||
var resp structs.LightClientBootstrapResponse
|
||||
err = json.Unmarshal(writer.Body.Bytes(), &resp)
|
||||
require.NoError(t, err)
|
||||
var respHeader structs.LightClientHeaderCapella
|
||||
var respHeader structs.LightClientHeader
|
||||
err = json.Unmarshal(resp.Data.Header, &respHeader)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "capella", resp.Version)
|
||||
require.Equal(t, hexutil.Encode(header.Header.BodyRoot), respHeader.Beacon.BodyRoot)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
blockHeader, err := l.Block.Header()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot)
|
||||
require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot)
|
||||
|
||||
require.NotNil(t, resp.Data.CurrentSyncCommittee)
|
||||
require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch)
|
||||
}
|
||||
|
||||
func TestLightClientHandler_GetLightClientBootstrap_Deneb(t *testing.T) {
|
||||
helpers.ClearCache()
|
||||
slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1)
|
||||
l := util.NewTestLightClient(t).SetupTestDeneb(false) // result is same for true and false
|
||||
|
||||
b := util.NewBeaconBlockDeneb()
|
||||
b.Block.StateRoot = bytesutil.PadTo([]byte("foo"), 32)
|
||||
b.Block.Slot = slot
|
||||
|
||||
signedBlock, err := blocks.NewSignedBeaconBlock(b)
|
||||
|
||||
require.NoError(t, err)
|
||||
header, err := signedBlock.Header()
|
||||
slot := l.State.Slot()
|
||||
stateRoot, err := l.State.HashTreeRoot(l.Ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
bs, err := util.NewBeaconStateDeneb(func(state *ethpb.BeaconStateDeneb) error {
|
||||
state.BlockRoots[0] = r[:]
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, bs.SetSlot(slot))
|
||||
require.NoError(t, bs.SetLatestBlockHeader(header.Header))
|
||||
|
||||
mockBlocker := &testutil.MockBlocker{BlockToReturn: signedBlock}
|
||||
mockBlocker := &testutil.MockBlocker{BlockToReturn: l.Block}
|
||||
mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot}
|
||||
s := &Server{
|
||||
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{
|
||||
slot: bs,
|
||||
slot: l.State,
|
||||
}},
|
||||
Blocker: mockBlocker,
|
||||
HeadFetcher: mockChainService,
|
||||
}
|
||||
request := httptest.NewRequest("GET", "http://foo.com/", nil)
|
||||
request.SetPathValue("block_root", hexutil.Encode(r[:]))
|
||||
request.SetPathValue("block_root", hexutil.Encode(stateRoot[:]))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
@@ -176,12 +132,58 @@ func TestLightClientHandler_GetLightClientBootstrap_Deneb(t *testing.T) {
|
||||
var resp structs.LightClientBootstrapResponse
|
||||
err = json.Unmarshal(writer.Body.Bytes(), &resp)
|
||||
require.NoError(t, err)
|
||||
var respHeader structs.LightClientHeaderDeneb
|
||||
var respHeader structs.LightClientHeader
|
||||
err = json.Unmarshal(resp.Data.Header, &respHeader)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "deneb", resp.Version)
|
||||
require.Equal(t, hexutil.Encode(header.Header.BodyRoot), respHeader.Beacon.BodyRoot)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
||||
blockHeader, err := l.Block.Header()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot)
|
||||
require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot)
|
||||
|
||||
require.NotNil(t, resp.Data.CurrentSyncCommittee)
|
||||
require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch)
|
||||
}
|
||||
|
||||
func TestLightClientHandler_GetLightClientBootstrap_Electra(t *testing.T) {
|
||||
l := util.NewTestLightClient(t).SetupTestElectra(false) // result is same for true and false
|
||||
|
||||
slot := l.State.Slot()
|
||||
stateRoot, err := l.State.HashTreeRoot(l.Ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
mockBlocker := &testutil.MockBlocker{BlockToReturn: l.Block}
|
||||
mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot}
|
||||
s := &Server{
|
||||
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{
|
||||
slot: l.State,
|
||||
}},
|
||||
Blocker: mockBlocker,
|
||||
HeadFetcher: mockChainService,
|
||||
}
|
||||
request := httptest.NewRequest("GET", "http://foo.com/", nil)
|
||||
request.SetPathValue("block_root", hexutil.Encode(stateRoot[:]))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetLightClientBootstrap(writer, request)
|
||||
require.Equal(t, http.StatusOK, writer.Code)
|
||||
var resp structs.LightClientBootstrapResponse
|
||||
err = json.Unmarshal(writer.Body.Bytes(), &resp)
|
||||
require.NoError(t, err)
|
||||
var respHeader structs.LightClientHeader
|
||||
err = json.Unmarshal(resp.Data.Header, &respHeader)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "electra", resp.Version)
|
||||
|
||||
blockHeader, err := l.Block.Header()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot)
|
||||
require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot)
|
||||
|
||||
require.NotNil(t, resp.Data.CurrentSyncCommittee)
|
||||
require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch)
|
||||
}
|
||||
|
||||
func TestLightClientHandler_GetLightClientUpdatesByRangeAltair(t *testing.T) {
|
||||
|
||||
@@ -7,10 +7,9 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/proto/migration"
|
||||
|
||||
lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client"
|
||||
consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
@@ -18,18 +17,17 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
v2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
)
|
||||
|
||||
func createLightClientBootstrap(ctx context.Context, state state.BeaconState, blk interfaces.ReadOnlyBeaconBlock) (*structs.LightClientBootstrap, error) {
|
||||
func createLightClientBootstrap(ctx context.Context, state state.BeaconState, blk interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientBootstrap, error) {
|
||||
switch blk.Version() {
|
||||
case version.Phase0:
|
||||
return nil, fmt.Errorf("light client bootstrap is not supported for phase0")
|
||||
case version.Altair, version.Bellatrix:
|
||||
return createLightClientBootstrapAltair(ctx, state)
|
||||
return createLightClientBootstrapAltair(ctx, state, blk)
|
||||
case version.Capella:
|
||||
return createLightClientBootstrapCapella(ctx, state, blk)
|
||||
case version.Deneb, version.Electra:
|
||||
@@ -38,24 +36,7 @@ func createLightClientBootstrap(ctx context.Context, state state.BeaconState, bl
|
||||
return nil, fmt.Errorf("unsupported block version %s", version.String(blk.Version()))
|
||||
}
|
||||
|
||||
// createLightClientBootstrapAltair - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_bootstrap
|
||||
// def create_light_client_bootstrap(state: BeaconState) -> LightClientBootstrap:
|
||||
//
|
||||
// assert compute_epoch_at_slot(state.slot) >= ALTAIR_FORK_EPOCH
|
||||
// assert state.slot == state.latest_block_header.slot
|
||||
//
|
||||
// return LightClientBootstrap(
|
||||
// header=BeaconBlockHeader(
|
||||
// slot=state.latest_block_header.slot,
|
||||
// proposer_index=state.latest_block_header.proposer_index,
|
||||
// parent_root=state.latest_block_header.parent_root,
|
||||
// state_root=hash_tree_root(state),
|
||||
// body_root=state.latest_block_header.body_root,
|
||||
// ),
|
||||
// current_sync_committee=state.current_sync_committee,
|
||||
// current_sync_committee_branch=compute_merkle_proof_for_state(state, CURRENT_SYNC_COMMITTEE_INDEX)
|
||||
// )
|
||||
func createLightClientBootstrapAltair(ctx context.Context, state state.BeaconState) (*structs.LightClientBootstrap, error) {
|
||||
func createLightClientBootstrapAltair(ctx context.Context, state state.BeaconState, block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientBootstrap, error) {
|
||||
// assert compute_epoch_at_slot(state.slot) >= ALTAIR_FORK_EPOCH
|
||||
if slots.ToEpoch(state.Slot()) < params.BeaconConfig().AltairForkEpoch {
|
||||
return nil, fmt.Errorf("light client bootstrap is not supported before Altair, invalid slot %d", state.Slot())
|
||||
@@ -67,55 +48,63 @@ func createLightClientBootstrapAltair(ctx context.Context, state state.BeaconSta
|
||||
return nil, fmt.Errorf("state slot %d not equal to latest block header slot %d", state.Slot(), latestBlockHeader.Slot)
|
||||
}
|
||||
|
||||
// Prepare data
|
||||
// header.state_root = hash_tree_root(state)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get state root")
|
||||
}
|
||||
latestBlockHeader.StateRoot = stateRoot[:]
|
||||
|
||||
// assert hash_tree_root(header) == hash_tree_root(block.message)
|
||||
latestBlockHeaderRoot, err := latestBlockHeader.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get latest block header root")
|
||||
}
|
||||
beaconBlockRoot, err := block.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get block root")
|
||||
}
|
||||
if latestBlockHeaderRoot != beaconBlockRoot {
|
||||
return nil, fmt.Errorf("latest block header root %#x not equal to block root %#x", latestBlockHeaderRoot, beaconBlockRoot)
|
||||
}
|
||||
|
||||
lightClientHeaderContainer, err := lightclient.BlockToLightClientHeader(block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert block to light client header")
|
||||
}
|
||||
lightClientHeader := lightClientHeaderContainer.GetHeaderAltair()
|
||||
|
||||
apiLightClientHeader := &structs.LightClientHeader{
|
||||
Beacon: structs.BeaconBlockHeaderFromConsensus(migration.V1HeaderToV1Alpha1(lightClientHeader.Beacon)),
|
||||
}
|
||||
|
||||
headerJSON, err := json.Marshal(apiLightClientHeader)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert header to raw message")
|
||||
}
|
||||
currentSyncCommittee, err := state.CurrentSyncCommittee()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get current sync committee")
|
||||
}
|
||||
|
||||
committee := structs.SyncCommitteeFromConsensus(currentSyncCommittee)
|
||||
|
||||
currentSyncCommitteeProof, err := state.CurrentSyncCommitteeProof(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get current sync committee proof")
|
||||
}
|
||||
|
||||
branch := make([]string, fieldparams.NextSyncCommitteeBranchDepth)
|
||||
branch := make([]string, fieldparams.SyncCommitteeBranchDepth)
|
||||
for i, proof := range currentSyncCommitteeProof {
|
||||
branch[i] = hexutil.Encode(proof)
|
||||
}
|
||||
|
||||
beacon := structs.BeaconBlockHeaderFromConsensus(latestBlockHeader)
|
||||
if beacon == nil {
|
||||
return nil, fmt.Errorf("could not get beacon block header")
|
||||
}
|
||||
header := &structs.LightClientHeader{
|
||||
Beacon: beacon,
|
||||
}
|
||||
|
||||
// Above shared util function won't calculate state root, so we need to do it manually
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get state root")
|
||||
}
|
||||
header.Beacon.StateRoot = hexutil.Encode(stateRoot[:])
|
||||
|
||||
headerJson, err := json.Marshal(header)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert header to raw message")
|
||||
}
|
||||
|
||||
// Return result
|
||||
result := &structs.LightClientBootstrap{
|
||||
Header: headerJson,
|
||||
CurrentSyncCommittee: committee,
|
||||
Header: headerJSON,
|
||||
CurrentSyncCommittee: structs.SyncCommitteeFromConsensus(currentSyncCommittee),
|
||||
CurrentSyncCommitteeBranch: branch,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func createLightClientBootstrapCapella(ctx context.Context, state state.BeaconState, block interfaces.ReadOnlyBeaconBlock) (*structs.LightClientBootstrap, error) {
|
||||
func createLightClientBootstrapCapella(ctx context.Context, state state.BeaconState, block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientBootstrap, error) {
|
||||
// assert compute_epoch_at_slot(state.slot) >= CAPELLA_FORK_EPOCH
|
||||
if slots.ToEpoch(state.Slot()) < params.BeaconConfig().CapellaForkEpoch {
|
||||
return nil, fmt.Errorf("creating Capella light client bootstrap is not supported before Capella, invalid slot %d", state.Slot())
|
||||
@@ -127,111 +116,63 @@ func createLightClientBootstrapCapella(ctx context.Context, state state.BeaconSt
|
||||
return nil, fmt.Errorf("state slot %d not equal to latest block header slot %d", state.Slot(), latestBlockHeader.Slot)
|
||||
}
|
||||
|
||||
// Prepare data
|
||||
// header.state_root = hash_tree_root(state)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get state root")
|
||||
}
|
||||
latestBlockHeader.StateRoot = stateRoot[:]
|
||||
|
||||
// assert hash_tree_root(header) == hash_tree_root(block.message)
|
||||
latestBlockHeaderRoot, err := latestBlockHeader.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get latest block header root")
|
||||
}
|
||||
beaconBlockRoot, err := block.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get block root")
|
||||
}
|
||||
if latestBlockHeaderRoot != beaconBlockRoot {
|
||||
return nil, fmt.Errorf("latest block header root %#x not equal to block root %#x", latestBlockHeaderRoot, beaconBlockRoot)
|
||||
}
|
||||
|
||||
lightClientHeaderContainer, err := lightclient.BlockToLightClientHeader(block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert block to light client header")
|
||||
}
|
||||
lightClientHeader := lightClientHeaderContainer.GetHeaderCapella()
|
||||
|
||||
apiLightClientHeader := &structs.LightClientHeader{
|
||||
Beacon: structs.BeaconBlockHeaderFromConsensus(migration.V1HeaderToV1Alpha1(lightClientHeader.Beacon)),
|
||||
}
|
||||
|
||||
headerJSON, err := json.Marshal(apiLightClientHeader)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert header to raw message")
|
||||
}
|
||||
currentSyncCommittee, err := state.CurrentSyncCommittee()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get current sync committee")
|
||||
}
|
||||
|
||||
committee := structs.SyncCommitteeFromConsensus(currentSyncCommittee)
|
||||
|
||||
currentSyncCommitteeProof, err := state.CurrentSyncCommitteeProof(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get current sync committee proof")
|
||||
}
|
||||
|
||||
branch := make([]string, fieldparams.NextSyncCommitteeBranchDepth)
|
||||
branch := make([]string, fieldparams.SyncCommitteeBranchDepth)
|
||||
for i, proof := range currentSyncCommitteeProof {
|
||||
branch[i] = hexutil.Encode(proof)
|
||||
}
|
||||
|
||||
beacon := structs.BeaconBlockHeaderFromConsensus(latestBlockHeader)
|
||||
|
||||
payloadInterface, err := block.Body().Execution()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload")
|
||||
}
|
||||
transactionsRoot, err := payloadInterface.TransactionsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
transactions, err := payloadInterface.Transactions()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions")
|
||||
}
|
||||
transactionsRootArray, err := ssz.TransactionsRoot(transactions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions root")
|
||||
}
|
||||
transactionsRoot = transactionsRootArray[:]
|
||||
} else if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions root")
|
||||
}
|
||||
withdrawalsRoot, err := payloadInterface.WithdrawalsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
withdrawals, err := payloadInterface.Withdrawals()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals")
|
||||
}
|
||||
withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||
}
|
||||
withdrawalsRoot = withdrawalsRootArray[:]
|
||||
}
|
||||
executionPayloadHeader := &structs.ExecutionPayloadHeaderCapella{
|
||||
ParentHash: hexutil.Encode(payloadInterface.ParentHash()),
|
||||
FeeRecipient: hexutil.Encode(payloadInterface.FeeRecipient()),
|
||||
StateRoot: hexutil.Encode(payloadInterface.StateRoot()),
|
||||
ReceiptsRoot: hexutil.Encode(payloadInterface.ReceiptsRoot()),
|
||||
LogsBloom: hexutil.Encode(payloadInterface.LogsBloom()),
|
||||
PrevRandao: hexutil.Encode(payloadInterface.PrevRandao()),
|
||||
BlockNumber: hexutil.EncodeUint64(payloadInterface.BlockNumber()),
|
||||
GasLimit: hexutil.EncodeUint64(payloadInterface.GasLimit()),
|
||||
GasUsed: hexutil.EncodeUint64(payloadInterface.GasUsed()),
|
||||
Timestamp: hexutil.EncodeUint64(payloadInterface.Timestamp()),
|
||||
ExtraData: hexutil.Encode(payloadInterface.ExtraData()),
|
||||
BaseFeePerGas: hexutil.Encode(payloadInterface.BaseFeePerGas()),
|
||||
BlockHash: hexutil.Encode(payloadInterface.BlockHash()),
|
||||
TransactionsRoot: hexutil.Encode(transactionsRoot),
|
||||
WithdrawalsRoot: hexutil.Encode(withdrawalsRoot),
|
||||
}
|
||||
|
||||
executionPayloadProof, err := blocks.PayloadProof(ctx, block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload proof")
|
||||
}
|
||||
executionPayloadProofStr := make([]string, len(executionPayloadProof))
|
||||
for i, proof := range executionPayloadProof {
|
||||
executionPayloadProofStr[i] = hexutil.Encode(proof)
|
||||
}
|
||||
header := &structs.LightClientHeaderCapella{
|
||||
Beacon: beacon,
|
||||
Execution: executionPayloadHeader,
|
||||
ExecutionBranch: executionPayloadProofStr,
|
||||
}
|
||||
|
||||
// Above shared util function won't calculate state root, so we need to do it manually
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get state root")
|
||||
}
|
||||
header.Beacon.StateRoot = hexutil.Encode(stateRoot[:])
|
||||
|
||||
headerJson, err := json.Marshal(header)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert header to raw message")
|
||||
}
|
||||
|
||||
// Return result
|
||||
result := &structs.LightClientBootstrap{
|
||||
Header: headerJson,
|
||||
CurrentSyncCommittee: committee,
|
||||
Header: headerJSON,
|
||||
CurrentSyncCommittee: structs.SyncCommitteeFromConsensus(currentSyncCommittee),
|
||||
CurrentSyncCommitteeBranch: branch,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func createLightClientBootstrapDeneb(ctx context.Context, state state.BeaconState, block interfaces.ReadOnlyBeaconBlock) (*structs.LightClientBootstrap, error) {
|
||||
func createLightClientBootstrapDeneb(ctx context.Context, state state.BeaconState, block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientBootstrap, error) {
|
||||
// assert compute_epoch_at_slot(state.slot) >= DENEB_FORK_EPOCH
|
||||
if slots.ToEpoch(state.Slot()) < params.BeaconConfig().DenebForkEpoch {
|
||||
return nil, fmt.Errorf("creating Deneb light client bootstrap is not supported before Deneb, invalid slot %d", state.Slot())
|
||||
@@ -243,103 +184,61 @@ func createLightClientBootstrapDeneb(ctx context.Context, state state.BeaconStat
|
||||
return nil, fmt.Errorf("state slot %d not equal to latest block header slot %d", state.Slot(), latestBlockHeader.Slot)
|
||||
}
|
||||
|
||||
// Prepare data
|
||||
currentSyncCommittee, err := state.CurrentSyncCommittee()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get current sync committee")
|
||||
}
|
||||
|
||||
committee := structs.SyncCommitteeFromConsensus(currentSyncCommittee)
|
||||
|
||||
currentSyncCommitteeProof, err := state.CurrentSyncCommitteeProof(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get current sync committee proof")
|
||||
}
|
||||
|
||||
branch := make([]string, fieldparams.NextSyncCommitteeBranchDepth)
|
||||
for i, proof := range currentSyncCommitteeProof {
|
||||
branch[i] = hexutil.Encode(proof)
|
||||
}
|
||||
|
||||
beacon := structs.BeaconBlockHeaderFromConsensus(latestBlockHeader)
|
||||
|
||||
payloadInterface, err := block.Body().Execution()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload")
|
||||
}
|
||||
transactionsRoot, err := payloadInterface.TransactionsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
transactions, err := payloadInterface.Transactions()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions")
|
||||
}
|
||||
transactionsRootArray, err := ssz.TransactionsRoot(transactions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions root")
|
||||
}
|
||||
transactionsRoot = transactionsRootArray[:]
|
||||
} else if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get transactions root")
|
||||
}
|
||||
withdrawalsRoot, err := payloadInterface.WithdrawalsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
withdrawals, err := payloadInterface.Withdrawals()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals")
|
||||
}
|
||||
withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||
}
|
||||
withdrawalsRoot = withdrawalsRootArray[:]
|
||||
}
|
||||
executionPayloadHeader := &structs.ExecutionPayloadHeaderDeneb{
|
||||
ParentHash: hexutil.Encode(payloadInterface.ParentHash()),
|
||||
FeeRecipient: hexutil.Encode(payloadInterface.FeeRecipient()),
|
||||
StateRoot: hexutil.Encode(payloadInterface.StateRoot()),
|
||||
ReceiptsRoot: hexutil.Encode(payloadInterface.ReceiptsRoot()),
|
||||
LogsBloom: hexutil.Encode(payloadInterface.LogsBloom()),
|
||||
PrevRandao: hexutil.Encode(payloadInterface.PrevRandao()),
|
||||
BlockNumber: hexutil.EncodeUint64(payloadInterface.BlockNumber()),
|
||||
GasLimit: hexutil.EncodeUint64(payloadInterface.GasLimit()),
|
||||
GasUsed: hexutil.EncodeUint64(payloadInterface.GasUsed()),
|
||||
Timestamp: hexutil.EncodeUint64(payloadInterface.Timestamp()),
|
||||
ExtraData: hexutil.Encode(payloadInterface.ExtraData()),
|
||||
BaseFeePerGas: hexutil.Encode(payloadInterface.BaseFeePerGas()),
|
||||
BlockHash: hexutil.Encode(payloadInterface.BlockHash()),
|
||||
TransactionsRoot: hexutil.Encode(transactionsRoot),
|
||||
WithdrawalsRoot: hexutil.Encode(withdrawalsRoot),
|
||||
}
|
||||
|
||||
executionPayloadProof, err := blocks.PayloadProof(ctx, block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload proof")
|
||||
}
|
||||
executionPayloadProofStr := make([]string, len(executionPayloadProof))
|
||||
for i, proof := range executionPayloadProof {
|
||||
executionPayloadProofStr[i] = hexutil.Encode(proof)
|
||||
}
|
||||
header := &structs.LightClientHeaderDeneb{
|
||||
Beacon: beacon,
|
||||
Execution: executionPayloadHeader,
|
||||
ExecutionBranch: executionPayloadProofStr,
|
||||
}
|
||||
|
||||
// Above shared util function won't calculate state root, so we need to do it manually
|
||||
// header.state_root = hash_tree_root(state)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get state root")
|
||||
}
|
||||
header.Beacon.StateRoot = hexutil.Encode(stateRoot[:])
|
||||
latestBlockHeader.StateRoot = stateRoot[:]
|
||||
|
||||
headerJson, err := json.Marshal(header)
|
||||
// assert hash_tree_root(header) == hash_tree_root(block.message)
|
||||
latestBlockHeaderRoot, err := latestBlockHeader.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get latest block header root")
|
||||
}
|
||||
beaconBlockRoot, err := block.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get block root")
|
||||
}
|
||||
if latestBlockHeaderRoot != beaconBlockRoot {
|
||||
return nil, fmt.Errorf("latest block header root %#x not equal to block root %#x", latestBlockHeaderRoot, beaconBlockRoot)
|
||||
}
|
||||
|
||||
lightClientHeaderContainer, err := lightclient.BlockToLightClientHeader(block)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert block to light client header")
|
||||
}
|
||||
lightClientHeader := lightClientHeaderContainer.GetHeaderDeneb()
|
||||
|
||||
apiLightClientHeader := &structs.LightClientHeader{
|
||||
Beacon: structs.BeaconBlockHeaderFromConsensus(migration.V1HeaderToV1Alpha1(lightClientHeader.Beacon)),
|
||||
}
|
||||
|
||||
headerJSON, err := json.Marshal(apiLightClientHeader)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert header to raw message")
|
||||
}
|
||||
// Return result
|
||||
currentSyncCommittee, err := state.CurrentSyncCommittee()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get current sync committee")
|
||||
}
|
||||
currentSyncCommitteeProof, err := state.CurrentSyncCommitteeProof(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get current sync committee proof")
|
||||
}
|
||||
var branch []string
|
||||
switch block.Version() {
|
||||
case version.Deneb:
|
||||
branch = make([]string, fieldparams.SyncCommitteeBranchDepth)
|
||||
case version.Electra:
|
||||
branch = make([]string, fieldparams.SyncCommitteeBranchDepthElectra)
|
||||
}
|
||||
for i, proof := range currentSyncCommitteeProof {
|
||||
branch[i] = hexutil.Encode(proof)
|
||||
}
|
||||
result := &structs.LightClientBootstrap{
|
||||
Header: headerJson,
|
||||
CurrentSyncCommittee: committee,
|
||||
Header: headerJSON,
|
||||
CurrentSyncCommittee: structs.SyncCommitteeFromConsensus(currentSyncCommittee),
|
||||
CurrentSyncCommitteeBranch: branch,
|
||||
}
|
||||
|
||||
@@ -351,9 +250,10 @@ func newLightClientUpdateFromBeaconState(
|
||||
state state.BeaconState,
|
||||
block interfaces.ReadOnlySignedBeaconBlock,
|
||||
attestedState state.BeaconState,
|
||||
attestedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
finalizedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
) (*structs.LightClientUpdate, error) {
|
||||
result, err := lightclient.NewLightClientUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock)
|
||||
result, err := lightclient.NewLightClientUpdateFromBeaconState(ctx, state, block, attestedState, attestedBlock, finalizedBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -366,9 +266,10 @@ func newLightClientFinalityUpdateFromBeaconState(
|
||||
state state.BeaconState,
|
||||
block interfaces.ReadOnlySignedBeaconBlock,
|
||||
attestedState state.BeaconState,
|
||||
attestedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
finalizedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
) (*structs.LightClientFinalityUpdate, error) {
|
||||
result, err := lightclient.NewLightClientFinalityUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock)
|
||||
result, err := lightclient.NewLightClientFinalityUpdateFromBeaconState(ctx, state, block, attestedState, attestedBlock, finalizedBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -381,8 +282,9 @@ func newLightClientOptimisticUpdateFromBeaconState(
|
||||
state state.BeaconState,
|
||||
block interfaces.ReadOnlySignedBeaconBlock,
|
||||
attestedState state.BeaconState,
|
||||
attestedBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
) (*structs.LightClientOptimisticUpdate, error) {
|
||||
result, err := lightclient.NewLightClientOptimisticUpdateFromBeaconState(ctx, state, block, attestedState)
|
||||
result, err := lightclient.NewLightClientOptimisticUpdateFromBeaconState(ctx, state, block, attestedState, attestedBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -391,7 +293,7 @@ func newLightClientOptimisticUpdateFromBeaconState(
|
||||
}
|
||||
|
||||
func IsSyncCommitteeUpdate(update *v2.LightClientUpdate) bool {
|
||||
nextSyncCommitteeBranch := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth)
|
||||
nextSyncCommitteeBranch := make([][]byte, fieldparams.SyncCommitteeBranchDepth)
|
||||
return !reflect.DeepEqual(update.NextSyncCommitteeBranch, nextSyncCommitteeBranch)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
// When the update has relevant sync committee
|
||||
func createNonEmptySyncCommitteeBranch() [][]byte {
|
||||
res := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth)
|
||||
res := make([][]byte, fieldparams.SyncCommitteeBranchDepth)
|
||||
res[0] = []byte("xyz")
|
||||
return res
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func TestIsBetterUpdate(t *testing.T) {
|
||||
}},
|
||||
},
|
||||
},
|
||||
NextSyncCommitteeBranch: make([][]byte, fieldparams.NextSyncCommitteeBranchDepth),
|
||||
NextSyncCommitteeBranch: make([][]byte, fieldparams.SyncCommitteeBranchDepth),
|
||||
SignatureSlot: 9999,
|
||||
},
|
||||
newUpdate: ðpbv2.LightClientUpdate{
|
||||
@@ -147,7 +147,7 @@ func TestIsBetterUpdate(t *testing.T) {
|
||||
}},
|
||||
},
|
||||
},
|
||||
NextSyncCommitteeBranch: make([][]byte, fieldparams.NextSyncCommitteeBranchDepth),
|
||||
NextSyncCommitteeBranch: make([][]byte, fieldparams.SyncCommitteeBranchDepth),
|
||||
SignatureSlot: 9999,
|
||||
},
|
||||
expectedResult: false,
|
||||
|
||||
@@ -287,6 +287,18 @@ func (s *Server) produceBlockV3(ctx context.Context, w http.ResponseWriter, r *h
|
||||
handleProduceDenebV3(w, isSSZ, denebBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
blindedElectraBlockContents, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedElectra)
|
||||
if ok {
|
||||
w.Header().Set(api.VersionHeader, version.String(version.Electra))
|
||||
handleProduceBlindedElectraV3(w, isSSZ, blindedElectraBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
electraBlockContents, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Electra)
|
||||
if ok {
|
||||
w.Header().Set(api.VersionHeader, version.String(version.Electra))
|
||||
handleProduceElectraV3(w, isSSZ, electraBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func getConsensusBlockValue(ctx context.Context, blockRewardsFetcher rewards.BlockRewardsFetcher, i interface{} /* block as argument */) (string, *httputil.DefaultJsonError) {
|
||||
@@ -587,3 +599,74 @@ func handleProduceDenebV3(
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
|
||||
func handleProduceBlindedElectraV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_BlindedElectra,
|
||||
executionPayloadValue string,
|
||||
consensusPayloadValue string,
|
||||
) {
|
||||
if isSSZ {
|
||||
sszResp, err := blk.BlindedElectra.MarshalSSZ()
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
httputil.WriteSsz(w, sszResp, "blindedElectraBlockContents.ssz")
|
||||
return
|
||||
}
|
||||
blindedBlock, err := structs.BlindedBeaconBlockElectraFromConsensus(blk.BlindedElectra)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
jsonBytes, err := json.Marshal(blindedBlock)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
httputil.WriteJson(w, &structs.ProduceBlockV3Response{
|
||||
Version: version.String(version.Electra),
|
||||
ExecutionPayloadBlinded: true,
|
||||
ExecutionPayloadValue: executionPayloadValue,
|
||||
ConsensusBlockValue: consensusPayloadValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
|
||||
func handleProduceElectraV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_Electra,
|
||||
executionPayloadValue string,
|
||||
consensusBlockValue string,
|
||||
) {
|
||||
if isSSZ {
|
||||
sszResp, err := blk.Electra.MarshalSSZ()
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
httputil.WriteSsz(w, sszResp, "electraBlockContents.ssz")
|
||||
return
|
||||
}
|
||||
|
||||
blockContents, err := structs.BeaconBlockContentsElectraFromConsensus(blk.Electra)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
jsonBytes, err := json.Marshal(blockContents)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
httputil.WriteJson(w, &structs.ProduceBlockV3Response{
|
||||
Version: version.String(version.Electra),
|
||||
ExecutionPayloadBlinded: false,
|
||||
ExecutionPayloadValue: executionPayloadValue, // mev not available at this point
|
||||
ConsensusBlockValue: consensusBlockValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -308,6 +308,75 @@ func TestProduceBlockV2(t *testing.T) {
|
||||
assert.Equal(t, http.StatusInternalServerError, e.Code)
|
||||
assert.StringContains(t, "Prepared block is blinded", e.Message)
|
||||
})
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBeaconBlockContentsElectra
|
||||
err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block)
|
||||
require.NoError(t, err)
|
||||
jsonBytes, err := json.Marshal(block.ToUnsigned())
|
||||
require.NoError(t, err)
|
||||
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: true,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
b, err := block.ToUnsigned().ToGeneric()
|
||||
require.NoError(t, err)
|
||||
b.PayloadValue = "2000"
|
||||
return b, nil
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"electra","execution_payload_blinded":false,"execution_payload_value":"2000","consensus_block_value":"10000000000","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, "electra", writer.Header().Get(api.VersionHeader))
|
||||
})
|
||||
t.Run("Blinded Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBlindedBeaconBlockElectra
|
||||
err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block)
|
||||
require.NoError(t, err)
|
||||
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: true,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
return block.Message.ToGeneric()
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV2(writer, request)
|
||||
assert.Equal(t, http.StatusInternalServerError, writer.Code)
|
||||
e := &httputil.DefaultJsonError{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusInternalServerError, e.Code)
|
||||
assert.StringContains(t, "Prepared block is blinded", e.Message)
|
||||
})
|
||||
t.Run("invalid query parameter slot empty", func(t *testing.T) {
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
server := &Server{
|
||||
@@ -650,6 +719,76 @@ func TestProduceBlockV2SSZ(t *testing.T) {
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
request.Header.Set("Accept", api.OctetStreamMediaType)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV2(writer, request)
|
||||
assert.Equal(t, http.StatusInternalServerError, writer.Code)
|
||||
e := &httputil.DefaultJsonError{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusInternalServerError, e.Code)
|
||||
assert.StringContains(t, "Prepared block is blinded", e.Message)
|
||||
})
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBeaconBlockContentsElectra
|
||||
err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block)
|
||||
require.NoError(t, err)
|
||||
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: true,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
return block.ToUnsigned().ToGeneric()
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
request.Header.Set("Accept", api.OctetStreamMediaType)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV2(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
g, err := block.ToUnsigned().ToGeneric()
|
||||
require.NoError(t, err)
|
||||
bl, ok := g.Block.(*eth.GenericBeaconBlock_Electra)
|
||||
require.Equal(t, true, ok)
|
||||
ssz, err := bl.Electra.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, "electra", writer.Header().Get(api.VersionHeader))
|
||||
})
|
||||
t.Run("Blinded Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBlindedBeaconBlockElectra
|
||||
err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block)
|
||||
require.NoError(t, err)
|
||||
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: true,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
return block.Message.ToGeneric()
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
request.Header.Set("Accept", api.OctetStreamMediaType)
|
||||
writer := httptest.NewRecorder()
|
||||
@@ -944,6 +1083,75 @@ func TestProduceBlindedBlock(t *testing.T) {
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, "deneb", writer.Header().Get(api.VersionHeader))
|
||||
})
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBeaconBlockContentsElectra
|
||||
err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block)
|
||||
require.NoError(t, err)
|
||||
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: false,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
return block.ToUnsigned().ToGeneric()
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v1/validator/blinded_blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlindedBlock(writer, request)
|
||||
assert.Equal(t, http.StatusInternalServerError, writer.Code)
|
||||
e := &httputil.DefaultJsonError{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusInternalServerError, e.Code)
|
||||
assert.StringContains(t, "Prepared block is not blinded", e.Message)
|
||||
})
|
||||
t.Run("Blinded Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBlindedBeaconBlockElectra
|
||||
err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block)
|
||||
require.NoError(t, err)
|
||||
jsonBytes, err := json.Marshal(block.Message)
|
||||
require.NoError(t, err)
|
||||
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: false,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
b, err := block.Message.ToGeneric()
|
||||
require.NoError(t, err)
|
||||
b.PayloadValue = "2000"
|
||||
return b, nil
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v1/validator/blinded_blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlindedBlock(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"electra","execution_payload_blinded":true,"execution_payload_value":"2000","consensus_block_value":"10000000000","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, "electra", writer.Header().Get(api.VersionHeader))
|
||||
})
|
||||
t.Run("invalid query parameter slot empty", func(t *testing.T) {
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
server := &Server{
|
||||
@@ -1309,6 +1517,82 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
require.Equal(t, "deneb", writer.Header().Get(api.VersionHeader))
|
||||
require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader))
|
||||
})
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBeaconBlockContentsElectra
|
||||
err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block)
|
||||
require.NoError(t, err)
|
||||
jsonBytes, err := json.Marshal(block.ToUnsigned())
|
||||
require.NoError(t, err)
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: false,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
b, err := block.ToUnsigned().ToGeneric()
|
||||
require.NoError(t, err)
|
||||
b.PayloadValue = "2000"
|
||||
return b, nil
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"electra","execution_payload_blinded":false,"execution_payload_value":"2000","consensus_block_value":"10000000000","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, "false", writer.Header().Get(api.ExecutionPayloadBlindedHeader))
|
||||
require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader))
|
||||
require.Equal(t, "electra", writer.Header().Get(api.VersionHeader))
|
||||
require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader))
|
||||
})
|
||||
t.Run("Blinded Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBlindedBeaconBlockElectra
|
||||
err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block)
|
||||
require.NoError(t, err)
|
||||
jsonBytes, err := json.Marshal(block.Message)
|
||||
require.NoError(t, err)
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: false,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
b, err := block.Message.ToGeneric()
|
||||
require.NoError(t, err)
|
||||
b.PayloadValue = "2000"
|
||||
return b, nil
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"electra","execution_payload_blinded":true,"execution_payload_value":"2000","consensus_block_value":"10000000000","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, "true", writer.Header().Get(api.ExecutionPayloadBlindedHeader))
|
||||
require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader))
|
||||
require.Equal(t, "electra", writer.Header().Get(api.VersionHeader))
|
||||
require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader))
|
||||
})
|
||||
t.Run("invalid query parameter slot empty", func(t *testing.T) {
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
server := &Server{
|
||||
@@ -1697,4 +1981,86 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, "deneb", writer.Header().Get(api.VersionHeader))
|
||||
require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader))
|
||||
})
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBeaconBlockContentsElectra
|
||||
err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block)
|
||||
require.NoError(t, err)
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: false,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
b, err := block.ToUnsigned().ToGeneric()
|
||||
require.NoError(t, err)
|
||||
b.PayloadValue = "2000"
|
||||
return b, nil
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
request.Header.Set("Accept", api.OctetStreamMediaType)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
g, err := block.ToUnsigned().ToGeneric()
|
||||
require.NoError(t, err)
|
||||
bl, ok := g.Block.(*eth.GenericBeaconBlock_Electra)
|
||||
require.Equal(t, true, ok)
|
||||
ssz, err := bl.Electra.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, "false", writer.Header().Get(api.ExecutionPayloadBlindedHeader))
|
||||
require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader))
|
||||
require.Equal(t, "electra", writer.Header().Get(api.VersionHeader))
|
||||
require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader))
|
||||
})
|
||||
t.Run("Blinded Electra", func(t *testing.T) {
|
||||
var block *structs.SignedBlindedBeaconBlockElectra
|
||||
err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block)
|
||||
require.NoError(t, err)
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{
|
||||
Slot: 1,
|
||||
RandaoReveal: bRandao,
|
||||
Graffiti: bGraffiti,
|
||||
SkipMevBoost: false,
|
||||
}).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
b, err := block.Message.ToGeneric()
|
||||
require.NoError(t, err)
|
||||
b.PayloadValue = "2000"
|
||||
return b, nil
|
||||
}())
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: syncChecker,
|
||||
OptimisticModeFetcher: chainService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil)
|
||||
request.Header.Set("Accept", api.OctetStreamMediaType)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
g, err := block.Message.ToGeneric()
|
||||
require.NoError(t, err)
|
||||
bl, ok := g.Block.(*eth.GenericBeaconBlock_BlindedElectra)
|
||||
require.Equal(t, true, ok)
|
||||
ssz, err := bl.BlindedElectra.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, "true", writer.Header().Get(api.ExecutionPayloadBlindedHeader))
|
||||
require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader))
|
||||
require.Equal(t, "electra", writer.Header().Get(api.VersionHeader))
|
||||
require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ go_library(
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/rpc/core:go_default_library",
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
"//beacon-chain/rpc/eth/shared:go_default_library",
|
||||
@@ -22,8 +23,10 @@ go_library(
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/sync:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//monitoring/tracing/trace:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
@@ -47,13 +50,16 @@ go_test(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
|
||||
"//beacon-chain/p2p/testing:go_default_library",
|
||||
"//beacon-chain/rpc/core:go_default_library",
|
||||
"//beacon-chain/rpc/lookup:go_default_library",
|
||||
"//beacon-chain/rpc/prysm/testing:go_default_library",
|
||||
"//beacon-chain/rpc/testutil:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/state/stategen/mock:go_default_library",
|
||||
"//beacon-chain/sync/initial-sync/testing:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
|
||||
@@ -15,7 +15,9 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
@@ -183,3 +185,52 @@ func (s *Server) GetChainHead(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
httputil.WriteJson(w, response)
|
||||
}
|
||||
|
||||
func (s *Server) PublishBlobs(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.PublishBlobs")
|
||||
defer span.End()
|
||||
if shared.IsSyncing(r.Context(), w, s.SyncChecker, s.HeadFetcher, s.TimeFetcher, s.OptimisticModeFetcher) {
|
||||
return
|
||||
}
|
||||
|
||||
var req structs.PublishBlobsRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
httputil.HandleError(w, "Could not decode JSON request body", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.BlobSidecars == nil {
|
||||
httputil.HandleError(w, "Missing blob sidecars", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
root, err := bytesutil.DecodeHexWithLength(req.BlockRoot, 32)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not decode block root: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
for _, blobSidecar := range req.BlobSidecars.Sidecars {
|
||||
sc, err := blobSidecar.ToConsensus()
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not decode blob sidecar: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
readOnlySc, err := blocks.NewROBlobWithRoot(sc, bytesutil.ToBytes32(root))
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not create read-only blob: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
verifiedBlob := blocks.NewVerifiedROBlob(readOnlySc)
|
||||
if err := s.BlobReceiver.ReceiveBlob(ctx, verifiedBlob); err != nil {
|
||||
httputil.HandleError(w, "Could not receive blob: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.Broadcaster.BroadcastBlob(ctx, sc.Index, sc); err != nil {
|
||||
httputil.HandleError(w, "Failed to broadcast blob: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,13 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
dbTest "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
mockp2p "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/testing"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core"
|
||||
rpctesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/prysm/testing"
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen"
|
||||
mockstategen "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen/mock"
|
||||
mockSync "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/initial-sync/testing"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
@@ -870,3 +873,163 @@ func TestServer_GetChainHead(t *testing.T) {
|
||||
assert.DeepEqual(t, hexutil.Encode(fRoot[:]), ch.FinalizedBlockRoot, "Unexpected FinalizedBlockRoot")
|
||||
assert.Equal(t, false, ch.OptimisticStatus)
|
||||
}
|
||||
|
||||
func TestPublishBlobs_InvalidJson(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.InvalidJson)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
assert.StringContains(t, "Could not decode JSON request body", writer.Body.String())
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false)
|
||||
}
|
||||
|
||||
func TestPublishBlobs_MissingBlob(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestMissingBlob)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
assert.StringContains(t, "Could not decode blob sidecar", writer.Body.String())
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false)
|
||||
}
|
||||
|
||||
func TestPublishBlobs_MissingSignedBlockHeader(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestMissingSignedBlockHeader)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
assert.StringContains(t, "Could not decode blob sidecar", writer.Body.String())
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false)
|
||||
}
|
||||
|
||||
func TestPublishBlobs_MissingSidecars(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestMissingSidecars)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
assert.StringContains(t, "Missing blob sidecars", writer.Body.String())
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false)
|
||||
}
|
||||
|
||||
func TestPublishBlobs_EmptySidecarsList(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestEmptySidecarsList)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false)
|
||||
}
|
||||
|
||||
func TestPublishBlobs_NullSidecar(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestNullSidecar)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
assert.StringContains(t, "Could not decode blob sidecar", writer.Body.String())
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false)
|
||||
}
|
||||
|
||||
func TestPublishBlobs_SeveralFieldsMissing(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestSeveralFieldsMissing)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
assert.StringContains(t, "Could not decode blob sidecar", writer.Body.String())
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false)
|
||||
}
|
||||
|
||||
func TestPublishBlobs_BadBlockRoot(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestBadBlockRoot)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
assert.StringContains(t, "Could not decode block root", writer.Body.String())
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false)
|
||||
}
|
||||
|
||||
func TestPublishBlobs(t *testing.T) {
|
||||
server := &Server{
|
||||
BlobReceiver: &chainMock.ChainService{},
|
||||
Broadcaster: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequest)))
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.PublishBlobs(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
|
||||
assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 1)
|
||||
assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), true)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package beacon
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain"
|
||||
beacondb "github.com/prysmaticlabs/prysm/v5/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen"
|
||||
@@ -20,4 +21,6 @@ type Server struct {
|
||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||
FinalizationFetcher blockchain.FinalizationFetcher
|
||||
CoreService *core.Service
|
||||
Broadcaster p2p.Broadcaster
|
||||
BlobReceiver blockchain.BlobReceiver
|
||||
}
|
||||
|
||||
9
beacon-chain/rpc/prysm/testing/BUILD.bazel
Normal file
9
beacon-chain/rpc/prysm/testing/BUILD.bazel
Normal file
@@ -0,0 +1,9 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
testonly = True,
|
||||
srcs = ["json.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/prysm/testing",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
210
beacon-chain/rpc/prysm/testing/json.go
Normal file
210
beacon-chain/rpc/prysm/testing/json.go
Normal file
File diff suppressed because one or more lines are too long
@@ -217,10 +217,10 @@ func (a proposerAtts) sort() (proposerAtts, error) {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
if features.Get().EnableCommitteeAwarePacking {
|
||||
return a.sortBySlotAndCommittee()
|
||||
if features.Get().DisableCommitteeAwarePacking {
|
||||
return a.sortByProfitabilityUsingMaxCover()
|
||||
}
|
||||
return a.sortByProfitabilityUsingMaxCover()
|
||||
return a.sortBySlotAndCommittee()
|
||||
}
|
||||
|
||||
// Separate attestations by slot, as slot number takes higher precedence when sorting.
|
||||
|
||||
@@ -21,6 +21,11 @@ import (
|
||||
)
|
||||
|
||||
func TestProposer_ProposerAtts_sort(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.DisableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
type testData struct {
|
||||
slot primitives.Slot
|
||||
bits bitfield.Bitlist
|
||||
@@ -186,11 +191,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("no atts", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
atts := getAtts([]testData{})
|
||||
want := getAtts([]testData{})
|
||||
atts, err := atts.sort()
|
||||
@@ -201,11 +201,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("single att", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
atts := getAtts([]testData{
|
||||
{4, bitfield.Bitlist{0b11100000, 0b1}},
|
||||
})
|
||||
@@ -220,11 +215,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("single att per slot", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
atts := getAtts([]testData{
|
||||
{1, bitfield.Bitlist{0b11000000, 0b1}},
|
||||
{4, bitfield.Bitlist{0b11100000, 0b1}},
|
||||
@@ -241,10 +231,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("two atts on one of the slots", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
atts := getAtts([]testData{
|
||||
{1, bitfield.Bitlist{0b11000000, 0b1}},
|
||||
@@ -263,11 +249,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("compare to native sort", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
// The max-cover based approach will select 0b00001100 instead, despite lower bit count
|
||||
// (since it has two new/unknown bits).
|
||||
t.Run("max-cover", func(t *testing.T) {
|
||||
@@ -289,11 +270,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("multiple slots", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
atts := getAtts([]testData{
|
||||
{2, bitfield.Bitlist{0b11100000, 0b1}},
|
||||
{4, bitfield.Bitlist{0b11100000, 0b1}},
|
||||
@@ -316,11 +292,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("follows max-cover", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
// Items at slot 4 must be first split into two lists by max-cover, with
|
||||
// 0b10000011 being selected and 0b11100001 being leftover (despite naive bit count suggesting otherwise).
|
||||
atts := getAtts([]testData{
|
||||
@@ -350,11 +321,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) {
|
||||
|
||||
func TestProposer_sort_DifferentCommittees(t *testing.T) {
|
||||
t.Run("one att per committee", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
c1_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11111000, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 1}})
|
||||
c2_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11100000, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 2}})
|
||||
atts := proposerAtts{c1_a1, c2_a1}
|
||||
@@ -364,11 +330,6 @@ func TestProposer_sort_DifferentCommittees(t *testing.T) {
|
||||
assert.DeepEqual(t, want, atts)
|
||||
})
|
||||
t.Run("multiple atts per committee", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
c1_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11111100, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 1}})
|
||||
c1_a2 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b10000010, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 1}})
|
||||
c2_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11110000, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 2}})
|
||||
@@ -381,11 +342,6 @@ func TestProposer_sort_DifferentCommittees(t *testing.T) {
|
||||
assert.DeepEqual(t, want, atts)
|
||||
})
|
||||
t.Run("multiple atts per committee, multiple slots", func(t *testing.T) {
|
||||
feat := features.Get()
|
||||
feat.EnableCommitteeAwarePacking = true
|
||||
reset := features.InitWithReset(feat)
|
||||
defer reset()
|
||||
|
||||
s2_c1_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11111100, 0b1}, Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 1}})
|
||||
s2_c1_a2 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b10000010, 0b1}, Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 1}})
|
||||
s2_c2_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11110000, 0b1}, Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 2}})
|
||||
|
||||
@@ -48,7 +48,7 @@ type Flags struct {
|
||||
EnableDoppelGanger bool // EnableDoppelGanger enables doppelganger protection on startup for the validator.
|
||||
EnableHistoricalSpaceRepresentation bool // EnableHistoricalSpaceRepresentation enables the saving of registry validators in separate buckets to save space
|
||||
EnableBeaconRESTApi bool // EnableBeaconRESTApi enables experimental usage of the beacon REST API by the validator when querying a beacon node
|
||||
EnableCommitteeAwarePacking bool // EnableCommitteeAwarePacking TODO
|
||||
DisableCommitteeAwarePacking bool // DisableCommitteeAwarePacking changes the attestation packing algorithm to one that is not aware of attesting committees.
|
||||
// Logging related toggles.
|
||||
DisableGRPCConnectionLogs bool // Disables logging when a new grpc client has connected.
|
||||
EnableFullSSZDataLogging bool // Enables logging for full ssz data on rejected gossip messages
|
||||
@@ -256,9 +256,9 @@ func ConfigureBeaconChain(ctx *cli.Context) error {
|
||||
logEnabled(EnableQUIC)
|
||||
cfg.EnableQUIC = true
|
||||
}
|
||||
if ctx.IsSet(EnableCommitteeAwarePacking.Name) {
|
||||
logEnabled(EnableCommitteeAwarePacking)
|
||||
cfg.EnableCommitteeAwarePacking = true
|
||||
if ctx.IsSet(DisableCommitteeAwarePacking.Name) {
|
||||
logEnabled(DisableCommitteeAwarePacking)
|
||||
cfg.DisableCommitteeAwarePacking = true
|
||||
}
|
||||
|
||||
cfg.AggregateIntervals = [3]time.Duration{aggregateFirstInterval.Value, aggregateSecondInterval.Value, aggregateThirdInterval.Value}
|
||||
|
||||
@@ -77,6 +77,12 @@ var (
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
deprecatedEnableCommitteeAwarePacking = &cli.BoolFlag{
|
||||
Name: "enable-committee-aware-packing",
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
|
||||
// Deprecated flags for both the beacon node and validator client.
|
||||
@@ -94,6 +100,7 @@ var deprecatedFlags = []cli.Flag{
|
||||
deprecatedBeaconRPCGatewayProviderFlag,
|
||||
deprecatedDisableGRPCGateway,
|
||||
deprecatedEnableExperimentalState,
|
||||
deprecatedEnableCommitteeAwarePacking,
|
||||
}
|
||||
|
||||
// deprecatedBeaconFlags contains flags that are still used by other components
|
||||
|
||||
@@ -166,9 +166,9 @@ var (
|
||||
Name: "enable-quic",
|
||||
Usage: "Enables connection using the QUIC protocol for peers which support it.",
|
||||
}
|
||||
EnableCommitteeAwarePacking = &cli.BoolFlag{
|
||||
Name: "enable-committee-aware-packing",
|
||||
Usage: "Changes the attestation packing algorithm to one that is aware of attesting committees.",
|
||||
DisableCommitteeAwarePacking = &cli.BoolFlag{
|
||||
Name: "disable-committee-aware-packing",
|
||||
Usage: "Changes the attestation packing algorithm to one that is not aware of attesting committees.",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -226,7 +226,7 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c
|
||||
EnableLightClient,
|
||||
BlobSaveFsync,
|
||||
EnableQUIC,
|
||||
EnableCommitteeAwarePacking,
|
||||
DisableCommitteeAwarePacking,
|
||||
}...)...)
|
||||
|
||||
// E2EBeaconChainFlags contains a list of the beacon chain feature flags to be tested in E2E.
|
||||
|
||||
@@ -33,7 +33,10 @@ const (
|
||||
BlobSize = 131072 // defined to match blob.size in bazel ssz codegen
|
||||
BlobSidecarSize = 131928 // defined to match blob sidecar size in bazel ssz codegen
|
||||
KzgCommitmentInclusionProofDepth = 17 // Merkle proof depth for blob_kzg_commitments list item
|
||||
NextSyncCommitteeBranchDepth = 5 // NextSyncCommitteeBranchDepth defines the depth of the next sync committee branch.
|
||||
ExecutionBranchDepth = 4 // ExecutionBranchDepth defines the number of leaves in a merkle proof of the execution payload header.
|
||||
SyncCommitteeBranchDepth = 5 // SyncCommitteeBranchDepth defines the number of leaves in a merkle proof of a sync committee.
|
||||
SyncCommitteeBranchDepthElectra = 6 // SyncCommitteeBranchDepthElectra defines the number of leaves in a merkle proof of a sync committee.
|
||||
FinalityBranchDepth = 6 // FinalityBranchDepth defines the number of leaves in a merkle proof of the finalized checkpoint root.
|
||||
PendingBalanceDepositsLimit = 134217728 // Maximum number of pending balance deposits in the beacon state.
|
||||
PendingPartialWithdrawalsLimit = 134217728 // Maximum number of pending partial withdrawals in the beacon state.
|
||||
PendingConsolidationsLimit = 262144 // Maximum number of pending consolidations in the beacon state.
|
||||
|
||||
@@ -33,7 +33,10 @@ const (
|
||||
BlobSize = 131072 // defined to match blob.size in bazel ssz codegen
|
||||
BlobSidecarSize = 131928 // defined to match blob sidecar size in bazel ssz codegen
|
||||
KzgCommitmentInclusionProofDepth = 17 // Merkle proof depth for blob_kzg_commitments list item
|
||||
NextSyncCommitteeBranchDepth = 5 // NextSyncCommitteeBranchDepth defines the depth of the next sync committee branch.
|
||||
ExecutionBranchDepth = 4 // ExecutionBranchDepth defines the number of leaves in a merkle proof of the execution payload header.
|
||||
SyncCommitteeBranchDepth = 5 // SyncCommitteeBranchDepth defines the number of leaves in a merkle proof of a sync committee.
|
||||
SyncCommitteeBranchDepthElectra = 6 // SyncCommitteeBranchDepthElectra defines the number of leaves in a merkle proof of a sync committee.
|
||||
FinalityBranchDepth = 6 // FinalityBranchDepth defines the number of leaves in a merkle proof of the finalized checkpoint root.
|
||||
PendingBalanceDepositsLimit = 134217728 // Maximum number of pending balance deposits in the beacon state.
|
||||
PendingPartialWithdrawalsLimit = 64 // Maximum number of pending partial withdrawals in the beacon state.
|
||||
PendingConsolidationsLimit = 64 // Maximum number of pending consolidations in the beacon state.
|
||||
|
||||
@@ -49,6 +49,7 @@ go_test(
|
||||
"mainnet_config_test.go",
|
||||
"testnet_config_test.go",
|
||||
"testnet_holesky_config_test.go",
|
||||
"testnet_sepolia_config_test.go",
|
||||
],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"testdata/e2e_config.yaml",
|
||||
@@ -57,6 +58,7 @@ go_test(
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
"@eth2_networks//:configs",
|
||||
"@holesky_testnet//:configs",
|
||||
"@sepolia_testnet//:configs",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
gotags = ["develop"],
|
||||
|
||||
@@ -11,11 +11,15 @@ func UseSepoliaNetworkConfig() {
|
||||
cfg := BeaconNetworkConfig().Copy()
|
||||
cfg.ContractDeploymentBlock = 1273020
|
||||
cfg.BootstrapNodes = []string{
|
||||
// EF boot nodes
|
||||
"enr:-Ku4QDZ_rCowZFsozeWr60WwLgOfHzv1Fz2cuMvJqN5iJzLxKtVjoIURY42X_YTokMi3IGstW5v32uSYZyGUXj9Q_IECh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhIpEe5iJc2VjcDI1NmsxoQNHTpFdaNSCEWiN_QqT396nb0PzcUpLe3OVtLph-AciBYN1ZHCCIy0",
|
||||
"enr:-Ku4QHRyRwEPT7s0XLYzJ_EeeWvZTXBQb4UCGy1F_3m-YtCNTtDlGsCMr4UTgo4uR89pv11uM-xq4w6GKfKhqU31hTgCh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhIrFM7WJc2VjcDI1NmsxoQI4diTwChN3zAAkarf7smOHCdFb1q3DSwdiQ_Lc_FdzFIN1ZHCCIy0",
|
||||
"enr:-Ku4QOkvvf0u5Hg4-HhY-SJmEyft77G5h3rUM8VF_e-Hag5cAma3jtmFoX4WElLAqdILCA-UWFRN1ZCDJJVuEHrFeLkDh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhJK-AWeJc2VjcDI1NmsxoQLFcT5VE_NMiIC8Ll7GypWDnQ4UEmuzD7hF_Hf4veDJwIN1ZHCCIy0",
|
||||
"enr:-Ku4QH6tYsHKITYeHUu5kdfXgEZWI18EWk_2RtGOn1jBPlx2UlS_uF3Pm5Dx7tnjOvla_zs-wwlPgjnEOcQDWXey51QCh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhIs7Mc6Jc2VjcDI1NmsxoQIET4Mlv9YzhrYhX_H9D7aWMemUrvki6W4J2Qo0YmFMp4N1ZHCCIy0",
|
||||
"enr:-Ku4QDmz-4c1InchGitsgNk4qzorWMiFUoaPJT4G0IiF8r2UaevrekND1o7fdoftNucirj7sFFTTn2-JdC2Ej0p1Mn8Ch2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhKpA-liJc2VjcDI1NmsxoQMpHP5U1DK8O_JQU6FadmWbE42qEdcGlllR8HcSkkfWq4N1ZHCCIy0",
|
||||
"enr:-KO4QP7MmB3juk8rUjJHcUoxZDU9Np4FlW0HyDEGIjSO7GD9PbSsabu7713cWSUWKDkxIypIXg1A-6lG7ySRGOMZHeGCAmuEZXRoMpDTH2GRkAAAc___________gmlkgnY0gmlwhBSoyGOJc2VjcDI1NmsxoQNta5b_bexSSwwrGW2Re24MjfMntzFd0f2SAxQtMj3ueYN0Y3CCIyiDdWRwgiMo",
|
||||
"enr:-KG4QJejf8KVtMeAPWFhN_P0c4efuwu1pZHELTveiXUeim6nKYcYcMIQpGxxdgT2Xp9h-M5pr9gn2NbbwEAtxzu50Y8BgmlkgnY0gmlwhEEVkQCDaXA2kCoBBPnAEJg4AAAAAAAAAAGJc2VjcDI1NmsxoQLEh_eVvk07AQABvLkTGBQTrrIOQkzouMgSBtNHIRUxOIN1ZHCCIyiEdWRwNoIjKA",
|
||||
"enr:-Iq4QMCTfIMXnow27baRUb35Q8iiFHSIDBJh6hQM5Axohhf4b6Kr_cOCu0htQ5WvVqKvFgY28893DHAg8gnBAXsAVqmGAX53x8JggmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk",
|
||||
"enr:-KG4QE5OIg5ThTjkzrlVF32WT_-XT14WeJtIz2zoTqLLjQhYAmJlnk4ItSoH41_2x0RX0wTFIe5GgjRzU2u7Q1fN4vADhGV0aDKQqP7o7pAAAHAyAAAAAAAAAIJpZIJ2NIJpcISlFsStiXNlY3AyNTZrMaEC-Rrd_bBZwhKpXzFCrStKp1q_HmGOewxY3KwM8ofAj_ODdGNwgiMog3VkcIIjKA",
|
||||
// Teku boot node
|
||||
"enr:-Ly4QFoZTWR8ulxGVsWydTNGdwEESueIdj-wB6UmmjUcm-AOPxnQi7wprzwcdo7-1jBW_JxELlUKJdJES8TDsbl1EdNlh2F0dG5ldHOI__78_v2bsV-EZXRoMpA2-lATkAAAcf__________gmlkgnY0gmlwhBLYJjGJc2VjcDI1NmsxoQI0gujXac9rMAb48NtMqtSTyHIeNYlpjkbYpWJw46PmYYhzeW5jbmV0cw-DdGNwgiMog3VkcIIjKA",
|
||||
"enr:-L64QC9Hhov4DhQ7mRukTOz4_jHm4DHlGL726NWH4ojH1wFgEwSin_6H95Gs6nW2fktTWbPachHJ6rUFu0iJNgA0SB2CARqHYXR0bmV0c4j__________4RldGgykDb6UBOQAABx__________-CaWSCdjSCaXCEA-2vzolzZWNwMjU2azGhA17lsUg60R776rauYMdrAz383UUgESoaHEzMkvm4K6k6iHN5bmNuZXRzD4N0Y3CCIyiDdWRwgiMo",
|
||||
}
|
||||
OverrideBeaconNetworkConfig(cfg)
|
||||
}
|
||||
|
||||
28
config/params/testnet_sepolia_config_test.go
Normal file
28
config/params/testnet_sepolia_config_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package params_test
|
||||
|
||||
import (
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/bazelbuild/rules_go/go/tools/bazel"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestSepoliaConfigMatchesUpstreamYaml(t *testing.T) {
|
||||
presetFPs := presetsFilePath(t, "mainnet")
|
||||
mn, err := params.ByName(params.MainnetName)
|
||||
require.NoError(t, err)
|
||||
cfg := mn.Copy()
|
||||
for _, fp := range presetFPs {
|
||||
cfg, err = params.UnmarshalConfigFile(fp, cfg)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
fPath, err := bazel.Runfile("external/sepolia_testnet")
|
||||
require.NoError(t, err)
|
||||
configFP := path.Join(fPath, "metadata", "config.yaml")
|
||||
pcfg, err := params.UnmarshalConfigFile(configFP, nil)
|
||||
require.NoError(t, err)
|
||||
fields := fieldsFromYamls(t, append(presetFPs, configFP))
|
||||
assertYamlFieldsMatch(t, "sepolia", fields, pcfg, params.SepoliaConfig())
|
||||
}
|
||||
@@ -5,6 +5,7 @@ go_library(
|
||||
srcs = [
|
||||
"beacon_block.go",
|
||||
"error.go",
|
||||
"light_client.go",
|
||||
"utils.go",
|
||||
"validator.go",
|
||||
],
|
||||
|
||||
58
consensus-types/interfaces/light_client.go
Normal file
58
consensus-types/interfaces/light_client.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package interfaces
|
||||
|
||||
import (
|
||||
ssz "github.com/prysmaticlabs/fastssz"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type LightClientExecutionBranch = [fieldparams.ExecutionBranchDepth][fieldparams.RootLength]byte
|
||||
type LightClientSyncCommitteeBranch = [fieldparams.SyncCommitteeBranchDepth][fieldparams.RootLength]byte
|
||||
type LightClientFinalityBranch = [fieldparams.FinalityBranchDepth][fieldparams.RootLength]byte
|
||||
|
||||
type LightClientHeader interface {
|
||||
ssz.Marshaler
|
||||
Version() int
|
||||
Beacon() *pb.BeaconBlockHeader
|
||||
Execution() (ExecutionData, error)
|
||||
ExecutionBranch() (LightClientExecutionBranch, error)
|
||||
}
|
||||
|
||||
type LightClientBootstrap interface {
|
||||
ssz.Marshaler
|
||||
Version() int
|
||||
Header() LightClientHeader
|
||||
CurrentSyncCommittee() *pb.SyncCommittee
|
||||
CurrentSyncCommitteeBranch() LightClientSyncCommitteeBranch
|
||||
}
|
||||
|
||||
type LightClientUpdate interface {
|
||||
ssz.Marshaler
|
||||
Version() int
|
||||
AttestedHeader() LightClientHeader
|
||||
NextSyncCommittee() *pb.SyncCommittee
|
||||
NextSyncCommitteeBranch() LightClientSyncCommitteeBranch
|
||||
FinalizedHeader() LightClientHeader
|
||||
FinalityBranch() LightClientFinalityBranch
|
||||
SyncAggregate() *pb.SyncAggregate
|
||||
SignatureSlot() primitives.Slot
|
||||
}
|
||||
|
||||
type LightClientFinalityUpdate interface {
|
||||
ssz.Marshaler
|
||||
Version() int
|
||||
AttestedHeader() LightClientHeader
|
||||
FinalizedHeader() LightClientHeader
|
||||
FinalityBranch() LightClientFinalityBranch
|
||||
SyncAggregate() *pb.SyncAggregate
|
||||
SignatureSlot() primitives.Slot
|
||||
}
|
||||
|
||||
type LightClientOptimisticUpdate interface {
|
||||
ssz.Marshaler
|
||||
Version() int
|
||||
AttestedHeader() LightClientHeader
|
||||
SyncAggregate() *pb.SyncAggregate
|
||||
SignatureSlot() primitives.Slot
|
||||
}
|
||||
26
consensus-types/light-client/BUILD.bazel
Normal file
26
consensus-types/light-client/BUILD.bazel
Normal file
@@ -0,0 +1,26 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bootstrap.go",
|
||||
"finality_update.go",
|
||||
"header.go",
|
||||
"helpers.go",
|
||||
"optimistic_update.go",
|
||||
"update.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//consensus-types:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
],
|
||||
)
|
||||
208
consensus-types/light-client/bootstrap.go
Normal file
208
consensus-types/light-client/bootstrap.go
Normal file
@@ -0,0 +1,208 @@
|
||||
package light_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func NewWrappedBootstrap(m proto.Message) (interfaces.LightClientBootstrap, error) {
|
||||
if m == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
switch t := m.(type) {
|
||||
case *pb.LightClientBootstrapAltair:
|
||||
return NewWrappedBootstrapAltair(t)
|
||||
case *pb.LightClientBootstrapCapella:
|
||||
return NewWrappedBootstrapCapella(t)
|
||||
case *pb.LightClientBootstrapDeneb:
|
||||
return NewWrappedBootstrapDeneb(t)
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot construct light client bootstrap from type %T", t)
|
||||
}
|
||||
}
|
||||
|
||||
type bootstrapAltair struct {
|
||||
p *pb.LightClientBootstrapAltair
|
||||
header interfaces.LightClientHeader
|
||||
currentSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientBootstrap = &bootstrapAltair{}
|
||||
|
||||
func NewWrappedBootstrapAltair(p *pb.LightClientBootstrapAltair) (interfaces.LightClientBootstrap, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
header, err := NewWrappedHeaderAltair(p.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branch, err := createBranch[interfaces.LightClientSyncCommitteeBranch](
|
||||
"sync committee",
|
||||
p.CurrentSyncCommitteeBranch,
|
||||
fieldparams.SyncCommitteeBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bootstrapAltair{
|
||||
p: p,
|
||||
header: header,
|
||||
currentSyncCommitteeBranch: branch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *bootstrapAltair) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return h.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (h *bootstrapAltair) MarshalSSZ() ([]byte, error) {
|
||||
return h.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (h *bootstrapAltair) SizeSSZ() int {
|
||||
return h.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (h *bootstrapAltair) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
func (h *bootstrapAltair) Header() interfaces.LightClientHeader {
|
||||
return h.header
|
||||
}
|
||||
|
||||
func (h *bootstrapAltair) CurrentSyncCommittee() *pb.SyncCommittee {
|
||||
return h.p.CurrentSyncCommittee
|
||||
}
|
||||
|
||||
func (h *bootstrapAltair) CurrentSyncCommitteeBranch() interfaces.LightClientSyncCommitteeBranch {
|
||||
return h.currentSyncCommitteeBranch
|
||||
}
|
||||
|
||||
type bootstrapCapella struct {
|
||||
p *pb.LightClientBootstrapCapella
|
||||
header interfaces.LightClientHeader
|
||||
currentSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientBootstrap = &bootstrapCapella{}
|
||||
|
||||
func NewWrappedBootstrapCapella(p *pb.LightClientBootstrapCapella) (interfaces.LightClientBootstrap, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
header, err := NewWrappedHeaderCapella(p.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branch, err := createBranch[interfaces.LightClientSyncCommitteeBranch](
|
||||
"sync committee",
|
||||
p.CurrentSyncCommitteeBranch,
|
||||
fieldparams.SyncCommitteeBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bootstrapCapella{
|
||||
p: p,
|
||||
header: header,
|
||||
currentSyncCommitteeBranch: branch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *bootstrapCapella) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return h.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (h *bootstrapCapella) MarshalSSZ() ([]byte, error) {
|
||||
return h.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (h *bootstrapCapella) SizeSSZ() int {
|
||||
return h.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (h *bootstrapCapella) Version() int {
|
||||
return version.Capella
|
||||
}
|
||||
|
||||
func (h *bootstrapCapella) Header() interfaces.LightClientHeader {
|
||||
return h.header
|
||||
}
|
||||
|
||||
func (h *bootstrapCapella) CurrentSyncCommittee() *pb.SyncCommittee {
|
||||
return h.p.CurrentSyncCommittee
|
||||
}
|
||||
|
||||
func (h *bootstrapCapella) CurrentSyncCommitteeBranch() interfaces.LightClientSyncCommitteeBranch {
|
||||
return h.currentSyncCommitteeBranch
|
||||
}
|
||||
|
||||
type bootstrapDeneb struct {
|
||||
p *pb.LightClientBootstrapDeneb
|
||||
header interfaces.LightClientHeader
|
||||
currentSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientBootstrap = &bootstrapDeneb{}
|
||||
|
||||
func NewWrappedBootstrapDeneb(p *pb.LightClientBootstrapDeneb) (interfaces.LightClientBootstrap, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
header, err := NewWrappedHeaderDeneb(p.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branch, err := createBranch[interfaces.LightClientSyncCommitteeBranch](
|
||||
"sync committee",
|
||||
p.CurrentSyncCommitteeBranch,
|
||||
fieldparams.SyncCommitteeBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bootstrapDeneb{
|
||||
p: p,
|
||||
header: header,
|
||||
currentSyncCommitteeBranch: branch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *bootstrapDeneb) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return h.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (h *bootstrapDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return h.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (h *bootstrapDeneb) SizeSSZ() int {
|
||||
return h.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (h *bootstrapDeneb) Version() int {
|
||||
return version.Deneb
|
||||
}
|
||||
|
||||
func (h *bootstrapDeneb) Header() interfaces.LightClientHeader {
|
||||
return h.header
|
||||
}
|
||||
|
||||
func (h *bootstrapDeneb) CurrentSyncCommittee() *pb.SyncCommittee {
|
||||
return h.p.CurrentSyncCommittee
|
||||
}
|
||||
|
||||
func (h *bootstrapDeneb) CurrentSyncCommitteeBranch() interfaces.LightClientSyncCommitteeBranch {
|
||||
return h.currentSyncCommitteeBranch
|
||||
}
|
||||
251
consensus-types/light-client/finality_update.go
Normal file
251
consensus-types/light-client/finality_update.go
Normal file
@@ -0,0 +1,251 @@
|
||||
package light_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func NewWrappedFinalityUpdate(m proto.Message) (interfaces.LightClientFinalityUpdate, error) {
|
||||
if m == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
switch t := m.(type) {
|
||||
case *pb.LightClientFinalityUpdateAltair:
|
||||
return NewWrappedFinalityUpdateAltair(t)
|
||||
case *pb.LightClientFinalityUpdateCapella:
|
||||
return NewWrappedFinalityUpdateCapella(t)
|
||||
case *pb.LightClientFinalityUpdateDeneb:
|
||||
return NewWrappedFinalityUpdateDeneb(t)
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot construct light client finality update from type %T", t)
|
||||
}
|
||||
}
|
||||
|
||||
type finalityUpdateAltair struct {
|
||||
p *pb.LightClientFinalityUpdateAltair
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
finalizedHeader interfaces.LightClientHeader
|
||||
finalityBranch interfaces.LightClientFinalityBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientFinalityUpdate = &finalityUpdateAltair{}
|
||||
|
||||
func NewWrappedFinalityUpdateAltair(p *pb.LightClientFinalityUpdateAltair) (interfaces.LightClientFinalityUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderAltair(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedHeader, err := NewWrappedHeaderAltair(p.FinalizedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branch, err := createBranch[interfaces.LightClientFinalityBranch](
|
||||
"finality",
|
||||
p.FinalityBranch,
|
||||
fieldparams.FinalityBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &finalityUpdateAltair{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
finalizedHeader: finalizedHeader,
|
||||
finalityBranch: branch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) FinalizedHeader() interfaces.LightClientHeader {
|
||||
return u.finalizedHeader
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) FinalityBranch() interfaces.LightClientFinalityBranch {
|
||||
return u.finalityBranch
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *finalityUpdateAltair) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
|
||||
type finalityUpdateCapella struct {
|
||||
p *pb.LightClientFinalityUpdateCapella
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
finalizedHeader interfaces.LightClientHeader
|
||||
finalityBranch interfaces.LightClientFinalityBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientFinalityUpdate = &finalityUpdateCapella{}
|
||||
|
||||
func NewWrappedFinalityUpdateCapella(p *pb.LightClientFinalityUpdateCapella) (interfaces.LightClientFinalityUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderCapella(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedHeader, err := NewWrappedHeaderCapella(p.FinalizedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branch, err := createBranch[interfaces.LightClientFinalityBranch](
|
||||
"finality",
|
||||
p.FinalityBranch,
|
||||
fieldparams.FinalityBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &finalityUpdateCapella{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
finalizedHeader: finalizedHeader,
|
||||
finalityBranch: branch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) Version() int {
|
||||
return version.Capella
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) FinalizedHeader() interfaces.LightClientHeader {
|
||||
return u.finalizedHeader
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) FinalityBranch() interfaces.LightClientFinalityBranch {
|
||||
return u.finalityBranch
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *finalityUpdateCapella) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
|
||||
type finalityUpdateDeneb struct {
|
||||
p *pb.LightClientFinalityUpdateDeneb
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
finalizedHeader interfaces.LightClientHeader
|
||||
finalityBranch interfaces.LightClientFinalityBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientFinalityUpdate = &finalityUpdateDeneb{}
|
||||
|
||||
func NewWrappedFinalityUpdateDeneb(p *pb.LightClientFinalityUpdateDeneb) (interfaces.LightClientFinalityUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderDeneb(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedHeader, err := NewWrappedHeaderDeneb(p.FinalizedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branch, err := createBranch[interfaces.LightClientFinalityBranch](
|
||||
"finality",
|
||||
p.FinalityBranch,
|
||||
fieldparams.FinalityBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &finalityUpdateDeneb{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
finalizedHeader: finalizedHeader,
|
||||
finalityBranch: branch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) Version() int {
|
||||
return version.Deneb
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) FinalizedHeader() interfaces.LightClientHeader {
|
||||
return u.finalizedHeader
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) FinalityBranch() interfaces.LightClientFinalityBranch {
|
||||
return u.finalityBranch
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *finalityUpdateDeneb) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
192
consensus-types/light-client/header.go
Normal file
192
consensus-types/light-client/header.go
Normal file
@@ -0,0 +1,192 @@
|
||||
package light_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func NewWrappedHeader(m proto.Message) (interfaces.LightClientHeader, error) {
|
||||
if m == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
switch t := m.(type) {
|
||||
case *pb.LightClientHeaderAltair:
|
||||
return NewWrappedHeaderAltair(t)
|
||||
case *pb.LightClientHeaderCapella:
|
||||
return NewWrappedHeaderCapella(t)
|
||||
case *pb.LightClientHeaderDeneb:
|
||||
return NewWrappedHeaderDeneb(t)
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot construct light client header from type %T", t)
|
||||
}
|
||||
}
|
||||
|
||||
type headerAltair struct {
|
||||
p *pb.LightClientHeaderAltair
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientHeader = &headerAltair{}
|
||||
|
||||
func NewWrappedHeaderAltair(p *pb.LightClientHeaderAltair) (interfaces.LightClientHeader, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
return &headerAltair{p: p}, nil
|
||||
}
|
||||
|
||||
func (h *headerAltair) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return h.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (h *headerAltair) MarshalSSZ() ([]byte, error) {
|
||||
return h.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (h *headerAltair) SizeSSZ() int {
|
||||
return h.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (h *headerAltair) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
func (h *headerAltair) Beacon() *pb.BeaconBlockHeader {
|
||||
return h.p.Beacon
|
||||
}
|
||||
|
||||
func (h *headerAltair) Execution() (interfaces.ExecutionData, error) {
|
||||
return nil, consensustypes.ErrNotSupported("Execution", version.Altair)
|
||||
}
|
||||
|
||||
func (h *headerAltair) ExecutionBranch() (interfaces.LightClientExecutionBranch, error) {
|
||||
return interfaces.LightClientExecutionBranch{}, consensustypes.ErrNotSupported("ExecutionBranch", version.Altair)
|
||||
}
|
||||
|
||||
type headerCapella struct {
|
||||
p *pb.LightClientHeaderCapella
|
||||
execution interfaces.ExecutionData
|
||||
executionBranch interfaces.LightClientExecutionBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientHeader = &headerCapella{}
|
||||
|
||||
func NewWrappedHeaderCapella(p *pb.LightClientHeaderCapella) (interfaces.LightClientHeader, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
execution, err := blocks.WrappedExecutionPayloadHeaderCapella(p.Execution)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
branch, err := createBranch[interfaces.LightClientExecutionBranch](
|
||||
"execution",
|
||||
p.ExecutionBranch,
|
||||
fieldparams.ExecutionBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &headerCapella{
|
||||
p: p,
|
||||
execution: execution,
|
||||
executionBranch: branch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *headerCapella) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return h.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (h *headerCapella) MarshalSSZ() ([]byte, error) {
|
||||
return h.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (h *headerCapella) SizeSSZ() int {
|
||||
return h.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (h *headerCapella) Version() int {
|
||||
return version.Capella
|
||||
}
|
||||
|
||||
func (h *headerCapella) Beacon() *pb.BeaconBlockHeader {
|
||||
return h.p.Beacon
|
||||
}
|
||||
|
||||
func (h *headerCapella) Execution() (interfaces.ExecutionData, error) {
|
||||
return h.execution, nil
|
||||
}
|
||||
|
||||
func (h *headerCapella) ExecutionBranch() (interfaces.LightClientExecutionBranch, error) {
|
||||
return h.executionBranch, nil
|
||||
}
|
||||
|
||||
type headerDeneb struct {
|
||||
p *pb.LightClientHeaderDeneb
|
||||
execution interfaces.ExecutionData
|
||||
executionBranch interfaces.LightClientExecutionBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientHeader = &headerDeneb{}
|
||||
|
||||
func NewWrappedHeaderDeneb(p *pb.LightClientHeaderDeneb) (interfaces.LightClientHeader, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
execution, err := blocks.WrappedExecutionPayloadHeaderDeneb(p.Execution)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
branch, err := createBranch[interfaces.LightClientExecutionBranch](
|
||||
"execution",
|
||||
p.ExecutionBranch,
|
||||
fieldparams.ExecutionBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &headerDeneb{
|
||||
p: p,
|
||||
execution: execution,
|
||||
executionBranch: branch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *headerDeneb) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return h.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (h *headerDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return h.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (h *headerDeneb) SizeSSZ() int {
|
||||
return h.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (h *headerDeneb) Version() int {
|
||||
return version.Deneb
|
||||
}
|
||||
|
||||
func (h *headerDeneb) Beacon() *pb.BeaconBlockHeader {
|
||||
return h.p.Beacon
|
||||
}
|
||||
|
||||
func (h *headerDeneb) Execution() (interfaces.ExecutionData, error) {
|
||||
return h.execution, nil
|
||||
}
|
||||
|
||||
func (h *headerDeneb) ExecutionBranch() (interfaces.LightClientExecutionBranch, error) {
|
||||
return h.executionBranch, nil
|
||||
}
|
||||
30
consensus-types/light-client/helpers.go
Normal file
30
consensus-types/light-client/helpers.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package light_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
)
|
||||
|
||||
type branchConstraint interface {
|
||||
~interfaces.LightClientExecutionBranch | ~interfaces.LightClientSyncCommitteeBranch | ~interfaces.LightClientFinalityBranch
|
||||
}
|
||||
|
||||
func createBranch[T branchConstraint](name string, input [][]byte, depth int) (T, error) {
|
||||
var zero T
|
||||
|
||||
if len(input) != depth {
|
||||
return zero, fmt.Errorf("%s branch has %d leaves instead of expected %d", name, len(input), depth)
|
||||
}
|
||||
var branch T
|
||||
for i, leaf := range input {
|
||||
if len(leaf) != fieldparams.RootLength {
|
||||
return zero, fmt.Errorf("%s branch leaf at index %d has length %d instead of expected %d", name, i, len(leaf), fieldparams.RootLength)
|
||||
}
|
||||
branch[i] = bytesutil.ToBytes32(leaf)
|
||||
}
|
||||
|
||||
return branch, nil
|
||||
}
|
||||
178
consensus-types/light-client/optimistic_update.go
Normal file
178
consensus-types/light-client/optimistic_update.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package light_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func NewWrappedOptimisticUpdate(m proto.Message) (interfaces.LightClientOptimisticUpdate, error) {
|
||||
if m == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
switch t := m.(type) {
|
||||
case *pb.LightClientOptimisticUpdateAltair:
|
||||
return NewWrappedOptimisticUpdateAltair(t)
|
||||
case *pb.LightClientOptimisticUpdateCapella:
|
||||
return NewWrappedOptimisticUpdateCapella(t)
|
||||
case *pb.LightClientOptimisticUpdateDeneb:
|
||||
return NewWrappedOptimisticUpdateDeneb(t)
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot construct light client optimistic update from type %T", t)
|
||||
}
|
||||
}
|
||||
|
||||
type OptimisticUpdateAltair struct {
|
||||
p *pb.LightClientOptimisticUpdateAltair
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientOptimisticUpdate = &OptimisticUpdateAltair{}
|
||||
|
||||
func NewWrappedOptimisticUpdateAltair(p *pb.LightClientOptimisticUpdateAltair) (interfaces.LightClientOptimisticUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderAltair(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OptimisticUpdateAltair{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateAltair) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateAltair) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateAltair) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateAltair) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateAltair) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateAltair) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateAltair) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
|
||||
type OptimisticUpdateCapella struct {
|
||||
p *pb.LightClientOptimisticUpdateCapella
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientOptimisticUpdate = &OptimisticUpdateCapella{}
|
||||
|
||||
func NewWrappedOptimisticUpdateCapella(p *pb.LightClientOptimisticUpdateCapella) (interfaces.LightClientOptimisticUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderCapella(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OptimisticUpdateCapella{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateCapella) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateCapella) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateCapella) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateCapella) Version() int {
|
||||
return version.Capella
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateCapella) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateCapella) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateCapella) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
|
||||
type OptimisticUpdateDeneb struct {
|
||||
p *pb.LightClientOptimisticUpdateDeneb
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientOptimisticUpdate = &OptimisticUpdateDeneb{}
|
||||
|
||||
func NewWrappedOptimisticUpdateDeneb(p *pb.LightClientOptimisticUpdateDeneb) (interfaces.LightClientOptimisticUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderDeneb(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OptimisticUpdateDeneb{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateDeneb) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateDeneb) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateDeneb) Version() int {
|
||||
return version.Deneb
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateDeneb) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateDeneb) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *OptimisticUpdateDeneb) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
305
consensus-types/light-client/update.go
Normal file
305
consensus-types/light-client/update.go
Normal file
@@ -0,0 +1,305 @@
|
||||
package light_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func NewWrappedUpdate(m proto.Message) (interfaces.LightClientUpdate, error) {
|
||||
if m == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
switch t := m.(type) {
|
||||
case *pb.LightClientUpdateAltair:
|
||||
return NewWrappedUpdateAltair(t)
|
||||
case *pb.LightClientUpdateCapella:
|
||||
return NewWrappedUpdateCapella(t)
|
||||
case *pb.LightClientUpdateDeneb:
|
||||
return NewWrappedUpdateDeneb(t)
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot construct light client update from type %T", t)
|
||||
}
|
||||
}
|
||||
|
||||
type updateAltair struct {
|
||||
p *pb.LightClientUpdateAltair
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
nextSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch
|
||||
finalizedHeader interfaces.LightClientHeader
|
||||
finalityBranch interfaces.LightClientFinalityBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientUpdate = &updateAltair{}
|
||||
|
||||
func NewWrappedUpdateAltair(p *pb.LightClientUpdateAltair) (interfaces.LightClientUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderAltair(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedHeader, err := NewWrappedHeaderAltair(p.FinalizedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scBranch, err := createBranch[interfaces.LightClientSyncCommitteeBranch](
|
||||
"sync committee",
|
||||
p.NextSyncCommitteeBranch,
|
||||
fieldparams.SyncCommitteeBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalityBranch, err := createBranch[interfaces.LightClientFinalityBranch](
|
||||
"finality",
|
||||
p.FinalityBranch,
|
||||
fieldparams.FinalityBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &updateAltair{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
nextSyncCommitteeBranch: scBranch,
|
||||
finalizedHeader: finalizedHeader,
|
||||
finalityBranch: finalityBranch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *updateAltair) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *updateAltair) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *updateAltair) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *updateAltair) Version() int {
|
||||
return version.Altair
|
||||
}
|
||||
|
||||
func (u *updateAltair) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *updateAltair) NextSyncCommittee() *pb.SyncCommittee {
|
||||
return u.p.NextSyncCommittee
|
||||
}
|
||||
|
||||
func (u *updateAltair) NextSyncCommitteeBranch() interfaces.LightClientSyncCommitteeBranch {
|
||||
return u.nextSyncCommitteeBranch
|
||||
}
|
||||
|
||||
func (u *updateAltair) FinalizedHeader() interfaces.LightClientHeader {
|
||||
return u.finalizedHeader
|
||||
}
|
||||
|
||||
func (u *updateAltair) FinalityBranch() interfaces.LightClientFinalityBranch {
|
||||
return u.finalityBranch
|
||||
}
|
||||
|
||||
func (u *updateAltair) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *updateAltair) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
|
||||
type updateCapella struct {
|
||||
p *pb.LightClientUpdateCapella
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
nextSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch
|
||||
finalizedHeader interfaces.LightClientHeader
|
||||
finalityBranch interfaces.LightClientFinalityBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientUpdate = &updateCapella{}
|
||||
|
||||
func NewWrappedUpdateCapella(p *pb.LightClientUpdateCapella) (interfaces.LightClientUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderCapella(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedHeader, err := NewWrappedHeaderCapella(p.FinalizedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scBranch, err := createBranch[interfaces.LightClientSyncCommitteeBranch](
|
||||
"sync committee",
|
||||
p.NextSyncCommitteeBranch,
|
||||
fieldparams.SyncCommitteeBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalityBranch, err := createBranch[interfaces.LightClientFinalityBranch](
|
||||
"finality",
|
||||
p.FinalityBranch,
|
||||
fieldparams.FinalityBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &updateCapella{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
nextSyncCommitteeBranch: scBranch,
|
||||
finalizedHeader: finalizedHeader,
|
||||
finalityBranch: finalityBranch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *updateCapella) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *updateCapella) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *updateCapella) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *updateCapella) Version() int {
|
||||
return version.Capella
|
||||
}
|
||||
|
||||
func (u *updateCapella) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *updateCapella) NextSyncCommittee() *pb.SyncCommittee {
|
||||
return u.p.NextSyncCommittee
|
||||
}
|
||||
|
||||
func (u *updateCapella) NextSyncCommitteeBranch() interfaces.LightClientSyncCommitteeBranch {
|
||||
return u.nextSyncCommitteeBranch
|
||||
}
|
||||
|
||||
func (u *updateCapella) FinalizedHeader() interfaces.LightClientHeader {
|
||||
return u.finalizedHeader
|
||||
}
|
||||
|
||||
func (u *updateCapella) FinalityBranch() interfaces.LightClientFinalityBranch {
|
||||
return u.finalityBranch
|
||||
}
|
||||
|
||||
func (u *updateCapella) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *updateCapella) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
|
||||
type updateDeneb struct {
|
||||
p *pb.LightClientUpdateDeneb
|
||||
attestedHeader interfaces.LightClientHeader
|
||||
nextSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch
|
||||
finalizedHeader interfaces.LightClientHeader
|
||||
finalityBranch interfaces.LightClientFinalityBranch
|
||||
}
|
||||
|
||||
var _ interfaces.LightClientUpdate = &updateDeneb{}
|
||||
|
||||
func NewWrappedUpdateDeneb(p *pb.LightClientUpdateDeneb) (interfaces.LightClientUpdate, error) {
|
||||
if p == nil {
|
||||
return nil, consensustypes.ErrNilObjectWrapped
|
||||
}
|
||||
attestedHeader, err := NewWrappedHeaderDeneb(p.AttestedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedHeader, err := NewWrappedHeaderDeneb(p.FinalizedHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scBranch, err := createBranch[interfaces.LightClientSyncCommitteeBranch](
|
||||
"sync committee",
|
||||
p.NextSyncCommitteeBranch,
|
||||
fieldparams.SyncCommitteeBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalityBranch, err := createBranch[interfaces.LightClientFinalityBranch](
|
||||
"finality",
|
||||
p.FinalityBranch,
|
||||
fieldparams.FinalityBranchDepth,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &updateDeneb{
|
||||
p: p,
|
||||
attestedHeader: attestedHeader,
|
||||
nextSyncCommitteeBranch: scBranch,
|
||||
finalizedHeader: finalizedHeader,
|
||||
finalityBranch: finalityBranch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *updateDeneb) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return u.p.MarshalSSZTo(dst)
|
||||
}
|
||||
|
||||
func (u *updateDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return u.p.MarshalSSZ()
|
||||
}
|
||||
|
||||
func (u *updateDeneb) SizeSSZ() int {
|
||||
return u.p.SizeSSZ()
|
||||
}
|
||||
|
||||
func (u *updateDeneb) Version() int {
|
||||
return version.Deneb
|
||||
}
|
||||
|
||||
func (u *updateDeneb) AttestedHeader() interfaces.LightClientHeader {
|
||||
return u.attestedHeader
|
||||
}
|
||||
|
||||
func (u *updateDeneb) NextSyncCommittee() *pb.SyncCommittee {
|
||||
return u.p.NextSyncCommittee
|
||||
}
|
||||
|
||||
func (u *updateDeneb) NextSyncCommitteeBranch() interfaces.LightClientSyncCommitteeBranch {
|
||||
return u.nextSyncCommitteeBranch
|
||||
}
|
||||
|
||||
func (u *updateDeneb) FinalizedHeader() interfaces.LightClientHeader {
|
||||
return u.finalizedHeader
|
||||
}
|
||||
|
||||
func (u *updateDeneb) FinalityBranch() interfaces.LightClientFinalityBranch {
|
||||
return u.finalityBranch
|
||||
}
|
||||
|
||||
func (u *updateDeneb) SyncAggregate() *pb.SyncAggregate {
|
||||
return u.p.SyncAggregate
|
||||
}
|
||||
|
||||
func (u *updateDeneb) SignatureSlot() primitives.Slot {
|
||||
return u.p.SignatureSlot
|
||||
}
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
"domain.go",
|
||||
"epoch.go",
|
||||
"execution_address.go",
|
||||
"kzg.go",
|
||||
"payload_id.go",
|
||||
"randao.go",
|
||||
"slot.go",
|
||||
@@ -21,6 +22,7 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//math:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
|
||||
15
consensus-types/primitives/kzg.go
Normal file
15
consensus-types/primitives/kzg.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package primitives
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
const blobCommitmentVersionKZG uint8 = 0x01
|
||||
|
||||
func ConvertKzgCommitmentToVersionedHash(commitment []byte) common.Hash {
|
||||
versionedHash := sha256.Sum256(commitment)
|
||||
versionedHash[0] = blobCommitmentVersionKZG
|
||||
return versionedHash
|
||||
}
|
||||
16
deps.bzl
16
deps.bzl
@@ -2781,8 +2781,8 @@ def prysm_deps():
|
||||
go_repository(
|
||||
name = "com_github_prysmaticlabs_fastssz",
|
||||
importpath = "github.com/prysmaticlabs/fastssz",
|
||||
sum = "h1:0LZAwwHnsZFfXm4IK4rzFV4N5IVSKZKLmuBMA4kAlFk=",
|
||||
version = "v0.0.0-20240620202422-a981b8ef89d3",
|
||||
sum = "h1:xuVAdtz5ShYblG2sPyb4gw01DF8InbOI/kBCQjk7NiM=",
|
||||
version = "v0.0.0-20241008181541-518c4ce73516",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_prysmaticlabs_go_bitfield",
|
||||
@@ -2833,6 +2833,12 @@ def prysm_deps():
|
||||
sum = "h1:HxSrwun11U+LlmwpgM1kEqIqH90IT4N8auv/cD7QFJg=",
|
||||
version = "v0.8.0",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_r3labs_sse_v2",
|
||||
importpath = "github.com/r3labs/sse/v2",
|
||||
sum = "h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=",
|
||||
version = "v2.10.0",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_raulk_go_watchdog",
|
||||
importpath = "github.com/raulk/go-watchdog",
|
||||
@@ -4304,6 +4310,12 @@ def prysm_deps():
|
||||
sum = "h1:stTHdEoWg1pQ8riaP5ROrjS6zy6wewH/Q2iwnLCQUXY=",
|
||||
version = "v1.0.0-20160220154919-db14e161995a",
|
||||
)
|
||||
go_repository(
|
||||
name = "in_gopkg_cenkalti_backoff_v1",
|
||||
importpath = "gopkg.in/cenkalti/backoff.v1",
|
||||
sum = "h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=",
|
||||
version = "v1.1.0",
|
||||
)
|
||||
go_repository(
|
||||
name = "in_gopkg_check_v1",
|
||||
importpath = "gopkg.in/check.v1",
|
||||
|
||||
4
go.mod
4
go.mod
@@ -62,10 +62,11 @@ require (
|
||||
github.com/prometheus/client_golang v1.20.0
|
||||
github.com/prometheus/client_model v0.6.1
|
||||
github.com/prometheus/prom2json v1.3.0
|
||||
github.com/prysmaticlabs/fastssz v0.0.0-20240620202422-a981b8ef89d3
|
||||
github.com/prysmaticlabs/fastssz v0.0.0-20241008181541-518c4ce73516
|
||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20240328144219-a1caa50c3a1e
|
||||
github.com/prysmaticlabs/prombbolt v0.0.0-20210126082820-9b7adba6db7c
|
||||
github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294
|
||||
github.com/r3labs/sse/v2 v2.10.0
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/schollz/progressbar/v3 v3.3.4
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
@@ -259,6 +260,7 @@ require (
|
||||
golang.org/x/term v0.23.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
|
||||
9
go.sum
9
go.sum
@@ -897,8 +897,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/prometheus/prom2json v1.3.0 h1:BlqrtbT9lLH3ZsOVhXPsHzFrApCTKRifB7gjJuypu6Y=
|
||||
github.com/prometheus/prom2json v1.3.0/go.mod h1:rMN7m0ApCowcoDlypBHlkNbp5eJQf/+1isKykIP5ZnM=
|
||||
github.com/prysmaticlabs/fastssz v0.0.0-20240620202422-a981b8ef89d3 h1:0LZAwwHnsZFfXm4IK4rzFV4N5IVSKZKLmuBMA4kAlFk=
|
||||
github.com/prysmaticlabs/fastssz v0.0.0-20240620202422-a981b8ef89d3/go.mod h1:h2OlIZD/M6wFvV3YMZbW16lFgh3Rsye00G44J2cwLyU=
|
||||
github.com/prysmaticlabs/fastssz v0.0.0-20241008181541-518c4ce73516 h1:xuVAdtz5ShYblG2sPyb4gw01DF8InbOI/kBCQjk7NiM=
|
||||
github.com/prysmaticlabs/fastssz v0.0.0-20241008181541-518c4ce73516/go.mod h1:h2OlIZD/M6wFvV3YMZbW16lFgh3Rsye00G44J2cwLyU=
|
||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20210108222456-8e92c3709aa0/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
|
||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20240328144219-a1caa50c3a1e h1:ATgOe+abbzfx9kCPeXIW4fiWyDdxlwHw07j8UGhdTd4=
|
||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20240328144219-a1caa50c3a1e/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4=
|
||||
@@ -914,6 +914,8 @@ github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7
|
||||
github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
||||
github.com/quic-go/webtransport-go v0.8.0 h1:HxSrwun11U+LlmwpgM1kEqIqH90IT4N8auv/cD7QFJg=
|
||||
github.com/quic-go/webtransport-go v0.8.0/go.mod h1:N99tjprW432Ut5ONql/aUhSLT0YVSlwHohQsuac9WaM=
|
||||
github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=
|
||||
github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I=
|
||||
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
|
||||
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
@@ -1223,6 +1225,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -1607,6 +1610,8 @@ google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6h
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 13c946aa898cca1afa84687b619bc5a10fc79a46340e98dcfb07dde835d39a0c
|
||||
// Hash: 2874e1dadeb47411763f48fe31e5daaa91ac663e796933d9a508c2e7be94fa5e
|
||||
package v1
|
||||
|
||||
import (
|
||||
@@ -2395,7 +2395,10 @@ func (v *Validator) UnmarshalSSZ(buf []byte) error {
|
||||
v.EffectiveBalance = ssz.UnmarshallUint64(buf[80:88])
|
||||
|
||||
// Field (3) 'Slashed'
|
||||
v.Slashed = ssz.UnmarshalBool(buf[88:89])
|
||||
v.Slashed, err = ssz.DecodeBool(buf[88:89])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (4) 'ActivationEligibilityEpoch'
|
||||
v.ActivationEligibilityEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[89:97]))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: bc8a0f7f6c8dadac6bcb0eaab2dea4888cc44c5b3f4fe9998a71e15f1a059399
|
||||
// Hash: 298a6e797d2a244a4eee0e60b198b11fd30b4b8596a8a5b911dd2e14fafebdad
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
@@ -81,6 +81,11 @@ ssz_altair_objs = [
|
||||
"BeaconBlockBodyAltair",
|
||||
"BeaconStateAltair",
|
||||
"ContributionAndProof",
|
||||
"LightClientBootstrapAltair",
|
||||
"LightClientFinalityUpdateAltair",
|
||||
"LightClientHeaderAltair",
|
||||
"LightClientOptimisticUpdateAltair",
|
||||
"LightClientUpdateAltair",
|
||||
"SignedBeaconBlockAltair",
|
||||
"SignedContributionAndProof",
|
||||
"SyncAggregate",
|
||||
@@ -110,6 +115,11 @@ ssz_capella_objs = [
|
||||
"BlindedBeaconBlockCapella",
|
||||
"BuilderBidCapella",
|
||||
"HistoricalSummary",
|
||||
"LightClientBootstrapCapella",
|
||||
"LightClientFinalityUpdateCapella",
|
||||
"LightClientHeaderCapella",
|
||||
"LightClientOptimisticUpdateCapella",
|
||||
"LightClientUpdateCapella",
|
||||
"SignedBLSToExecutionChange",
|
||||
"SignedBeaconBlockCapella",
|
||||
"SignedBlindedBeaconBlockCapella",
|
||||
@@ -127,6 +137,11 @@ ssz_deneb_objs = [
|
||||
"BlobSidecar",
|
||||
"BlobSidecars",
|
||||
"BuilderBidDeneb",
|
||||
"LightClientBootstrapDeneb",
|
||||
"LightClientFinalityUpdateDeneb",
|
||||
"LightClientHeaderDeneb",
|
||||
"LightClientOptimisticUpdateDeneb",
|
||||
"LightClientUpdateDeneb",
|
||||
"SignedBeaconBlockContentsDeneb",
|
||||
"SignedBeaconBlockDeneb",
|
||||
"SignedBlindedBeaconBlockDeneb",
|
||||
@@ -136,7 +151,8 @@ ssz_electra_objs = [
|
||||
"AggregateAttestationAndProofElectra",
|
||||
"AttestationElectra",
|
||||
"AttesterSlashingElectra",
|
||||
"BeaconBlockElectra",
|
||||
"BeaconBlockBodyElectra",
|
||||
"BeaconBlockContentsElectra",
|
||||
"BeaconBlockElectra",
|
||||
"BeaconStateElectra",
|
||||
"BlindedBeaconBlockBodyElectra",
|
||||
@@ -333,6 +349,7 @@ ssz_proto_files(
|
||||
"beacon_block.proto",
|
||||
"beacon_state.proto",
|
||||
"blobs.proto",
|
||||
"light_client.proto",
|
||||
"sync_committee.proto",
|
||||
"withdrawals.proto",
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: bb838fc0c2dfdadd4a8274dd1b438b1051f7b84d7c8e7470900621284dba8f43
|
||||
// Hash: 18a07a11eb3d1daaafe0b6b1ac8934e9333ea6eceed7d5ef30166b9c2fb50d39
|
||||
package eth
|
||||
|
||||
import (
|
||||
@@ -1747,6 +1747,651 @@ func (s *SyncAggregatorSelectionData) HashTreeRootWith(hh *ssz.Hasher) (err erro
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientHeaderAltair object
|
||||
func (l *LightClientHeaderAltair) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientHeaderAltair object to a target array
|
||||
func (l *LightClientHeaderAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if l.Beacon == nil {
|
||||
l.Beacon = new(BeaconBlockHeader)
|
||||
}
|
||||
if dst, err = l.Beacon.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientHeaderAltair object
|
||||
func (l *LightClientHeaderAltair) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 112 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if l.Beacon == nil {
|
||||
l.Beacon = new(BeaconBlockHeader)
|
||||
}
|
||||
if err = l.Beacon.UnmarshalSSZ(buf[0:112]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientHeaderAltair object
|
||||
func (l *LightClientHeaderAltair) SizeSSZ() (size int) {
|
||||
size = 112
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientHeaderAltair object
|
||||
func (l *LightClientHeaderAltair) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientHeaderAltair object with a hasher
|
||||
func (l *LightClientHeaderAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if err = l.Beacon.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientBootstrapAltair object
|
||||
func (l *LightClientBootstrapAltair) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientBootstrapAltair object to a target array
|
||||
func (l *LightClientBootstrapAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
|
||||
// Field (0) 'Header'
|
||||
if l.Header == nil {
|
||||
l.Header = new(LightClientHeaderAltair)
|
||||
}
|
||||
if dst, err = l.Header.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if l.CurrentSyncCommittee == nil {
|
||||
l.CurrentSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if dst, err = l.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
if size := len(l.CurrentSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if size := len(l.CurrentSyncCommitteeBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.CurrentSyncCommitteeBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.CurrentSyncCommitteeBranch[ii]...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientBootstrapAltair object
|
||||
func (l *LightClientBootstrapAltair) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 24896 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
// Field (0) 'Header'
|
||||
if l.Header == nil {
|
||||
l.Header = new(LightClientHeaderAltair)
|
||||
}
|
||||
if err = l.Header.UnmarshalSSZ(buf[0:112]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if l.CurrentSyncCommittee == nil {
|
||||
l.CurrentSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if err = l.CurrentSyncCommittee.UnmarshalSSZ(buf[112:24736]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
l.CurrentSyncCommitteeBranch = make([][]byte, 5)
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if cap(l.CurrentSyncCommitteeBranch[ii]) == 0 {
|
||||
l.CurrentSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24736:24896][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.CurrentSyncCommitteeBranch[ii] = append(l.CurrentSyncCommitteeBranch[ii], buf[24736:24896][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientBootstrapAltair object
|
||||
func (l *LightClientBootstrapAltair) SizeSSZ() (size int) {
|
||||
size = 24896
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientBootstrapAltair object
|
||||
func (l *LightClientBootstrapAltair) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientBootstrapAltair object with a hasher
|
||||
func (l *LightClientBootstrapAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Header'
|
||||
if err = l.Header.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if err = l.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
{
|
||||
if size := len(l.CurrentSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.CurrentSyncCommitteeBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientUpdateAltair object
|
||||
func (l *LightClientUpdateAltair) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientUpdateAltair object to a target array
|
||||
func (l *LightClientUpdateAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if l.NextSyncCommittee == nil {
|
||||
l.NextSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if dst, err = l.NextSyncCommittee.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
if size := len(l.NextSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if size := len(l.NextSyncCommitteeBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.NextSyncCommitteeBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.NextSyncCommitteeBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if size := len(l.FinalityBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.FinalityBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientUpdateAltair object
|
||||
func (l *LightClientUpdateAltair) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 25368 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf[0:112]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if l.NextSyncCommittee == nil {
|
||||
l.NextSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if err = l.NextSyncCommittee.UnmarshalSSZ(buf[112:24736]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
l.NextSyncCommitteeBranch = make([][]byte, 5)
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if cap(l.NextSyncCommitteeBranch[ii]) == 0 {
|
||||
l.NextSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24736:24896][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.NextSyncCommitteeBranch[ii] = append(l.NextSyncCommitteeBranch[ii], buf[24736:24896][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if err = l.FinalizedHeader.UnmarshalSSZ(buf[24896:25008]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
l.FinalityBranch = make([][]byte, 6)
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if cap(l.FinalityBranch[ii]) == 0 {
|
||||
l.FinalityBranch[ii] = make([]byte, 0, len(buf[25008:25200][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[25008:25200][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[25200:25360]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[25360:25368]))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientUpdateAltair object
|
||||
func (l *LightClientUpdateAltair) SizeSSZ() (size int) {
|
||||
size = 25368
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientUpdateAltair object
|
||||
func (l *LightClientUpdateAltair) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientUpdateAltair object with a hasher
|
||||
func (l *LightClientUpdateAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if err = l.NextSyncCommittee.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
{
|
||||
if size := len(l.NextSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.NextSyncCommitteeBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
{
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.FinalityBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientFinalityUpdateAltair object
|
||||
func (l *LightClientFinalityUpdateAltair) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientFinalityUpdateAltair object to a target array
|
||||
func (l *LightClientFinalityUpdateAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if size := len(l.FinalityBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.FinalityBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientFinalityUpdateAltair object
|
||||
func (l *LightClientFinalityUpdateAltair) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 584 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf[0:112]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if err = l.FinalizedHeader.UnmarshalSSZ(buf[112:224]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
l.FinalityBranch = make([][]byte, 6)
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if cap(l.FinalityBranch[ii]) == 0 {
|
||||
l.FinalityBranch[ii] = make([]byte, 0, len(buf[224:416][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[224:416][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[416:576]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[576:584]))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientFinalityUpdateAltair object
|
||||
func (l *LightClientFinalityUpdateAltair) SizeSSZ() (size int) {
|
||||
size = 584
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientFinalityUpdateAltair object
|
||||
func (l *LightClientFinalityUpdateAltair) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientFinalityUpdateAltair object with a hasher
|
||||
func (l *LightClientFinalityUpdateAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
{
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.FinalityBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientOptimisticUpdateAltair object
|
||||
func (l *LightClientOptimisticUpdateAltair) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientOptimisticUpdateAltair object to a target array
|
||||
func (l *LightClientOptimisticUpdateAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientOptimisticUpdateAltair object
|
||||
func (l *LightClientOptimisticUpdateAltair) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 280 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderAltair)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf[0:112]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[112:272]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[272:280]))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientOptimisticUpdateAltair object
|
||||
func (l *LightClientOptimisticUpdateAltair) SizeSSZ() (size int) {
|
||||
size = 280
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientOptimisticUpdateAltair object
|
||||
func (l *LightClientOptimisticUpdateAltair) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientOptimisticUpdateAltair object with a hasher
|
||||
func (l *LightClientOptimisticUpdateAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the SyncCommitteeMessage object
|
||||
func (s *SyncCommitteeMessage) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(s)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 693cad07de8560b2681132d912aebb927e668fe15e5cb9f42e8a36bbac6e2c5e
|
||||
// Hash: c6614861443f105e2d5445ca29187cc78c2a929161d0a15b36ce2f0e6517a0ea
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: a5507ef7d71897486989f37eb4dbb19fc2c49e7c47f244291a9f3122c9bfe546
|
||||
// Hash: 6bee0cf7c5707af68be518a221b248ce37edd4b0b1e6fec9703c6152a5107a1d
|
||||
package eth
|
||||
|
||||
import (
|
||||
@@ -2729,6 +2729,877 @@ func (h *HistoricalSummary) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientHeaderCapella object
|
||||
func (l *LightClientHeaderCapella) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientHeaderCapella object to a target array
|
||||
func (l *LightClientHeaderCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(244)
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if l.Beacon == nil {
|
||||
l.Beacon = new(BeaconBlockHeader)
|
||||
}
|
||||
if dst, err = l.Beacon.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Offset (1) 'Execution'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.Execution == nil {
|
||||
l.Execution = new(v1.ExecutionPayloadHeaderCapella)
|
||||
}
|
||||
offset += l.Execution.SizeSSZ()
|
||||
|
||||
// Field (2) 'ExecutionBranch'
|
||||
if size := len(l.ExecutionBranch); size != 4 {
|
||||
err = ssz.ErrVectorLengthFn("--.ExecutionBranch", size, 4)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 4; ii++ {
|
||||
if size := len(l.ExecutionBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.ExecutionBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.ExecutionBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (1) 'Execution'
|
||||
if dst, err = l.Execution.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientHeaderCapella object
|
||||
func (l *LightClientHeaderCapella) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 244 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o1 uint64
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if l.Beacon == nil {
|
||||
l.Beacon = new(BeaconBlockHeader)
|
||||
}
|
||||
if err = l.Beacon.UnmarshalSSZ(buf[0:112]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Offset (1) 'Execution'
|
||||
if o1 = ssz.ReadOffset(buf[112:116]); o1 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o1 != 244 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (2) 'ExecutionBranch'
|
||||
l.ExecutionBranch = make([][]byte, 4)
|
||||
for ii := 0; ii < 4; ii++ {
|
||||
if cap(l.ExecutionBranch[ii]) == 0 {
|
||||
l.ExecutionBranch[ii] = make([]byte, 0, len(buf[116:244][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.ExecutionBranch[ii] = append(l.ExecutionBranch[ii], buf[116:244][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (1) 'Execution'
|
||||
{
|
||||
buf = tail[o1:]
|
||||
if l.Execution == nil {
|
||||
l.Execution = new(v1.ExecutionPayloadHeaderCapella)
|
||||
}
|
||||
if err = l.Execution.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientHeaderCapella object
|
||||
func (l *LightClientHeaderCapella) SizeSSZ() (size int) {
|
||||
size = 244
|
||||
|
||||
// Field (1) 'Execution'
|
||||
if l.Execution == nil {
|
||||
l.Execution = new(v1.ExecutionPayloadHeaderCapella)
|
||||
}
|
||||
size += l.Execution.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientHeaderCapella object
|
||||
func (l *LightClientHeaderCapella) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientHeaderCapella object with a hasher
|
||||
func (l *LightClientHeaderCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if err = l.Beacon.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'Execution'
|
||||
if err = l.Execution.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'ExecutionBranch'
|
||||
{
|
||||
if size := len(l.ExecutionBranch); size != 4 {
|
||||
err = ssz.ErrVectorLengthFn("--.ExecutionBranch", size, 4)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.ExecutionBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientBootstrapCapella object
|
||||
func (l *LightClientBootstrapCapella) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientBootstrapCapella object to a target array
|
||||
func (l *LightClientBootstrapCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(24788)
|
||||
|
||||
// Offset (0) 'Header'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.Header == nil {
|
||||
l.Header = new(LightClientHeaderCapella)
|
||||
}
|
||||
offset += l.Header.SizeSSZ()
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if l.CurrentSyncCommittee == nil {
|
||||
l.CurrentSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if dst, err = l.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
if size := len(l.CurrentSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if size := len(l.CurrentSyncCommitteeBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.CurrentSyncCommitteeBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.CurrentSyncCommitteeBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (0) 'Header'
|
||||
if dst, err = l.Header.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientBootstrapCapella object
|
||||
func (l *LightClientBootstrapCapella) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 24788 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0 uint64
|
||||
|
||||
// Offset (0) 'Header'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 24788 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if l.CurrentSyncCommittee == nil {
|
||||
l.CurrentSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if err = l.CurrentSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
l.CurrentSyncCommitteeBranch = make([][]byte, 5)
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if cap(l.CurrentSyncCommitteeBranch[ii]) == 0 {
|
||||
l.CurrentSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24788][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.CurrentSyncCommitteeBranch[ii] = append(l.CurrentSyncCommitteeBranch[ii], buf[24628:24788][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (0) 'Header'
|
||||
{
|
||||
buf = tail[o0:]
|
||||
if l.Header == nil {
|
||||
l.Header = new(LightClientHeaderCapella)
|
||||
}
|
||||
if err = l.Header.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientBootstrapCapella object
|
||||
func (l *LightClientBootstrapCapella) SizeSSZ() (size int) {
|
||||
size = 24788
|
||||
|
||||
// Field (0) 'Header'
|
||||
if l.Header == nil {
|
||||
l.Header = new(LightClientHeaderCapella)
|
||||
}
|
||||
size += l.Header.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientBootstrapCapella object
|
||||
func (l *LightClientBootstrapCapella) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientBootstrapCapella object with a hasher
|
||||
func (l *LightClientBootstrapCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Header'
|
||||
if err = l.Header.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if err = l.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
{
|
||||
if size := len(l.CurrentSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.CurrentSyncCommitteeBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientUpdateCapella object
|
||||
func (l *LightClientUpdateCapella) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientUpdateCapella object to a target array
|
||||
func (l *LightClientUpdateCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(25152)
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
offset += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if l.NextSyncCommittee == nil {
|
||||
l.NextSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if dst, err = l.NextSyncCommittee.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
if size := len(l.NextSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if size := len(l.NextSyncCommitteeBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.NextSyncCommitteeBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.NextSyncCommitteeBranch[ii]...)
|
||||
}
|
||||
|
||||
// Offset (3) 'FinalizedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
offset += l.FinalizedHeader.SizeSSZ()
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if size := len(l.FinalityBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.FinalityBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientUpdateCapella object
|
||||
func (l *LightClientUpdateCapella) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 25152 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0, o3 uint64
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 25152 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if l.NextSyncCommittee == nil {
|
||||
l.NextSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if err = l.NextSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
l.NextSyncCommitteeBranch = make([][]byte, 5)
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if cap(l.NextSyncCommitteeBranch[ii]) == 0 {
|
||||
l.NextSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24788][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.NextSyncCommitteeBranch[ii] = append(l.NextSyncCommitteeBranch[ii], buf[24628:24788][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Offset (3) 'FinalizedHeader'
|
||||
if o3 = ssz.ReadOffset(buf[24788:24792]); o3 > size || o0 > o3 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
l.FinalityBranch = make([][]byte, 6)
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if cap(l.FinalityBranch[ii]) == 0 {
|
||||
l.FinalityBranch[ii] = make([]byte, 0, len(buf[24792:24984][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[24792:24984][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[24984:25144]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[25144:25152]))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
{
|
||||
buf = tail[o0:o3]
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
{
|
||||
buf = tail[o3:]
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientUpdateCapella object
|
||||
func (l *LightClientUpdateCapella) SizeSSZ() (size int) {
|
||||
size = 25152
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
size += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
size += l.FinalizedHeader.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientUpdateCapella object
|
||||
func (l *LightClientUpdateCapella) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientUpdateCapella object with a hasher
|
||||
func (l *LightClientUpdateCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if err = l.NextSyncCommittee.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
{
|
||||
if size := len(l.NextSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.NextSyncCommitteeBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
{
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.FinalityBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientFinalityUpdateCapella object
|
||||
func (l *LightClientFinalityUpdateCapella) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientFinalityUpdateCapella object to a target array
|
||||
func (l *LightClientFinalityUpdateCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(368)
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
offset += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Offset (1) 'FinalizedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
offset += l.FinalizedHeader.SizeSSZ()
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if size := len(l.FinalityBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.FinalityBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientFinalityUpdateCapella object
|
||||
func (l *LightClientFinalityUpdateCapella) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 368 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0, o1 uint64
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 368 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Offset (1) 'FinalizedHeader'
|
||||
if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
l.FinalityBranch = make([][]byte, 6)
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if cap(l.FinalityBranch[ii]) == 0 {
|
||||
l.FinalityBranch[ii] = make([]byte, 0, len(buf[8:200][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[8:200][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[200:360]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[360:368]))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
{
|
||||
buf = tail[o0:o1]
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
{
|
||||
buf = tail[o1:]
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientFinalityUpdateCapella object
|
||||
func (l *LightClientFinalityUpdateCapella) SizeSSZ() (size int) {
|
||||
size = 368
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
size += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
size += l.FinalizedHeader.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientFinalityUpdateCapella object
|
||||
func (l *LightClientFinalityUpdateCapella) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientFinalityUpdateCapella object with a hasher
|
||||
func (l *LightClientFinalityUpdateCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
{
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.FinalityBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientOptimisticUpdateCapella object
|
||||
func (l *LightClientOptimisticUpdateCapella) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientOptimisticUpdateCapella object to a target array
|
||||
func (l *LightClientOptimisticUpdateCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(172)
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
offset += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientOptimisticUpdateCapella object
|
||||
func (l *LightClientOptimisticUpdateCapella) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 172 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0 uint64
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 172 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[4:164]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[164:172]))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
{
|
||||
buf = tail[o0:]
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientOptimisticUpdateCapella object
|
||||
func (l *LightClientOptimisticUpdateCapella) SizeSSZ() (size int) {
|
||||
size = 172
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderCapella)
|
||||
}
|
||||
size += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientOptimisticUpdateCapella object
|
||||
func (l *LightClientOptimisticUpdateCapella) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientOptimisticUpdateCapella object with a hasher
|
||||
func (l *LightClientOptimisticUpdateCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the BLSToExecutionChange object
|
||||
func (b *BLSToExecutionChange) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(b)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 4c3e6932bf84838e8de21e5c121c14d03cbccb051c3990d3b924932f531f4d30
|
||||
// Hash: dc56f26fb2603482588d88426187e889583abce2eeb7556ac0dc1ebaa891c455
|
||||
package eth
|
||||
|
||||
import (
|
||||
@@ -3593,3 +3593,874 @@ func (b *BlobIdentifier) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientHeaderDeneb object
|
||||
func (l *LightClientHeaderDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientHeaderDeneb object to a target array
|
||||
func (l *LightClientHeaderDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(244)
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if l.Beacon == nil {
|
||||
l.Beacon = new(BeaconBlockHeader)
|
||||
}
|
||||
if dst, err = l.Beacon.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Offset (1) 'Execution'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.Execution == nil {
|
||||
l.Execution = new(v1.ExecutionPayloadHeaderDeneb)
|
||||
}
|
||||
offset += l.Execution.SizeSSZ()
|
||||
|
||||
// Field (2) 'ExecutionBranch'
|
||||
if size := len(l.ExecutionBranch); size != 4 {
|
||||
err = ssz.ErrVectorLengthFn("--.ExecutionBranch", size, 4)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 4; ii++ {
|
||||
if size := len(l.ExecutionBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.ExecutionBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.ExecutionBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (1) 'Execution'
|
||||
if dst, err = l.Execution.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientHeaderDeneb object
|
||||
func (l *LightClientHeaderDeneb) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 244 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o1 uint64
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if l.Beacon == nil {
|
||||
l.Beacon = new(BeaconBlockHeader)
|
||||
}
|
||||
if err = l.Beacon.UnmarshalSSZ(buf[0:112]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Offset (1) 'Execution'
|
||||
if o1 = ssz.ReadOffset(buf[112:116]); o1 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o1 != 244 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (2) 'ExecutionBranch'
|
||||
l.ExecutionBranch = make([][]byte, 4)
|
||||
for ii := 0; ii < 4; ii++ {
|
||||
if cap(l.ExecutionBranch[ii]) == 0 {
|
||||
l.ExecutionBranch[ii] = make([]byte, 0, len(buf[116:244][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.ExecutionBranch[ii] = append(l.ExecutionBranch[ii], buf[116:244][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (1) 'Execution'
|
||||
{
|
||||
buf = tail[o1:]
|
||||
if l.Execution == nil {
|
||||
l.Execution = new(v1.ExecutionPayloadHeaderDeneb)
|
||||
}
|
||||
if err = l.Execution.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientHeaderDeneb object
|
||||
func (l *LightClientHeaderDeneb) SizeSSZ() (size int) {
|
||||
size = 244
|
||||
|
||||
// Field (1) 'Execution'
|
||||
if l.Execution == nil {
|
||||
l.Execution = new(v1.ExecutionPayloadHeaderDeneb)
|
||||
}
|
||||
size += l.Execution.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientHeaderDeneb object
|
||||
func (l *LightClientHeaderDeneb) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientHeaderDeneb object with a hasher
|
||||
func (l *LightClientHeaderDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Beacon'
|
||||
if err = l.Beacon.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'Execution'
|
||||
if err = l.Execution.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'ExecutionBranch'
|
||||
{
|
||||
if size := len(l.ExecutionBranch); size != 4 {
|
||||
err = ssz.ErrVectorLengthFn("--.ExecutionBranch", size, 4)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.ExecutionBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientBootstrapDeneb object
|
||||
func (l *LightClientBootstrapDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientBootstrapDeneb object to a target array
|
||||
func (l *LightClientBootstrapDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(24788)
|
||||
|
||||
// Offset (0) 'Header'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.Header == nil {
|
||||
l.Header = new(LightClientHeaderDeneb)
|
||||
}
|
||||
offset += l.Header.SizeSSZ()
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if l.CurrentSyncCommittee == nil {
|
||||
l.CurrentSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if dst, err = l.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
if size := len(l.CurrentSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if size := len(l.CurrentSyncCommitteeBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.CurrentSyncCommitteeBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.CurrentSyncCommitteeBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (0) 'Header'
|
||||
if dst, err = l.Header.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientBootstrapDeneb object
|
||||
func (l *LightClientBootstrapDeneb) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 24788 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0 uint64
|
||||
|
||||
// Offset (0) 'Header'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 24788 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if l.CurrentSyncCommittee == nil {
|
||||
l.CurrentSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if err = l.CurrentSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
l.CurrentSyncCommitteeBranch = make([][]byte, 5)
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if cap(l.CurrentSyncCommitteeBranch[ii]) == 0 {
|
||||
l.CurrentSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24788][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.CurrentSyncCommitteeBranch[ii] = append(l.CurrentSyncCommitteeBranch[ii], buf[24628:24788][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (0) 'Header'
|
||||
{
|
||||
buf = tail[o0:]
|
||||
if l.Header == nil {
|
||||
l.Header = new(LightClientHeaderDeneb)
|
||||
}
|
||||
if err = l.Header.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientBootstrapDeneb object
|
||||
func (l *LightClientBootstrapDeneb) SizeSSZ() (size int) {
|
||||
size = 24788
|
||||
|
||||
// Field (0) 'Header'
|
||||
if l.Header == nil {
|
||||
l.Header = new(LightClientHeaderDeneb)
|
||||
}
|
||||
size += l.Header.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientBootstrapDeneb object
|
||||
func (l *LightClientBootstrapDeneb) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientBootstrapDeneb object with a hasher
|
||||
func (l *LightClientBootstrapDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Header'
|
||||
if err = l.Header.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'CurrentSyncCommittee'
|
||||
if err = l.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'CurrentSyncCommitteeBranch'
|
||||
{
|
||||
if size := len(l.CurrentSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.CurrentSyncCommitteeBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientUpdateDeneb object
|
||||
func (l *LightClientUpdateDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientUpdateDeneb object to a target array
|
||||
func (l *LightClientUpdateDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(25152)
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
offset += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if l.NextSyncCommittee == nil {
|
||||
l.NextSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if dst, err = l.NextSyncCommittee.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
if size := len(l.NextSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if size := len(l.NextSyncCommitteeBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.NextSyncCommitteeBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.NextSyncCommitteeBranch[ii]...)
|
||||
}
|
||||
|
||||
// Offset (3) 'FinalizedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
offset += l.FinalizedHeader.SizeSSZ()
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if size := len(l.FinalityBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.FinalityBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientUpdateDeneb object
|
||||
func (l *LightClientUpdateDeneb) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 25152 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0, o3 uint64
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 25152 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if l.NextSyncCommittee == nil {
|
||||
l.NextSyncCommittee = new(SyncCommittee)
|
||||
}
|
||||
if err = l.NextSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
l.NextSyncCommitteeBranch = make([][]byte, 5)
|
||||
for ii := 0; ii < 5; ii++ {
|
||||
if cap(l.NextSyncCommitteeBranch[ii]) == 0 {
|
||||
l.NextSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24788][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.NextSyncCommitteeBranch[ii] = append(l.NextSyncCommitteeBranch[ii], buf[24628:24788][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Offset (3) 'FinalizedHeader'
|
||||
if o3 = ssz.ReadOffset(buf[24788:24792]); o3 > size || o0 > o3 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
l.FinalityBranch = make([][]byte, 6)
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if cap(l.FinalityBranch[ii]) == 0 {
|
||||
l.FinalityBranch[ii] = make([]byte, 0, len(buf[24792:24984][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[24792:24984][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[24984:25144]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[25144:25152]))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
{
|
||||
buf = tail[o0:o3]
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
{
|
||||
buf = tail[o3:]
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientUpdateDeneb object
|
||||
func (l *LightClientUpdateDeneb) SizeSSZ() (size int) {
|
||||
size = 25152
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
size += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
size += l.FinalizedHeader.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientUpdateDeneb object
|
||||
func (l *LightClientUpdateDeneb) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientUpdateDeneb object with a hasher
|
||||
func (l *LightClientUpdateDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'NextSyncCommittee'
|
||||
if err = l.NextSyncCommittee.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'NextSyncCommitteeBranch'
|
||||
{
|
||||
if size := len(l.NextSyncCommitteeBranch); size != 5 {
|
||||
err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.NextSyncCommitteeBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (3) 'FinalizedHeader'
|
||||
if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'FinalityBranch'
|
||||
{
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.FinalityBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (5) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (6) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientFinalityUpdateDeneb object
|
||||
func (l *LightClientFinalityUpdateDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientFinalityUpdateDeneb object to a target array
|
||||
func (l *LightClientFinalityUpdateDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(368)
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
offset += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Offset (1) 'FinalizedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
offset += l.FinalizedHeader.SizeSSZ()
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if size := len(l.FinalityBranch[ii]); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, l.FinalityBranch[ii]...)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientFinalityUpdateDeneb object
|
||||
func (l *LightClientFinalityUpdateDeneb) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 368 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0, o1 uint64
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 368 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Offset (1) 'FinalizedHeader'
|
||||
if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
l.FinalityBranch = make([][]byte, 6)
|
||||
for ii := 0; ii < 6; ii++ {
|
||||
if cap(l.FinalityBranch[ii]) == 0 {
|
||||
l.FinalityBranch[ii] = make([]byte, 0, len(buf[8:200][ii*32:(ii+1)*32]))
|
||||
}
|
||||
l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[8:200][ii*32:(ii+1)*32]...)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[200:360]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[360:368]))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
{
|
||||
buf = tail[o0:o1]
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
{
|
||||
buf = tail[o1:]
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientFinalityUpdateDeneb object
|
||||
func (l *LightClientFinalityUpdateDeneb) SizeSSZ() (size int) {
|
||||
size = 368
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
size += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if l.FinalizedHeader == nil {
|
||||
l.FinalizedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
size += l.FinalizedHeader.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientFinalityUpdateDeneb object
|
||||
func (l *LightClientFinalityUpdateDeneb) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientFinalityUpdateDeneb object with a hasher
|
||||
func (l *LightClientFinalityUpdateDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'FinalizedHeader'
|
||||
if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'FinalityBranch'
|
||||
{
|
||||
if size := len(l.FinalityBranch); size != 6 {
|
||||
err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range l.FinalityBranch {
|
||||
if len(i) != 32 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.Append(i)
|
||||
}
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (3) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (4) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the LightClientOptimisticUpdateDeneb object
|
||||
func (l *LightClientOptimisticUpdateDeneb) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(l)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the LightClientOptimisticUpdateDeneb object to a target array
|
||||
func (l *LightClientOptimisticUpdateDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(172)
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
offset += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the LightClientOptimisticUpdateDeneb object
|
||||
func (l *LightClientOptimisticUpdateDeneb) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 172 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0 uint64
|
||||
|
||||
// Offset (0) 'AttestedHeader'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 172 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if l.SyncAggregate == nil {
|
||||
l.SyncAggregate = new(SyncAggregate)
|
||||
}
|
||||
if err = l.SyncAggregate.UnmarshalSSZ(buf[4:164]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[164:172]))
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
{
|
||||
buf = tail[o0:]
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the LightClientOptimisticUpdateDeneb object
|
||||
func (l *LightClientOptimisticUpdateDeneb) SizeSSZ() (size int) {
|
||||
size = 172
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if l.AttestedHeader == nil {
|
||||
l.AttestedHeader = new(LightClientHeaderDeneb)
|
||||
}
|
||||
size += l.AttestedHeader.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the LightClientOptimisticUpdateDeneb object
|
||||
func (l *LightClientOptimisticUpdateDeneb) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(l)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the LightClientOptimisticUpdateDeneb object with a hasher
|
||||
func (l *LightClientOptimisticUpdateDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'AttestedHeader'
|
||||
if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'SyncAggregate'
|
||||
if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (2) 'SignatureSlot'
|
||||
hh.PutUint64(uint64(l.SignatureSlot))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 6d900c40d922575c27ef51a244f7bf935f56aa440017288a3405a3025d7750a6
|
||||
// Hash: 3a2dbf56ebf4e81fbf961840a4cd2addac9047b17c12bad04e60879df5b69277
|
||||
package eth
|
||||
|
||||
import (
|
||||
@@ -862,6 +862,215 @@ func (s *SignedBeaconBlockContentsElectra) HashTreeRootWith(hh *ssz.Hasher) (err
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the BeaconBlockContentsElectra object
|
||||
func (b *BeaconBlockContentsElectra) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(b)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the BeaconBlockContentsElectra object to a target array
|
||||
func (b *BeaconBlockContentsElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(12)
|
||||
|
||||
// Offset (0) 'Block'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if b.Block == nil {
|
||||
b.Block = new(BeaconBlockElectra)
|
||||
}
|
||||
offset += b.Block.SizeSSZ()
|
||||
|
||||
// Offset (1) 'KzgProofs'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(b.KzgProofs) * 48
|
||||
|
||||
// Offset (2) 'Blobs'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(b.Blobs) * 131072
|
||||
|
||||
// Field (0) 'Block'
|
||||
if dst, err = b.Block.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'KzgProofs'
|
||||
if size := len(b.KzgProofs); size > 4096 {
|
||||
err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < len(b.KzgProofs); ii++ {
|
||||
if size := len(b.KzgProofs[ii]); size != 48 {
|
||||
err = ssz.ErrBytesLengthFn("--.KzgProofs[ii]", size, 48)
|
||||
return
|
||||
}
|
||||
dst = append(dst, b.KzgProofs[ii]...)
|
||||
}
|
||||
|
||||
// Field (2) 'Blobs'
|
||||
if size := len(b.Blobs); size > 4096 {
|
||||
err = ssz.ErrListTooBigFn("--.Blobs", size, 4096)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < len(b.Blobs); ii++ {
|
||||
if size := len(b.Blobs[ii]); size != 131072 {
|
||||
err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072)
|
||||
return
|
||||
}
|
||||
dst = append(dst, b.Blobs[ii]...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the BeaconBlockContentsElectra object
|
||||
func (b *BeaconBlockContentsElectra) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 12 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0, o1, o2 uint64
|
||||
|
||||
// Offset (0) 'Block'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 12 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Offset (1) 'KzgProofs'
|
||||
if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Offset (2) 'Blobs'
|
||||
if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (0) 'Block'
|
||||
{
|
||||
buf = tail[o0:o1]
|
||||
if b.Block == nil {
|
||||
b.Block = new(BeaconBlockElectra)
|
||||
}
|
||||
if err = b.Block.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Field (1) 'KzgProofs'
|
||||
{
|
||||
buf = tail[o1:o2]
|
||||
num, err := ssz.DivideInt2(len(buf), 48, 4096)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.KzgProofs = make([][]byte, num)
|
||||
for ii := 0; ii < num; ii++ {
|
||||
if cap(b.KzgProofs[ii]) == 0 {
|
||||
b.KzgProofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48]))
|
||||
}
|
||||
b.KzgProofs[ii] = append(b.KzgProofs[ii], buf[ii*48:(ii+1)*48]...)
|
||||
}
|
||||
}
|
||||
|
||||
// Field (2) 'Blobs'
|
||||
{
|
||||
buf = tail[o2:]
|
||||
num, err := ssz.DivideInt2(len(buf), 131072, 4096)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Blobs = make([][]byte, num)
|
||||
for ii := 0; ii < num; ii++ {
|
||||
if cap(b.Blobs[ii]) == 0 {
|
||||
b.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072]))
|
||||
}
|
||||
b.Blobs[ii] = append(b.Blobs[ii], buf[ii*131072:(ii+1)*131072]...)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockContentsElectra object
|
||||
func (b *BeaconBlockContentsElectra) SizeSSZ() (size int) {
|
||||
size = 12
|
||||
|
||||
// Field (0) 'Block'
|
||||
if b.Block == nil {
|
||||
b.Block = new(BeaconBlockElectra)
|
||||
}
|
||||
size += b.Block.SizeSSZ()
|
||||
|
||||
// Field (1) 'KzgProofs'
|
||||
size += len(b.KzgProofs) * 48
|
||||
|
||||
// Field (2) 'Blobs'
|
||||
size += len(b.Blobs) * 131072
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the BeaconBlockContentsElectra object
|
||||
func (b *BeaconBlockContentsElectra) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(b)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the BeaconBlockContentsElectra object with a hasher
|
||||
func (b *BeaconBlockContentsElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Block'
|
||||
if err = b.Block.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'KzgProofs'
|
||||
{
|
||||
if size := len(b.KzgProofs); size > 4096 {
|
||||
err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range b.KzgProofs {
|
||||
if len(i) != 48 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.PutBytes(i)
|
||||
}
|
||||
|
||||
numItems := uint64(len(b.KzgProofs))
|
||||
hh.MerkleizeWithMixin(subIndx, numItems, 4096)
|
||||
}
|
||||
|
||||
// Field (2) 'Blobs'
|
||||
{
|
||||
if size := len(b.Blobs); size > 4096 {
|
||||
err = ssz.ErrListTooBigFn("--.Blobs", size, 4096)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range b.Blobs {
|
||||
if len(i) != 131072 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.PutBytes(i)
|
||||
}
|
||||
|
||||
numItems := uint64(len(b.Blobs))
|
||||
hh.MerkleizeWithMixin(subIndx, numItems, 4096)
|
||||
}
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the SignedBeaconBlockElectra object
|
||||
func (s *SignedBeaconBlockElectra) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(s)
|
||||
|
||||
1759
proto/prysm/v1alpha1/light_client.pb.go
generated
Executable file
1759
proto/prysm/v1alpha1/light_client.pb.go
generated
Executable file
File diff suppressed because it is too large
Load Diff
134
proto/prysm/v1alpha1/light_client.proto
Normal file
134
proto/prysm/v1alpha1/light_client.proto
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright 2024 Prysmatic Labs.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
syntax = "proto3";
|
||||
|
||||
package ethereum.eth.v1alpha1;
|
||||
|
||||
import "proto/eth/ext/options.proto";
|
||||
import "proto/prysm/v1alpha1/beacon_block.proto";
|
||||
import "proto/engine/v1/execution_engine.proto";
|
||||
import "proto/prysm/v1alpha1/beacon_state.proto";
|
||||
|
||||
option csharp_namespace = "Ethereum.Eth.V1alpha1";
|
||||
option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v1alpha1;eth";
|
||||
option java_multiple_files = true;
|
||||
option java_outer_classname = "LightClientProto";
|
||||
option java_package = "org.ethereum.eth.v1alpha1";
|
||||
option php_namespace = "Ethereum\\Eth\\v1alpha1";
|
||||
|
||||
message LightClientHeaderAltair {
|
||||
BeaconBlockHeader beacon = 1;
|
||||
}
|
||||
|
||||
message LightClientHeaderCapella {
|
||||
BeaconBlockHeader beacon = 1;
|
||||
ethereum.engine.v1.ExecutionPayloadHeaderCapella execution = 2;
|
||||
repeated bytes execution_branch = 3 [(ethereum.eth.ext.ssz_size) = "4,32"];
|
||||
}
|
||||
|
||||
message LightClientHeaderDeneb {
|
||||
BeaconBlockHeader beacon = 1;
|
||||
ethereum.engine.v1.ExecutionPayloadHeaderDeneb execution = 2;
|
||||
repeated bytes execution_branch = 3 [(ethereum.eth.ext.ssz_size) = "4,32"];
|
||||
}
|
||||
|
||||
message LightClientBootstrapAltair {
|
||||
LightClientHeaderAltair header = 1;
|
||||
SyncCommittee current_sync_committee = 2;
|
||||
repeated bytes current_sync_committee_branch = 3 [(ethereum.eth.ext.ssz_size) = "5,32"];
|
||||
}
|
||||
|
||||
message LightClientBootstrapCapella {
|
||||
LightClientHeaderCapella header = 1;
|
||||
SyncCommittee current_sync_committee = 2;
|
||||
repeated bytes current_sync_committee_branch = 3 [(ethereum.eth.ext.ssz_size) = "5,32"];
|
||||
}
|
||||
|
||||
message LightClientBootstrapDeneb {
|
||||
LightClientHeaderDeneb header = 1;
|
||||
SyncCommittee current_sync_committee = 2;
|
||||
repeated bytes current_sync_committee_branch = 3 [(ethereum.eth.ext.ssz_size) = "5,32"];
|
||||
}
|
||||
|
||||
message LightClientUpdateAltair {
|
||||
LightClientHeaderAltair attested_header = 1;
|
||||
SyncCommittee next_sync_committee = 2;
|
||||
repeated bytes next_sync_committee_branch = 3 [(ethereum.eth.ext.ssz_size) = "5,32"];
|
||||
LightClientHeaderAltair finalized_header = 4;
|
||||
repeated bytes finality_branch = 5 [(ethereum.eth.ext.ssz_size) = "6,32"];
|
||||
SyncAggregate sync_aggregate = 6;
|
||||
uint64 signature_slot = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
|
||||
message LightClientUpdateCapella {
|
||||
LightClientHeaderCapella attested_header = 1;
|
||||
SyncCommittee next_sync_committee = 2;
|
||||
repeated bytes next_sync_committee_branch = 3 [(ethereum.eth.ext.ssz_size) = "5,32"];
|
||||
LightClientHeaderCapella finalized_header = 4;
|
||||
repeated bytes finality_branch = 5 [(ethereum.eth.ext.ssz_size) = "6,32"];
|
||||
SyncAggregate sync_aggregate = 6;
|
||||
uint64 signature_slot = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
|
||||
message LightClientUpdateDeneb {
|
||||
LightClientHeaderDeneb attested_header = 1;
|
||||
SyncCommittee next_sync_committee = 2;
|
||||
repeated bytes next_sync_committee_branch = 3 [(ethereum.eth.ext.ssz_size) = "5,32"];
|
||||
LightClientHeaderDeneb finalized_header = 4;
|
||||
repeated bytes finality_branch = 5 [(ethereum.eth.ext.ssz_size) = "6,32"];
|
||||
SyncAggregate sync_aggregate = 6;
|
||||
uint64 signature_slot = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
|
||||
message LightClientFinalityUpdateAltair {
|
||||
LightClientHeaderAltair attested_header = 1;
|
||||
LightClientHeaderAltair finalized_header = 2;
|
||||
repeated bytes finality_branch = 3 [(ethereum.eth.ext.ssz_size) = "6,32"];
|
||||
SyncAggregate sync_aggregate = 4;
|
||||
uint64 signature_slot = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
|
||||
message LightClientFinalityUpdateCapella {
|
||||
LightClientHeaderCapella attested_header = 1;
|
||||
LightClientHeaderCapella finalized_header = 2;
|
||||
repeated bytes finality_branch = 3 [(ethereum.eth.ext.ssz_size) = "6,32"];
|
||||
SyncAggregate sync_aggregate = 4;
|
||||
uint64 signature_slot = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
|
||||
message LightClientFinalityUpdateDeneb {
|
||||
LightClientHeaderDeneb attested_header = 1;
|
||||
LightClientHeaderDeneb finalized_header = 2;
|
||||
repeated bytes finality_branch = 3 [(ethereum.eth.ext.ssz_size) = "6,32"];
|
||||
SyncAggregate sync_aggregate = 4;
|
||||
uint64 signature_slot = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
|
||||
message LightClientOptimisticUpdateAltair {
|
||||
LightClientHeaderAltair attested_header = 1;
|
||||
SyncAggregate sync_aggregate = 2;
|
||||
uint64 signature_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
|
||||
message LightClientOptimisticUpdateCapella {
|
||||
LightClientHeaderCapella attested_header = 1;
|
||||
SyncAggregate sync_aggregate = 2;
|
||||
uint64 signature_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
|
||||
message LightClientOptimisticUpdateDeneb {
|
||||
LightClientHeaderDeneb attested_header = 1;
|
||||
SyncAggregate sync_aggregate = 2;
|
||||
uint64 signature_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"];
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 4cb7a5705004491db2ef29a5080a4cc56a1b618de948a86f9e5275858b48e6c4
|
||||
// Hash: bfd7d6b556134c3bd236b880245717aa01ae79573b33f2746a08c165ba5dcedb
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 0afa289ce68dc2913d8000d495c6069832f35b66a6c0cf1bb0d1299fcad7047a
|
||||
// Hash: 5797213d138ec1a089f9dae2198cab6f4f829ac0cc1f0bda2633fff544db4e68
|
||||
package eth
|
||||
|
||||
import (
|
||||
@@ -3979,7 +3979,10 @@ func (v *Validator) UnmarshalSSZ(buf []byte) error {
|
||||
v.EffectiveBalance = ssz.UnmarshallUint64(buf[80:88])
|
||||
|
||||
// Field (3) 'Slashed'
|
||||
v.Slashed = ssz.UnmarshalBool(buf[88:89])
|
||||
v.Slashed, err = ssz.DecodeBool(buf[88:89])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (4) 'ActivationEligibilityEpoch'
|
||||
v.ActivationEligibilityEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[89:97]))
|
||||
|
||||
@@ -49,6 +49,7 @@ go_test(
|
||||
"generate_genesis_state_bellatrix_test.go",
|
||||
"generate_genesis_state_test.go",
|
||||
"generate_keys_test.go",
|
||||
"premine-state_test.go",
|
||||
],
|
||||
data = [
|
||||
"keygen_test_vector.yaml",
|
||||
@@ -61,9 +62,12 @@ go_test(
|
||||
"//container/trie:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//time:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||
"@com_github_go_yaml_yaml//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
],
|
||||
|
||||
@@ -155,6 +155,11 @@ func (s *PremineGenesisConfig) empty() (state.BeaconState, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case version.Electra:
|
||||
e, err = state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, errUnsupportedVersion
|
||||
}
|
||||
@@ -336,6 +341,8 @@ func (s *PremineGenesisConfig) setFork(g state.BeaconState) error {
|
||||
pv, cv = params.BeaconConfig().BellatrixForkVersion, params.BeaconConfig().CapellaForkVersion
|
||||
case version.Deneb:
|
||||
pv, cv = params.BeaconConfig().CapellaForkVersion, params.BeaconConfig().DenebForkVersion
|
||||
case version.Electra:
|
||||
pv, cv = params.BeaconConfig().ElectraForkVersion, params.BeaconConfig().ElectraForkVersion
|
||||
default:
|
||||
return errUnsupportedVersion
|
||||
}
|
||||
@@ -524,6 +531,39 @@ func (s *PremineGenesisConfig) setLatestBlockHeader(g state.BeaconState) error {
|
||||
BlsToExecutionChanges: make([]*ethpb.SignedBLSToExecutionChange, 0),
|
||||
BlobKzgCommitments: make([][]byte, 0),
|
||||
}
|
||||
case version.Electra:
|
||||
body = ðpb.BeaconBlockBodyElectra{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
},
|
||||
Graffiti: make([]byte, 32),
|
||||
SyncAggregate: ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8),
|
||||
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
},
|
||||
ExecutionPayload: &enginev1.ExecutionPayloadElectra{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, 32),
|
||||
ReceiptsRoot: make([]byte, 32),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, 32),
|
||||
ExtraData: make([]byte, 0),
|
||||
BaseFeePerGas: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
Transactions: make([][]byte, 0),
|
||||
Withdrawals: make([]*enginev1.Withdrawal, 0),
|
||||
},
|
||||
BlsToExecutionChanges: make([]*ethpb.SignedBLSToExecutionChange, 0),
|
||||
BlobKzgCommitments: make([][]byte, 0),
|
||||
ExecutionRequests: &enginev1.ExecutionRequests{
|
||||
Deposits: make([]*enginev1.DepositRequest, 0),
|
||||
Withdrawals: make([]*enginev1.WithdrawalRequest, 0),
|
||||
Consolidations: make([]*enginev1.ConsolidationRequest, 0),
|
||||
},
|
||||
}
|
||||
default:
|
||||
return errUnsupportedVersion
|
||||
}
|
||||
@@ -640,6 +680,38 @@ func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case version.Electra:
|
||||
payload := &enginev1.ExecutionPayloadElectra{
|
||||
ParentHash: gb.ParentHash().Bytes(),
|
||||
FeeRecipient: gb.Coinbase().Bytes(),
|
||||
StateRoot: gb.Root().Bytes(),
|
||||
ReceiptsRoot: gb.ReceiptHash().Bytes(),
|
||||
LogsBloom: gb.Bloom().Bytes(),
|
||||
PrevRandao: params.BeaconConfig().ZeroHash[:],
|
||||
BlockNumber: gb.NumberU64(),
|
||||
GasLimit: gb.GasLimit(),
|
||||
GasUsed: gb.GasUsed(),
|
||||
Timestamp: gb.Time(),
|
||||
ExtraData: gb.Extra()[:32],
|
||||
BaseFeePerGas: bytesutil.PadTo(bytesutil.ReverseByteOrder(gb.BaseFee().Bytes()), fieldparams.RootLength),
|
||||
BlockHash: gb.Hash().Bytes(),
|
||||
Transactions: make([][]byte, 0),
|
||||
Withdrawals: make([]*enginev1.Withdrawal, 0),
|
||||
ExcessBlobGas: *gb.ExcessBlobGas(),
|
||||
BlobGasUsed: *gb.BlobGasUsed(),
|
||||
}
|
||||
wep, err := blocks.WrappedExecutionPayloadElectra(payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eph, err := blocks.PayloadToHeaderElectra(wep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ed, err = blocks.WrappedExecutionPayloadHeaderElectra(eph)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errUnsupportedVersion
|
||||
}
|
||||
|
||||
26
runtime/interop/premine-state_test.go
Normal file
26
runtime/interop/premine-state_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package interop
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/time"
|
||||
)
|
||||
|
||||
func TestPremineGenesis_Electra(t *testing.T) {
|
||||
one := uint64(1)
|
||||
|
||||
genesis := types.NewBlockWithHeader(&types.Header{
|
||||
Time: uint64(time.Now().Unix()),
|
||||
Extra: make([]byte, 32),
|
||||
BaseFee: big.NewInt(1),
|
||||
ExcessBlobGas: &one,
|
||||
BlobGasUsed: &one,
|
||||
})
|
||||
_, err := NewPreminedGenesis(context.Background(), genesis.Time(), 10, 10, version.Electra, genesis)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -43,6 +43,7 @@ go_library(
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
@@ -51,6 +52,7 @@ go_library(
|
||||
"//crypto/hash:go_default_library",
|
||||
"//crypto/rand:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//network/forks:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
|
||||
@@ -4,14 +4,20 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||
v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
@@ -21,7 +27,7 @@ type TestLightClient struct {
|
||||
State state.BeaconState
|
||||
Block interfaces.ReadOnlySignedBeaconBlock
|
||||
AttestedState state.BeaconState
|
||||
AttestedHeader *ethpb.BeaconBlockHeader
|
||||
AttestedBlock interfaces.ReadOnlySignedBeaconBlock
|
||||
FinalizedBlock interfaces.ReadOnlySignedBeaconBlock
|
||||
}
|
||||
|
||||
@@ -39,6 +45,19 @@ func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient {
|
||||
err = attestedState.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockCapella())
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.SetSlot(1)
|
||||
finalizedHeader, err := finalizedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
finalizedRoot, err := finalizedHeader.Header.HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: params.BeaconConfig().CapellaForkEpoch - 10,
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
parent := NewBeaconBlockCapella()
|
||||
parent.Block.Slot = slot
|
||||
|
||||
@@ -120,9 +139,122 @@ func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient {
|
||||
|
||||
l.State = state
|
||||
l.AttestedState = attestedState
|
||||
l.AttestedHeader = attestedHeader
|
||||
l.AttestedBlock = signedParent
|
||||
l.Block = signedBlock
|
||||
l.Ctx = ctx
|
||||
l.FinalizedBlock = finalizedBlock
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *TestLightClient) SetupTestCapellaFinalizedBlockAltair(blinded bool) *TestLightClient {
|
||||
ctx := context.Background()
|
||||
|
||||
slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1)
|
||||
|
||||
attestedState, err := NewBeaconStateCapella()
|
||||
require.NoError(l.T, err)
|
||||
err = attestedState.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockAltair())
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.SetSlot(1)
|
||||
finalizedHeader, err := finalizedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
finalizedRoot, err := finalizedHeader.Header.HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: params.BeaconConfig().AltairForkEpoch - 10,
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
parent := NewBeaconBlockCapella()
|
||||
parent.Block.Slot = slot
|
||||
|
||||
signedParent, err := blocks.NewSignedBeaconBlock(parent)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
parentHeader, err := signedParent.Header()
|
||||
require.NoError(l.T, err)
|
||||
attestedHeader := parentHeader.Header
|
||||
|
||||
err = attestedState.SetLatestBlockHeader(attestedHeader)
|
||||
require.NoError(l.T, err)
|
||||
attestedStateRoot, err := attestedState.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
parent.Block.StateRoot = attestedStateRoot[:]
|
||||
signedParent, err = blocks.NewSignedBeaconBlock(parent)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
state, err := NewBeaconStateCapella()
|
||||
require.NoError(l.T, err)
|
||||
err = state.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
parentRoot, err := signedParent.Block().HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
var signedBlock interfaces.SignedBeaconBlock
|
||||
if blinded {
|
||||
block := NewBlindedBeaconBlockCapella()
|
||||
block.Block.Slot = slot
|
||||
block.Block.ParentRoot = parentRoot[:]
|
||||
|
||||
for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ {
|
||||
block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
|
||||
}
|
||||
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
h, err := signedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
err = state.SetLatestBlockHeader(h.Header)
|
||||
require.NoError(l.T, err)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
block.Block.StateRoot = stateRoot[:]
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
} else {
|
||||
block := NewBeaconBlockCapella()
|
||||
block.Block.Slot = slot
|
||||
block.Block.ParentRoot = parentRoot[:]
|
||||
|
||||
for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ {
|
||||
block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
|
||||
}
|
||||
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
h, err := signedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
err = state.SetLatestBlockHeader(h.Header)
|
||||
require.NoError(l.T, err)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
block.Block.StateRoot = stateRoot[:]
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
|
||||
l.State = state
|
||||
l.AttestedState = attestedState
|
||||
l.AttestedBlock = signedParent
|
||||
l.Block = signedBlock
|
||||
l.Ctx = ctx
|
||||
l.FinalizedBlock = finalizedBlock
|
||||
|
||||
return l
|
||||
}
|
||||
@@ -137,6 +269,19 @@ func (l *TestLightClient) SetupTestAltair() *TestLightClient {
|
||||
err = attestedState.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockAltair())
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.SetSlot(1)
|
||||
finalizedHeader, err := finalizedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
finalizedRoot, err := finalizedHeader.Header.HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: params.BeaconConfig().AltairForkEpoch - 10,
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
parent := NewBeaconBlockAltair()
|
||||
parent.Block.Slot = slot
|
||||
|
||||
@@ -191,9 +336,10 @@ func (l *TestLightClient) SetupTestAltair() *TestLightClient {
|
||||
|
||||
l.State = state
|
||||
l.AttestedState = attestedState
|
||||
l.AttestedHeader = attestedHeader
|
||||
l.Block = signedBlock
|
||||
l.Ctx = ctx
|
||||
l.FinalizedBlock = finalizedBlock
|
||||
l.AttestedBlock = signedParent
|
||||
|
||||
return l
|
||||
}
|
||||
@@ -208,6 +354,19 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient {
|
||||
err = attestedState.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockDeneb())
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.SetSlot(1)
|
||||
finalizedHeader, err := finalizedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
finalizedRoot, err := finalizedHeader.Header.HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: params.BeaconConfig().DenebForkEpoch - 10,
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
parent := NewBeaconBlockDeneb()
|
||||
parent.Block.Slot = slot
|
||||
|
||||
@@ -289,9 +448,234 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient {
|
||||
|
||||
l.State = state
|
||||
l.AttestedState = attestedState
|
||||
l.AttestedHeader = attestedHeader
|
||||
l.AttestedBlock = signedParent
|
||||
l.Block = signedBlock
|
||||
l.Ctx = ctx
|
||||
l.FinalizedBlock = finalizedBlock
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *TestLightClient) SetupTestElectra(blinded bool) *TestLightClient {
|
||||
ctx := context.Background()
|
||||
|
||||
slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1)
|
||||
|
||||
attestedState, err := NewBeaconStateElectra()
|
||||
require.NoError(l.T, err)
|
||||
err = attestedState.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockElectra())
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.SetSlot(1)
|
||||
finalizedHeader, err := finalizedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
finalizedRoot, err := finalizedHeader.Header.HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: params.BeaconConfig().ElectraForkEpoch - 10,
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
parent := NewBeaconBlockElectra()
|
||||
parent.Block.Slot = slot
|
||||
|
||||
signedParent, err := blocks.NewSignedBeaconBlock(parent)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
parentHeader, err := signedParent.Header()
|
||||
require.NoError(l.T, err)
|
||||
attestedHeader := parentHeader.Header
|
||||
|
||||
err = attestedState.SetLatestBlockHeader(attestedHeader)
|
||||
require.NoError(l.T, err)
|
||||
attestedStateRoot, err := attestedState.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
parent.Block.StateRoot = attestedStateRoot[:]
|
||||
signedParent, err = blocks.NewSignedBeaconBlock(parent)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
state, err := NewBeaconStateElectra()
|
||||
require.NoError(l.T, err)
|
||||
err = state.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
parentRoot, err := signedParent.Block().HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
var signedBlock interfaces.SignedBeaconBlock
|
||||
if blinded {
|
||||
block := NewBlindedBeaconBlockElectra()
|
||||
block.Message.Slot = slot
|
||||
block.Message.ParentRoot = parentRoot[:]
|
||||
|
||||
for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ {
|
||||
block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
|
||||
}
|
||||
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
h, err := signedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
err = state.SetLatestBlockHeader(h.Header)
|
||||
require.NoError(l.T, err)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
block.Message.StateRoot = stateRoot[:]
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
} else {
|
||||
block := NewBeaconBlockElectra()
|
||||
block.Block.Slot = slot
|
||||
block.Block.ParentRoot = parentRoot[:]
|
||||
|
||||
for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ {
|
||||
block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
|
||||
}
|
||||
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
h, err := signedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
err = state.SetLatestBlockHeader(h.Header)
|
||||
require.NoError(l.T, err)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
block.Block.StateRoot = stateRoot[:]
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
|
||||
l.State = state
|
||||
l.AttestedState = attestedState
|
||||
l.AttestedBlock = signedParent
|
||||
l.Block = signedBlock
|
||||
l.Ctx = ctx
|
||||
l.FinalizedBlock = finalizedBlock
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *TestLightClient) SetupTestDenebFinalizedBlockCapella(blinded bool) *TestLightClient {
|
||||
ctx := context.Background()
|
||||
|
||||
slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1)
|
||||
|
||||
attestedState, err := NewBeaconStateDeneb()
|
||||
require.NoError(l.T, err)
|
||||
err = attestedState.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockCapella())
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.SetSlot(1)
|
||||
finalizedHeader, err := finalizedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
finalizedRoot, err := finalizedHeader.Header.HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: params.BeaconConfig().CapellaForkEpoch - 10,
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
parent := NewBeaconBlockDeneb()
|
||||
parent.Block.Slot = slot
|
||||
|
||||
signedParent, err := blocks.NewSignedBeaconBlock(parent)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
parentHeader, err := signedParent.Header()
|
||||
require.NoError(l.T, err)
|
||||
attestedHeader := parentHeader.Header
|
||||
|
||||
err = attestedState.SetLatestBlockHeader(attestedHeader)
|
||||
require.NoError(l.T, err)
|
||||
attestedStateRoot, err := attestedState.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
parent.Block.StateRoot = attestedStateRoot[:]
|
||||
signedParent, err = blocks.NewSignedBeaconBlock(parent)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
state, err := NewBeaconStateDeneb()
|
||||
require.NoError(l.T, err)
|
||||
err = state.SetSlot(slot)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
parentRoot, err := signedParent.Block().HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
var signedBlock interfaces.SignedBeaconBlock
|
||||
if blinded {
|
||||
block := NewBlindedBeaconBlockDeneb()
|
||||
block.Message.Slot = slot
|
||||
block.Message.ParentRoot = parentRoot[:]
|
||||
|
||||
for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ {
|
||||
block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
|
||||
}
|
||||
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
h, err := signedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
err = state.SetLatestBlockHeader(h.Header)
|
||||
require.NoError(l.T, err)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
block.Message.StateRoot = stateRoot[:]
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
} else {
|
||||
block := NewBeaconBlockDeneb()
|
||||
block.Block.Slot = slot
|
||||
block.Block.ParentRoot = parentRoot[:]
|
||||
|
||||
for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ {
|
||||
block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
|
||||
}
|
||||
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
h, err := signedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
err = state.SetLatestBlockHeader(h.Header)
|
||||
require.NoError(l.T, err)
|
||||
stateRoot, err := state.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// get a new signed block so the root is updated with the new state root
|
||||
block.Block.StateRoot = stateRoot[:]
|
||||
signedBlock, err = blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
|
||||
l.State = state
|
||||
l.AttestedState = attestedState
|
||||
l.AttestedBlock = signedParent
|
||||
l.Block = signedBlock
|
||||
l.Ctx = ctx
|
||||
l.FinalizedBlock = finalizedBlock
|
||||
|
||||
return l
|
||||
}
|
||||
@@ -299,14 +683,124 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient {
|
||||
func (l *TestLightClient) CheckAttestedHeader(container *ethpbv2.LightClientHeaderContainer) {
|
||||
updateAttestedHeaderBeacon, err := container.GetBeacon()
|
||||
require.NoError(l.T, err)
|
||||
require.Equal(l.T, l.AttestedHeader.Slot, updateAttestedHeaderBeacon.Slot, "Attested header slot is not equal")
|
||||
require.Equal(l.T, l.AttestedHeader.ProposerIndex, updateAttestedHeaderBeacon.ProposerIndex, "Attested header proposer index is not equal")
|
||||
require.DeepSSZEqual(l.T, l.AttestedHeader.ParentRoot, updateAttestedHeaderBeacon.ParentRoot, "Attested header parent root is not equal")
|
||||
require.DeepSSZEqual(l.T, l.AttestedHeader.BodyRoot, updateAttestedHeaderBeacon.BodyRoot, "Attested header body root is not equal")
|
||||
testAttestedHeader, err := l.AttestedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
require.Equal(l.T, l.AttestedBlock.Block().Slot(), updateAttestedHeaderBeacon.Slot, "Attested block slot is not equal")
|
||||
require.Equal(l.T, testAttestedHeader.Header.ProposerIndex, updateAttestedHeaderBeacon.ProposerIndex, "Attested block proposer index is not equal")
|
||||
require.DeepSSZEqual(l.T, testAttestedHeader.Header.ParentRoot, updateAttestedHeaderBeacon.ParentRoot, "Attested block parent root is not equal")
|
||||
require.DeepSSZEqual(l.T, testAttestedHeader.Header.BodyRoot, updateAttestedHeaderBeacon.BodyRoot, "Attested block body root is not equal")
|
||||
|
||||
attestedStateRoot, err := l.AttestedState.HashTreeRoot(l.Ctx)
|
||||
require.NoError(l.T, err)
|
||||
require.DeepSSZEqual(l.T, attestedStateRoot[:], updateAttestedHeaderBeacon.StateRoot, "Attested header state root is not equal")
|
||||
require.DeepSSZEqual(l.T, attestedStateRoot[:], updateAttestedHeaderBeacon.StateRoot, "Attested block state root is not equal")
|
||||
|
||||
if l.AttestedBlock.Version() == version.Capella {
|
||||
payloadInterface, err := l.AttestedBlock.Block().Body().Execution()
|
||||
require.NoError(l.T, err)
|
||||
transactionsRoot, err := payloadInterface.TransactionsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
transactions, err := payloadInterface.Transactions()
|
||||
require.NoError(l.T, err)
|
||||
transactionsRootArray, err := ssz.TransactionsRoot(transactions)
|
||||
require.NoError(l.T, err)
|
||||
transactionsRoot = transactionsRootArray[:]
|
||||
} else {
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
withdrawalsRoot, err := payloadInterface.WithdrawalsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
withdrawals, err := payloadInterface.Withdrawals()
|
||||
require.NoError(l.T, err)
|
||||
withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
require.NoError(l.T, err)
|
||||
withdrawalsRoot = withdrawalsRootArray[:]
|
||||
} else {
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
execution := &v11.ExecutionPayloadHeaderCapella{
|
||||
ParentHash: payloadInterface.ParentHash(),
|
||||
FeeRecipient: payloadInterface.FeeRecipient(),
|
||||
StateRoot: payloadInterface.StateRoot(),
|
||||
ReceiptsRoot: payloadInterface.ReceiptsRoot(),
|
||||
LogsBloom: payloadInterface.LogsBloom(),
|
||||
PrevRandao: payloadInterface.PrevRandao(),
|
||||
BlockNumber: payloadInterface.BlockNumber(),
|
||||
GasLimit: payloadInterface.GasLimit(),
|
||||
GasUsed: payloadInterface.GasUsed(),
|
||||
Timestamp: payloadInterface.Timestamp(),
|
||||
ExtraData: payloadInterface.ExtraData(),
|
||||
BaseFeePerGas: payloadInterface.BaseFeePerGas(),
|
||||
BlockHash: payloadInterface.BlockHash(),
|
||||
TransactionsRoot: transactionsRoot,
|
||||
WithdrawalsRoot: withdrawalsRoot,
|
||||
}
|
||||
|
||||
updateAttestedHeaderExecution, err := container.GetExecutionHeaderCapella()
|
||||
require.NoError(l.T, err)
|
||||
require.DeepSSZEqual(l.T, execution, updateAttestedHeaderExecution, "Attested Block Execution is not equal")
|
||||
|
||||
executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.AttestedBlock.Block())
|
||||
require.NoError(l.T, err)
|
||||
updateAttestedHeaderExecutionBranch, err := container.GetExecutionBranch()
|
||||
require.NoError(l.T, err)
|
||||
for i, leaf := range updateAttestedHeaderExecutionBranch {
|
||||
require.DeepSSZEqual(l.T, executionPayloadProof[i], leaf, "Leaf is not equal")
|
||||
}
|
||||
}
|
||||
|
||||
if l.AttestedBlock.Version() == version.Deneb {
|
||||
payloadInterface, err := l.AttestedBlock.Block().Body().Execution()
|
||||
require.NoError(l.T, err)
|
||||
transactionsRoot, err := payloadInterface.TransactionsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
transactions, err := payloadInterface.Transactions()
|
||||
require.NoError(l.T, err)
|
||||
transactionsRootArray, err := ssz.TransactionsRoot(transactions)
|
||||
require.NoError(l.T, err)
|
||||
transactionsRoot = transactionsRootArray[:]
|
||||
} else {
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
withdrawalsRoot, err := payloadInterface.WithdrawalsRoot()
|
||||
if errors.Is(err, consensus_types.ErrUnsupportedField) {
|
||||
withdrawals, err := payloadInterface.Withdrawals()
|
||||
require.NoError(l.T, err)
|
||||
withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
require.NoError(l.T, err)
|
||||
withdrawalsRoot = withdrawalsRootArray[:]
|
||||
} else {
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
execution := &v11.ExecutionPayloadHeaderDeneb{
|
||||
ParentHash: payloadInterface.ParentHash(),
|
||||
FeeRecipient: payloadInterface.FeeRecipient(),
|
||||
StateRoot: payloadInterface.StateRoot(),
|
||||
ReceiptsRoot: payloadInterface.ReceiptsRoot(),
|
||||
LogsBloom: payloadInterface.LogsBloom(),
|
||||
PrevRandao: payloadInterface.PrevRandao(),
|
||||
BlockNumber: payloadInterface.BlockNumber(),
|
||||
GasLimit: payloadInterface.GasLimit(),
|
||||
GasUsed: payloadInterface.GasUsed(),
|
||||
Timestamp: payloadInterface.Timestamp(),
|
||||
ExtraData: payloadInterface.ExtraData(),
|
||||
BaseFeePerGas: payloadInterface.BaseFeePerGas(),
|
||||
BlockHash: payloadInterface.BlockHash(),
|
||||
TransactionsRoot: transactionsRoot,
|
||||
WithdrawalsRoot: withdrawalsRoot,
|
||||
}
|
||||
|
||||
updateAttestedHeaderExecution, err := container.GetExecutionHeaderDeneb()
|
||||
require.NoError(l.T, err)
|
||||
require.DeepSSZEqual(l.T, execution, updateAttestedHeaderExecution, "Attested Block Execution is not equal")
|
||||
|
||||
executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.AttestedBlock.Block())
|
||||
require.NoError(l.T, err)
|
||||
updateAttestedHeaderExecutionBranch, err := container.GetExecutionBranch()
|
||||
require.NoError(l.T, err)
|
||||
for i, leaf := range updateAttestedHeaderExecutionBranch {
|
||||
require.DeepSSZEqual(l.T, executionPayloadProof[i], leaf, "Leaf is not equal")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *TestLightClient) CheckSyncAggregate(sa *ethpbv1.SyncAggregate) {
|
||||
|
||||
@@ -1262,13 +1262,16 @@ func (v *validator) updateValidatorStatusCache(ctx context.Context, pubkeys [][f
|
||||
if len(resp.Statuses) != len(resp.Indices) {
|
||||
return fmt.Errorf("expected %d indices in status, received %d", len(resp.Statuses), len(resp.Indices))
|
||||
}
|
||||
pubkeyToStatus := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus, len(resp.Statuses))
|
||||
for i, s := range resp.Statuses {
|
||||
v.pubkeyToStatus[bytesutil.ToBytes48(resp.PublicKeys[i])] = &validatorStatus{
|
||||
pubkeyToStatus[bytesutil.ToBytes48(resp.PublicKeys[i])] = &validatorStatus{
|
||||
publicKey: resp.PublicKeys[i],
|
||||
status: s,
|
||||
index: resp.Indices[i],
|
||||
}
|
||||
}
|
||||
v.pubkeyToStatus = pubkeyToStatus
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2908,3 +2908,63 @@ func TestValidator_ChangeHost(t *testing.T) {
|
||||
v.ChangeHost()
|
||||
assert.Equal(t, uint64(0), v.currentHostIndex)
|
||||
}
|
||||
|
||||
func TestUpdateValidatorStatusCache(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
pubkeys := [][fieldparams.BLSPubkeyLength]byte{
|
||||
{0x01},
|
||||
{0x02},
|
||||
}
|
||||
statusRequestKeys := [][]byte{
|
||||
pubkeys[0][:],
|
||||
pubkeys[1][:],
|
||||
}
|
||||
|
||||
client := validatormock.NewMockValidatorClient(ctrl)
|
||||
mockResponse := ðpb.MultipleValidatorStatusResponse{
|
||||
PublicKeys: statusRequestKeys,
|
||||
Statuses: []*ethpb.ValidatorStatusResponse{
|
||||
{
|
||||
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||
}, {
|
||||
Status: ethpb.ValidatorStatus_EXITING,
|
||||
}},
|
||||
Indices: []primitives.ValidatorIndex{1, 2},
|
||||
}
|
||||
client.EXPECT().MultipleValidatorStatus(
|
||||
gomock.Any(),
|
||||
gomock.Any()).Return(mockResponse, nil)
|
||||
|
||||
v := &validator{
|
||||
validatorClient: client,
|
||||
beaconNodeHosts: []string{"http://localhost:8080", "http://localhost:8081"},
|
||||
currentHostIndex: 0,
|
||||
pubkeyToStatus: map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus{
|
||||
[fieldparams.BLSPubkeyLength]byte{0x03}: &validatorStatus{ // add non existant key and status to cache, should be fully removed on update
|
||||
publicKey: []byte{0x03},
|
||||
status: ðpb.ValidatorStatusResponse{
|
||||
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||
},
|
||||
index: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := v.updateValidatorStatusCache(ctx, pubkeys)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// make sure the nonexistant key is fully removed
|
||||
_, ok := v.pubkeyToStatus[[fieldparams.BLSPubkeyLength]byte{0x03}]
|
||||
require.Equal(t, false, ok)
|
||||
// make sure we only have the added values
|
||||
assert.Equal(t, 2, len(v.pubkeyToStatus))
|
||||
for i, pk := range pubkeys {
|
||||
status, exists := v.pubkeyToStatus[pk]
|
||||
require.Equal(t, true, exists)
|
||||
require.DeepEqual(t, pk[:], status.publicKey)
|
||||
require.Equal(t, mockResponse.Statuses[i], status.status)
|
||||
require.Equal(t, mockResponse.Indices[i], status.index)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user