mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Remove Beacon API endpoints that were deprecated in Electra (#15962)
* Remove Beacon API endpoints that were deprecated in Electra * changelog <3 * build fix * remove more stuff * fix post-submit e2e and remove structs * list endpoints in the changelog --------- Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
This commit is contained in:
@@ -33,7 +33,6 @@ go_library(
|
||||
"//beacon-chain/rpc/core:go_default_library",
|
||||
"//beacon-chain/rpc/eth/beacon:go_default_library",
|
||||
"//beacon-chain/rpc/eth/blob:go_default_library",
|
||||
"//beacon-chain/rpc/eth/builder:go_default_library",
|
||||
"//beacon-chain/rpc/eth/config:go_default_library",
|
||||
"//beacon-chain/rpc/eth/debug:go_default_library",
|
||||
"//beacon-chain/rpc/eth/events:go_default_library",
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/core"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/beacon"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/blob"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/builder"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/config"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/debug"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/events"
|
||||
@@ -90,7 +89,6 @@ func (s *Service) endpoints(
|
||||
) []endpoint {
|
||||
endpoints := make([]endpoint, 0)
|
||||
endpoints = append(endpoints, s.rewardsEndpoints(blocker, stater, rewardFetcher)...)
|
||||
endpoints = append(endpoints, s.builderEndpoints(stater)...)
|
||||
endpoints = append(endpoints, s.blobEndpoints(blocker)...)
|
||||
endpoints = append(endpoints, s.validatorEndpoints(validatorServer, stater, coreService, rewardFetcher)...)
|
||||
endpoints = append(endpoints, s.nodeEndpoints()...)
|
||||
@@ -160,29 +158,6 @@ func (s *Service) rewardsEndpoints(blocker lookup.Blocker, stater lookup.Stater,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) builderEndpoints(stater lookup.Stater) []endpoint {
|
||||
server := &builder.Server{
|
||||
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||
Stater: stater,
|
||||
}
|
||||
|
||||
const namespace = "builder"
|
||||
return []endpoint{
|
||||
{
|
||||
// Deprecated: use SSE from /eth/v1/events for `Payload Attributes` instead
|
||||
template: "/eth/v1/builder/states/{state_id}/expected_withdrawals",
|
||||
name: namespace + ".ExpectedWithdrawals",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.ExpectedWithdrawals,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) blobEndpoints(blocker lookup.Blocker) []endpoint {
|
||||
server := &blob.Server{
|
||||
Blocker: blocker,
|
||||
@@ -248,17 +223,6 @@ func (s *Service) validatorEndpoints(
|
||||
|
||||
const namespace = "validator"
|
||||
return []endpoint{
|
||||
{
|
||||
// Deprecated: use /eth/v2/validator/aggregate_attestation instead
|
||||
template: "/eth/v1/validator/aggregate_attestation",
|
||||
name: namespace + ".GetAggregateAttestation",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.GetAggregateAttestation,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
template: "/eth/v2/validator/aggregate_attestation",
|
||||
name: namespace + ".GetAggregateAttestationV2",
|
||||
@@ -280,18 +244,6 @@ func (s *Service) validatorEndpoints(
|
||||
handler: server.SubmitContributionAndProofs,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/validator/aggregate_and_proofs instead
|
||||
template: "/eth/v1/validator/aggregate_and_proofs",
|
||||
name: namespace + ".SubmitAggregateAndProofs",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.SubmitAggregateAndProofs,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
template: "/eth/v2/validator/aggregate_and_proofs",
|
||||
name: namespace + ".SubmitAggregateAndProofsV2",
|
||||
@@ -618,30 +570,6 @@ func (s *Service) beaconEndpoints(
|
||||
handler: server.GetRandao,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/blocks instead
|
||||
template: "/eth/v1/beacon/blocks",
|
||||
name: namespace + ".PublishBlock",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.PublishBlock,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/blinded_blocks instead
|
||||
template: "/eth/v1/beacon/blinded_blocks",
|
||||
name: namespace + ".PublishBlindedBlock",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.PublishBlindedBlock,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
template: "/eth/v2/beacon/blocks",
|
||||
name: namespace + ".PublishBlockV2",
|
||||
@@ -674,17 +602,6 @@ func (s *Service) beaconEndpoints(
|
||||
handler: server.GetBlockV2,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/blocks/{block_id}/attestations instead
|
||||
template: "/eth/v1/beacon/blocks/{block_id}/attestations",
|
||||
name: namespace + ".GetBlockAttestations",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.GetBlockAttestations,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
template: "/eth/v2/beacon/blocks/{block_id}/attestations",
|
||||
name: namespace + ".GetBlockAttestationsV2",
|
||||
@@ -715,17 +632,6 @@ func (s *Service) beaconEndpoints(
|
||||
handler: server.GetBlockRoot,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/pool/attestations instead
|
||||
template: "/eth/v1/beacon/pool/attestations",
|
||||
name: namespace + ".ListAttestations",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.ListAttestations,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
template: "/eth/v2/beacon/pool/attestations",
|
||||
name: namespace + ".ListAttestationsV2",
|
||||
@@ -736,17 +642,6 @@ func (s *Service) beaconEndpoints(
|
||||
handler: server.ListAttestationsV2,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
template: "/eth/v1/beacon/pool/attestations",
|
||||
name: namespace + ".SubmitAttestations",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.SubmitAttestations,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
template: "/eth/v2/beacon/pool/attestations",
|
||||
name: namespace + ".SubmitAttestationsV2",
|
||||
@@ -811,17 +706,6 @@ func (s *Service) beaconEndpoints(
|
||||
handler: server.SubmitBLSToExecutionChanges,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
// Deprecated: use /eth/v2/beacon/pool/attester_slashings instead
|
||||
template: "/eth/v1/beacon/pool/attester_slashings",
|
||||
name: namespace + ".GetAttesterSlashings",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.GetAttesterSlashings,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
template: "/eth/v2/beacon/pool/attester_slashings",
|
||||
name: namespace + ".GetAttesterSlashingsV2",
|
||||
@@ -832,17 +716,6 @@ func (s *Service) beaconEndpoints(
|
||||
handler: server.GetAttesterSlashingsV2,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
template: "/eth/v1/beacon/pool/attester_slashings",
|
||||
name: namespace + ".SubmitAttesterSlashings",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.ContentTypeHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.SubmitAttesterSlashings,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
template: "/eth/v2/beacon/pool/attester_slashings",
|
||||
name: namespace + ".SubmitAttesterSlashingsV2",
|
||||
@@ -957,17 +830,6 @@ func (s *Service) beaconEndpoints(
|
||||
handler: server.GetValidatorIdentities,
|
||||
methods: []string{http.MethodPost},
|
||||
},
|
||||
{
|
||||
// Deprecated: no longer needed post Electra
|
||||
template: "/eth/v1/beacon/deposit_snapshot",
|
||||
name: namespace + ".GetDepositSnapshot",
|
||||
middleware: []middleware.Middleware{
|
||||
middleware.AcceptHeaderHandler([]string{api.JsonMediaType}),
|
||||
middleware.AcceptEncodingHeaderHandler(),
|
||||
},
|
||||
handler: server.GetDepositSnapshot,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
template: "/eth/v1/beacon/states/{state_id}/pending_deposits",
|
||||
name: namespace + ".GetPendingDeposits",
|
||||
|
||||
@@ -35,20 +35,14 @@ func Test_endpoints(t *testing.T) {
|
||||
"/eth/v1/beacon/states/{state_id}/proposer_lookahead": {http.MethodGet},
|
||||
"/eth/v1/beacon/headers": {http.MethodGet},
|
||||
"/eth/v1/beacon/headers/{block_id}": {http.MethodGet},
|
||||
"/eth/v1/beacon/blinded_blocks": {http.MethodPost},
|
||||
"/eth/v2/beacon/blinded_blocks": {http.MethodPost},
|
||||
"/eth/v1/beacon/blocks": {http.MethodPost},
|
||||
"/eth/v2/beacon/blocks": {http.MethodPost},
|
||||
"/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},
|
||||
"/eth/v2/beacon/blocks/{block_id}/attestations": {http.MethodGet},
|
||||
"/eth/v1/beacon/blob_sidecars/{block_id}": {http.MethodGet},
|
||||
"/eth/v1/beacon/deposit_snapshot": {http.MethodGet},
|
||||
"/eth/v1/beacon/blinded_blocks/{block_id}": {http.MethodGet},
|
||||
"/eth/v1/beacon/pool/attestations": {http.MethodGet, http.MethodPost},
|
||||
"/eth/v2/beacon/pool/attestations": {http.MethodGet, http.MethodPost},
|
||||
"/eth/v1/beacon/pool/attester_slashings": {http.MethodGet, http.MethodPost},
|
||||
"/eth/v2/beacon/pool/attester_slashings": {http.MethodGet, http.MethodPost},
|
||||
"/eth/v1/beacon/pool/proposer_slashings": {http.MethodGet, http.MethodPost},
|
||||
"/eth/v1/beacon/pool/sync_committees": {http.MethodPost},
|
||||
@@ -64,10 +58,6 @@ func Test_endpoints(t *testing.T) {
|
||||
"/eth/v1/beacon/light_client/optimistic_update": {http.MethodGet},
|
||||
}
|
||||
|
||||
builderRoutes := map[string][]string{
|
||||
"/eth/v1/builder/states/{state_id}/expected_withdrawals": {http.MethodGet},
|
||||
}
|
||||
|
||||
blobRoutes := map[string][]string{
|
||||
"/eth/v1/beacon/blob_sidecars/{block_id}": {http.MethodGet},
|
||||
"/eth/v1/beacon/blobs/{block_id}": {http.MethodGet},
|
||||
@@ -106,9 +96,7 @@ func Test_endpoints(t *testing.T) {
|
||||
"/eth/v1/validator/duties/sync/{epoch}": {http.MethodPost},
|
||||
"/eth/v3/validator/blocks/{slot}": {http.MethodGet},
|
||||
"/eth/v1/validator/attestation_data": {http.MethodGet},
|
||||
"/eth/v1/validator/aggregate_attestation": {http.MethodGet},
|
||||
"/eth/v2/validator/aggregate_attestation": {http.MethodGet},
|
||||
"/eth/v1/validator/aggregate_and_proofs": {http.MethodPost},
|
||||
"/eth/v2/validator/aggregate_and_proofs": {http.MethodPost},
|
||||
"/eth/v1/validator/beacon_committee_subscriptions": {http.MethodPost},
|
||||
"/eth/v1/validator/sync_committee_subscriptions": {http.MethodPost},
|
||||
@@ -182,7 +170,7 @@ func Test_endpoints(t *testing.T) {
|
||||
}
|
||||
expectedRoutes := make(map[string][]string)
|
||||
for _, m := range []map[string][]string{
|
||||
beaconRoutes, builderRoutes, configRoutes, debugRoutes, eventsRoutes,
|
||||
beaconRoutes, configRoutes, debugRoutes, eventsRoutes,
|
||||
nodeRoutes, validatorRoutes, rewardsRoutes, blobRoutes,
|
||||
prysmValidatorRoutes, prysmNodeRoutes, prysmBeaconRoutes,
|
||||
} {
|
||||
|
||||
@@ -20,7 +20,6 @@ go_library(
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/kzg:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/cache/depositsnapshot:go_default_library",
|
||||
"//beacon-chain/core/altair:go_default_library",
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/feed:go_default_library",
|
||||
@@ -86,7 +85,6 @@ go_test(
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/blockchain/kzg:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/cache/depositsnapshot:go_default_library",
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v6/api"
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/structs"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain/kzg"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/cache/depositsnapshot"
|
||||
corehelpers "github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/transition"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/db/filters"
|
||||
@@ -293,35 +292,6 @@ func (s *Server) getBlockResponseBodyJson(ctx context.Context, blk interfaces.Re
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use GetBlockAttestationsV2 instead
|
||||
// GetBlockAttestations retrieves attestation included in requested block.
|
||||
func (s *Server) GetBlockAttestations(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockAttestations")
|
||||
defer span.End()
|
||||
|
||||
blk, isOptimistic, root := s.blockData(ctx, w, r)
|
||||
if blk == nil {
|
||||
return
|
||||
}
|
||||
consensusAtts := blk.Block().Body().Attestations()
|
||||
atts := make([]*structs.Attestation, len(consensusAtts))
|
||||
for i, att := range consensusAtts {
|
||||
a, ok := att.(*eth.Attestation)
|
||||
if ok {
|
||||
atts[i] = structs.AttFromConsensus(a)
|
||||
} else {
|
||||
httputil.HandleError(w, fmt.Sprintf("unable to convert consensus attestations of type %T", att), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
resp := &structs.GetBlockAttestationsResponse{
|
||||
Data: atts,
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
Finalized: s.FinalizationFetcher.IsFinalized(ctx, root),
|
||||
}
|
||||
httputil.WriteJson(w, resp)
|
||||
}
|
||||
|
||||
// GetBlockAttestationsV2 retrieves attestation included in requested block.
|
||||
func (s *Server) GetBlockAttestationsV2(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockAttestationsV2")
|
||||
@@ -396,28 +366,6 @@ func (s *Server) blockData(ctx context.Context, w http.ResponseWriter, r *http.R
|
||||
return blk, isOptimistic, root
|
||||
}
|
||||
|
||||
// Deprecated: use PublishBlindedBlockV2 instead
|
||||
// PublishBlindedBlock instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct
|
||||
// and publish a SignedBeaconBlock by swapping out the transactions_root for the corresponding full list of `transactions`.
|
||||
// The beacon node should broadcast a newly constructed SignedBeaconBlock to the beacon network, to be included in the
|
||||
// beacon chain. The beacon node is not required to validate the signed BeaconBlock, and a successful response (20X)
|
||||
// only indicates that the broadcast has been successful. The beacon node is expected to integrate the new block into
|
||||
// its state, and therefore validate the block internally, however blocks which fail the validation are still broadcast
|
||||
// but a different status code is returned (202). Pre-Bellatrix, this endpoint will accept a SignedBeaconBlock. After
|
||||
// Deneb, this additionally instructs the beacon node to broadcast all given signed blobs.
|
||||
func (s *Server) PublishBlindedBlock(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.PublishBlindedBlock")
|
||||
defer span.End()
|
||||
if shared.IsSyncing(r.Context(), w, s.SyncChecker, s.HeadFetcher, s.TimeFetcher, s.OptimisticModeFetcher) {
|
||||
return
|
||||
}
|
||||
if httputil.IsRequestSsz(r) {
|
||||
s.publishBlindedBlockSSZ(ctx, w, r, false)
|
||||
} else {
|
||||
s.publishBlindedBlock(ctx, w, r, false)
|
||||
}
|
||||
}
|
||||
|
||||
// PublishBlindedBlockV2 instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct and publish a
|
||||
// `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`.
|
||||
// The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network,
|
||||
@@ -627,28 +575,6 @@ func decodeBlindedBellatrixJSON(body []byte) (*eth.GenericSignedBeaconBlock, err
|
||||
)
|
||||
}
|
||||
|
||||
// Deprecated: use PublishBlockV2 instead
|
||||
// PublishBlock instructs the beacon node to broadcast a newly signed beacon block to the beacon network,
|
||||
// to be included in the beacon chain. A success response (20x) indicates that the block
|
||||
// passed gossip validation and was successfully broadcast onto the network.
|
||||
// The beacon node is also expected to integrate the block into state, but may broadcast it
|
||||
// before doing so, so as to aid timely delivery of the block. Should the block fail full
|
||||
// validation, a separate success response code (202) is used to indicate that the block was
|
||||
// successfully broadcast but failed integration. After Deneb, this additionally instructs the
|
||||
// beacon node to broadcast all given signed blobs.
|
||||
func (s *Server) PublishBlock(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.PublishBlock")
|
||||
defer span.End()
|
||||
if shared.IsSyncing(r.Context(), w, s.SyncChecker, s.HeadFetcher, s.TimeFetcher, s.OptimisticModeFetcher) {
|
||||
return
|
||||
}
|
||||
if httputil.IsRequestSsz(r) {
|
||||
s.publishBlockSSZ(ctx, w, r, false)
|
||||
} else {
|
||||
s.publishBlock(ctx, w, r, false)
|
||||
}
|
||||
}
|
||||
|
||||
// PublishBlockV2 instructs the beacon node to broadcast a newly signed beacon block to the beacon network,
|
||||
// to be included in the beacon chain. A success response (20x) indicates that the block
|
||||
// passed gossip validation and was successfully broadcast onto the network.
|
||||
@@ -1589,48 +1515,6 @@ func (s *Server) GetGenesis(w http.ResponseWriter, r *http.Request) {
|
||||
httputil.WriteJson(w, resp)
|
||||
}
|
||||
|
||||
// Deprecated: no longer needed post Electra
|
||||
// GetDepositSnapshot retrieves the EIP-4881 Deposit Tree Snapshot. Either a JSON or,
|
||||
// if the Accept header was added, bytes serialized by SSZ will be returned.
|
||||
func (s *Server) GetDepositSnapshot(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.GetDepositSnapshot")
|
||||
defer span.End()
|
||||
|
||||
eth1data, err := s.BeaconDB.ExecutionChainData(ctx)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not retrieve execution chain data: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if eth1data == nil {
|
||||
httputil.HandleError(w, "Could not retrieve execution chain data: empty Eth1Data", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
snapshot := eth1data.DepositSnapshot
|
||||
if snapshot == nil || len(snapshot.Finalized) == 0 {
|
||||
httputil.HandleError(w, "No finalized snapshot available", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if len(snapshot.Finalized) > depositsnapshot.DepositContractDepth {
|
||||
httputil.HandleError(w, "Retrieved invalid deposit snapshot", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if httputil.RespondWithSsz(r) {
|
||||
sszData, err := snapshot.MarshalSSZ()
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not marshal deposit snapshot into SSZ: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
httputil.WriteSsz(w, sszData)
|
||||
return
|
||||
}
|
||||
httputil.WriteJson(
|
||||
w,
|
||||
&structs.GetDepositSnapshotResponse{
|
||||
Data: structs.DepositSnapshotFromConsensus(snapshot),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Broadcast blob sidecars even if the block of the same slot has been imported.
|
||||
// To ensure safety, we will only broadcast blob sidecars if the header references the same block that was previously seen.
|
||||
// Otherwise, a proposer could get slashed through a different blob sidecar header reference.
|
||||
|
||||
@@ -34,58 +34,6 @@ import (
|
||||
|
||||
const broadcastBLSChangesRateLimit = 128
|
||||
|
||||
// Deprecated: use ListAttestationsV2 instead
|
||||
// ListAttestations retrieves attestations known by the node but
|
||||
// not necessarily incorporated into any block. Allows filtering by committee index or slot.
|
||||
func (s *Server) ListAttestations(w http.ResponseWriter, r *http.Request) {
|
||||
_, span := trace.StartSpan(r.Context(), "beacon.ListAttestations")
|
||||
defer span.End()
|
||||
|
||||
rawSlot, slot, ok := shared.UintFromQuery(w, r, "slot", false)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
rawCommitteeIndex, committeeIndex, ok := shared.UintFromQuery(w, r, "committee_index", false)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var attestations []eth.Att
|
||||
if features.Get().EnableExperimentalAttestationPool {
|
||||
attestations = s.AttestationCache.GetAll()
|
||||
} else {
|
||||
attestations = s.AttestationsPool.AggregatedAttestations()
|
||||
unaggAtts := s.AttestationsPool.UnaggregatedAttestations()
|
||||
attestations = append(attestations, unaggAtts...)
|
||||
}
|
||||
|
||||
filteredAtts := make([]*structs.Attestation, 0, len(attestations))
|
||||
for _, a := range attestations {
|
||||
var includeAttestation bool
|
||||
att, ok := a.(*eth.Attestation)
|
||||
if !ok {
|
||||
httputil.HandleError(w, fmt.Sprintf("Unable to convert attestation of type %T", a), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
includeAttestation = shouldIncludeAttestation(att, rawSlot, slot, rawCommitteeIndex, committeeIndex)
|
||||
if includeAttestation {
|
||||
attStruct := structs.AttFromConsensus(att)
|
||||
filteredAtts = append(filteredAtts, attStruct)
|
||||
}
|
||||
}
|
||||
|
||||
attsData, err := json.Marshal(filteredAtts)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not marshal attestations: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
httputil.WriteJson(w, &structs.ListAttestationsResponse{
|
||||
Data: attsData,
|
||||
})
|
||||
}
|
||||
|
||||
// ListAttestationsV2 retrieves attestations known by the node but
|
||||
// not necessarily incorporated into any block. Allows filtering by committee index or slot.
|
||||
func (s *Server) ListAttestationsV2(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -176,49 +124,6 @@ func shouldIncludeAttestation(
|
||||
return committeeIndexMatch && slotMatch
|
||||
}
|
||||
|
||||
// SubmitAttestations submits an attestation object to node. If the attestation passes all validation
|
||||
// constraints, node MUST publish the attestation on an appropriate subnet.
|
||||
func (s *Server) SubmitAttestations(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.SubmitAttestations")
|
||||
defer span.End()
|
||||
|
||||
var req structs.SubmitAttestationsRequest
|
||||
err := json.NewDecoder(r.Body).Decode(&req.Data)
|
||||
switch {
|
||||
case errors.Is(err, io.EOF):
|
||||
httputil.HandleError(w, "No data submitted", http.StatusBadRequest)
|
||||
return
|
||||
case err != nil:
|
||||
httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
attFailures, failedBroadcasts, err := s.handleAttestations(ctx, req.Data)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if len(attFailures) > 0 {
|
||||
failuresErr := &server.IndexedErrorContainer{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: server.ErrIndexedValidationFail,
|
||||
Failures: attFailures,
|
||||
}
|
||||
httputil.WriteError(w, failuresErr)
|
||||
return
|
||||
}
|
||||
if len(failedBroadcasts) > 0 {
|
||||
failuresErr := &server.IndexedErrorContainer{
|
||||
Code: http.StatusInternalServerError,
|
||||
Message: server.ErrIndexedBroadcastFail,
|
||||
Failures: failedBroadcasts,
|
||||
}
|
||||
httputil.WriteError(w, failuresErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// SubmitAttestationsV2 submits an attestation object to node. If the attestation passes all validation
|
||||
// constraints, node MUST publish the attestation on an appropriate subnet.
|
||||
func (s *Server) SubmitAttestationsV2(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -749,36 +654,6 @@ func (s *Server) ListBLSToExecutionChanges(w http.ResponseWriter, r *http.Reques
|
||||
})
|
||||
}
|
||||
|
||||
// Deprecated: use GetAttesterSlashingsV2 instead
|
||||
// GetAttesterSlashings retrieves attester slashings known by the node but
|
||||
// not necessarily incorporated into any block.
|
||||
func (s *Server) GetAttesterSlashings(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.GetAttesterSlashings")
|
||||
defer span.End()
|
||||
|
||||
headState, err := s.ChainInfoFetcher.HeadStateReadOnly(ctx)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not get head state: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
sourceSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, headState, true /* return unlimited slashings */)
|
||||
slashings := make([]*structs.AttesterSlashing, len(sourceSlashings))
|
||||
for i, slashing := range sourceSlashings {
|
||||
as, ok := slashing.(*eth.AttesterSlashing)
|
||||
if !ok {
|
||||
httputil.HandleError(w, fmt.Sprintf("Unable to convert slashing of type %T", slashing), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
slashings[i] = structs.AttesterSlashingFromConsensus(as)
|
||||
}
|
||||
attBytes, err := json.Marshal(slashings)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, fmt.Sprintf("Failed to marshal slashings: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
httputil.WriteJson(w, &structs.GetAttesterSlashingsResponse{Data: attBytes})
|
||||
}
|
||||
|
||||
// GetAttesterSlashingsV2 retrieves attester slashings known by the node but
|
||||
// not necessarily incorporated into any block, supporting both AttesterSlashing and AttesterSlashingElectra.
|
||||
func (s *Server) GetAttesterSlashingsV2(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -830,31 +705,6 @@ func (s *Server) GetAttesterSlashingsV2(w http.ResponseWriter, r *http.Request)
|
||||
httputil.WriteJson(w, resp)
|
||||
}
|
||||
|
||||
// SubmitAttesterSlashings submits an attester slashing object to node's pool and
|
||||
// if passes validation node MUST broadcast it to network.
|
||||
func (s *Server) SubmitAttesterSlashings(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.SubmitAttesterSlashings")
|
||||
defer span.End()
|
||||
|
||||
var req structs.AttesterSlashing
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
switch {
|
||||
case errors.Is(err, io.EOF):
|
||||
httputil.HandleError(w, "No data submitted", http.StatusBadRequest)
|
||||
return
|
||||
case err != nil:
|
||||
httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
slashing, err := req.ToConsensus()
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not convert request slashing to consensus slashing: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
s.submitAttesterSlashing(w, ctx, slashing)
|
||||
}
|
||||
|
||||
// SubmitAttesterSlashingsV2 submits an attester slashing object to node's pool and
|
||||
// if passes validation node MUST broadcast it to network.
|
||||
func (s *Server) SubmitAttesterSlashingsV2(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"handlers.go",
|
||||
"server.go",
|
||||
],
|
||||
importpath = "github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/builder",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/rpc/lookup:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["handlers_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/rpc/testutil:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -1,132 +0,0 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/structs"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/transition"
|
||||
"github.com/OffchainLabs/prysm/v6/config/params"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v6/network/httputil"
|
||||
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
|
||||
"github.com/OffchainLabs/prysm/v6/time/slots"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Deprecated: use SSE from events for `payload attributes` instead
|
||||
// ExpectedWithdrawals get the withdrawals computed from the specified state, that will be included in the block that gets built on the specified state.
|
||||
func (s *Server) ExpectedWithdrawals(w http.ResponseWriter, r *http.Request) {
|
||||
// Retrieve beacon state
|
||||
stateId := r.PathValue("state_id")
|
||||
if stateId == "" {
|
||||
httputil.WriteError(w, &httputil.DefaultJsonError{
|
||||
Message: "state_id is required in URL params",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
st, err := s.Stater.State(r.Context(), []byte(stateId))
|
||||
if err != nil {
|
||||
httputil.WriteError(w, handleWrapError(err, "could not retrieve state", http.StatusNotFound))
|
||||
return
|
||||
}
|
||||
queryParam := r.URL.Query().Get("proposal_slot")
|
||||
var proposalSlot primitives.Slot
|
||||
if queryParam != "" {
|
||||
pSlot, err := strconv.ParseUint(queryParam, 10, 64)
|
||||
if err != nil {
|
||||
httputil.WriteError(w, handleWrapError(err, "invalid proposal slot value", http.StatusBadRequest))
|
||||
return
|
||||
}
|
||||
proposalSlot = primitives.Slot(pSlot)
|
||||
} else {
|
||||
proposalSlot = st.Slot() + 1
|
||||
}
|
||||
// Perform sanity checks on proposal slot before computing state
|
||||
capellaStart, err := slots.EpochStart(params.BeaconConfig().CapellaForkEpoch)
|
||||
if err != nil {
|
||||
httputil.WriteError(w, handleWrapError(err, "could not calculate Capella start slot", http.StatusInternalServerError))
|
||||
return
|
||||
}
|
||||
if proposalSlot < capellaStart {
|
||||
httputil.WriteError(w, &httputil.DefaultJsonError{
|
||||
Message: "expected withdrawals are not supported before Capella fork",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
if proposalSlot <= st.Slot() {
|
||||
httputil.WriteError(w, &httputil.DefaultJsonError{
|
||||
Message: fmt.Sprintf("proposal slot must be bigger than state slot. proposal slot: %d, state slot: %d", proposalSlot, st.Slot()),
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
lookAheadLimit := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().MaxSeedLookahead)))
|
||||
if st.Slot().Add(lookAheadLimit) <= proposalSlot {
|
||||
httputil.WriteError(w, &httputil.DefaultJsonError{
|
||||
Message: fmt.Sprintf("proposal slot cannot be >= %d slots ahead of state slot", lookAheadLimit),
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
// Get metadata for response
|
||||
isOptimistic, err := s.OptimisticModeFetcher.IsOptimistic(r.Context())
|
||||
if err != nil {
|
||||
httputil.WriteError(w, handleWrapError(err, "could not get optimistic mode info", http.StatusInternalServerError))
|
||||
return
|
||||
}
|
||||
root, err := helpers.BlockRootAtSlot(st, slots.PrevSlot(st.Slot()))
|
||||
if err != nil {
|
||||
httputil.WriteError(w, handleWrapError(err, "could not get block root", http.StatusInternalServerError))
|
||||
return
|
||||
}
|
||||
var blockRoot = [32]byte(root)
|
||||
isFinalized := s.FinalizationFetcher.IsFinalized(r.Context(), blockRoot)
|
||||
// Advance state forward to proposal slot
|
||||
st, err = transition.ProcessSlots(r.Context(), st, proposalSlot)
|
||||
if err != nil {
|
||||
httputil.WriteError(w, &httputil.DefaultJsonError{
|
||||
Message: "could not process slots",
|
||||
Code: http.StatusInternalServerError,
|
||||
})
|
||||
return
|
||||
}
|
||||
withdrawals, _, err := st.ExpectedWithdrawals()
|
||||
if err != nil {
|
||||
httputil.WriteError(w, &httputil.DefaultJsonError{
|
||||
Message: "could not get expected withdrawals",
|
||||
Code: http.StatusInternalServerError,
|
||||
})
|
||||
return
|
||||
}
|
||||
httputil.WriteJson(w, &structs.ExpectedWithdrawalsResponse{
|
||||
ExecutionOptimistic: isOptimistic,
|
||||
Finalized: isFinalized,
|
||||
Data: buildExpectedWithdrawalsData(withdrawals),
|
||||
})
|
||||
}
|
||||
|
||||
func buildExpectedWithdrawalsData(withdrawals []*enginev1.Withdrawal) []*structs.ExpectedWithdrawal {
|
||||
data := make([]*structs.ExpectedWithdrawal, len(withdrawals))
|
||||
for i, withdrawal := range withdrawals {
|
||||
data[i] = &structs.ExpectedWithdrawal{
|
||||
Address: hexutil.Encode(withdrawal.Address),
|
||||
Amount: strconv.FormatUint(withdrawal.Amount, 10),
|
||||
Index: strconv.FormatUint(withdrawal.Index, 10),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(withdrawal.ValidatorIndex), 10),
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func handleWrapError(err error, message string, code int) *httputil.DefaultJsonError {
|
||||
return &httputil.DefaultJsonError{
|
||||
Message: errors.Wrap(err, message).Error(),
|
||||
Code: code,
|
||||
}
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/structs"
|
||||
mock "github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain/testing"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/testutil"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/state"
|
||||
"github.com/OffchainLabs/prysm/v6/config/params"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v6/crypto/bls"
|
||||
"github.com/OffchainLabs/prysm/v6/network/httputil"
|
||||
eth "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v6/testing/assert"
|
||||
"github.com/OffchainLabs/prysm/v6/testing/require"
|
||||
"github.com/OffchainLabs/prysm/v6/testing/util"
|
||||
"github.com/OffchainLabs/prysm/v6/time/slots"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
func TestExpectedWithdrawals_BadRequest(t *testing.T) {
|
||||
st, err := util.NewBeaconStateCapella()
|
||||
slotsAhead := 5000
|
||||
require.NoError(t, err)
|
||||
capellaSlot, err := slots.EpochStart(params.BeaconConfig().CapellaForkEpoch)
|
||||
require.NoError(t, err)
|
||||
currentSlot := capellaSlot + primitives.Slot(slotsAhead)
|
||||
require.NoError(t, st.SetSlot(currentSlot))
|
||||
mockChainService := &mock.ChainService{Optimistic: true}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
path string
|
||||
urlParams map[string]string
|
||||
state state.BeaconState
|
||||
errorMessage string
|
||||
}{
|
||||
{
|
||||
name: "no state_id url params",
|
||||
path: "/eth/v1/builder/states/{state_id}/expected_withdrawals?proposal_slot" +
|
||||
strconv.FormatUint(uint64(currentSlot), 10),
|
||||
urlParams: map[string]string{},
|
||||
state: nil,
|
||||
errorMessage: "state_id is required in URL params",
|
||||
},
|
||||
{
|
||||
name: "invalid proposal slot value",
|
||||
path: "/eth/v1/builder/states/{state_id}/expected_withdrawals?proposal_slot=aaa",
|
||||
urlParams: map[string]string{"state_id": "head"},
|
||||
state: st,
|
||||
errorMessage: "invalid proposal slot value",
|
||||
},
|
||||
{
|
||||
name: "proposal slot < Capella start slot",
|
||||
path: "/eth/v1/builder/states/{state_id}/expected_withdrawals?proposal_slot=" +
|
||||
strconv.FormatUint(uint64(capellaSlot)-1, 10),
|
||||
urlParams: map[string]string{"state_id": "head"},
|
||||
state: st,
|
||||
errorMessage: "expected withdrawals are not supported before Capella fork",
|
||||
},
|
||||
{
|
||||
name: "proposal slot == Capella start slot",
|
||||
path: "/eth/v1/builder/states/{state_id}/expected_withdrawals?proposal_slot=" +
|
||||
strconv.FormatUint(uint64(capellaSlot), 10),
|
||||
urlParams: map[string]string{"state_id": "head"},
|
||||
state: st,
|
||||
errorMessage: "proposal slot must be bigger than state slot",
|
||||
},
|
||||
{
|
||||
name: "Proposal slot >= 128 slots ahead of state slot",
|
||||
path: "/eth/v1/builder/states/{state_id}/expected_withdrawals?proposal_slot=" +
|
||||
strconv.FormatUint(uint64(currentSlot+128), 10),
|
||||
urlParams: map[string]string{"state_id": "head"},
|
||||
state: st,
|
||||
errorMessage: "proposal slot cannot be >= 128 slots ahead of state slot",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
s := &Server{
|
||||
FinalizationFetcher: mockChainService,
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
Stater: &testutil.MockStater{BeaconState: testCase.state},
|
||||
}
|
||||
request := httptest.NewRequest("GET", testCase.path, nil)
|
||||
request.SetPathValue("state_id", testCase.urlParams["state_id"])
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.ExpectedWithdrawals(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
e := &httputil.DefaultJsonError{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusBadRequest, e.Code)
|
||||
assert.StringContains(t, testCase.errorMessage, e.Message)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpectedWithdrawals(t *testing.T) {
|
||||
st, err := util.NewBeaconStateCapella()
|
||||
slotsAhead := 5000
|
||||
require.NoError(t, err)
|
||||
capellaSlot, err := slots.EpochStart(params.BeaconConfig().CapellaForkEpoch)
|
||||
require.NoError(t, err)
|
||||
currentSlot := capellaSlot + primitives.Slot(slotsAhead)
|
||||
require.NoError(t, st.SetSlot(currentSlot))
|
||||
mockChainService := &mock.ChainService{Optimistic: true}
|
||||
|
||||
t.Run("get correct expected withdrawals", func(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig().Copy()
|
||||
cfg.MaxValidatorsPerWithdrawalsSweep = 16
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
// Update state with updated validator fields
|
||||
valCount := 17
|
||||
validators := make([]*eth.Validator, 0, valCount)
|
||||
balances := make([]uint64, 0, valCount)
|
||||
for i := 0; i < valCount; i++ {
|
||||
blsKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
val := ð.Validator{
|
||||
PublicKey: blsKey.PublicKey().Marshal(),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
validators = append(validators, val)
|
||||
balances = append(balances, params.BeaconConfig().MaxEffectiveBalance)
|
||||
}
|
||||
|
||||
epoch := slots.ToEpoch(st.Slot())
|
||||
// Fully withdrawable now with more than 0 balance
|
||||
validators[5].WithdrawableEpoch = epoch
|
||||
// Fully withdrawable now but 0 balance
|
||||
validators[10].WithdrawableEpoch = epoch
|
||||
balances[10] = 0
|
||||
// Partially withdrawable now but fully withdrawable after 1 epoch
|
||||
validators[14].WithdrawableEpoch = epoch + 1
|
||||
balances[14] += params.BeaconConfig().MinDepositAmount
|
||||
// Partially withdrawable
|
||||
validators[15].WithdrawableEpoch = epoch + 2
|
||||
balances[15] += params.BeaconConfig().MinDepositAmount
|
||||
// Above sweep bound
|
||||
validators[16].WithdrawableEpoch = epoch + 1
|
||||
balances[16] += params.BeaconConfig().MinDepositAmount
|
||||
|
||||
require.NoError(t, st.SetValidators(validators))
|
||||
require.NoError(t, st.SetBalances(balances))
|
||||
inactivityScores := make([]uint64, valCount)
|
||||
for i := range inactivityScores {
|
||||
inactivityScores[i] = 10
|
||||
}
|
||||
require.NoError(t, st.SetInactivityScores(inactivityScores))
|
||||
|
||||
s := &Server{
|
||||
FinalizationFetcher: mockChainService,
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
Stater: &testutil.MockStater{BeaconState: st},
|
||||
}
|
||||
request := httptest.NewRequest(
|
||||
"GET", "/eth/v1/builder/states/{state_id}/expected_withdrawals?proposal_slot="+
|
||||
strconv.FormatUint(uint64(currentSlot+params.BeaconConfig().SlotsPerEpoch), 10), nil)
|
||||
request.SetPathValue("state_id", "head")
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.ExpectedWithdrawals(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &structs.ExpectedWithdrawalsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, true, resp.ExecutionOptimistic)
|
||||
assert.Equal(t, false, resp.Finalized)
|
||||
assert.Equal(t, 3, len(resp.Data))
|
||||
expectedWithdrawal1 := &structs.ExpectedWithdrawal{
|
||||
Index: strconv.FormatUint(0, 10),
|
||||
ValidatorIndex: strconv.FormatUint(5, 10),
|
||||
Address: hexutil.Encode(validators[5].WithdrawalCredentials[12:]),
|
||||
// Decreased due to epoch processing when state advanced forward
|
||||
Amount: strconv.FormatUint(31998257885, 10),
|
||||
}
|
||||
expectedWithdrawal2 := &structs.ExpectedWithdrawal{
|
||||
Index: strconv.FormatUint(1, 10),
|
||||
ValidatorIndex: strconv.FormatUint(14, 10),
|
||||
Address: hexutil.Encode(validators[14].WithdrawalCredentials[12:]),
|
||||
// MaxEffectiveBalance + MinDepositAmount + decrease after epoch processing
|
||||
Amount: strconv.FormatUint(32998257885, 10),
|
||||
}
|
||||
expectedWithdrawal3 := &structs.ExpectedWithdrawal{
|
||||
Index: strconv.FormatUint(2, 10),
|
||||
ValidatorIndex: strconv.FormatUint(15, 10),
|
||||
Address: hexutil.Encode(validators[15].WithdrawalCredentials[12:]),
|
||||
// MinDepositAmount + decrease after epoch processing
|
||||
Amount: strconv.FormatUint(998257885, 10),
|
||||
}
|
||||
require.DeepEqual(t, expectedWithdrawal1, resp.Data[0])
|
||||
require.DeepEqual(t, expectedWithdrawal2, resp.Data[1])
|
||||
require.DeepEqual(t, expectedWithdrawal3, resp.Data[2])
|
||||
})
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/lookup"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
FinalizationFetcher blockchain.FinalizationFetcher
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
Stater lookup.Stater
|
||||
}
|
||||
@@ -44,38 +44,6 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Deprecated: use GetAggregateAttestationV2 instead
|
||||
// GetAggregateAttestation aggregates all attestations matching the given attestation data root and slot, returning the aggregated result.
|
||||
func (s *Server) GetAggregateAttestation(w http.ResponseWriter, r *http.Request) {
|
||||
_, span := trace.StartSpan(r.Context(), "validator.GetAggregateAttestation")
|
||||
defer span.End()
|
||||
|
||||
_, attDataRoot, ok := shared.HexFromQuery(w, r, "attestation_data_root", fieldparams.RootLength, true)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_, slot, ok := shared.UintFromQuery(w, r, "slot", true)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
agg := s.aggregatedAttestation(w, primitives.Slot(slot), attDataRoot, 0)
|
||||
if agg == nil {
|
||||
return
|
||||
}
|
||||
typedAgg, ok := agg.(*ethpbalpha.Attestation)
|
||||
if !ok {
|
||||
httputil.HandleError(w, fmt.Sprintf("Attestation is not of type %T", ðpbalpha.Attestation{}), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
data, err := json.Marshal(structs.AttFromConsensus(typedAgg))
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not marshal attestation: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
httputil.WriteJson(w, &structs.AggregateAttestationResponse{Data: data})
|
||||
}
|
||||
|
||||
// GetAggregateAttestationV2 aggregates all attestations matching the given attestation data root and slot, returning the aggregated result.
|
||||
func (s *Server) GetAggregateAttestationV2(w http.ResponseWriter, r *http.Request) {
|
||||
_, span := trace.StartSpan(r.Context(), "validator.GetAggregateAttestationV2")
|
||||
@@ -326,58 +294,6 @@ func (s *Server) SubmitContributionAndProofs(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: use SubmitAggregateAndProofsV2 instead
|
||||
// SubmitAggregateAndProofs verifies given aggregate and proofs and publishes them on appropriate gossipsub topic.
|
||||
func (s *Server) SubmitAggregateAndProofs(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "validator.SubmitAggregateAndProofs")
|
||||
defer span.End()
|
||||
|
||||
var req structs.SubmitAggregateAndProofsRequest
|
||||
err := json.NewDecoder(r.Body).Decode(&req.Data)
|
||||
switch {
|
||||
case errors.Is(err, io.EOF):
|
||||
httputil.HandleError(w, "No data submitted", http.StatusBadRequest)
|
||||
return
|
||||
case err != nil:
|
||||
httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if len(req.Data) == 0 {
|
||||
httputil.HandleError(w, "No data submitted", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
broadcastFailed := false
|
||||
for _, item := range req.Data {
|
||||
var signedAggregate structs.SignedAggregateAttestationAndProof
|
||||
err := json.Unmarshal(item, &signedAggregate)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not decode item: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
consensusItem, err := signedAggregate.ToConsensus()
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "Could not convert request aggregate to consensus aggregate: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
rpcError := s.CoreService.SubmitSignedAggregateSelectionProof(ctx, consensusItem)
|
||||
if rpcError != nil {
|
||||
var broadcastFailedErr *server.BroadcastFailedError
|
||||
ok := errors.As(rpcError.Err, &broadcastFailedErr)
|
||||
if ok {
|
||||
broadcastFailed = true
|
||||
} else {
|
||||
httputil.HandleError(w, rpcError.Err.Error(), core.ErrorReasonToHTTP(rpcError.Reason))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if broadcastFailed {
|
||||
httputil.HandleError(w, "Could not broadcast one or more signed aggregated attestations", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
// SubmitAggregateAndProofsV2 verifies given aggregate and proofs and publishes them on appropriate gossipsub topic.
|
||||
func (s *Server) SubmitAggregateAndProofsV2(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "validator.SubmitAggregateAndProofsV2")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user