mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -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:
@@ -13,7 +13,6 @@ go_library(
|
||||
"conversions_state.go",
|
||||
"endpoints_beacon.go",
|
||||
"endpoints_blob.go",
|
||||
"endpoints_builder.go",
|
||||
"endpoints_config.go",
|
||||
"endpoints_debug.go",
|
||||
"endpoints_events.go",
|
||||
|
||||
@@ -1492,20 +1492,6 @@ func sszBytesToUint256String(b []byte) (string, error) {
|
||||
return bi.String(), nil
|
||||
}
|
||||
|
||||
func DepositSnapshotFromConsensus(ds *eth.DepositSnapshot) *DepositSnapshot {
|
||||
finalized := make([]string, 0, len(ds.Finalized))
|
||||
for _, f := range ds.Finalized {
|
||||
finalized = append(finalized, hexutil.Encode(f))
|
||||
}
|
||||
return &DepositSnapshot{
|
||||
Finalized: finalized,
|
||||
DepositRoot: hexutil.Encode(ds.DepositRoot),
|
||||
DepositCount: fmt.Sprintf("%d", ds.DepositCount),
|
||||
ExecutionBlockHash: hexutil.Encode(ds.ExecutionHash),
|
||||
ExecutionBlockHeight: fmt.Sprintf("%d", ds.ExecutionDepth),
|
||||
}
|
||||
}
|
||||
|
||||
func PendingDepositsFromConsensus(ds []*eth.PendingDeposit) []*PendingDeposit {
|
||||
deposits := make([]*PendingDeposit, len(ds))
|
||||
for i, d := range ds {
|
||||
|
||||
@@ -9,24 +9,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
func TestDepositSnapshotFromConsensus(t *testing.T) {
|
||||
ds := ð.DepositSnapshot{
|
||||
Finalized: [][]byte{{0xde, 0xad, 0xbe, 0xef}, {0xca, 0xfe, 0xba, 0xbe}},
|
||||
DepositRoot: []byte{0xab, 0xcd},
|
||||
DepositCount: 12345,
|
||||
ExecutionHash: []byte{0x12, 0x34},
|
||||
ExecutionDepth: 67890,
|
||||
}
|
||||
|
||||
res := DepositSnapshotFromConsensus(ds)
|
||||
require.NotNil(t, res)
|
||||
require.DeepEqual(t, []string{"0xdeadbeef", "0xcafebabe"}, res.Finalized)
|
||||
require.Equal(t, "0xabcd", res.DepositRoot)
|
||||
require.Equal(t, "12345", res.DepositCount)
|
||||
require.Equal(t, "0x1234", res.ExecutionBlockHash)
|
||||
require.Equal(t, "67890", res.ExecutionBlockHeight)
|
||||
}
|
||||
|
||||
func TestSignedBLSToExecutionChange_ToConsensus(t *testing.T) {
|
||||
s := &SignedBLSToExecutionChange{Message: nil, Signature: ""}
|
||||
_, err := s.ToConsensus()
|
||||
|
||||
@@ -206,18 +206,6 @@ type WeakSubjectivityData struct {
|
||||
StateRoot string `json:"state_root"`
|
||||
}
|
||||
|
||||
type GetDepositSnapshotResponse struct {
|
||||
Data *DepositSnapshot `json:"data"`
|
||||
}
|
||||
|
||||
type DepositSnapshot struct {
|
||||
Finalized []string `json:"finalized"`
|
||||
DepositRoot string `json:"deposit_root"`
|
||||
DepositCount string `json:"deposit_count"`
|
||||
ExecutionBlockHash string `json:"execution_block_hash"`
|
||||
ExecutionBlockHeight string `json:"execution_block_height"`
|
||||
}
|
||||
|
||||
type GetIndividualVotesRequest struct {
|
||||
Epoch string `json:"epoch"`
|
||||
PublicKeys []string `json:"public_keys,omitempty"`
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package structs
|
||||
|
||||
type ExpectedWithdrawalsResponse struct {
|
||||
Data []*ExpectedWithdrawal `json:"data"`
|
||||
ExecutionOptimistic bool `json:"execution_optimistic"`
|
||||
Finalized bool `json:"finalized"`
|
||||
}
|
||||
|
||||
type ExpectedWithdrawal struct {
|
||||
Address string `json:"address" hex:"true"`
|
||||
Amount string `json:"amount"`
|
||||
Index string `json:"index"`
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
}
|
||||
@@ -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
3
changelog/radek_v7-remove-apis.md
Normal file
3
changelog/radek_v7-remove-apis.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Removed
|
||||
|
||||
- Remove Beacon API endpoints that were deprecated in Electra: `GET /eth/v1/beacon/deposit_snapshot`, `GET /eth/v1/beacon/blocks/{block_id}/attestations`, `GET /eth/v1/beacon/pool/attestations`, `POST /eth/v1/beacon/pool/attestations`, `GET /eth/v1/beacon/pool/attester_slashings`, `POST /eth/v1/beacon/pool/attester_slashings`, `GET /eth/v1/validator/aggregate_attestation`, `POST /eth/v1/validator/aggregate_and_proofs`, `POST /eth/v1/beacon/blocks`, `POST /eth/v1/beacon/blinded_blocks`, `GET /eth/v1/builder/states/{state_id}/expected_withdrawals`.
|
||||
@@ -136,7 +136,7 @@ var getRequests = map[string]endpoint{
|
||||
v2PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/beacon/pool/attester_slashings": newMetadata[structs.GetAttesterSlashingsResponse](
|
||||
v1PathTemplate,
|
||||
v2PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/beacon/pool/proposer_slashings": newMetadata[structs.GetProposerSlashingsResponse](
|
||||
v1PathTemplate,
|
||||
@@ -147,12 +147,6 @@ var getRequests = map[string]endpoint{
|
||||
"/beacon/pool/bls_to_execution_changes": newMetadata[structs.BLSToExecutionChangesPoolResponse](
|
||||
v1PathTemplate,
|
||||
withSanityCheckOnly()),
|
||||
"/builder/states/{param1}/expected_withdrawals": newMetadata[structs.ExpectedWithdrawalsResponse](
|
||||
v1PathTemplate,
|
||||
withStart(params.CapellaE2EForkEpoch),
|
||||
withParams(func(_ primitives.Epoch) []string {
|
||||
return []string{"head"}
|
||||
})),
|
||||
"/config/fork_schedule": newMetadata[structs.GetForkScheduleResponse](
|
||||
v1PathTemplate,
|
||||
withCustomEval(func(p interface{}, lh interface{}) error {
|
||||
@@ -208,7 +202,7 @@ var getRequests = map[string]endpoint{
|
||||
withCustomEval(func(p interface{}, _ interface{}) error {
|
||||
pResp, ok := p.(*structs.GetVersionResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf(msgWrongJSON, &structs.ListAttestationsResponse{}, p)
|
||||
return fmt.Errorf(msgWrongJSON, &structs.GetVersionResponse{}, p)
|
||||
}
|
||||
if pResp.Data == nil {
|
||||
return errEmptyPrysmData
|
||||
|
||||
@@ -4,10 +4,8 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/network/httputil"
|
||||
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v6/runtime/version"
|
||||
"github.com/OffchainLabs/prysm/v6/time/slots"
|
||||
@@ -31,25 +29,8 @@ func (c *beaconApiValidatorClient) proposeAttestation(ctx context.Context, attes
|
||||
bytes.NewBuffer(marshalledAttestation),
|
||||
nil,
|
||||
)
|
||||
errJson := &httputil.DefaultJsonError{}
|
||||
if err != nil {
|
||||
// TODO: remove this when v2 becomes default
|
||||
if !errors.As(err, &errJson) {
|
||||
return nil, err
|
||||
}
|
||||
if errJson.Code != http.StatusNotFound {
|
||||
return nil, errJson
|
||||
}
|
||||
log.Debug("Endpoint /eth/v2/beacon/pool/attestations is not supported, falling back to older endpoints for submit attestation.")
|
||||
if err = c.jsonRestHandler.Post(
|
||||
ctx,
|
||||
"/eth/v1/beacon/pool/attestations",
|
||||
nil,
|
||||
bytes.NewBuffer(marshalledAttestation),
|
||||
nil,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attestationDataRoot, err := attestation.Data.HashTreeRoot()
|
||||
|
||||
@@ -4,13 +4,11 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/config/params"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v6/network/httputil"
|
||||
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v6/runtime/version"
|
||||
"github.com/OffchainLabs/prysm/v6/testing/assert"
|
||||
@@ -150,72 +148,6 @@ func TestProposeAttestation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProposeAttestationFallBack(t *testing.T) {
|
||||
attestation := ðpb.Attestation{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 75,
|
||||
CommitteeIndex: 76,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 78,
|
||||
Root: testhelpers.FillByteSlice(32, 79),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 80,
|
||||
Root: testhelpers.FillByteSlice(32, 81),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
var marshalledAttestations []byte
|
||||
if helpers.ValidateNilAttestation(attestation) == nil {
|
||||
b, err := json.Marshal(jsonifyAttestations([]*ethpb.Attestation{attestation}))
|
||||
require.NoError(t, err)
|
||||
marshalledAttestations = b
|
||||
}
|
||||
|
||||
ctx := t.Context()
|
||||
headers := map[string]string{"Eth-Consensus-Version": version.String(attestation.Version())}
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
"/eth/v2/beacon/pool/attestations",
|
||||
headers,
|
||||
bytes.NewBuffer(marshalledAttestations),
|
||||
nil,
|
||||
).Return(
|
||||
&httputil.DefaultJsonError{
|
||||
Code: http.StatusNotFound,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/pool/attestations",
|
||||
nil,
|
||||
bytes.NewBuffer(marshalledAttestations),
|
||||
nil,
|
||||
).Return(
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
proposeResponse, err := validatorClient.proposeAttestation(ctx, attestation)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, proposeResponse)
|
||||
|
||||
expectedAttestationDataRoot, err := attestation.Data.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Make sure that the attestation data root is set
|
||||
assert.DeepEqual(t, expectedAttestationDataRoot[:], proposeResponse.AttestationDataRoot)
|
||||
}
|
||||
|
||||
func TestProposeAttestationElectra(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.BeaconConfig().ElectraForkEpoch = 0
|
||||
|
||||
@@ -3,7 +3,6 @@ package beacon_api
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
@@ -11,7 +10,6 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/structs"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v6/network/httputil"
|
||||
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
@@ -132,23 +130,8 @@ func (c *beaconApiValidatorClient) aggregateAttestation(
|
||||
|
||||
var aggregateAttestationResponse structs.AggregateAttestationResponse
|
||||
err := c.jsonRestHandler.Get(ctx, endpoint, &aggregateAttestationResponse)
|
||||
errJson := &httputil.DefaultJsonError{}
|
||||
if err != nil {
|
||||
// TODO: remove this when v2 becomes default
|
||||
if !errors.As(err, &errJson) {
|
||||
return nil, err
|
||||
}
|
||||
if errJson.Code != http.StatusNotFound {
|
||||
return nil, errJson
|
||||
}
|
||||
log.Debug("Endpoint /eth/v2/validator/aggregate_attestation is not supported, falling back to older endpoints for get aggregated attestation.")
|
||||
params = url.Values{}
|
||||
params.Add("slot", strconv.FormatUint(uint64(slot), 10))
|
||||
params.Add("attestation_data_root", hexutil.Encode(attestationDataRoot))
|
||||
oldEndpoint := apiutil.BuildURL("/eth/v1/validator/aggregate_attestation", params)
|
||||
if err = c.jsonRestHandler.Get(ctx, oldEndpoint, &aggregateAttestationResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &aggregateAttestationResponse, nil
|
||||
|
||||
@@ -4,12 +4,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/structs"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v6/network/httputil"
|
||||
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v6/testing/assert"
|
||||
"github.com/OffchainLabs/prysm/v6/testing/require"
|
||||
@@ -187,129 +185,6 @@ func TestSubmitAggregateSelectionProof(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubmitAggregateSelectionProofFallBack(t *testing.T) {
|
||||
const (
|
||||
pubkeyStr = "0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13"
|
||||
syncingEndpoint = "/eth/v1/node/syncing"
|
||||
attestationDataEndpoint = "/eth/v1/validator/attestation_data"
|
||||
aggregateAttestationEndpoint = "/eth/v1/validator/aggregate_attestation"
|
||||
aggregateAttestationV2Endpoint = "/eth/v2/validator/aggregate_attestation"
|
||||
validatorIndex = primitives.ValidatorIndex(55293)
|
||||
slotSignature = "0x8776a37d6802c4797d113169c5fcfda50e68a32058eb6356a6f00d06d7da64c841a00c7c38b9b94a204751eca53707bd03523ce4797827d9bacff116a6e776a20bbccff4b683bf5201b610797ed0502557a58a65c8395f8a1649b976c3112d15"
|
||||
slot = primitives.Slot(123)
|
||||
committeeIndex = primitives.CommitteeIndex(1)
|
||||
committeesAtSlot = uint64(1)
|
||||
)
|
||||
|
||||
attestationDataResponse := generateValidAttestation(uint64(slot), uint64(committeeIndex))
|
||||
attestationDataProto, err := attestationDataResponse.Data.ToConsensus()
|
||||
require.NoError(t, err)
|
||||
attestationDataRootBytes, err := attestationDataProto.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
aggregateAttestation := ðpb.Attestation{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
Data: attestationDataProto,
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
ctx := t.Context()
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
// Call node syncing endpoint to check if head is optimistic.
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
syncingEndpoint,
|
||||
&structs.SyncStatusResponse{},
|
||||
).SetArg(
|
||||
2,
|
||||
structs.SyncStatusResponse{
|
||||
Data: &structs.SyncStatusResponseData{
|
||||
IsOptimistic: false,
|
||||
},
|
||||
},
|
||||
).Return(
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
// Call attestation data to get attestation data root to query aggregate attestation.
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?committee_index=%d&slot=%d", attestationDataEndpoint, committeeIndex, slot),
|
||||
&structs.GetAttestationDataResponse{},
|
||||
).SetArg(
|
||||
2,
|
||||
attestationDataResponse,
|
||||
).Return(
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
attestationJSON, err := json.Marshal(jsonifyAttestation(aggregateAttestation))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Call attestation data to get attestation data root to query aggregate attestation.
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?attestation_data_root=%s&committee_index=%d&slot=%d", aggregateAttestationV2Endpoint, hexutil.Encode(attestationDataRootBytes[:]), committeeIndex, slot),
|
||||
&structs.AggregateAttestationResponse{},
|
||||
).Return(
|
||||
&httputil.DefaultJsonError{
|
||||
Code: http.StatusNotFound,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
// Call attestation data to get attestation data root to query aggregate attestation.
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?attestation_data_root=%s&slot=%d", aggregateAttestationEndpoint, hexutil.Encode(attestationDataRootBytes[:]), slot),
|
||||
&structs.AggregateAttestationResponse{},
|
||||
).SetArg(
|
||||
2,
|
||||
structs.AggregateAttestationResponse{
|
||||
Data: attestationJSON,
|
||||
},
|
||||
).Return(
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
pubkey, err := hexutil.Decode(pubkeyStr)
|
||||
require.NoError(t, err)
|
||||
|
||||
slotSignatureBytes, err := hexutil.Decode(slotSignature)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedResponse := ðpb.AggregateSelectionResponse{
|
||||
AggregateAndProof: ðpb.AggregateAttestationAndProof{
|
||||
AggregatorIndex: primitives.ValidatorIndex(55293),
|
||||
Aggregate: aggregateAttestation,
|
||||
SelectionProof: slotSignatureBytes,
|
||||
},
|
||||
}
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
dutiesProvider: beaconApiDutiesProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
}
|
||||
|
||||
actualResponse, err := validatorClient.submitAggregateSelectionProof(ctx, ðpb.AggregateSelectionRequest{
|
||||
Slot: slot,
|
||||
CommitteeIndex: committeeIndex,
|
||||
PublicKey: pubkey,
|
||||
SlotSignature: slotSignatureBytes,
|
||||
}, validatorIndex, committeesAtSlot)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedResponse, actualResponse)
|
||||
|
||||
}
|
||||
|
||||
func TestSubmitAggregateSelectionProofElectra(t *testing.T) {
|
||||
const (
|
||||
pubkeyStr = "0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13"
|
||||
|
||||
@@ -4,10 +4,8 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/structs"
|
||||
"github.com/OffchainLabs/prysm/v6/network/httputil"
|
||||
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v6/runtime/version"
|
||||
"github.com/OffchainLabs/prysm/v6/time/slots"
|
||||
@@ -21,25 +19,8 @@ func (c *beaconApiValidatorClient) submitSignedAggregateSelectionProof(ctx conte
|
||||
}
|
||||
headers := map[string]string{"Eth-Consensus-Version": version.String(in.SignedAggregateAndProof.Version())}
|
||||
err = c.jsonRestHandler.Post(ctx, "/eth/v2/validator/aggregate_and_proofs", headers, bytes.NewBuffer(body), nil)
|
||||
errJson := &httputil.DefaultJsonError{}
|
||||
if err != nil {
|
||||
// TODO: remove this when v2 becomes default
|
||||
if !errors.As(err, &errJson) {
|
||||
return nil, err
|
||||
}
|
||||
if errJson.Code != http.StatusNotFound {
|
||||
return nil, errJson
|
||||
}
|
||||
log.Debug("Endpoint /eth/v2/validator/aggregate_and_proofs is not supported, falling back to older endpoints for publish aggregate and proofs.")
|
||||
if err = c.jsonRestHandler.Post(
|
||||
ctx,
|
||||
"/eth/v1/validator/aggregate_and_proofs",
|
||||
nil,
|
||||
bytes.NewBuffer(body),
|
||||
nil,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attestationDataRoot, err := in.SignedAggregateAndProof.Message.Aggregate.Data.HashTreeRoot()
|
||||
|
||||
@@ -3,12 +3,10 @@ package beacon_api
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/api/server/structs"
|
||||
"github.com/OffchainLabs/prysm/v6/config/params"
|
||||
"github.com/OffchainLabs/prysm/v6/network/httputil"
|
||||
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v6/runtime/version"
|
||||
"github.com/OffchainLabs/prysm/v6/testing/assert"
|
||||
@@ -80,50 +78,6 @@ func TestSubmitSignedAggregateSelectionProof_BadRequest(t *testing.T) {
|
||||
assert.ErrorContains(t, "bad request", err)
|
||||
}
|
||||
|
||||
func TestSubmitSignedAggregateSelectionProof_Fallback(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
signedAggregateAndProof := generateSignedAggregateAndProofJson()
|
||||
marshalledSignedAggregateSignedAndProof, err := json.Marshal([]*structs.SignedAggregateAttestationAndProof{jsonifySignedAggregateAndProof(signedAggregateAndProof)})
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := t.Context()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
headers := map[string]string{"Eth-Consensus-Version": version.String(signedAggregateAndProof.Message.Version())}
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
"/eth/v2/validator/aggregate_and_proofs",
|
||||
headers,
|
||||
bytes.NewBuffer(marshalledSignedAggregateSignedAndProof),
|
||||
nil,
|
||||
).Return(
|
||||
&httputil.DefaultJsonError{
|
||||
Code: http.StatusNotFound,
|
||||
},
|
||||
).Times(1)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
"/eth/v1/validator/aggregate_and_proofs",
|
||||
nil,
|
||||
bytes.NewBuffer(marshalledSignedAggregateSignedAndProof),
|
||||
nil,
|
||||
).Return(
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
attestationDataRoot, err := signedAggregateAndProof.Message.Aggregate.Data.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
resp, err := validatorClient.submitSignedAggregateSelectionProof(ctx, ðpb.SignedAggregateSubmitRequest{
|
||||
SignedAggregateAndProof: signedAggregateAndProof,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, attestationDataRoot[:], resp.AttestationDataRoot)
|
||||
}
|
||||
|
||||
func TestSubmitSignedAggregateSelectionProofElectra_Valid(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.BeaconConfig().ElectraForkEpoch = 0
|
||||
|
||||
Reference in New Issue
Block a user