mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 07:28:06 -05:00
Deneb: Produce Block V3 - adding consensus block value (#12948)
* adding in block rewards to represent consensus payload * Update beacon-chain/rpc/eth/validator/handlers_block.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * radek's comments * more review changes * adding more tests for forks * gaz * updating names * gaz * fixing imports * fixing variable name * gaz * fixing test * renaming variables to match data --------- Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
@@ -4,6 +4,7 @@ const (
|
||||
VersionHeader = "Eth-Consensus-Version"
|
||||
ExecutionPayloadBlindedHeader = "Eth-Execution-Payload-Blinded"
|
||||
ExecutionPayloadValueHeader = "Eth-Execution-Payload-Value"
|
||||
ConsensusBlockValueHeader = "Eth-Consensus-Block-Value"
|
||||
JsonMediaType = "application/json"
|
||||
OctetStreamMediaType = "application/octet-stream"
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@ go_library(
|
||||
srcs = [
|
||||
"handlers.go",
|
||||
"server.go",
|
||||
"service.go",
|
||||
"structs.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards",
|
||||
@@ -21,11 +22,13 @@ go_library(
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//network/http:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_wealdtech_go_bytesutil//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -54,6 +57,7 @@ go_test(
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -8,9 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair"
|
||||
coreblocks "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||
@@ -20,10 +18,13 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v4/time/slots"
|
||||
"github.com/wealdtech/go-bytesutil"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// BlockRewards is an HTTP handler for Beacon API getBlockRewards.
|
||||
func (s *Server) BlockRewards(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.BlockRewards")
|
||||
defer span.End()
|
||||
segments := strings.Split(r.URL.Path, "/")
|
||||
blockId := segments[len(segments)-1]
|
||||
|
||||
@@ -36,63 +37,6 @@ func (s *Server) BlockRewards(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// We want to run several block processing functions that update the proposer's balance.
|
||||
// This will allow us to calculate proposer rewards for each operation (atts, slashings etc).
|
||||
// To do this, we replay the state up to the block's slot, but before processing the block.
|
||||
st, err := s.ReplayerBuilder.ReplayerForSlot(blk.Block().Slot()-1).ReplayToSlot(r.Context(), blk.Block().Slot())
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get state: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
proposerIndex := blk.Block().ProposerIndex()
|
||||
initBalance, err := st.BalanceAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get proposer's balance: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
st, err = altair.ProcessAttestationsNoVerifySignature(r.Context(), st, blk)
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get attestation rewards"+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
attBalance, err := st.BalanceAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get proposer's balance: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
st, err = coreblocks.ProcessAttesterSlashings(r.Context(), st, blk.Block().Body().AttesterSlashings(), validators.SlashValidator)
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get attester slashing rewards: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
attSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get proposer's balance: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
st, err = coreblocks.ProcessProposerSlashings(r.Context(), st, blk.Block().Body().ProposerSlashings(), validators.SlashValidator)
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get proposer slashing rewards"+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
proposerSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get proposer's balance: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
sa, err := blk.Block().Body().SyncAggregate()
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get sync aggregate: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
var syncCommitteeReward uint64
|
||||
_, syncCommitteeReward, err = altair.ProcessSyncAggregate(r.Context(), st, sa)
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get sync aggregate rewards: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
optimistic, err := s.OptimisticModeFetcher.IsOptimistic(r.Context())
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get optimistic mode info: "+err.Error(), http.StatusInternalServerError)
|
||||
@@ -103,18 +47,15 @@ func (s *Server) BlockRewards(w http.ResponseWriter, r *http.Request) {
|
||||
http2.HandleError(w, "Could not get block root: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
blockRewards, httpError := s.BlockRewardFetcher.GetBlockRewardsData(ctx, blk)
|
||||
if httpError != nil {
|
||||
http2.WriteError(w, httpError)
|
||||
return
|
||||
}
|
||||
response := &BlockRewardsResponse{
|
||||
Data: BlockRewards{
|
||||
ProposerIndex: strconv.FormatUint(uint64(proposerIndex), 10),
|
||||
Total: strconv.FormatUint(proposerSlashingsBalance-initBalance+syncCommitteeReward, 10),
|
||||
Attestations: strconv.FormatUint(attBalance-initBalance, 10),
|
||||
SyncAggregate: strconv.FormatUint(syncCommitteeReward, 10),
|
||||
ProposerSlashings: strconv.FormatUint(proposerSlashingsBalance-attSlashingsBalance, 10),
|
||||
AttesterSlashings: strconv.FormatUint(attSlashingsBalance-attBalance, 10),
|
||||
},
|
||||
Data: blockRewards,
|
||||
ExecutionOptimistic: optimistic,
|
||||
Finalized: s.FinalizationFetcher.IsFinalized(r.Context(), blkRoot),
|
||||
Finalized: s.FinalizationFetcher.IsFinalized(ctx, blkRoot),
|
||||
}
|
||||
http2.WriteJson(w, response)
|
||||
}
|
||||
@@ -165,6 +106,8 @@ func (s *Server) AttestationRewards(w http.ResponseWriter, r *http.Request) {
|
||||
// SyncCommitteeRewards retrieves rewards info for sync committee members specified by array of public keys or validator index.
|
||||
// If no array is provided, return reward info for every committee member.
|
||||
func (s *Server) SyncCommitteeRewards(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "beacon.SyncCommitteeRewards")
|
||||
defer span.End()
|
||||
segments := strings.Split(r.URL.Path, "/")
|
||||
blockId := segments[len(segments)-1]
|
||||
|
||||
@@ -176,9 +119,10 @@ func (s *Server) SyncCommitteeRewards(w http.ResponseWriter, r *http.Request) {
|
||||
http2.HandleError(w, "Sync committee rewards are not supported for Phase 0", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
st, err := s.ReplayerBuilder.ReplayerForSlot(blk.Block().Slot()-1).ReplayToSlot(r.Context(), blk.Block().Slot())
|
||||
if err != nil {
|
||||
http2.HandleError(w, "Could not get state: "+err.Error(), http.StatusInternalServerError)
|
||||
|
||||
st, httpErr := s.BlockRewardFetcher.GetStateForRewards(ctx, blk)
|
||||
if httpErr != nil {
|
||||
http2.WriteError(w, httpErr)
|
||||
return
|
||||
}
|
||||
sa, err := blk.Block().Body().SyncAggregate()
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair"
|
||||
@@ -34,12 +35,42 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/util"
|
||||
)
|
||||
|
||||
func TestBlockRewards(t *testing.T) {
|
||||
func BlockRewardTestSetup(t *testing.T, forkName string) (state.BeaconState, interfaces.SignedBeaconBlock, error) {
|
||||
helpers.ClearCache()
|
||||
|
||||
var sbb interfaces.SignedBeaconBlock
|
||||
var st state.BeaconState
|
||||
var err error
|
||||
switch forkName {
|
||||
case "phase0":
|
||||
return nil, nil, errors.New("phase0 not supported")
|
||||
case "altair":
|
||||
st, err = util.NewBeaconStateAltair()
|
||||
require.NoError(t, err)
|
||||
b := util.HydrateSignedBeaconBlockAltair(util.NewBeaconBlockAltair())
|
||||
sbb, err = blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
case "bellatrix":
|
||||
st, err = util.NewBeaconStateBellatrix()
|
||||
require.NoError(t, err)
|
||||
b := util.HydrateSignedBeaconBlockBellatrix(util.NewBeaconBlockBellatrix())
|
||||
sbb, err = blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
case "capella":
|
||||
st, err = util.NewBeaconStateCapella()
|
||||
require.NoError(t, err)
|
||||
b := util.HydrateSignedBeaconBlockCapella(util.NewBeaconBlockCapella())
|
||||
sbb, err = blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
case "deneb":
|
||||
st, err = util.NewBeaconStateDeneb()
|
||||
require.NoError(t, err)
|
||||
b := util.HydrateSignedBeaconBlockDeneb(util.NewBeaconBlockDeneb())
|
||||
sbb, err = blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
default:
|
||||
return nil, nil, errors.New("fork is not supported")
|
||||
}
|
||||
valCount := 64
|
||||
|
||||
st, err := util.NewBeaconStateCapella()
|
||||
require.NoError(t, st.SetSlot(1))
|
||||
require.NoError(t, err)
|
||||
validators := make([]*eth.Validator, 0, valCount)
|
||||
@@ -68,11 +99,10 @@ func TestBlockRewards(t *testing.T) {
|
||||
bRoots[0] = slot0bRoot
|
||||
require.NoError(t, st.SetBlockRoots(bRoots))
|
||||
|
||||
b := util.HydrateSignedBeaconBlockCapella(util.NewBeaconBlockCapella())
|
||||
b.Block.Slot = 2
|
||||
sbb.SetSlot(2)
|
||||
// we have to set the proposer index to the value that will be randomly chosen (fortunately it's deterministic)
|
||||
b.Block.ProposerIndex = 12
|
||||
b.Block.Body.Attestations = []*eth.Attestation{
|
||||
sbb.SetProposerIndex(12)
|
||||
sbb.SetAttestations([]*eth.Attestation{
|
||||
{
|
||||
AggregationBits: bitfield.Bitlist{0b00000111},
|
||||
Data: util.HydrateAttestationData(ð.AttestationData{}),
|
||||
@@ -83,7 +113,8 @@ func TestBlockRewards(t *testing.T) {
|
||||
Data: util.HydrateAttestationData(ð.AttestationData{}),
|
||||
Signature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
attData1 := util.HydrateAttestationData(ð.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte("root1"), 32)})
|
||||
attData2 := util.HydrateAttestationData(ð.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte("root2"), 32)})
|
||||
domain, err := signing.Domain(st.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorsRoot())
|
||||
@@ -92,7 +123,7 @@ func TestBlockRewards(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
sigRoot2, err := signing.ComputeSigningRoot(attData2, domain)
|
||||
require.NoError(t, err)
|
||||
b.Block.Body.AttesterSlashings = []*eth.AttesterSlashing{
|
||||
sbb.SetAttesterSlashings([]*eth.AttesterSlashing{
|
||||
{
|
||||
Attestation_1: ð.IndexedAttestation{
|
||||
AttestingIndices: []uint64{0},
|
||||
@@ -105,7 +136,7 @@ func TestBlockRewards(t *testing.T) {
|
||||
Signature: secretKeys[0].Sign(sigRoot2[:]).Marshal(),
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
header1 := ð.BeaconBlockHeader{
|
||||
Slot: 0,
|
||||
ProposerIndex: 1,
|
||||
@@ -126,7 +157,7 @@ func TestBlockRewards(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
sigRoot2, err = signing.ComputeSigningRoot(header2, domain)
|
||||
require.NoError(t, err)
|
||||
b.Block.Body.ProposerSlashings = []*eth.ProposerSlashing{
|
||||
sbb.SetProposerSlashings([]*eth.ProposerSlashing{
|
||||
{
|
||||
Header_1: ð.SignedBeaconBlockHeader{
|
||||
Header: header1,
|
||||
@@ -137,7 +168,7 @@ func TestBlockRewards(t *testing.T) {
|
||||
Signature: secretKeys[1].Sign(sigRoot2[:]).Marshal(),
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
scBits := bitfield.NewBitvector512()
|
||||
scBits.SetBitAt(10, true)
|
||||
scBits.SetBitAt(100, true)
|
||||
@@ -153,24 +184,51 @@ func TestBlockRewards(t *testing.T) {
|
||||
sig2, err := blst.SignatureFromBytes(secretKeys[19].Sign(r[:]).Marshal())
|
||||
require.NoError(t, err)
|
||||
aggSig := bls.AggregateSignatures([]bls.Signature{sig1, sig2}).Marshal()
|
||||
b.Block.Body.SyncAggregate = ð.SyncAggregate{SyncCommitteeBits: scBits, SyncCommitteeSignature: aggSig}
|
||||
|
||||
sbb, err := blocks.NewSignedBeaconBlock(b)
|
||||
err = sbb.SetSyncAggregate(ð.SyncAggregate{SyncCommitteeBits: scBits, SyncCommitteeSignature: aggSig})
|
||||
require.NoError(t, err)
|
||||
|
||||
return st, sbb, nil
|
||||
}
|
||||
|
||||
func TestBlockRewards(t *testing.T) {
|
||||
phase0block, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
mockChainService := &mock.ChainService{Optimistic: true}
|
||||
s := &Server{
|
||||
Blocker: &testutil.MockBlocker{SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{
|
||||
0: phase0block,
|
||||
2: sbb,
|
||||
}},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
ReplayerBuilder: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st)),
|
||||
}
|
||||
t.Run("phase 0", func(t *testing.T) {
|
||||
mockChainService := &mock.ChainService{Optimistic: true}
|
||||
s := &Server{
|
||||
Blocker: &testutil.MockBlocker{SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{
|
||||
0: phase0block,
|
||||
}},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
}
|
||||
url := "http://only.the.slot.number.at.the.end.is.important/0"
|
||||
request := httptest.NewRequest("GET", url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.BlockRewards(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
e := &http2.DefaultErrorJson{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusBadRequest, e.Code)
|
||||
assert.Equal(t, "Block rewards are not supported for Phase 0 blocks", e.Message)
|
||||
})
|
||||
t.Run("altair", func(t *testing.T) {
|
||||
st, sbb, err := BlockRewardTestSetup(t, "altair")
|
||||
require.NoError(t, err)
|
||||
|
||||
mockChainService := &mock.ChainService{Optimistic: true}
|
||||
s := &Server{
|
||||
Blocker: &testutil.MockBlocker{SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{
|
||||
0: phase0block,
|
||||
2: sbb,
|
||||
}},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
BlockRewardFetcher: &BlockRewardService{Replayer: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st))},
|
||||
}
|
||||
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
url := "http://only.the.slot.number.at.the.end.is.important/2"
|
||||
request := httptest.NewRequest("GET", url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
@@ -189,18 +247,104 @@ func TestBlockRewards(t *testing.T) {
|
||||
assert.Equal(t, true, resp.ExecutionOptimistic)
|
||||
assert.Equal(t, false, resp.Finalized)
|
||||
})
|
||||
t.Run("phase 0", func(t *testing.T) {
|
||||
url := "http://only.the.slot.number.at.the.end.is.important/0"
|
||||
t.Run("bellatrix", func(t *testing.T) {
|
||||
st, sbb, err := BlockRewardTestSetup(t, "bellatrix")
|
||||
require.NoError(t, err)
|
||||
|
||||
mockChainService := &mock.ChainService{Optimistic: true}
|
||||
s := &Server{
|
||||
Blocker: &testutil.MockBlocker{SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{
|
||||
0: phase0block,
|
||||
2: sbb,
|
||||
}},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
BlockRewardFetcher: &BlockRewardService{Replayer: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st))},
|
||||
}
|
||||
|
||||
url := "http://only.the.slot.number.at.the.end.is.important/2"
|
||||
request := httptest.NewRequest("GET", url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.BlockRewards(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
e := &http2.DefaultErrorJson{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusBadRequest, e.Code)
|
||||
assert.Equal(t, "Block rewards are not supported for Phase 0 blocks", e.Message)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &BlockRewardsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, "12", resp.Data.ProposerIndex)
|
||||
assert.Equal(t, "125089490", resp.Data.Total)
|
||||
assert.Equal(t, "89442", resp.Data.Attestations)
|
||||
assert.Equal(t, "48", resp.Data.SyncAggregate)
|
||||
assert.Equal(t, "62500000", resp.Data.AttesterSlashings)
|
||||
assert.Equal(t, "62500000", resp.Data.ProposerSlashings)
|
||||
assert.Equal(t, true, resp.ExecutionOptimistic)
|
||||
assert.Equal(t, false, resp.Finalized)
|
||||
})
|
||||
t.Run("capella", func(t *testing.T) {
|
||||
st, sbb, err := BlockRewardTestSetup(t, "capella")
|
||||
require.NoError(t, err)
|
||||
|
||||
mockChainService := &mock.ChainService{Optimistic: true}
|
||||
s := &Server{
|
||||
Blocker: &testutil.MockBlocker{SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{
|
||||
0: phase0block,
|
||||
2: sbb,
|
||||
}},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
BlockRewardFetcher: &BlockRewardService{Replayer: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st))},
|
||||
}
|
||||
|
||||
url := "http://only.the.slot.number.at.the.end.is.important/2"
|
||||
request := httptest.NewRequest("GET", url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.BlockRewards(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &BlockRewardsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, "12", resp.Data.ProposerIndex)
|
||||
assert.Equal(t, "125089490", resp.Data.Total)
|
||||
assert.Equal(t, "89442", resp.Data.Attestations)
|
||||
assert.Equal(t, "48", resp.Data.SyncAggregate)
|
||||
assert.Equal(t, "62500000", resp.Data.AttesterSlashings)
|
||||
assert.Equal(t, "62500000", resp.Data.ProposerSlashings)
|
||||
assert.Equal(t, true, resp.ExecutionOptimistic)
|
||||
assert.Equal(t, false, resp.Finalized)
|
||||
})
|
||||
t.Run("deneb", func(t *testing.T) {
|
||||
st, sbb, err := BlockRewardTestSetup(t, "deneb")
|
||||
require.NoError(t, err)
|
||||
|
||||
mockChainService := &mock.ChainService{Optimistic: true}
|
||||
s := &Server{
|
||||
Blocker: &testutil.MockBlocker{SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{
|
||||
0: phase0block,
|
||||
2: sbb,
|
||||
}},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
BlockRewardFetcher: &BlockRewardService{Replayer: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st))},
|
||||
}
|
||||
|
||||
url := "http://only.the.slot.number.at.the.end.is.important/2"
|
||||
request := httptest.NewRequest("GET", url, nil)
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.BlockRewards(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &BlockRewardsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, "12", resp.Data.ProposerIndex)
|
||||
assert.Equal(t, "125089490", resp.Data.Total)
|
||||
assert.Equal(t, "89442", resp.Data.Attestations)
|
||||
assert.Equal(t, "48", resp.Data.SyncAggregate)
|
||||
assert.Equal(t, "62500000", resp.Data.AttesterSlashings)
|
||||
assert.Equal(t, "62500000", resp.Data.ProposerSlashings)
|
||||
assert.Equal(t, true, resp.ExecutionOptimistic)
|
||||
assert.Equal(t, false, resp.Finalized)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -560,7 +704,7 @@ func TestSyncCommiteeRewards(t *testing.T) {
|
||||
}},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
FinalizationFetcher: mockChainService,
|
||||
ReplayerBuilder: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st)),
|
||||
BlockRewardFetcher: &BlockRewardService{Replayer: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st))},
|
||||
}
|
||||
|
||||
t.Run("ok - filtered vals", func(t *testing.T) {
|
||||
|
||||
@@ -3,15 +3,14 @@ package rewards
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Blocker lookup.Blocker
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
FinalizationFetcher blockchain.FinalizationFetcher
|
||||
ReplayerBuilder stategen.ReplayerBuilder
|
||||
TimeFetcher blockchain.TimeFetcher
|
||||
Stater lookup.Stater
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
BlockRewardFetcher BlockRewardsFetcher
|
||||
}
|
||||
|
||||
124
beacon-chain/rpc/eth/rewards/service.go
Normal file
124
beacon-chain/rpc/eth/rewards/service.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package rewards
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair"
|
||||
coreblocks "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
|
||||
http2 "github.com/prysmaticlabs/prysm/v4/network/http"
|
||||
)
|
||||
|
||||
// BlockRewardsFetcher is a interface that provides access to reward related responses
|
||||
type BlockRewardsFetcher interface {
|
||||
GetBlockRewardsData(context.Context, interfaces.ReadOnlySignedBeaconBlock) (*BlockRewards, *http2.DefaultErrorJson)
|
||||
GetStateForRewards(context.Context, interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, *http2.DefaultErrorJson)
|
||||
}
|
||||
|
||||
// BlockRewardService implements BlockRewardsFetcher and can be declared to access the underlying functions
|
||||
type BlockRewardService struct {
|
||||
Replayer stategen.ReplayerBuilder
|
||||
}
|
||||
|
||||
// GetBlockRewardsData returns the BlockRewards Object which is used for the BlockRewardsResponse and ProduceBlockV3
|
||||
func (rs *BlockRewardService) GetBlockRewardsData(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*BlockRewards, *http2.DefaultErrorJson) {
|
||||
st, httpErr := rs.GetStateForRewards(ctx, blk)
|
||||
if httpErr != nil {
|
||||
return nil, httpErr
|
||||
}
|
||||
|
||||
proposerIndex := blk.Block().ProposerIndex()
|
||||
initBalance, err := st.BalanceAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get proposer's balance: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
st, err = altair.ProcessAttestationsNoVerifySignature(ctx, st, blk)
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get attestation rewards: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
attBalance, err := st.BalanceAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get proposer's balance: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
st, err = coreblocks.ProcessAttesterSlashings(ctx, st, blk.Block().Body().AttesterSlashings(), validators.SlashValidator)
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get attester slashing rewards: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
attSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get proposer's balance: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
st, err = coreblocks.ProcessProposerSlashings(ctx, st, blk.Block().Body().ProposerSlashings(), validators.SlashValidator)
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get proposer slashing rewards: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
proposerSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get proposer's balance: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
sa, err := blk.Block().Body().SyncAggregate()
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get sync aggregate: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
var syncCommitteeReward uint64
|
||||
_, syncCommitteeReward, err = altair.ProcessSyncAggregate(ctx, st, sa)
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get sync aggregate rewards: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
|
||||
return &BlockRewards{
|
||||
ProposerIndex: strconv.FormatUint(uint64(proposerIndex), 10),
|
||||
Total: strconv.FormatUint(proposerSlashingsBalance-initBalance+syncCommitteeReward, 10),
|
||||
Attestations: strconv.FormatUint(attBalance-initBalance, 10),
|
||||
SyncAggregate: strconv.FormatUint(syncCommitteeReward, 10),
|
||||
ProposerSlashings: strconv.FormatUint(proposerSlashingsBalance-attSlashingsBalance, 10),
|
||||
AttesterSlashings: strconv.FormatUint(attSlashingsBalance-attBalance, 10),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetStateForRewards returns the state replayed up to the block's slot
|
||||
func (rs *BlockRewardService) GetStateForRewards(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, *http2.DefaultErrorJson) {
|
||||
// We want to run several block processing functions that update the proposer's balance.
|
||||
// This will allow us to calculate proposer rewards for each operation (atts, slashings etc).
|
||||
// To do this, we replay the state up to the block's slot, but before processing the block.
|
||||
st, err := rs.Replayer.ReplayerForSlot(blk.Block().Slot()-1).ReplayToSlot(ctx, blk.Block().Slot())
|
||||
if err != nil {
|
||||
return nil, &http2.DefaultErrorJson{
|
||||
Message: "Could not get state: " + err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package rewards
|
||||
|
||||
type BlockRewardsResponse struct {
|
||||
Data BlockRewards `json:"data"`
|
||||
ExecutionOptimistic bool `json:"execution_optimistic"`
|
||||
Finalized bool `json:"finalized"`
|
||||
Data *BlockRewards `json:"data"`
|
||||
ExecutionOptimistic bool `json:"execution_optimistic"`
|
||||
Finalized bool `json:"finalized"`
|
||||
}
|
||||
|
||||
type BlockRewards struct {
|
||||
|
||||
14
beacon-chain/rpc/eth/rewards/testing/BUILD.bazel
Normal file
14
beacon-chain/rpc/eth/rewards/testing/BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["mock.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards/testing",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/rpc/eth/rewards:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//network/http:go_default_library",
|
||||
],
|
||||
)
|
||||
30
beacon-chain/rpc/eth/rewards/testing/mock.go
Normal file
30
beacon-chain/rpc/eth/rewards/testing/mock.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
|
||||
http2 "github.com/prysmaticlabs/prysm/v4/network/http"
|
||||
)
|
||||
|
||||
type MockBlockRewardFetcher struct {
|
||||
Rewards *rewards.BlockRewards
|
||||
Error *http2.DefaultErrorJson
|
||||
State state.BeaconState
|
||||
}
|
||||
|
||||
func (m *MockBlockRewardFetcher) GetBlockRewardsData(_ context.Context, _ interfaces.ReadOnlySignedBeaconBlock) (*rewards.BlockRewards, *http2.DefaultErrorJson) {
|
||||
if m.Error != nil {
|
||||
return nil, m.Error
|
||||
}
|
||||
return m.Rewards, nil
|
||||
}
|
||||
|
||||
func (m *MockBlockRewardFetcher) GetStateForRewards(_ context.Context, _ interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, *http2.DefaultErrorJson) {
|
||||
if m.Error != nil {
|
||||
return nil, m.Error
|
||||
}
|
||||
return m.State, nil
|
||||
}
|
||||
@@ -162,7 +162,7 @@ const (
|
||||
}`
|
||||
AltairBlock = `{
|
||||
"message": {
|
||||
"slot": "1",
|
||||
"slot": "2",
|
||||
"proposer_index": "1",
|
||||
"parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||
"state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||
@@ -204,7 +204,7 @@ const (
|
||||
"attesting_indices": [
|
||||
"1"
|
||||
],
|
||||
"signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
|
||||
"signature": "0xabb0124c7574f281a293f4185cad3cb22681d520917ce46665243eacb051000d8bacf75e1451870ca6b3b9e6c9d41a7b02ead2685a84188a4fafd3825daf6a989625d719ccd2d83a40101f4a453fca62878c890eca622363f9ddb8f367a91e84",
|
||||
"data": {
|
||||
"slot": "1",
|
||||
"index": "1",
|
||||
@@ -223,18 +223,18 @@ const (
|
||||
"attesting_indices": [
|
||||
"1"
|
||||
],
|
||||
"signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
|
||||
"signature": "0xabb0124c7574f281a293f4185cad3cb22681d520917ce46665243eacb051000d8bacf75e1451870ca6b3b9e6c9d41a7b02ead2685a84188a4fafd3825daf6a989625d719ccd2d83a40101f4a453fca62878c890eca622363f9ddb8f367a91e84",
|
||||
"data": {
|
||||
"slot": "1",
|
||||
"index": "1",
|
||||
"beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||
"source": {
|
||||
"epoch": "1",
|
||||
"root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
"root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f3"
|
||||
},
|
||||
"target": {
|
||||
"epoch": "1",
|
||||
"root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
"root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f3"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,18 +242,18 @@ const (
|
||||
],
|
||||
"attestations": [
|
||||
{
|
||||
"aggregation_bits": "0xffffffffffffffffffffffffffffffffff3f",
|
||||
"signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
|
||||
"aggregation_bits": "0x07",
|
||||
"signature": "0xabb0124c7574f281a293f4185cad3cb22681d520917ce46665243eacb051000d8bacf75e1451870ca6b3b9e6c9d41a7b02ead2685a84188a4fafd3825daf6a989625d719ccd2d83a40101f4a453fca62878c890eca622363f9ddb8f367a91e84",
|
||||
"data": {
|
||||
"slot": "1",
|
||||
"index": "1",
|
||||
"slot": "0",
|
||||
"index": "0",
|
||||
"beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||
"source": {
|
||||
"epoch": "1",
|
||||
"root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
},
|
||||
"target": {
|
||||
"epoch": "1",
|
||||
"epoch": "0",
|
||||
"root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ go_library(
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/rpc/core:go_default_library",
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
"//beacon-chain/rpc/eth/rewards:go_default_library",
|
||||
"//beacon-chain/rpc/eth/shared:go_default_library",
|
||||
"//beacon-chain/rpc/lookup:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
@@ -33,6 +34,8 @@ go_library(
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
@@ -75,6 +78,8 @@ go_test(
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
"//beacon-chain/p2p/testing:go_default_library",
|
||||
"//beacon-chain/rpc/core:go_default_library",
|
||||
"//beacon-chain/rpc/eth/rewards:go_default_library",
|
||||
"//beacon-chain/rpc/eth/rewards/testing:go_default_library",
|
||||
"//beacon-chain/rpc/eth/shared:go_default_library",
|
||||
"//beacon-chain/rpc/eth/shared/testing:go_default_library",
|
||||
"//beacon-chain/rpc/testutil:go_default_library",
|
||||
|
||||
@@ -9,8 +9,11 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/api"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||
http2 "github.com/prysmaticlabs/prysm/v4/network/http"
|
||||
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
@@ -84,16 +87,26 @@ func (s *Server) produceBlockV3(ctx context.Context, w http.ResponseWriter, r *h
|
||||
http2.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
consensusBlockValue, httpError := getConsensusBlockValue(ctx, s.BlockRewardFetcher, v1alpha1resp.Block)
|
||||
if httpError != nil {
|
||||
http2.WriteError(w, httpError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set(api.ExecutionPayloadBlindedHeader, fmt.Sprintf("%v", v1alpha1resp.IsBlinded))
|
||||
w.Header().Set(api.ExecutionPayloadValueHeader, fmt.Sprintf("%d", v1alpha1resp.PayloadValue))
|
||||
w.Header().Set(api.ConsensusBlockValueHeader, consensusBlockValue)
|
||||
|
||||
phase0Block, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Phase0)
|
||||
if ok {
|
||||
// rewards aren't used in phase 0
|
||||
handleProducePhase0V3(ctx, w, isSSZ, phase0Block, v1alpha1resp.PayloadValue)
|
||||
return
|
||||
}
|
||||
altairBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Altair)
|
||||
if ok {
|
||||
handleProduceAltairV3(ctx, w, isSSZ, altairBlock, v1alpha1resp.PayloadValue)
|
||||
handleProduceAltairV3(ctx, w, isSSZ, altairBlock, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
optimistic, err := s.OptimisticModeFetcher.IsOptimistic(ctx)
|
||||
@@ -107,36 +120,82 @@ func (s *Server) produceBlockV3(ctx context.Context, w http.ResponseWriter, r *h
|
||||
}
|
||||
blindedBellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedBellatrix)
|
||||
if ok {
|
||||
handleProduceBlindedBellatrixV3(ctx, w, isSSZ, blindedBellatrixBlock, v1alpha1resp.PayloadValue)
|
||||
handleProduceBlindedBellatrixV3(ctx, w, isSSZ, blindedBellatrixBlock, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
bellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Bellatrix)
|
||||
if ok {
|
||||
handleProduceBellatrixV3(ctx, w, isSSZ, bellatrixBlock, v1alpha1resp.PayloadValue)
|
||||
handleProduceBellatrixV3(ctx, w, isSSZ, bellatrixBlock, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
blindedCapellaBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedCapella)
|
||||
if ok {
|
||||
handleProduceBlindedCapellaV3(ctx, w, isSSZ, blindedCapellaBlock, v1alpha1resp.PayloadValue)
|
||||
handleProduceBlindedCapellaV3(ctx, w, isSSZ, blindedCapellaBlock, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
capellaBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Capella)
|
||||
if ok {
|
||||
handleProduceCapellaV3(ctx, w, isSSZ, capellaBlock, v1alpha1resp.PayloadValue)
|
||||
handleProduceCapellaV3(ctx, w, isSSZ, capellaBlock, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
blindedDenebBlockContents, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedDeneb)
|
||||
if ok {
|
||||
handleProduceBlindedDenebV3(ctx, w, isSSZ, blindedDenebBlockContents, v1alpha1resp.PayloadValue)
|
||||
handleProduceBlindedDenebV3(ctx, w, isSSZ, blindedDenebBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
denebBlockContents, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Deneb)
|
||||
if ok {
|
||||
handleProduceDenebV3(ctx, w, isSSZ, denebBlockContents, v1alpha1resp.PayloadValue)
|
||||
handleProduceDenebV3(ctx, w, isSSZ, denebBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func getConsensusBlockValue(ctx context.Context, blockRewardsFetcher rewards.BlockRewardsFetcher, i interface{} /* block as argument */) (string, *http2.DefaultErrorJson) {
|
||||
var wrapper interfaces.ReadOnlySignedBeaconBlock
|
||||
var err error
|
||||
|
||||
// TODO: we should not require this fake signed wrapper and fix associated functions in the future.
|
||||
switch b := i.(type) {
|
||||
case *eth.GenericBeaconBlock_Phase0:
|
||||
//ignore for phase0
|
||||
return "", nil
|
||||
case *eth.GenericBeaconBlock_Altair:
|
||||
wrapper, err = blocks.NewSignedBeaconBlock(ð.GenericSignedBeaconBlock_Altair{Altair: ð.SignedBeaconBlockAltair{Block: b.Altair}})
|
||||
case *eth.GenericBeaconBlock_Bellatrix:
|
||||
wrapper, err = blocks.NewSignedBeaconBlock(ð.GenericSignedBeaconBlock_Bellatrix{Bellatrix: ð.SignedBeaconBlockBellatrix{Block: b.Bellatrix}})
|
||||
case *eth.GenericBeaconBlock_BlindedBellatrix:
|
||||
wrapper, err = blocks.NewSignedBeaconBlock(ð.GenericSignedBeaconBlock_BlindedBellatrix{BlindedBellatrix: ð.SignedBlindedBeaconBlockBellatrix{Block: b.BlindedBellatrix}})
|
||||
case *eth.GenericBeaconBlock_Capella:
|
||||
wrapper, err = blocks.NewSignedBeaconBlock(ð.GenericSignedBeaconBlock_Capella{Capella: ð.SignedBeaconBlockCapella{Block: b.Capella}})
|
||||
case *eth.GenericBeaconBlock_BlindedCapella:
|
||||
wrapper, err = blocks.NewSignedBeaconBlock(ð.GenericSignedBeaconBlock_BlindedCapella{BlindedCapella: ð.SignedBlindedBeaconBlockCapella{Block: b.BlindedCapella}})
|
||||
case *eth.GenericBeaconBlock_Deneb:
|
||||
// no need for sidecar
|
||||
wrapper, err = blocks.NewSignedBeaconBlock(ð.GenericSignedBeaconBlock_Deneb{Deneb: ð.SignedBeaconBlockAndBlobsDeneb{Block: ð.SignedBeaconBlockDeneb{Block: b.Deneb.Block}}})
|
||||
case *eth.GenericBeaconBlock_BlindedDeneb:
|
||||
// no need for sidecar
|
||||
wrapper, err = blocks.NewSignedBeaconBlock(ð.GenericSignedBeaconBlock_BlindedDeneb{BlindedDeneb: ð.SignedBlindedBeaconBlockAndBlobsDeneb{SignedBlindedBlock: ð.SignedBlindedBeaconBlockDeneb{Message: b.BlindedDeneb.Block}}})
|
||||
default:
|
||||
return "", &http2.DefaultErrorJson{
|
||||
Message: fmt.Errorf("type %T is not supported", b).Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return "", &http2.DefaultErrorJson{
|
||||
Message: err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
|
||||
//get consensus payload value which is the same as the total from the block rewards api
|
||||
blockRewards, httpError := blockRewardsFetcher.GetBlockRewardsData(ctx, wrapper)
|
||||
if httpError != nil {
|
||||
return "", httpError
|
||||
}
|
||||
return blockRewards.Total, nil
|
||||
}
|
||||
|
||||
func handleProducePhase0V3(
|
||||
ctx context.Context,
|
||||
w http.ResponseWriter,
|
||||
@@ -169,6 +228,7 @@ func handleProducePhase0V3(
|
||||
Version: version.String(version.Phase0),
|
||||
ExecutionPayloadBlinded: false,
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", payloadValue), // mev not available at this point
|
||||
ConsensusBlockValue: "", // rewards not applicable before altair
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
@@ -178,10 +238,12 @@ func handleProduceAltairV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_Altair,
|
||||
payloadValue uint64,
|
||||
executionPayloadValue uint64,
|
||||
consensusPayloadValue string,
|
||||
) {
|
||||
_, span := trace.StartSpan(ctx, "validator.ProduceBlockV3.internal.handleProduceAltairV3")
|
||||
defer span.End()
|
||||
|
||||
if isSSZ {
|
||||
sszResp, err := blk.Altair.MarshalSSZ()
|
||||
if err != nil {
|
||||
@@ -204,7 +266,8 @@ func handleProduceAltairV3(
|
||||
http2.WriteJson(w, &ProduceBlockV3Response{
|
||||
Version: version.String(version.Altair),
|
||||
ExecutionPayloadBlinded: false,
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", payloadValue), // mev not available at this point
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", executionPayloadValue), // mev not available at this point
|
||||
ConsensusBlockValue: consensusPayloadValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
@@ -214,7 +277,8 @@ func handleProduceBellatrixV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_Bellatrix,
|
||||
payloadValue uint64,
|
||||
executionPayloadValue uint64,
|
||||
consensusPayloadValue string,
|
||||
) {
|
||||
_, span := trace.StartSpan(ctx, "validator.ProduceBlockV3.internal.handleProduceBellatrixV3")
|
||||
defer span.End()
|
||||
@@ -240,7 +304,8 @@ func handleProduceBellatrixV3(
|
||||
http2.WriteJson(w, &ProduceBlockV3Response{
|
||||
Version: version.String(version.Bellatrix),
|
||||
ExecutionPayloadBlinded: false,
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", payloadValue), // mev not available at this point
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", executionPayloadValue), // mev not available at this point
|
||||
ConsensusBlockValue: consensusPayloadValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
@@ -250,7 +315,8 @@ func handleProduceBlindedBellatrixV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_BlindedBellatrix,
|
||||
payloadValue uint64,
|
||||
executionPayloadValue uint64,
|
||||
consensusPayloadValue string,
|
||||
) {
|
||||
_, span := trace.StartSpan(ctx, "validator.ProduceBlockV3.internal.handleProduceBlindedBellatrixV3")
|
||||
defer span.End()
|
||||
@@ -276,7 +342,8 @@ func handleProduceBlindedBellatrixV3(
|
||||
http2.WriteJson(w, &ProduceBlockV3Response{
|
||||
Version: version.String(version.Bellatrix),
|
||||
ExecutionPayloadBlinded: true,
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", payloadValue),
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", executionPayloadValue),
|
||||
ConsensusBlockValue: consensusPayloadValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
@@ -286,7 +353,8 @@ func handleProduceBlindedCapellaV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_BlindedCapella,
|
||||
payloadValue uint64,
|
||||
executionPayloadValue uint64,
|
||||
consensusPayloadValue string,
|
||||
) {
|
||||
_, span := trace.StartSpan(ctx, "validator.ProduceBlockV3.internal.handleProduceBlindedCapellaV3")
|
||||
defer span.End()
|
||||
@@ -312,7 +380,8 @@ func handleProduceBlindedCapellaV3(
|
||||
http2.WriteJson(w, &ProduceBlockV3Response{
|
||||
Version: version.String(version.Capella),
|
||||
ExecutionPayloadBlinded: true,
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", payloadValue),
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", executionPayloadValue),
|
||||
ConsensusBlockValue: consensusPayloadValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
@@ -322,7 +391,8 @@ func handleProduceCapellaV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_Capella,
|
||||
payloadValue uint64,
|
||||
executionPayloadValue uint64,
|
||||
consensusPayloadValue string,
|
||||
) {
|
||||
_, span := trace.StartSpan(ctx, "validator.ProduceBlockV3.internal.handleProduceCapellaV3")
|
||||
defer span.End()
|
||||
@@ -348,7 +418,8 @@ func handleProduceCapellaV3(
|
||||
http2.WriteJson(w, &ProduceBlockV3Response{
|
||||
Version: version.String(version.Capella),
|
||||
ExecutionPayloadBlinded: false,
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", payloadValue), // mev not available at this point
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", executionPayloadValue), // mev not available at this point
|
||||
ConsensusBlockValue: consensusPayloadValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
@@ -358,7 +429,8 @@ func handleProduceBlindedDenebV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_BlindedDeneb,
|
||||
payloadValue uint64,
|
||||
executionPayloadValue uint64,
|
||||
consensusPayloadValue string,
|
||||
) {
|
||||
_, span := trace.StartSpan(ctx, "validator.ProduceBlockV3.internal.handleProduceBlindedDenebV3")
|
||||
defer span.End()
|
||||
@@ -384,7 +456,8 @@ func handleProduceBlindedDenebV3(
|
||||
http2.WriteJson(w, &ProduceBlockV3Response{
|
||||
Version: version.String(version.Deneb),
|
||||
ExecutionPayloadBlinded: true,
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", payloadValue),
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", executionPayloadValue),
|
||||
ConsensusBlockValue: consensusPayloadValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
@@ -394,7 +467,8 @@ func handleProduceDenebV3(
|
||||
w http.ResponseWriter,
|
||||
isSSZ bool,
|
||||
blk *eth.GenericBeaconBlock_Deneb,
|
||||
payloadValue uint64,
|
||||
executionPayloadValue uint64,
|
||||
consensusBlockValue string,
|
||||
) {
|
||||
_, span := trace.StartSpan(ctx, "validator.ProduceBlockV3.internal.handleProduceDenebV3")
|
||||
defer span.End()
|
||||
@@ -420,7 +494,8 @@ func handleProduceDenebV3(
|
||||
http2.WriteJson(w, &ProduceBlockV3Response{
|
||||
Version: version.String(version.Deneb),
|
||||
ExecutionPayloadBlinded: false,
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", payloadValue), // mev not available at this point
|
||||
ExecutionPayloadValue: fmt.Sprintf("%d", executionPayloadValue), // mev not available at this point
|
||||
ConsensusBlockValue: consensusBlockValue,
|
||||
Data: jsonBytes,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/prysmaticlabs/prysm/v4/api"
|
||||
blockchainTesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards"
|
||||
rewardtesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards/testing"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
|
||||
rpctesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared/testing"
|
||||
mockSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/initial-sync/testing"
|
||||
@@ -46,26 +48,31 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"phase0","execution_payload_blinded":false,"execution_payload_value":"0","data":%s}`, string(jsonBytes))
|
||||
want := fmt.Sprintf(`{"version":"phase0","execution_payload_blinded":false,"execution_payload_value":"0","consensus_block_value":"","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "", true)
|
||||
})
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlockAltair
|
||||
err := json.Unmarshal([]byte(rpctesting.AltairBlock), &block)
|
||||
|
||||
require.NoError(t, err)
|
||||
jsonBytes, err := json.Marshal(block.Message)
|
||||
require.NoError(t, err)
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), gomock.Any()).Return(
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
|
||||
return block.Message.ToGeneric()
|
||||
}())
|
||||
mockRewards := &rewards.BlockRewards{Total: "10"}
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -74,11 +81,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"altair","execution_payload_blinded":false,"execution_payload_value":"0","data":%s}`, string(jsonBytes))
|
||||
want := fmt.Sprintf(`{"version":"altair","execution_payload_blinded":false,"execution_payload_value":"0","consensus_block_value":"10","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Bellatrix", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlockBellatrix
|
||||
@@ -92,10 +100,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
return block.Message.ToGeneric()
|
||||
}())
|
||||
mockChainService := &blockchainTesting.ChainService{}
|
||||
mockRewards := &rewards.BlockRewards{Total: "10"}
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -104,11 +114,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"bellatrix","execution_payload_blinded":false,"execution_payload_value":"0","data":%s}`, string(jsonBytes))
|
||||
want := fmt.Sprintf(`{"version":"bellatrix","execution_payload_blinded":false,"execution_payload_value":"0","consensus_block_value":"10","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("BlindedBellatrix", func(t *testing.T) {
|
||||
var block *shared.SignedBlindedBeaconBlockBellatrix
|
||||
@@ -122,10 +133,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
return block.Message.ToGeneric()
|
||||
}())
|
||||
mockChainService := &blockchainTesting.ChainService{}
|
||||
mockRewards := &rewards.BlockRewards{Total: "10"}
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -134,11 +147,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"bellatrix","execution_payload_blinded":true,"execution_payload_value":"0","data":%s}`, string(jsonBytes))
|
||||
want := fmt.Sprintf(`{"version":"bellatrix","execution_payload_blinded":true,"execution_payload_value":"0","consensus_block_value":"10","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "true", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlockCapella
|
||||
@@ -152,10 +166,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
return block.Message.ToGeneric()
|
||||
}())
|
||||
mockChainService := &blockchainTesting.ChainService{}
|
||||
mockRewards := &rewards.BlockRewards{Total: "10"}
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -164,11 +180,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"capella","execution_payload_blinded":false,"execution_payload_value":"0","data":%s}`, string(jsonBytes))
|
||||
want := fmt.Sprintf(`{"version":"capella","execution_payload_blinded":false,"execution_payload_value":"0","consensus_block_value":"10","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Blinded Capella", func(t *testing.T) {
|
||||
var block *shared.SignedBlindedBeaconBlockCapella
|
||||
@@ -185,10 +202,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
return g, err
|
||||
}())
|
||||
mockChainService := &blockchainTesting.ChainService{}
|
||||
mockRewards := &rewards.BlockRewards{Total: "10"}
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -197,11 +216,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"capella","execution_payload_blinded":true,"execution_payload_value":"2000","data":%s}`, string(jsonBytes))
|
||||
want := fmt.Sprintf(`{"version":"capella","execution_payload_blinded":true,"execution_payload_value":"2000","consensus_block_value":"10","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "true", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "2000", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Deneb", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlockContentsDeneb
|
||||
@@ -215,10 +235,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
return block.ToUnsigned().ToGeneric()
|
||||
}())
|
||||
mockChainService := &blockchainTesting.ChainService{}
|
||||
mockRewards := &rewards.BlockRewards{Total: "10"}
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -227,11 +249,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"deneb","execution_payload_blinded":false,"execution_payload_value":"0","data":%s}`, string(jsonBytes))
|
||||
want := fmt.Sprintf(`{"version":"deneb","execution_payload_blinded":false,"execution_payload_value":"0","consensus_block_value":"10","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Blinded Deneb", func(t *testing.T) {
|
||||
var block *shared.SignedBlindedBeaconBlockContentsDeneb
|
||||
@@ -245,10 +268,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
return block.ToUnsigned().ToGeneric()
|
||||
}())
|
||||
mockChainService := &blockchainTesting.ChainService{}
|
||||
mockRewards := &rewards.BlockRewards{Total: "10"}
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -257,11 +282,12 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
server.ProduceBlockV3(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
want := fmt.Sprintf(`{"version":"deneb","execution_payload_blinded":true,"execution_payload_value":"0","data":%s}`, string(jsonBytes))
|
||||
want := fmt.Sprintf(`{"version":"deneb","execution_payload_blinded":true,"execution_payload_value":"0","consensus_block_value":"10","data":%s}`, string(jsonBytes))
|
||||
body := strings.ReplaceAll(writer.Body.String(), "\n", "")
|
||||
require.Equal(t, want, body)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "true", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("invalid query parameter slot empty", func(t *testing.T) {
|
||||
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
|
||||
@@ -321,6 +347,7 @@ func TestProduceBlockV3(t *testing.T) {
|
||||
|
||||
func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
mockRewards := &rewards.BlockRewards{Total: "10"}
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlock
|
||||
err := json.Unmarshal([]byte(rpctesting.Phase0Block), &block)
|
||||
@@ -351,6 +378,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "", true)
|
||||
})
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlockAltair
|
||||
@@ -361,9 +389,11 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
func() (*eth.GenericBeaconBlock, error) {
|
||||
return block.Message.ToGeneric()
|
||||
}())
|
||||
|
||||
server := &Server{
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -382,6 +412,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Bellatrix", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlockBellatrix
|
||||
@@ -397,6 +428,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -415,6 +447,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("BlindedBellatrix", func(t *testing.T) {
|
||||
var block *shared.SignedBlindedBeaconBlockBellatrix
|
||||
@@ -430,6 +463,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -448,6 +482,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "true", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlockCapella
|
||||
@@ -463,6 +498,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -481,6 +517,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Blinded Capella", func(t *testing.T) {
|
||||
var block *shared.SignedBlindedBeaconBlockCapella
|
||||
@@ -499,6 +536,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -517,6 +555,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "true", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "2000", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Deneb", func(t *testing.T) {
|
||||
var block *shared.SignedBeaconBlockContentsDeneb
|
||||
@@ -532,6 +571,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -550,6 +590,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "false", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
t.Run("Blinded Deneb", func(t *testing.T) {
|
||||
var block *shared.SignedBlindedBeaconBlockContentsDeneb
|
||||
@@ -565,6 +606,7 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
V1Alpha1Server: v1alpha1Server,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
BlockRewardFetcher: &rewardtesting.MockBlockRewardFetcher{Rewards: mockRewards},
|
||||
}
|
||||
rr := "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +
|
||||
"&graffiti=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
|
||||
@@ -583,5 +625,6 @@ func TestProduceBlockV3SSZ(t *testing.T) {
|
||||
require.Equal(t, string(ssz), writer.Body.String())
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadBlindedHeader) == "true", true)
|
||||
require.Equal(t, writer.Header().Get(api.ExecutionPayloadValueHeader) == "0", true)
|
||||
require.Equal(t, writer.Header().Get(api.ConsensusBlockValueHeader) == "10", true)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/core"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
|
||||
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
@@ -34,4 +35,5 @@ type Server struct {
|
||||
BlockBuilder builder.BlockBuilder
|
||||
OperationNotifier operation.Notifier
|
||||
CoreService *core.Service
|
||||
BlockRewardFetcher rewards.BlockRewardsFetcher
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ type ProduceBlockV3Response struct {
|
||||
Version string `json:"version"`
|
||||
ExecutionPayloadBlinded bool `json:"execution_payload_blinded"`
|
||||
ExecutionPayloadValue string `json:"execution_payload_value"`
|
||||
ConsensusBlockValue string `json:"consensus_block_value"`
|
||||
Data json.RawMessage `json:"data"` // represents the block values based on the version
|
||||
}
|
||||
|
||||
|
||||
@@ -211,15 +211,15 @@ func (s *Service) Start() {
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
}
|
||||
|
||||
rewardFetcher := &rewards.BlockRewardService{Replayer: ch}
|
||||
rewardsServer := &rewards.Server{
|
||||
Blocker: blocker,
|
||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
||||
ReplayerBuilder: ch,
|
||||
TimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
Stater: stater,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/blocks/{block_id}", rewardsServer.BlockRewards).Methods(http.MethodGet)
|
||||
@@ -304,6 +304,7 @@ func (s *Service) Start() {
|
||||
BlockBuilder: s.cfg.BlockBuilder,
|
||||
OperationNotifier: s.cfg.OperationNotifier,
|
||||
CoreService: coreService,
|
||||
BlockRewardFetcher: rewardFetcher,
|
||||
}
|
||||
|
||||
s.cfg.Router.HandleFunc("/eth/v1/validator/aggregate_attestation", validatorServerV1.GetAggregateAttestation).Methods(http.MethodGet)
|
||||
|
||||
@@ -73,7 +73,8 @@ func AttestingIndices(bf bitfield.Bitfield, committee []primitives.ValidatorInde
|
||||
return nil, fmt.Errorf("bitfield length %d is not equal to committee length %d", bf.Len(), len(committee))
|
||||
}
|
||||
indices := make([]uint64, 0, bf.Count())
|
||||
for _, idx := range bf.BitIndices() {
|
||||
p := bf.BitIndices()
|
||||
for _, idx := range p {
|
||||
if idx < len(committee) {
|
||||
indices = append(indices, uint64(committee[idx]))
|
||||
}
|
||||
@@ -104,6 +105,7 @@ func VerifyIndexedAttestationSig(ctx context.Context, indexedAtt *ethpb.IndexedA
|
||||
ctx, span := trace.StartSpan(ctx, "attestationutil.VerifyIndexedAttestationSig")
|
||||
defer span.End()
|
||||
indices := indexedAtt.AttestingIndices
|
||||
|
||||
messageHash, err := signing.ComputeSigningRoot(indexedAtt.Data, domain)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get signing root of object")
|
||||
|
||||
Reference in New Issue
Block a user