Block rewards API endpoint (#12020)

Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
Radosław Kapka
2023-03-28 18:44:41 +02:00
committed by GitHub
parent 5cbbd26df4
commit 98949d8075
50 changed files with 1772 additions and 2569 deletions

View File

@@ -70,15 +70,16 @@ type Gateway struct {
func New(ctx context.Context, opts ...Option) (*Gateway, error) {
g := &Gateway{
ctx: ctx,
cfg: &config{
router: mux.NewRouter(),
},
cfg: &config{},
}
for _, opt := range opts {
if err := opt(g); err != nil {
return nil, err
}
}
if g.cfg.router == nil {
g.cfg.router = mux.NewRouter()
}
return g, nil
}

View File

@@ -10,11 +10,6 @@ import (
type Option func(g *Gateway) error
func (g *Gateway) SetRouter(r *mux.Router) *Gateway {
g.cfg.router = r
return g
}
func WithPbHandlers(handlers []*PbMux) Option {
return func(g *Gateway) error {
g.cfg.pbHandlers = handlers

View File

@@ -61,6 +61,7 @@ go_library(
"//runtime/prereqs:go_default_library",
"//runtime/version:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_gorilla_mux//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",

View File

@@ -15,6 +15,7 @@ import (
"syscall"
"github.com/ethereum/go-ethereum/common"
"github.com/gorilla/mux"
"github.com/pkg/errors"
apigateway "github.com/prysmaticlabs/prysm/v4/api/gateway"
"github.com/prysmaticlabs/prysm/v4/async/event"
@@ -253,12 +254,13 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
}
log.Debugln("Registering RPC Service")
if err := beacon.registerRPCService(); err != nil {
router := mux.NewRouter()
if err := beacon.registerRPCService(router); err != nil {
return nil, err
}
log.Debugln("Registering GRPC Gateway Service")
if err := beacon.registerGRPCGateway(); err != nil {
if err := beacon.registerGRPCGateway(router); err != nil {
return nil, err
}
@@ -734,7 +736,7 @@ func (b *BeaconNode) registerSlasherService() error {
return b.services.RegisterService(slasherSrv)
}
func (b *BeaconNode) registerRPCService() error {
func (b *BeaconNode) registerRPCService(router *mux.Router) error {
var chainService *blockchain.Service
if err := b.services.FetchService(&chainService); err != nil {
return err
@@ -830,6 +832,7 @@ func (b *BeaconNode) registerRPCService() error {
MaxMsgSize: maxMsgSize,
ProposerIdsCache: b.proposerIdsCache,
BlockBuilder: b.fetchBuilderService(),
Router: router,
})
return b.services.RegisterService(rpcService)
@@ -858,7 +861,7 @@ func (b *BeaconNode) registerPrometheusService(_ *cli.Context) error {
return b.services.RegisterService(service)
}
func (b *BeaconNode) registerGRPCGateway() error {
func (b *BeaconNode) registerGRPCGateway(router *mux.Router) error {
if b.cliCtx.Bool(flags.DisableGRPCGateway.Name) {
return nil
}
@@ -884,6 +887,7 @@ func (b *BeaconNode) registerGRPCGateway() error {
}
opts := []apigateway.Option{
apigateway.WithRouter(router),
apigateway.WithGatewayAddr(gatewayAddress),
apigateway.WithRemoteAddr(selfAddress),
apigateway.WithPbHandlers(muxs),

View File

@@ -28,12 +28,13 @@ go_library(
"//beacon-chain/rpc/eth/debug:go_default_library",
"//beacon-chain/rpc/eth/events:go_default_library",
"//beacon-chain/rpc/eth/node:go_default_library",
"//beacon-chain/rpc/eth/rewards:go_default_library",
"//beacon-chain/rpc/eth/validator:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/beacon:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/debug:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/node:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/slasher:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
@@ -43,6 +44,7 @@ go_library(
"//monitoring/tracing:go_default_library",
"//proto/eth/service:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_gorilla_mux//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//tracing/opentracing:go_default_library",
@@ -68,6 +70,7 @@ go_test(
"//beacon-chain/sync/initial-sync/testing:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_gorilla_mux//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],

View File

@@ -34,8 +34,8 @@ go_library(
"//beacon-chain/operations/voluntaryexits:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
@@ -92,7 +92,6 @@ go_test(
"//beacon-chain/core/transition:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/execution/testing:go_default_library",
"//beacon-chain/operations/attestations:go_default_library",
"//beacon-chain/operations/blstoexec:go_default_library",
"//beacon-chain/operations/blstoexec/mock:go_default_library",
@@ -101,12 +100,11 @@ go_test(
"//beacon-chain/operations/voluntaryexits/mock:go_default_library",
"//beacon-chain/p2p/testing:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//config/features:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",

View File

@@ -25,7 +25,7 @@ func (bs *Server) GetBlindedBlock(ctx context.Context, req *ethpbv1.BlockRequest
ctx, span := trace.StartSpan(ctx, "beacon.GetBlindedBlock")
defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
@@ -80,7 +80,7 @@ func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequ
ctx, span := trace.StartSpan(ctx, "beacon.GetBlindedBlockSSZ")
defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err

View File

@@ -2,17 +2,15 @@ package beacon
import (
"context"
"fmt"
"reflect"
"testing"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
builderTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/builder/testing"
dbTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
executionTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/synccommittee"
mockp2p "github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
@@ -21,7 +19,6 @@ import (
ethpbv1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1"
ethpbv2 "github.com/prysmaticlabs/prysm/v4/proto/eth/v2"
"github.com/prysmaticlabs/prysm/v4/proto/migration"
ethpbalpha "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/testing/util"
@@ -29,774 +26,284 @@ import (
)
func TestServer_GetBlindedBlock(t *testing.T) {
ctx := context.Background()
t.Run("Phase 0", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetPhase0Block().Block.Slot + 1
wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block)
b := util.NewBeaconBlock()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: wsb,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
FinalizationFetcher: &mock.ChainService{},
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
root, err := genBlk.Block.HashTreeRoot()
expected, err := migration.V1Alpha1ToV1SignedBlock(b)
require.NoError(t, err)
tests := []struct {
name string
blockID []byte
want *ethpbalpha.SignedBeaconBlock
wantErr bool
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
wantErr: true,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v1Block, err := migration.V1Alpha1ToV1SignedBlock(tt.want)
require.NoError(t, err)
phase0Block, ok := blk.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_Phase0Block)
require.Equal(t, true, ok)
if !reflect.DeepEqual(phase0Block.Phase0Block, v1Block.Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_PHASE0, blk.Version)
})
}
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
phase0Block, ok := resp.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_Phase0Block)
require.Equal(t, true, ok)
assert.DeepEqual(t, expected.Block, phase0Block.Phase0Block)
assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version)
})
t.Run("Altair", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
genBlk, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetAltairBlock().Block.Slot + 1
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock())
b := util.NewBeaconBlockAltair()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
FinalizationFetcher: &mock.ChainService{},
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
root, err := genBlk.Block.HashTreeRoot()
expected, err := migration.V1Alpha1BeaconBlockAltairToV2(b.Block)
require.NoError(t, err)
tests := []struct {
name string
blockID []byte
want *ethpbalpha.SignedBeaconBlockAltair
wantErr bool
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].GetAltairBlock(),
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].GetAltairBlock(),
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
wantErr: true,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.GetAltairBlock(),
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].GetAltairBlock(),
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].GetAltairBlock(),
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v2Block, err := migration.V1Alpha1BeaconBlockAltairToV2(tt.want.Block)
require.NoError(t, err)
altairBlock, ok := blk.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_AltairBlock)
require.Equal(t, true, ok)
if !reflect.DeepEqual(altairBlock.AltairBlock, v2Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_ALTAIR, blk.Version)
})
}
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
altairBlock, ok := resp.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_AltairBlock)
require.Equal(t, true, ok)
assert.DeepEqual(t, expected, altairBlock.AltairBlock)
assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version)
})
t.Run("Bellatrix", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
genBlk, blkContainers := fillDBTestBlocksBellatrixBlinded(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetBlindedBellatrixBlock().Block.Slot + 1
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedBellatrixBlock())
b := util.NewBlindedBeaconBlockBellatrix()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
FinalizedRoots: map[[32]byte]bool{},
}
mockChainService := &mock.ChainService{}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
ExecutionPayloadReconstructor: &executionTest.EngineClient{
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{},
},
FinalizationFetcher: mockChainService,
}
root, err := genBlk.Block.HashTreeRoot()
expected, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(b.Block)
require.NoError(t, err)
tests := []struct {
name string
blockID []byte
want *ethpbalpha.SignedBlindedBeaconBlockBellatrix
wantErr bool
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].GetBlindedBellatrixBlock(),
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].GetBlindedBellatrixBlock(),
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
wantErr: true,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.GetBlindedBellatrixBlock(),
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].GetBlindedBellatrixBlock(),
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].GetBlindedBellatrixBlock(),
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v2Block, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(tt.want.Block)
require.NoError(t, err)
b, ok := blk.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_BellatrixBlock)
require.Equal(t, true, ok)
if !reflect.DeepEqual(b.BellatrixBlock, v2Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_BELLATRIX, blk.Version)
})
}
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
bellatrixBlock, ok := resp.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_BellatrixBlock)
require.Equal(t, true, ok)
assert.DeepEqual(t, expected, bellatrixBlock.BellatrixBlock)
assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version)
})
t.Run("Capella", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
genBlk, blkContainers := fillDBTestBlocksCapellaBlinded(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetBlindedCapellaBlock().Block.Slot + 1
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedCapellaBlock())
b := util.NewBlindedBeaconBlockCapella()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
FinalizedRoots: map[[32]byte]bool{},
}
mockChainService := &mock.ChainService{}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
ExecutionPayloadReconstructor: &executionTest.EngineClient{
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{},
},
FinalizationFetcher: mockChainService,
}
root, err := genBlk.Block.HashTreeRoot()
expected, err := migration.V1Alpha1BeaconBlockBlindedCapellaToV2Blinded(b.Block)
require.NoError(t, err)
tests := []struct {
name string
blockID []byte
want *ethpbalpha.SignedBlindedBeaconBlockCapella
wantErr bool
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].GetBlindedCapellaBlock(),
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].GetBlindedCapellaBlock(),
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
wantErr: true,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.GetBlindedCapellaBlock(),
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].GetBlindedCapellaBlock(),
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].GetBlindedCapellaBlock(),
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v2Block, err := migration.V1Alpha1BeaconBlockBlindedCapellaToV2Blinded(tt.want.Block)
require.NoError(t, err)
b, ok := blk.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_CapellaBlock)
require.Equal(t, true, ok)
if !reflect.DeepEqual(b.CapellaBlock, v2Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_CAPELLA, blk.Version)
})
}
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
capellaBlock, ok := resp.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_CapellaBlock)
require.Equal(t, true, ok)
assert.DeepEqual(t, expected, capellaBlock.CapellaBlock)
assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version)
})
t.Run("execution optimistic", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock())
b := util.NewBlindedBeaconBlockBellatrix()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
r, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
OptimisticRoots: map[[32]byte]bool{
bytesutil.ToBytes32(headBlock.BlockRoot): true,
},
OptimisticRoots: map[[32]byte]bool{r: true},
}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
}
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: []byte("head"),
})
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
assert.Equal(t, true, blk.ExecutionOptimistic)
assert.Equal(t, true, resp.ExecutionOptimistic)
})
t.Run("finalized", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetPhase0Block())
b := util.NewBeaconBlock()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
root, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
Optimistic: true,
FinalizedRoots: map[[32]byte]bool{
bytesutil.ToBytes32(blkContainers[32].BlockRoot): true,
bytesutil.ToBytes32(blkContainers[64].BlockRoot): false,
},
FinalizedRoots: map[[32]byte]bool{root: true},
}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
t.Run("true", func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: []byte("32"),
})
require.NoError(t, err)
assert.Equal(t, true, blk.Finalized)
})
t.Run("false", func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: []byte("64"),
})
require.NoError(t, err)
assert.Equal(t, false, blk.Finalized)
})
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{BlockId: root[:]})
require.NoError(t, err)
assert.Equal(t, true, resp.Finalized)
})
t.Run("not finalized", func(t *testing.T) {
b := util.NewBeaconBlock()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
root, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{
FinalizedRoots: map[[32]byte]bool{root: false},
}
bs := &Server{
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{BlockId: root[:]})
require.NoError(t, err)
assert.Equal(t, false, resp.Finalized)
})
}
func TestServer_GetBlindedBlockSSZ(t *testing.T) {
ctx := context.Background()
t.Run("Phase 0", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block)
b := util.NewBeaconBlock()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: wsb,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
FinalizationFetcher: mockChainService,
FinalizationFetcher: &mock.ChainService{},
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
blks, err := beaconDB.BlocksBySlot(ctx, 30)
require.Equal(t, true, len(blks) > 0)
expected, err := blk.MarshalSSZ()
require.NoError(t, err)
sszBlock, err := blks[0].MarshalSSZ()
require.NoError(t, err)
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: []byte("30")})
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
assert.NotNil(t, resp)
assert.DeepEqual(t, sszBlock, resp.Data)
assert.DeepEqual(t, expected, resp.Data)
assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version)
})
t.Run("Altair", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock())
b := util.NewBeaconBlockAltair()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
FinalizationFetcher: mockChainService,
FinalizationFetcher: &mock.ChainService{},
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
blks, err := beaconDB.BlocksBySlot(ctx, 30)
require.Equal(t, true, len(blks) > 0)
expected, err := blk.MarshalSSZ()
require.NoError(t, err)
sszBlock, err := blks[0].MarshalSSZ()
require.NoError(t, err)
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: []byte("30")})
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
assert.NotNil(t, resp)
assert.DeepEqual(t, sszBlock, resp.Data)
assert.DeepEqual(t, expected, resp.Data)
assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version)
})
t.Run("Bellatrix", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocksBellatrixBlinded(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedBellatrixBlock())
b := util.NewBlindedBeaconBlockBellatrix()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
}
mockChainService := &mock.ChainService{}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
}
blks, err := beaconDB.BlocksBySlot(ctx, 30)
require.Equal(t, true, len(blks) > 0)
expected, err := blk.MarshalSSZ()
require.NoError(t, err)
sszBlock, err := blks[0].MarshalSSZ()
require.NoError(t, err)
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: []byte("30")})
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
assert.NotNil(t, resp)
assert.DeepEqual(t, sszBlock, resp.Data)
assert.DeepEqual(t, expected, resp.Data)
assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version)
})
t.Run("Capella", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocksCapellaBlinded(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedCapellaBlock())
b := util.NewBlindedBeaconBlockCapella()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
}
mockChainService := &mock.ChainService{}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
}
blks, err := beaconDB.BlocksBySlot(ctx, 30)
require.Equal(t, true, len(blks) > 0)
expected, err := blk.MarshalSSZ()
require.NoError(t, err)
sszBlock, err := blks[0].MarshalSSZ()
require.NoError(t, err)
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: []byte("30")})
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
assert.NotNil(t, resp)
assert.DeepEqual(t, sszBlock, resp.Data)
assert.DeepEqual(t, expected, resp.Data)
assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version)
})
t.Run("execution optimistic", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock())
b := util.NewBlindedBeaconBlockBellatrix()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
r, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
OptimisticRoots: map[[32]byte]bool{
bytesutil.ToBytes32(headBlock.BlockRoot): true,
},
OptimisticRoots: map[[32]byte]bool{r: true},
}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
}
blk, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{
BlockId: []byte("head"),
})
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
assert.Equal(t, true, blk.ExecutionOptimistic)
assert.Equal(t, true, resp.ExecutionOptimistic)
})
t.Run("finalized", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t)
ctx := context.Background()
_, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetPhase0Block())
b := util.NewBeaconBlock()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
root, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
Optimistic: true,
FinalizedRoots: map[[32]byte]bool{
bytesutil.ToBytes32(blkContainers[32].BlockRoot): true,
bytesutil.ToBytes32(blkContainers[64].BlockRoot): false,
},
FinalizedRoots: map[[32]byte]bool{root: true},
}
bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
t.Run("true", func(t *testing.T) {
blk, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{
BlockId: []byte("32"),
})
require.NoError(t, err)
assert.Equal(t, true, blk.Finalized)
})
t.Run("false", func(t *testing.T) {
blk, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{
BlockId: []byte("64"),
})
require.NoError(t, err)
assert.Equal(t, false, blk.Finalized)
})
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: root[:]})
require.NoError(t, err)
assert.Equal(t, true, resp.Finalized)
})
t.Run("not finalized", func(t *testing.T) {
b := util.NewBeaconBlock()
blk, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
root, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{
FinalizedRoots: map[[32]byte]bool{root: false},
}
bs := &Server{
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: root[:]})
require.NoError(t, err)
assert.Equal(t, false, resp.Finalized)
})
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/filters"
rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
@@ -37,23 +38,6 @@ var (
errNilBlock = errors.New("nil block")
)
// blockIdParseError represents an error scenario where a block ID could not be parsed.
type blockIdParseError struct {
message string
}
// newBlockIdParseError creates a new error instance.
func newBlockIdParseError(reason error) blockIdParseError {
return blockIdParseError{
message: errors.Wrapf(reason, "could not parse block ID").Error(),
}
}
// Error returns the underlying error message.
func (e *blockIdParseError) Error() string {
return e.message
}
// GetWeakSubjectivity computes the starting epoch of the current weak subjectivity period, and then also
// determines the best block root and state root to use for a Checkpoint Sync starting from that point.
// DEPRECATED: GetWeakSubjectivity endpoint will no longer be supported
@@ -101,7 +85,7 @@ func (bs *Server) GetBlockHeader(ctx context.Context, req *ethpbv1.BlockRequest)
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockHeader")
defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
@@ -290,7 +274,7 @@ func (bs *Server) GetBlock(ctx context.Context, req *ethpbv1.BlockRequest) (*eth
ctx, span := trace.StartSpan(ctx, "beacon.GetBlock")
defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
@@ -314,7 +298,7 @@ func (bs *Server) GetBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequest) (*
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockSSZ")
defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
@@ -336,7 +320,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockV2")
defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
@@ -390,7 +374,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockSSZV2")
defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
@@ -532,7 +516,7 @@ func (bs *Server) ListBlockAttestations(ctx context.Context, req *ethpbv1.BlockR
ctx, span := trace.StartSpan(ctx, "beacon.ListBlockAttestations")
defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId)
blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err)
if err != nil {
return nil, err
@@ -559,68 +543,8 @@ func (bs *Server) ListBlockAttestations(ctx context.Context, req *ethpbv1.BlockR
}, nil
}
func (bs *Server) blockFromBlockID(ctx context.Context, blockId []byte) (interfaces.ReadOnlySignedBeaconBlock, error) {
var err error
var blk interfaces.ReadOnlySignedBeaconBlock
switch string(blockId) {
case "head":
blk, err = bs.ChainInfoFetcher.HeadBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve head block")
}
case "finalized":
finalized := bs.ChainInfoFetcher.FinalizedCheckpt()
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
blk, err = bs.BeaconDB.Block(ctx, finalizedRoot)
if err != nil {
return nil, errors.New("could not get finalized block from db")
}
case "genesis":
blk, err = bs.BeaconDB.GenesisBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve blocks for genesis slot")
}
default:
if len(blockId) == 32 {
blk, err = bs.BeaconDB.Block(ctx, bytesutil.ToBytes32(blockId))
if err != nil {
return nil, errors.Wrap(err, "could not retrieve block")
}
} else {
slot, err := strconv.ParseUint(string(blockId), 10, 64)
if err != nil {
e := newBlockIdParseError(err)
return nil, &e
}
blks, err := bs.BeaconDB.BlocksBySlot(ctx, primitives.Slot(slot))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve blocks for slot %d", slot)
}
_, roots, err := bs.BeaconDB.BlockRootsBySlot(ctx, primitives.Slot(slot))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve block roots for slot %d", slot)
}
numBlks := len(blks)
if numBlks == 0 {
return nil, nil
}
for i, b := range blks {
canonical, err := bs.ChainInfoFetcher.IsCanonical(ctx, roots[i])
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine if block root is canonical: %v", err)
}
if canonical {
blk = b
break
}
}
}
}
return blk, nil
}
func handleGetBlockError(blk interfaces.ReadOnlySignedBeaconBlock, err error) error {
if invalidBlockIdErr, ok := err.(*blockIdParseError); ok {
if invalidBlockIdErr, ok := err.(*lookup.BlockIdParseError); ok {
return status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr)
}
if err != nil {

File diff suppressed because it is too large Load Diff

View File

@@ -14,8 +14,8 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/slashings"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
v1alpha1validator "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
)
@@ -34,7 +34,8 @@ type Server struct {
SlashingsPool slashings.PoolManager
VoluntaryExitsPool voluntaryexits.PoolManager
StateGenService stategen.StateManager
StateFetcher statefetcher.Fetcher
Stater lookup.Stater
Blocker lookup.Blocker
HeadFetcher blockchain.HeadFetcher
OptimisticModeFetcher blockchain.OptimisticModeFetcher
V1Alpha1ValidatorServer *v1alpha1validator.Server

View File

@@ -6,7 +6,7 @@ import (
"strconv"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
@@ -58,20 +58,20 @@ func (bs *Server) GetStateRoot(ctx context.Context, req *ethpb.StateRequest) (*e
ctx, span := trace.StartSpan(ctx, "beacon.GetStateRoot")
defer span.End()
stateRoot, err := bs.StateFetcher.StateRoot(ctx, req.StateId)
stateRoot, err := bs.Stater.StateRoot(ctx, req.StateId)
if err != nil {
if rootNotFoundErr, ok := err.(*statefetcher.StateRootNotFoundError); ok {
if rootNotFoundErr, ok := err.(*lookup.StateRootNotFoundError); ok {
return nil, status.Errorf(codes.NotFound, "State root not found: %v", rootNotFoundErr)
} else if parseErr, ok := err.(*statefetcher.StateIdParseError); ok {
} else if parseErr, ok := err.(*lookup.StateIdParseError); ok {
return nil, status.Errorf(codes.InvalidArgument, "Invalid state ID: %v", parseErr)
}
return nil, status.Errorf(codes.Internal, "Could not get state root: %v", err)
}
st, err := bs.StateFetcher.State(ctx, req.StateId)
st, err := bs.Stater.State(ctx, req.StateId)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}
@@ -95,12 +95,12 @@ func (bs *Server) GetStateFork(ctx context.Context, req *ethpb.StateRequest) (*e
ctx, span := trace.StartSpan(ctx, "beacon.GetStateFork")
defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId)
st, err := bs.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
fork := st.Fork()
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}
@@ -127,11 +127,11 @@ func (bs *Server) GetFinalityCheckpoints(ctx context.Context, req *ethpb.StateRe
ctx, span := trace.StartSpan(ctx, "beacon.GetFinalityCheckpoints")
defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId)
st, err := bs.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}
@@ -160,7 +160,7 @@ func (bs *Server) GetRandao(ctx context.Context, req *eth2.RandaoRequest) (*eth2
ctx, span := trace.StartSpan(ctx, "beacon.GetRandao")
defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId)
st, err := bs.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
@@ -186,7 +186,7 @@ func (bs *Server) GetRandao(ctx context.Context, req *eth2.RandaoRequest) (*eth2
return nil, status.Errorf(codes.Internal, "Could not get randao mix at index %d", idx)
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}
@@ -215,14 +215,14 @@ func (bs *Server) stateFromRequest(ctx context.Context, req *stateRequest) (stat
err,
)
}
st, err := bs.StateFetcher.State(ctx, []byte(strconv.FormatUint(uint64(slot), 10)))
st, err := bs.Stater.State(ctx, []byte(strconv.FormatUint(uint64(slot), 10)))
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
return st, nil
}
var err error
st, err := bs.StateFetcher.State(ctx, req.stateId)
st, err := bs.Stater.State(ctx, req.stateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}

View File

@@ -83,7 +83,7 @@ func TestGetStateRoot(t *testing.T) {
chainService := &chainMock.ChainService{}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconStateRoot: stateRoot[:],
BeaconState: fakeState,
},
@@ -111,7 +111,7 @@ func TestGetStateRoot(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconStateRoot: stateRoot[:],
BeaconState: fakeState,
},
@@ -145,7 +145,7 @@ func TestGetStateRoot(t *testing.T) {
},
}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconStateRoot: stateRoot[:],
BeaconState: fakeState,
},
@@ -179,7 +179,7 @@ func TestGetStateFork(t *testing.T) {
chainService := &chainMock.ChainService{}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: chainService,
@@ -209,7 +209,7 @@ func TestGetStateFork(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: chainService,
@@ -242,7 +242,7 @@ func TestGetStateFork(t *testing.T) {
},
}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: chainService,
@@ -282,7 +282,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
chainService := &chainMock.ChainService{}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: chainService,
@@ -314,7 +314,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: chainService,
@@ -347,7 +347,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
},
}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: chainService,
@@ -388,7 +388,7 @@ func TestGetRandao(t *testing.T) {
db := dbTest.SetupDB(t)
chainService := &chainMock.ChainService{}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -413,7 +413,7 @@ func TestGetRandao(t *testing.T) {
assert.DeepEqual(t, mixOld, resp.Data.Randao)
})
t.Run("head state below `EpochsPerHistoricalVector`", func(t *testing.T) {
server.StateFetcher = &testutil.MockFetcher{
server.Stater = &testutil.MockStater{
BeaconState: headSt,
}
resp, err := server.GetRandao(ctx, &eth2.RandaoRequest{StateId: []byte("head")})
@@ -441,7 +441,7 @@ func TestGetRandao(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -473,7 +473,7 @@ func TestGetRandao(t *testing.T) {
},
}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,

View File

@@ -91,7 +91,7 @@ func (bs *Server) ListSyncCommittees(ctx context.Context, req *ethpbv2.StateSync
return nil, status.Errorf(codes.Internal, "Could not extract sync subcommittees: %v", err)
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}

View File

@@ -167,7 +167,7 @@ func TestListSyncCommittees(t *testing.T) {
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -213,7 +213,7 @@ func TestListSyncCommittees(t *testing.T) {
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -249,7 +249,7 @@ func TestListSyncCommittees(t *testing.T) {
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -309,7 +309,7 @@ func TestListSyncCommitteesFuture(t *testing.T) {
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(),
},
StateFetcher: &futureSyncMockFetcher{
Stater: &futureSyncMockFetcher{
BeaconState: st,
},
HeadFetcher: chainService,

View File

@@ -42,7 +42,7 @@ func (bs *Server) GetValidator(ctx context.Context, req *ethpb.StateValidatorReq
ctx, span := trace.StartSpan(ctx, "beacon.GetValidator")
defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId)
st, err := bs.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
@@ -57,7 +57,7 @@ func (bs *Server) GetValidator(ctx context.Context, req *ethpb.StateValidatorReq
return nil, status.Error(codes.NotFound, "Could not find validator")
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}
@@ -76,7 +76,7 @@ func (bs *Server) ListValidators(ctx context.Context, req *ethpb.StateValidators
ctx, span := trace.StartSpan(ctx, "beacon.ListValidators")
defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId)
st, err := bs.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
@@ -86,7 +86,7 @@ func (bs *Server) ListValidators(ctx context.Context, req *ethpb.StateValidators
return nil, handleValContainerErr(err)
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}
@@ -138,7 +138,7 @@ func (bs *Server) ListValidatorBalances(ctx context.Context, req *ethpb.Validato
ctx, span := trace.StartSpan(ctx, "beacon.ListValidatorBalances")
defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId)
st, err := bs.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
@@ -155,7 +155,7 @@ func (bs *Server) ListValidatorBalances(ctx context.Context, req *ethpb.Validato
}
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}
@@ -175,7 +175,7 @@ func (bs *Server) ListCommittees(ctx context.Context, req *ethpb.StateCommittees
ctx, span := trace.StartSpan(ctx, "beacon.ListCommittees")
defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId)
st, err := bs.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
@@ -220,7 +220,7 @@ func (bs *Server) ListCommittees(ctx context.Context, req *ethpb.StateCommittees
}
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}

View File

@@ -9,7 +9,7 @@ import (
chainMock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
dbTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native"
@@ -34,7 +34,7 @@ func TestGetValidator(t *testing.T) {
t.Run("Head Get Validator by index", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -54,7 +54,7 @@ func TestGetValidator(t *testing.T) {
t.Run("Head Get Validator by pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -75,7 +75,7 @@ func TestGetValidator(t *testing.T) {
t.Run("Validator ID required", func(t *testing.T) {
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: &chainMock.ChainService{},
@@ -98,7 +98,7 @@ func TestGetValidator(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -131,7 +131,7 @@ func TestGetValidator(t *testing.T) {
},
}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -157,7 +157,7 @@ func TestListValidators(t *testing.T) {
t.Run("Head List All Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -179,7 +179,7 @@ func TestListValidators(t *testing.T) {
t.Run("Head List Validators by index", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -204,7 +204,7 @@ func TestListValidators(t *testing.T) {
t.Run("Head List Validators by pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -233,7 +233,7 @@ func TestListValidators(t *testing.T) {
t.Run("Head List Validators by both index and pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -264,7 +264,7 @@ func TestListValidators(t *testing.T) {
t.Run("Unknown public key is ignored", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -287,7 +287,7 @@ func TestListValidators(t *testing.T) {
t.Run("Unknown index is ignored", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -317,7 +317,7 @@ func TestListValidators(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -349,7 +349,7 @@ func TestListValidators(t *testing.T) {
},
}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -440,7 +440,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All ACTIVE Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &statefetcher.StateProvider{
Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st},
},
HeadFetcher: chainService,
@@ -478,7 +478,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All ACTIVE_ONGOING Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &statefetcher.StateProvider{
Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st},
},
HeadFetcher: chainService,
@@ -515,7 +515,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All EXITED Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &statefetcher.StateProvider{
Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st},
},
HeadFetcher: chainService,
@@ -551,7 +551,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All PENDING_INITIALIZED and EXITED_UNSLASHED Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &statefetcher.StateProvider{
Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st},
},
HeadFetcher: chainService,
@@ -587,7 +587,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All PENDING and EXITED Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &statefetcher.StateProvider{
Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st},
},
HeadFetcher: chainService,
@@ -638,7 +638,7 @@ func TestListValidatorBalances(t *testing.T) {
t.Run("Head List Validators Balance by index", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -663,7 +663,7 @@ func TestListValidatorBalances(t *testing.T) {
t.Run("Head List Validators Balance by pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -691,7 +691,7 @@ func TestListValidatorBalances(t *testing.T) {
t.Run("Head List Validators Balance by both index and pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -726,7 +726,7 @@ func TestListValidatorBalances(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -761,7 +761,7 @@ func TestListValidatorBalances(t *testing.T) {
},
}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -791,7 +791,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -814,7 +814,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees of Epoch 10", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -836,7 +836,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees of Slot 4", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -864,7 +864,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees of Index 1", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -892,7 +892,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees of Slot 2, Index 1", func(t *testing.T) {
chainService := &chainMock.ChainService{}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -928,7 +928,7 @@ func TestListCommittees(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,
@@ -961,7 +961,7 @@ func TestListCommittees(t *testing.T) {
},
}
s := Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: st,
},
HeadFetcher: chainService,

View File

@@ -12,7 +12,7 @@ go_library(
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/migration:go_default_library",

View File

@@ -19,7 +19,7 @@ func (ds *Server) GetBeaconStateSSZ(ctx context.Context, req *ethpbv1.StateReque
ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateSSZ")
defer span.End()
state, err := ds.StateFetcher.State(ctx, req.StateId)
state, err := ds.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
@@ -37,11 +37,11 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.BeaconState
ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateV2")
defer span.End()
beaconSt, err := ds.StateFetcher.State(ctx, req.StateId)
beaconSt, err := ds.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, ds.OptimisticModeFetcher, ds.StateFetcher, ds.ChainInfoFetcher, ds.BeaconDB)
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, ds.OptimisticModeFetcher, ds.Stater, ds.ChainInfoFetcher, ds.BeaconDB)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
}
@@ -114,7 +114,7 @@ func (ds *Server) GetBeaconStateSSZV2(ctx context.Context, req *ethpbv2.BeaconSt
ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateSSZV2")
defer span.End()
st, err := ds.StateFetcher.State(ctx, req.StateId)
st, err := ds.Stater.State(ctx, req.StateId)
if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err)
}

View File

@@ -28,7 +28,7 @@ func TestGetBeaconStateV2(t *testing.T) {
fakeState, err := util.NewBeaconState()
require.NoError(t, err)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: &blockchainmock.ChainService{},
@@ -46,7 +46,7 @@ func TestGetBeaconStateV2(t *testing.T) {
t.Run("Altair", func(t *testing.T) {
fakeState, _ := util.DeterministicGenesisStateAltair(t, 1)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: &blockchainmock.ChainService{},
@@ -64,7 +64,7 @@ func TestGetBeaconStateV2(t *testing.T) {
t.Run("Bellatrix", func(t *testing.T) {
fakeState, _ := util.DeterministicGenesisStateBellatrix(t, 1)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: &blockchainmock.ChainService{},
@@ -82,7 +82,7 @@ func TestGetBeaconStateV2(t *testing.T) {
t.Run("Capella", func(t *testing.T) {
fakeState, _ := util.DeterministicGenesisStateCapella(t, 1)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: &blockchainmock.ChainService{},
@@ -108,7 +108,7 @@ func TestGetBeaconStateV2(t *testing.T) {
fakeState, _ := util.DeterministicGenesisStateBellatrix(t, 1)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: &blockchainmock.ChainService{},
@@ -141,7 +141,7 @@ func TestGetBeaconStateV2(t *testing.T) {
},
}
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
HeadFetcher: chainService,
@@ -165,7 +165,7 @@ func TestGetBeaconStateSSZ(t *testing.T) {
require.NoError(t, err)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
}
@@ -186,7 +186,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) {
require.NoError(t, err)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
}
@@ -205,7 +205,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) {
require.NoError(t, err)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
}
@@ -224,7 +224,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) {
require.NoError(t, err)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
}
@@ -243,7 +243,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) {
require.NoError(t, err)
server := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
BeaconState: fakeState,
},
}

View File

@@ -6,7 +6,7 @@ package debug
import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
)
// Server defines a server implementation of the gRPC Beacon Chain service,
@@ -14,7 +14,7 @@ import (
type Server struct {
BeaconDB db.ReadOnlyDatabase
HeadFetcher blockchain.HeadFetcher
StateFetcher statefetcher.Fetcher
Stater lookup.Stater
OptimisticModeFetcher blockchain.OptimisticModeFetcher
ForkFetcher blockchain.ForkFetcher
ForkchoiceFetcher blockchain.ForkchoiceFetcher

View File

@@ -13,7 +13,7 @@ go_library(
"//api/grpc:go_default_library",
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",

View File

@@ -3,7 +3,7 @@ package helpers
import (
"errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -15,10 +15,10 @@ func PrepareStateFetchGRPCError(err error) error {
if errors.Is(err, stategen.ErrNoDataForSlot) {
return status.Errorf(codes.NotFound, "lacking historical data needed to fulfill request")
}
if stateNotFoundErr, ok := err.(*statefetcher.StateNotFoundError); ok {
if stateNotFoundErr, ok := err.(*lookup.StateNotFoundError); ok {
return status.Errorf(codes.NotFound, "State not found: %v", stateNotFoundErr)
}
if parseErr, ok := err.(*statefetcher.StateIdParseError); ok {
if parseErr, ok := err.(*lookup.StateIdParseError); ok {
return status.Errorf(codes.InvalidArgument, "Invalid state ID: %v", parseErr)
}
return status.Errorf(codes.Internal, "Invalid state ID: %v", err)

View File

@@ -9,7 +9,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/api/grpc"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
@@ -61,7 +61,7 @@ func IsOptimistic(
ctx context.Context,
stateId []byte,
optimisticModeFetcher blockchain.OptimisticModeFetcher,
stateFetcher statefetcher.Fetcher,
stateFetcher lookup.Stater,
chainInfo blockchain.ChainInfoFetcher,
database db.ReadOnlyDatabase,
) (bool, error) {
@@ -97,7 +97,7 @@ func IsOptimistic(
slotNumber, parseErr := strconv.ParseUint(stateIdString, 10, 64)
if parseErr != nil {
// ID format does not match any valid options.
e := statefetcher.NewStateIdParseError(parseErr)
e := lookup.NewStateIdParseError(parseErr)
return true, &e
}
fcp := chainInfo.FinalizedCheckpt()
@@ -146,7 +146,7 @@ func isStateRootOptimistic(
ctx context.Context,
stateId []byte,
optimisticModeFetcher blockchain.OptimisticModeFetcher,
stateFetcher statefetcher.Fetcher,
stateFetcher lookup.Stater,
chainInfo blockchain.ChainInfoFetcher,
database db.ReadOnlyDatabase,
) (bool, error) {

View File

@@ -97,7 +97,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: &eth.Checkpoint{}, OptimisticRoots: map[[32]byte]bool{[32]byte{}: true}}
mf := &testutil.MockFetcher{BeaconState: st}
mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte("finalized"), cs, mf, cs, nil)
require.NoError(t, err)
assert.Equal(t, true, o)
@@ -106,7 +106,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: &eth.Checkpoint{}}
mf := &testutil.MockFetcher{BeaconState: st}
mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte("finalized"), cs, mf, cs, nil)
require.NoError(t, err)
assert.Equal(t, false, o)
@@ -117,7 +117,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true, CurrentJustifiedCheckPoint: &eth.Checkpoint{}, OptimisticRoots: map[[32]byte]bool{[32]byte{}: true}}
mf := &testutil.MockFetcher{BeaconState: st}
mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte("justified"), cs, mf, cs, nil)
require.NoError(t, err)
assert.Equal(t, true, o)
@@ -126,7 +126,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true, CurrentJustifiedCheckPoint: &eth.Checkpoint{}}
mf := &testutil.MockFetcher{BeaconState: st}
mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte("justified"), cs, mf, cs, nil)
require.NoError(t, err)
assert.Equal(t, false, o)
@@ -137,7 +137,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true}
mf := &testutil.MockFetcher{BeaconState: st}
mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, nil)
require.NoError(t, err)
assert.Equal(t, true, o)
@@ -146,7 +146,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: false}
mf := &testutil.MockFetcher{BeaconState: st}
mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, nil)
require.NoError(t, err)
assert.Equal(t, false, o)
@@ -165,7 +165,7 @@ func TestIsOptimistic(t *testing.T) {
bRoot, err := b.Block().HashTreeRoot()
require.NoError(t, err)
cs := &chainmock.ChainService{State: chainSt, OptimisticRoots: map[[32]byte]bool{bRoot: true}}
mf := &testutil.MockFetcher{BeaconState: fetcherSt}
mf := &testutil.MockStater{BeaconState: fetcherSt}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, db)
require.NoError(t, err)
assert.Equal(t, true, o)
@@ -182,7 +182,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err)
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch))
cs := &chainmock.ChainService{State: chainSt}
mf := &testutil.MockFetcher{BeaconState: fetcherSt}
mf := &testutil.MockStater{BeaconState: fetcherSt}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, db)
require.NoError(t, err)
assert.Equal(t, false, o)
@@ -198,7 +198,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err)
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch))
cs := &chainmock.ChainService{Optimistic: false, State: chainSt, CanonicalRoots: map[[32]byte]bool{}}
mf := &testutil.MockFetcher{BeaconState: fetcherSt}
mf := &testutil.MockStater{BeaconState: fetcherSt}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), nil, mf, cs, db)
require.NoError(t, err)
assert.Equal(t, true, o)
@@ -248,7 +248,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err)
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch*2))
cs := &chainmock.ChainService{Optimistic: true, State: chainSt, FinalizedCheckPoint: &eth.Checkpoint{Epoch: 0}}
mf := &testutil.MockFetcher{BeaconState: fetcherSt}
mf := &testutil.MockStater{BeaconState: fetcherSt}
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
require.NoError(t, err)
assert.Equal(t, true, o)
@@ -268,7 +268,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err)
require.NoError(t, fcs.InsertNode(ctx, st, root))
cs := &chainmock.ChainService{Root: headRoot[:], Optimistic: true, ForkChoiceStore: fcs, OptimisticRoots: map[[32]byte]bool{r: true}, FinalizedCheckPoint: finalizedCheckpt}
mf := &testutil.MockFetcher{BeaconState: st}
mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
require.NoError(t, err)
assert.Equal(t, true, o)
@@ -288,7 +288,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err)
require.NoError(t, fcs.InsertNode(ctx, st, root))
cs := &chainmock.ChainService{Root: headRoot[:], Optimistic: true, ForkChoiceStore: fcs, OptimisticRoots: map[[32]byte]bool{r: false}, FinalizedCheckPoint: finalizedCheckpt}
mf := &testutil.MockFetcher{BeaconState: st}
mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
require.NoError(t, err)
assert.Equal(t, false, o)

View File

@@ -0,0 +1,52 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"handlers.go",
"server.go",
"structs.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//network:go_default_library",
"//runtime/version: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 = [
"//beacon-chain/blockchain/testing:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state/stategen/mock:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/bls/blst:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
],
)

View File

@@ -0,0 +1,189 @@
package rewards
import (
"net/http"
"strconv"
"strings"
"github.com/pkg/errors"
"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/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/network"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
)
// BlockRewards is an HTTP handler for Beacon API getBlockRewards.
func (s *Server) BlockRewards(w http.ResponseWriter, r *http.Request) {
segments := strings.Split(r.URL.Path, "/")
blockId := segments[len(segments)-1]
blk, err := s.Blocker.Block(r.Context(), []byte(blockId))
if errJson := handleGetBlockError(blk, err); errJson != nil {
network.WriteError(w, errJson)
return
}
if blk.Version() == version.Phase0 {
errJson := &network.DefaultErrorJson{
Message: "block rewards are not supported for Phase 0 blocks",
Code: http.StatusBadRequest,
}
network.WriteError(w, errJson)
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 {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get state").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
proposerIndex := blk.Block().ProposerIndex()
initBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer's balance").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
st, err = altair.ProcessAttestationsNoVerifySignature(r.Context(), st, blk)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get attestation rewards").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
attBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer's balance").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
st, err = coreblocks.ProcessAttesterSlashings(r.Context(), st, blk.Block().Body().AttesterSlashings(), validators.SlashValidator)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get attester slashing rewards").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
attSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer's balance").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
st, err = coreblocks.ProcessProposerSlashings(r.Context(), st, blk.Block().Body().ProposerSlashings(), validators.SlashValidator)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer slashing rewards").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
proposerSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer's balance").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
sa, err := blk.Block().Body().SyncAggregate()
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get sync aggregate").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
var syncCommitteeReward uint64
_, syncCommitteeReward, err = altair.ProcessSyncAggregate(r.Context(), st, sa)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get sync aggregate rewards").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
optimistic, err := s.OptimisticModeFetcher.IsOptimistic(r.Context())
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get optimistic mode info").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
blkRoot, err := blk.Block().HashTreeRoot()
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get block root").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
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),
},
ExecutionOptimistic: optimistic,
Finalized: s.FinalizationFetcher.IsFinalized(r.Context(), blkRoot),
}
network.WriteJson(w, response)
}
func handleGetBlockError(blk interfaces.ReadOnlySignedBeaconBlock, err error) *network.DefaultErrorJson {
if errors.Is(err, lookup.BlockIdParseError{}) {
return &network.DefaultErrorJson{
Message: errors.Wrapf(err, "invalid block ID").Error(),
Code: http.StatusBadRequest,
}
}
if err != nil {
return &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get block from block ID").Error(),
Code: http.StatusInternalServerError,
}
}
if err := blocks.BeaconBlockIsNil(blk); err != nil {
return &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not find requested block").Error(),
Code: http.StatusNotFound,
}
}
return nil
}

View File

@@ -0,0 +1,198 @@
package rewards
import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/prysmaticlabs/go-bitfield"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/signing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
mockstategen "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen/mock"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/prysmaticlabs/prysm/v4/crypto/bls/blst"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/network"
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/testing/util"
)
func TestBlockRewards(t *testing.T) {
valCount := 64
st, err := util.NewBeaconStateAltair()
require.NoError(t, st.SetSlot(1))
require.NoError(t, err)
validators := make([]*eth.Validator, 0, valCount)
balances := make([]uint64, 0, valCount)
secretKeys := make([]bls.SecretKey, 0, valCount)
for i := 0; i < valCount; i++ {
blsKey, err := bls.RandKey()
require.NoError(t, err)
secretKeys = append(secretKeys, blsKey)
validators = append(validators, &eth.Validator{
PublicKey: blsKey.PublicKey().Marshal(),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
})
balances = append(balances, params.BeaconConfig().MaxEffectiveBalance)
}
require.NoError(t, st.SetValidators(validators))
require.NoError(t, st.SetBalances(balances))
require.NoError(t, st.SetCurrentParticipationBits(make([]byte, valCount)))
syncCommittee, err := altair.NextSyncCommittee(context.Background(), st)
require.NoError(t, err)
require.NoError(t, st.SetCurrentSyncCommittee(syncCommittee))
slot0bRoot := bytesutil.PadTo([]byte("slot0root"), 32)
bRoots := make([][]byte, fieldparams.BlockRootsLength)
bRoots[0] = slot0bRoot
require.NoError(t, st.SetBlockRoots(bRoots))
b := util.HydrateSignedBeaconBlockAltair(util.NewBeaconBlockAltair())
b.Block.Slot = 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{
{
AggregationBits: bitfield.Bitlist{0b00000111},
Data: util.HydrateAttestationData(&eth.AttestationData{}),
Signature: make([]byte, fieldparams.BLSSignatureLength),
},
{
AggregationBits: bitfield.Bitlist{0b00000111},
Data: util.HydrateAttestationData(&eth.AttestationData{}),
Signature: make([]byte, fieldparams.BLSSignatureLength),
},
}
attData1 := util.HydrateAttestationData(&eth.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte("root1"), 32)})
attData2 := util.HydrateAttestationData(&eth.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte("root2"), 32)})
domain, err := signing.Domain(st.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorsRoot())
require.NoError(t, err)
sigRoot1, err := signing.ComputeSigningRoot(attData1, domain)
require.NoError(t, err)
sigRoot2, err := signing.ComputeSigningRoot(attData2, domain)
require.NoError(t, err)
b.Block.Body.AttesterSlashings = []*eth.AttesterSlashing{
{
Attestation_1: &eth.IndexedAttestation{
AttestingIndices: []uint64{0},
Data: attData1,
Signature: secretKeys[0].Sign(sigRoot1[:]).Marshal(),
},
Attestation_2: &eth.IndexedAttestation{
AttestingIndices: []uint64{0},
Data: attData2,
Signature: secretKeys[0].Sign(sigRoot2[:]).Marshal(),
},
},
}
header1 := &eth.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 1,
ParentRoot: bytesutil.PadTo([]byte("root1"), 32),
StateRoot: bytesutil.PadTo([]byte("root1"), 32),
BodyRoot: bytesutil.PadTo([]byte("root1"), 32),
}
header2 := &eth.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 1,
ParentRoot: bytesutil.PadTo([]byte("root2"), 32),
StateRoot: bytesutil.PadTo([]byte("root2"), 32),
BodyRoot: bytesutil.PadTo([]byte("root2"), 32),
}
domain, err = signing.Domain(st.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, st.GenesisValidatorsRoot())
require.NoError(t, err)
sigRoot1, err = signing.ComputeSigningRoot(header1, domain)
require.NoError(t, err)
sigRoot2, err = signing.ComputeSigningRoot(header2, domain)
require.NoError(t, err)
b.Block.Body.ProposerSlashings = []*eth.ProposerSlashing{
{
Header_1: &eth.SignedBeaconBlockHeader{
Header: header1,
Signature: secretKeys[1].Sign(sigRoot1[:]).Marshal(),
},
Header_2: &eth.SignedBeaconBlockHeader{
Header: header2,
Signature: secretKeys[1].Sign(sigRoot2[:]).Marshal(),
},
},
}
scBits := bitfield.NewBitvector512()
scBits.SetBitAt(10, true)
scBits.SetBitAt(100, true)
domain, err = signing.Domain(st.Fork(), 0, params.BeaconConfig().DomainSyncCommittee, st.GenesisValidatorsRoot())
require.NoError(t, err)
sszBytes := primitives.SSZBytes(slot0bRoot)
r, err := signing.ComputeSigningRoot(&sszBytes, domain)
require.NoError(t, err)
// Bits set in sync committee bits determine which validators will be treated as participating in sync committee.
// These validators have to sign the message.
sig1, err := blst.SignatureFromBytes(secretKeys[47].Sign(r[:]).Marshal())
require.NoError(t, err)
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 = &eth.SyncAggregate{SyncCommitteeBits: scBits, SyncCommitteeSignature: aggSig}
sbb, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
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("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()
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("phase 0", func(t *testing.T) {
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 := &network.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)
})
}

View File

@@ -0,0 +1,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
}

View File

@@ -0,0 +1,16 @@
package rewards
type BlockRewardsResponse struct {
Data *BlockRewards `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
type BlockRewards struct {
ProposerIndex string `json:"proposer_index"`
Total string `json:"total"`
Attestations string `json:"attestations"`
SyncAggregate string `json:"sync_aggregate"`
ProposerSlashings string `json:"proposer_slashings"`
AttesterSlashings string `json:"attester_slashings"`
}

View File

@@ -19,8 +19,8 @@ go_library(
"//beacon-chain/operations/synccommittee:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/sync:go_default_library",

View File

@@ -7,8 +7,8 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/attestations"
"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/lookup"
v1alpha1validator "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
)
@@ -21,7 +21,7 @@ type Server struct {
AttestationsPool attestations.Pool
PeerManager p2p.PeerManager
Broadcaster p2p.Broadcaster
StateFetcher statefetcher.Fetcher
Stater lookup.Stater
OptimisticModeFetcher blockchain.OptimisticModeFetcher
SyncCommitteePool synccommittee.Pool
V1Alpha1Server *v1alpha1validator.Server

View File

@@ -70,7 +70,7 @@ func (vs *Server) GetAttesterDuties(ctx context.Context, req *ethpbv1.AttesterDu
return nil, status.Errorf(codes.Internal, "Could not get start slot from epoch %d: %v", req.Epoch, err)
}
s, err := vs.StateFetcher.StateBySlot(ctx, startSlot)
s, err := vs.Stater.StateBySlot(ctx, startSlot)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
}
@@ -159,7 +159,7 @@ func (vs *Server) GetProposerDuties(ctx context.Context, req *ethpbv1.ProposerDu
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get start slot from epoch %d: %v", req.Epoch, err)
}
s, err := vs.StateFetcher.StateBySlot(ctx, startSlot)
s, err := vs.Stater.StateBySlot(ctx, startSlot)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
}
@@ -243,7 +243,7 @@ func (vs *Server) GetSyncCommitteeDuties(ctx context.Context, req *ethpbv2.SyncC
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get sync committee slot: %v", err)
}
st, err := vs.StateFetcher.State(ctx, []byte(strconv.FormatUint(uint64(slot), 10)))
st, err := vs.Stater.State(ctx, []byte(strconv.FormatUint(uint64(slot), 10)))
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get sync committee state: %v", err)
}
@@ -282,7 +282,7 @@ func (vs *Server) GetSyncCommitteeDuties(ctx context.Context, req *ethpbv2.SyncC
ctx,
[]byte(strconv.FormatUint(uint64(slot), 10)),
vs.OptimisticModeFetcher,
vs.StateFetcher,
vs.Stater,
vs.ChainInfoFetcher,
vs.BeaconDB,
)
@@ -1081,7 +1081,7 @@ func (vs *Server) GetLiveness(ctx context.Context, req *ethpbv2.GetLivenessReque
if err != nil {
return nil, status.Error(codes.Internal, "Could not get requested epoch's end slot")
}
st, err = vs.StateFetcher.StateBySlot(ctx, epochEnd)
st, err = vs.Stater.StateBySlot(ctx, epochEnd)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get slot for requested epoch")
}

View File

@@ -93,7 +93,7 @@ func TestGetAttesterDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
}
vs := &Server{
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
StatesBySlot: map[primitives.Slot]state.BeaconState{
0: bs,
params.BeaconConfig().SlotsPerEpoch: nextEpochState,
@@ -198,7 +198,7 @@ func TestGetAttesterDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true,
}
vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
TimeFetcher: chain,
OptimisticModeFetcher: chain,
SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -258,7 +258,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
}
vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
HeadFetcher: chain,
TimeFetcher: chain,
OptimisticModeFetcher: chain,
@@ -297,7 +297,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
}
vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
HeadFetcher: chain,
TimeFetcher: chain,
OptimisticModeFetcher: chain,
@@ -337,7 +337,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
}
vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{params.BeaconConfig().SlotsPerEpoch: bs}},
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{params.BeaconConfig().SlotsPerEpoch: bs}},
HeadFetcher: chain,
TimeFetcher: chain,
OptimisticModeFetcher: chain,
@@ -377,7 +377,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
}
vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
HeadFetcher: chain,
TimeFetcher: chain,
OptimisticModeFetcher: chain,
@@ -414,7 +414,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true,
}
vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
HeadFetcher: chain,
TimeFetcher: chain,
OptimisticModeFetcher: chain,
@@ -469,7 +469,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
mockChainService := &mockChain.ChainService{Genesis: genesisTime}
vs := &Server{
StateFetcher: &testutil.MockFetcher{BeaconState: st},
Stater: &testutil.MockStater{BeaconState: st},
SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: mockChainService,
HeadFetcher: mockChainService,
@@ -611,7 +611,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
}
mockChainService := &mockChain.ChainService{Genesis: genesisTime, Slot: &newSyncPeriodStartSlot}
vs := &Server{
StateFetcher: &testutil.MockFetcher{BeaconState: stateFetchFn(newSyncPeriodStartSlot)},
Stater: &testutil.MockStater{BeaconState: stateFetchFn(newSyncPeriodStartSlot)},
SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: mockChainService,
HeadFetcher: mockChainService,
@@ -665,7 +665,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
State: state,
}
vs := &Server{
StateFetcher: &testutil.MockFetcher{BeaconState: st},
Stater: &testutil.MockStater{BeaconState: st},
SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: mockChainService,
HeadFetcher: mockChainService,
@@ -5021,7 +5021,7 @@ func TestGetLiveness(t *testing.T) {
server := &Server{
HeadFetcher: &mockChain.ChainService{State: headSt},
StateFetcher: &testutil.MockFetcher{
Stater: &testutil.MockStater{
// We configure states for last slots of an epoch
StatesBySlot: map[primitives.Slot]state.BeaconState{
params.BeaconConfig().SlotsPerEpoch - 1: oldSt,

View File

@@ -2,9 +2,12 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["fetcher.go"],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher",
visibility = ["//beacon-chain:__subpackages__"],
srcs = [
"blocker.go",
"stater.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/db:go_default_library",
@@ -12,6 +15,7 @@ go_library(
"//beacon-chain/state/stategen:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//time/slots:go_default_library",
@@ -22,11 +26,15 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["fetcher_test.go"],
srcs = [
"blocker_test.go",
"stater_test.go",
],
embed = [":go_default_library"],
deps = [
"//beacon-chain/blockchain/testing:go_default_library",
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/state/stategen/mock:go_default_library",

View File

@@ -0,0 +1,108 @@
package lookup
import (
"context"
"strconv"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
)
// BlockIdParseError represents an error scenario where a block ID could not be parsed.
type BlockIdParseError struct {
message string
}
// NewBlockIdParseError creates a new error instance.
func NewBlockIdParseError(reason error) BlockIdParseError {
return BlockIdParseError{
message: errors.Wrapf(reason, "could not parse block ID").Error(),
}
}
// Error returns the underlying error message.
func (e BlockIdParseError) Error() string {
return e.message
}
// Blocker is responsible for retrieving blocks.
type Blocker interface {
Block(ctx context.Context, id []byte) (interfaces.ReadOnlySignedBeaconBlock, error)
}
// BeaconDbBlocker is an implementation of Blocker. It retrieves blocks from the beacon chain database.
type BeaconDbBlocker struct {
BeaconDB db.ReadOnlyDatabase
ChainInfoFetcher blockchain.ChainInfoFetcher
}
// Block returns the beacon block for a given identifier. The identifier can be one of:
// - "head" (canonical head in node's view)
// - "genesis"
// - "finalized"
// - "justified"
// - <slot>
// - <hex encoded block root with '0x' prefix>
func (p *BeaconDbBlocker) Block(ctx context.Context, id []byte) (interfaces.ReadOnlySignedBeaconBlock, error) {
var err error
var blk interfaces.ReadOnlySignedBeaconBlock
switch string(id) {
case "head":
blk, err = p.ChainInfoFetcher.HeadBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve head block")
}
case "finalized":
finalized := p.ChainInfoFetcher.FinalizedCheckpt()
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
blk, err = p.BeaconDB.Block(ctx, finalizedRoot)
if err != nil {
return nil, errors.New("could not get finalized block from db")
}
case "genesis":
blk, err = p.BeaconDB.GenesisBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve genesis block")
}
default:
if len(id) == 32 {
blk, err = p.BeaconDB.Block(ctx, bytesutil.ToBytes32(id))
if err != nil {
return nil, errors.Wrap(err, "could not retrieve block")
}
} else {
slot, err := strconv.ParseUint(string(id), 10, 64)
if err != nil {
e := NewBlockIdParseError(err)
return nil, &e
}
blks, err := p.BeaconDB.BlocksBySlot(ctx, primitives.Slot(slot))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve blocks for slot %d", slot)
}
_, roots, err := p.BeaconDB.BlockRootsBySlot(ctx, primitives.Slot(slot))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve block roots for slot %d", slot)
}
numBlks := len(blks)
if numBlks == 0 {
return nil, nil
}
for i, b := range blks {
canonical, err := p.ChainInfoFetcher.IsCanonical(ctx, roots[i])
if err != nil {
return nil, errors.Wrapf(err, "could not determine if block root is canonical")
}
if canonical {
blk = b
break
}
}
}
}
return blk, nil
}

View File

@@ -0,0 +1,144 @@
package lookup
import (
"context"
"fmt"
"reflect"
"testing"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
dbtesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpbalpha "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/testing/util"
)
func TestGetBlock(t *testing.T) {
beaconDB := dbtesting.SetupDB(t)
ctx := context.Background()
genBlk, blkContainers := testutil.FillDBWithBlocks(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetPhase0Block().Block.Slot + 1
b2 := util.NewBeaconBlock()
b2.Block.Slot = 30
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
util.SaveBlock(t, ctx, beaconDB, b2)
b3 := util.NewBeaconBlock()
b3.Block.Slot = 30
b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32)
util.SaveBlock(t, ctx, beaconDB, b3)
b4 := util.NewBeaconBlock()
b4.Block.Slot = nextSlot
b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32)
util.SaveBlock(t, ctx, beaconDB, b4)
wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block)
require.NoError(t, err)
fetcher := &BeaconDbBlocker{
BeaconDB: beaconDB,
ChainInfoFetcher: &mock.ChainService{
DB: beaconDB,
Block: wsb,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
},
}
root, err := genBlk.Block.HashTreeRoot()
require.NoError(t, err)
tests := []struct {
name string
blockID []byte
want *ethpbalpha.SignedBeaconBlock
wantErr bool
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
want: nil,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
want: nil,
},
{
name: "no block",
blockID: []byte("105"),
want: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := fetcher.Block(ctx, tt.blockID)
if tt.wantErr {
assert.NotEqual(t, err, nil, "no error has been returned")
return
}
if tt.want == nil {
assert.Equal(t, nil, result)
return
}
require.NoError(t, err)
pbBlock, err := result.PbPhase0Block()
require.NoError(t, err)
if !reflect.DeepEqual(pbBlock, tt.want) {
t.Error("Expected blocks to equal")
}
})
}
}

View File

@@ -1,4 +1,4 @@
package statefetcher
package lookup
import (
"bytes"
@@ -71,15 +71,15 @@ func (e *StateRootNotFoundError) Error() string {
return e.message
}
// Fetcher is responsible for retrieving info related with the beacon chain.
type Fetcher interface {
State(ctx context.Context, stateId []byte) (state.BeaconState, error)
StateRoot(ctx context.Context, stateId []byte) ([]byte, error)
// Stater is responsible for retrieving states.
type Stater interface {
State(ctx context.Context, id []byte) (state.BeaconState, error)
StateRoot(ctx context.Context, id []byte) ([]byte, error)
StateBySlot(ctx context.Context, slot primitives.Slot) (state.BeaconState, error)
}
// StateProvider is a real implementation of Fetcher.
type StateProvider struct {
// BeaconDbStater is an implementation of Stater. It retrieves states from the beacon chain database.
type BeaconDbStater struct {
BeaconDB db.ReadOnlyDatabase
ChainInfoFetcher blockchain.ChainInfoFetcher
GenesisTimeFetcher blockchain.TimeFetcher
@@ -94,7 +94,7 @@ type StateProvider struct {
// - "justified"
// - <slot>
// - <hex encoded state root with '0x' prefix>
func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.BeaconState, error) {
func (p *BeaconDbStater) State(ctx context.Context, stateId []byte) (state.BeaconState, error) {
var (
s state.BeaconState
err error
@@ -164,7 +164,7 @@ func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.Beacon
// - "justified"
// - <slot>
// - <hex encoded state root with '0x' prefix>
func (p *StateProvider) StateRoot(ctx context.Context, stateId []byte) (root []byte, err error) {
func (p *BeaconDbStater) StateRoot(ctx context.Context, stateId []byte) (root []byte, err error) {
stateIdString := strings.ToLower(string(stateId))
switch stateIdString {
case "head":
@@ -192,7 +192,7 @@ func (p *StateProvider) StateRoot(ctx context.Context, stateId []byte) (root []b
return root, err
}
func (p *StateProvider) stateByRoot(ctx context.Context, stateRoot []byte) (state.BeaconState, error) {
func (p *BeaconDbStater) stateByRoot(ctx context.Context, stateRoot []byte) (state.BeaconState, error) {
headState, err := p.ChainInfoFetcher.HeadStateReadOnly(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get head state")
@@ -213,7 +213,7 @@ func (p *StateProvider) stateByRoot(ctx context.Context, stateRoot []byte) (stat
// between the found state's slot and the target slot.
// process_blocks is applied for all canonical blocks, and process_slots is called for any skipped
// slots, or slots following the most recent canonical block up to and including the target slot.
func (p *StateProvider) StateBySlot(ctx context.Context, target primitives.Slot) (state.BeaconState, error) {
func (p *BeaconDbStater) StateBySlot(ctx context.Context, target primitives.Slot) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "statefetcher.StateBySlot")
defer span.End()
@@ -229,7 +229,7 @@ func (p *StateProvider) StateBySlot(ctx context.Context, target primitives.Slot)
return st, nil
}
func (p *StateProvider) headStateRoot(ctx context.Context) ([]byte, error) {
func (p *BeaconDbStater) headStateRoot(ctx context.Context) ([]byte, error) {
b, err := p.ChainInfoFetcher.HeadBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get head block")
@@ -241,7 +241,7 @@ func (p *StateProvider) headStateRoot(ctx context.Context) ([]byte, error) {
return stateRoot[:], nil
}
func (p *StateProvider) genesisStateRoot(ctx context.Context) ([]byte, error) {
func (p *BeaconDbStater) genesisStateRoot(ctx context.Context) ([]byte, error) {
b, err := p.BeaconDB.GenesisBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get genesis block")
@@ -253,7 +253,7 @@ func (p *StateProvider) genesisStateRoot(ctx context.Context) ([]byte, error) {
return stateRoot[:], nil
}
func (p *StateProvider) finalizedStateRoot(ctx context.Context) ([]byte, error) {
func (p *BeaconDbStater) finalizedStateRoot(ctx context.Context) ([]byte, error) {
cp, err := p.BeaconDB.FinalizedCheckpoint(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get finalized checkpoint")
@@ -269,7 +269,7 @@ func (p *StateProvider) finalizedStateRoot(ctx context.Context) ([]byte, error)
return stateRoot[:], nil
}
func (p *StateProvider) justifiedStateRoot(ctx context.Context) ([]byte, error) {
func (p *BeaconDbStater) justifiedStateRoot(ctx context.Context) ([]byte, error) {
cp, err := p.BeaconDB.JustifiedCheckpoint(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not get justified checkpoint")
@@ -285,7 +285,7 @@ func (p *StateProvider) justifiedStateRoot(ctx context.Context) ([]byte, error)
return stateRoot[:], nil
}
func (p *StateProvider) stateRootByRoot(ctx context.Context, stateRoot []byte) ([]byte, error) {
func (p *BeaconDbStater) stateRootByRoot(ctx context.Context, stateRoot []byte) ([]byte, error) {
var r [32]byte
copy(r[:], stateRoot)
headState, err := p.ChainInfoFetcher.HeadStateReadOnly(ctx)
@@ -302,7 +302,7 @@ func (p *StateProvider) stateRootByRoot(ctx context.Context, stateRoot []byte) (
return nil, &rootNotFoundErr
}
func (p *StateProvider) stateRootBySlot(ctx context.Context, slot primitives.Slot) ([]byte, error) {
func (p *BeaconDbStater) stateRootBySlot(ctx context.Context, slot primitives.Slot) ([]byte, error) {
currentSlot := p.GenesisTimeFetcher.CurrentSlot()
if slot > currentSlot {
return nil, errors.New("slot cannot be in the future")

View File

@@ -1,4 +1,4 @@
package statefetcher
package lookup
import (
"context"
@@ -38,7 +38,7 @@ func TestGetState(t *testing.T) {
require.NoError(t, err)
t.Run("head", func(t *testing.T) {
p := StateProvider{
p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
}
@@ -78,7 +78,7 @@ func TestGetState(t *testing.T) {
cs := &mockstategen.MockCurrentSlotter{Slot: bs.Slot() + 1}
ch := stategen.NewCanonicalHistory(db, cc, cs)
currentSlot := primitives.Slot(0)
p := StateProvider{
p := BeaconDbStater{
BeaconDB: db,
ReplayerBuilder: ch,
GenesisTimeFetcher: &chainMock.ChainService{Slot: &currentSlot},
@@ -98,7 +98,7 @@ func TestGetState(t *testing.T) {
replayer.SetMockStateForSlot(newBeaconState, params.BeaconConfig().SlotsPerEpoch*10)
stateGen.StatesByRoot[stateRoot] = newBeaconState
p := StateProvider{
p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{
FinalizedCheckPoint: &ethpb.Checkpoint{
Root: stateRoot[:],
@@ -122,7 +122,7 @@ func TestGetState(t *testing.T) {
replayer.SetMockStateForSlot(newBeaconState, params.BeaconConfig().SlotsPerEpoch*10)
stateGen.StatesByRoot[stateRoot] = newBeaconState
p := StateProvider{
p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{
CurrentJustifiedCheckPoint: &ethpb.Checkpoint{
Root: stateRoot[:],
@@ -146,7 +146,7 @@ func TestGetState(t *testing.T) {
stateGen := mockstategen.NewMockService()
stateGen.StatesByRoot[bytesutil.ToBytes32(stateId)] = newBeaconState
p := StateProvider{
p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
StateGenService: stateGen,
}
@@ -159,7 +159,7 @@ func TestGetState(t *testing.T) {
})
t.Run("hex_root_not_found", func(t *testing.T) {
p := StateProvider{
p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
}
stateId, err := hexutil.Decode("0x" + strings.Repeat("f", 64))
@@ -169,7 +169,7 @@ func TestGetState(t *testing.T) {
})
t.Run("slot", func(t *testing.T) {
p := StateProvider{
p := BeaconDbStater{
GenesisTimeFetcher: &chainMock.ChainService{Slot: &headSlot},
ChainInfoFetcher: &chainMock.ChainService{
CanonicalRoots: map[[32]byte]bool{
@@ -188,7 +188,7 @@ func TestGetState(t *testing.T) {
})
t.Run("invalid_state", func(t *testing.T) {
p := StateProvider{}
p := BeaconDbStater{}
_, err := p.State(ctx, []byte("foo"))
require.ErrorContains(t, "could not parse state ID", err)
})
@@ -212,7 +212,7 @@ func TestGetStateRoot(t *testing.T) {
b.Block.StateRoot = stateRoot[:]
wsb, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
p := StateProvider{
p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{
State: newBeaconState,
Block: wsb,
@@ -241,7 +241,7 @@ func TestGetStateRoot(t *testing.T) {
require.NoError(t, db.SaveGenesisBlockRoot(ctx, r))
require.NoError(t, db.SaveState(ctx, bs, r))
p := StateProvider{
p := BeaconDbStater{
BeaconDB: db,
}
@@ -275,7 +275,7 @@ func TestGetStateRoot(t *testing.T) {
require.NoError(t, db.SaveState(ctx, st, root))
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp))
p := StateProvider{
p := BeaconDbStater{
BeaconDB: db,
}
@@ -306,7 +306,7 @@ func TestGetStateRoot(t *testing.T) {
require.NoError(t, db.SaveState(ctx, st, root))
require.NoError(t, db.SaveJustifiedCheckpoint(ctx, cp))
p := StateProvider{
p := BeaconDbStater{
BeaconDB: db,
}
@@ -319,7 +319,7 @@ func TestGetStateRoot(t *testing.T) {
stateId, err := hexutil.Decode("0x" + strings.Repeat("0", 63) + "1")
require.NoError(t, err)
p := StateProvider{
p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
}
@@ -329,7 +329,7 @@ func TestGetStateRoot(t *testing.T) {
})
t.Run("hex_root_not_found", func(t *testing.T) {
p := StateProvider{
p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
}
stateId, err := hexutil.Decode("0x" + strings.Repeat("f", 64))
@@ -355,7 +355,7 @@ func TestGetStateRoot(t *testing.T) {
require.NoError(t, db.SaveState(ctx, st, root))
slot := primitives.Slot(40)
p := StateProvider{
p := BeaconDbStater{
GenesisTimeFetcher: &chainMock.ChainService{Slot: &slot},
BeaconDB: db,
}
@@ -366,7 +366,7 @@ func TestGetStateRoot(t *testing.T) {
})
t.Run("slot_too_big", func(t *testing.T) {
p := StateProvider{
p := BeaconDbStater{
GenesisTimeFetcher: &chainMock.ChainService{
Genesis: time.Now(),
},
@@ -376,7 +376,7 @@ func TestGetStateRoot(t *testing.T) {
})
t.Run("invalid_state", func(t *testing.T) {
p := StateProvider{}
p := BeaconDbStater{}
_, err := p.StateRoot(ctx, []byte("foo"))
require.ErrorContains(t, "could not parse state ID", err)
})
@@ -389,7 +389,7 @@ func TestNewStateNotFoundError(t *testing.T) {
func TestStateBySlot_FutureSlot(t *testing.T) {
slot := primitives.Slot(100)
p := StateProvider{GenesisTimeFetcher: &chainMock.ChainService{Slot: &slot}}
p := BeaconDbStater{GenesisTimeFetcher: &chainMock.ChainService{Slot: &slot}}
_, err := p.StateBySlot(context.Background(), 101)
assert.ErrorContains(t, "requested slot is in the future", err)
}
@@ -403,7 +403,7 @@ func TestStateBySlot_AfterHeadSlot(t *testing.T) {
mock := &chainMock.ChainService{State: headSt, Slot: &currentSlot}
mockReplayer := mockstategen.NewMockReplayerBuilder()
mockReplayer.SetMockStateForSlot(slotSt, 101)
p := StateProvider{ChainInfoFetcher: mock, GenesisTimeFetcher: mock, ReplayerBuilder: mockReplayer}
p := BeaconDbStater{ChainInfoFetcher: mock, GenesisTimeFetcher: mock, ReplayerBuilder: mockReplayer}
st, err := p.StateBySlot(context.Background(), 101)
require.NoError(t, err)
assert.Equal(t, primitives.Slot(101), st.Slot())

View File

@@ -8,6 +8,7 @@ import (
"net"
"sync"
"github.com/gorilla/mux"
middleware "github.com/grpc-ecosystem/go-grpc-middleware"
recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
@@ -32,12 +33,13 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/debug"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/events"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/node"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
beaconv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/beacon"
debugv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/debug"
nodev1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/node"
validatorv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
slasherservice "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
chainSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
@@ -117,6 +119,7 @@ type Config struct {
ProposerIdsCache *cache.ProposerPayloadIDsCache
OptimisticModeFetcher blockchain.OptimisticModeFetcher
BlockBuilder builder.BlockBuilder
Router *mux.Router
}
// NewService instantiates a new RPC service instance that will
@@ -189,6 +192,25 @@ func (s *Service) Start() {
}
withCache := stategen.WithCache(stateCache)
ch := stategen.NewCanonicalHistory(s.cfg.BeaconDB, s.cfg.ChainInfoFetcher, s.cfg.ChainInfoFetcher, withCache)
stater := &lookup.BeaconDbStater{
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
StateGenService: s.cfg.StateGen,
ReplayerBuilder: ch,
}
blocker := &lookup.BeaconDbBlocker{
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
}
rewardsServer := &rewards.Server{
Blocker: blocker,
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
FinalizationFetcher: s.cfg.FinalizationFetcher,
ReplayerBuilder: ch,
}
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/blocks/{block_id}", rewardsServer.BlockRewards)
validatorServer := &validatorv1alpha1.Server{
Ctx: s.ctx,
@@ -226,21 +248,15 @@ func (s *Service) Start() {
BLSChangesPool: s.cfg.BLSChangesPool,
}
validatorServerV1 := &validator.Server{
HeadFetcher: s.cfg.HeadFetcher,
TimeFetcher: s.cfg.GenesisTimeFetcher,
SyncChecker: s.cfg.SyncService,
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
AttestationsPool: s.cfg.AttestationsPool,
PeerManager: s.cfg.PeerManager,
Broadcaster: s.cfg.Broadcaster,
V1Alpha1Server: validatorServer,
StateFetcher: &statefetcher.StateProvider{
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
StateGenService: s.cfg.StateGen,
ReplayerBuilder: ch,
},
HeadFetcher: s.cfg.HeadFetcher,
TimeFetcher: s.cfg.GenesisTimeFetcher,
SyncChecker: s.cfg.SyncService,
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
AttestationsPool: s.cfg.AttestationsPool,
PeerManager: s.cfg.PeerManager,
Broadcaster: s.cfg.Broadcaster,
V1Alpha1Server: validatorServer,
Stater: stater,
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
ProposerSlotIndexCache: s.cfg.ProposerIdsCache,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
@@ -298,24 +314,19 @@ func (s *Service) Start() {
ReplayerBuilder: ch,
}
beaconChainServerV1 := &beacon.Server{
CanonicalHistory: ch,
BeaconDB: s.cfg.BeaconDB,
AttestationsPool: s.cfg.AttestationsPool,
SlashingsPool: s.cfg.SlashingsPool,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
BlockNotifier: s.cfg.BlockNotifier,
OperationNotifier: s.cfg.OperationNotifier,
Broadcaster: s.cfg.Broadcaster,
BlockReceiver: s.cfg.BlockReceiver,
StateGenService: s.cfg.StateGen,
StateFetcher: &statefetcher.StateProvider{
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
StateGenService: s.cfg.StateGen,
ReplayerBuilder: ch,
},
CanonicalHistory: ch,
BeaconDB: s.cfg.BeaconDB,
AttestationsPool: s.cfg.AttestationsPool,
SlashingsPool: s.cfg.SlashingsPool,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
BlockNotifier: s.cfg.BlockNotifier,
OperationNotifier: s.cfg.OperationNotifier,
Broadcaster: s.cfg.Broadcaster,
BlockReceiver: s.cfg.BlockReceiver,
StateGenService: s.cfg.StateGen,
Stater: stater,
Blocker: blocker,
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
HeadFetcher: s.cfg.HeadFetcher,
VoluntaryExitsPool: s.cfg.ExitPool,
@@ -350,15 +361,9 @@ func (s *Service) Start() {
ReplayerBuilder: ch,
}
debugServerV1 := &debug.Server{
BeaconDB: s.cfg.BeaconDB,
HeadFetcher: s.cfg.HeadFetcher,
StateFetcher: &statefetcher.StateProvider{
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
StateGenService: s.cfg.StateGen,
ReplayerBuilder: ch,
},
BeaconDB: s.cfg.BeaconDB,
HeadFetcher: s.cfg.HeadFetcher,
Stater: stater,
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
ForkFetcher: s.cfg.ForkFetcher,
ForkchoiceFetcher: s.cfg.ForkchoiceFetcher,

View File

@@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/gorilla/mux"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
mockExecution "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing"
mockSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/initial-sync/testing"
@@ -35,6 +36,7 @@ func TestLifecycle_OK(t *testing.T) {
GenesisTimeFetcher: chainService,
ExecutionChainService: &mockExecution.Chain{},
StateNotifier: chainService.StateNotifier(),
Router: mux.NewRouter(),
})
rpcService.Start()
@@ -75,6 +77,7 @@ func TestRPC_InsecureEndpoint(t *testing.T) {
HeadFetcher: chainService,
ExecutionChainService: &mockExecution.Chain{},
StateNotifier: chainService.StateNotifier(),
Router: mux.NewRouter(),
})
rpcService.Start()

View File

@@ -4,15 +4,24 @@ go_library(
name = "go_default_library",
testonly = True,
srcs = [
"db.go",
"mock_blocker.go",
"mock_exec_chain_info_fetcher.go",
"mock_genesis_timefetcher.go",
"mock_state_fetcher.go",
"mock_stater.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/db:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
],
)

View File

@@ -0,0 +1,51 @@
package testutil
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpbalpha "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/testing/util"
)
func FillDBWithBlocks(ctx context.Context, t *testing.T, beaconDB db.Database) (*ethpbalpha.SignedBeaconBlock, []*ethpbalpha.BeaconBlockContainer) {
parentRoot := [32]byte{1, 2, 3}
genBlk := util.NewBeaconBlock()
genBlk.Block.ParentRoot = parentRoot[:]
root, err := genBlk.Block.HashTreeRoot()
require.NoError(t, err)
util.SaveBlock(t, ctx, beaconDB, genBlk)
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, root))
count := primitives.Slot(100)
blks := make([]interfaces.ReadOnlySignedBeaconBlock, count)
blkContainers := make([]*ethpbalpha.BeaconBlockContainer, count)
for i := primitives.Slot(0); i < count; i++ {
b := util.NewBeaconBlock()
b.Block.Slot = i
b.Block.ParentRoot = bytesutil.PadTo([]byte{uint8(i)}, 32)
root, err := b.Block.HashTreeRoot()
require.NoError(t, err)
blks[i], err = blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
blkContainers[i] = &ethpbalpha.BeaconBlockContainer{
Block: &ethpbalpha.BeaconBlockContainer_Phase0Block{Phase0Block: b},
BlockRoot: root[:],
}
}
require.NoError(t, beaconDB.SaveBlocks(ctx, blks))
headRoot := bytesutil.ToBytes32(blkContainers[len(blks)-1].BlockRoot)
summary := &ethpbalpha.StateSummary{
Root: headRoot[:],
Slot: blkContainers[len(blks)-1].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block.Block.Slot,
}
require.NoError(t, beaconDB.SaveStateSummary(ctx, summary))
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, headRoot))
return genBlk, blkContainers
}

View File

@@ -0,0 +1,28 @@
package testutil
import (
"context"
"strconv"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
)
// MockBlocker is a fake implementation of lookup.Blocker.
type MockBlocker struct {
BlockToReturn interfaces.ReadOnlySignedBeaconBlock
ErrorToReturn error
SlotBlockMap map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock
}
// Block --
func (m *MockBlocker) Block(_ context.Context, b []byte) (interfaces.ReadOnlySignedBeaconBlock, error) {
if m.ErrorToReturn != nil {
return nil, m.ErrorToReturn
}
slotNumber, parseErr := strconv.ParseUint(string(b), 10, 64)
if parseErr != nil {
return m.BlockToReturn, nil
}
return m.SlotBlockMap[primitives.Slot(slotNumber)], nil
}

View File

@@ -7,23 +7,24 @@ import (
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
)
// MockFetcher is a fake implementation of statefetcher.Fetcher.
type MockFetcher struct {
// MockStater is a fake implementation of lookup.Stater.
type MockStater struct {
BeaconState state.BeaconState
BeaconStateRoot []byte
StatesBySlot map[primitives.Slot]state.BeaconState
}
// State --
func (m *MockFetcher) State(context.Context, []byte) (state.BeaconState, error) {
func (m *MockStater) State(context.Context, []byte) (state.BeaconState, error) {
return m.BeaconState, nil
}
// StateRoot --
func (m *MockFetcher) StateRoot(context.Context, []byte) ([]byte, error) {
func (m *MockStater) StateRoot(context.Context, []byte) ([]byte, error) {
return m.BeaconStateRoot, nil
}
func (m *MockFetcher) StateBySlot(_ context.Context, s primitives.Slot) (state.BeaconState, error) {
// StateBySlot --
func (m *MockStater) StateBySlot(_ context.Context, s primitives.Slot) (state.BeaconState, error) {
return m.StatesBySlot[s], nil
}

View File

@@ -45,6 +45,7 @@ func main() {
log.SetLevel(logrus.DebugLevel)
}
r := mux.NewRouter()
gatewayConfig := beaconGateway.DefaultConfig(*enableDebugRPCEndpoints, *httpModules)
muxs := make([]*gateway.PbMux, 0)
if gatewayConfig.V1AlphaPbMux != nil {
@@ -54,6 +55,7 @@ func main() {
muxs = append(muxs, gatewayConfig.EthPbMux)
}
opts := []gateway.Option{
gateway.WithRouter(r),
gateway.WithPbHandlers(muxs),
gateway.WithMuxHandler(gatewayConfig.Handler),
gateway.WithRemoteAddr(*beaconRPC),
@@ -71,10 +73,8 @@ func main() {
log.Fatal(err)
}
r := mux.NewRouter()
r.HandleFunc("/swagger/", gateway.SwaggerServer())
r.HandleFunc("/healthz", healthzServer(gw))
gw.SetRouter(r)
gw.Start()

View File

@@ -6,6 +6,7 @@ go_library(
"auth.go",
"endpoint.go",
"external_ip.go",
"writer.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/network",
visibility = ["//visibility:public"],
@@ -13,6 +14,7 @@ go_library(
"//network/authorization:go_default_library",
"@com_github_golang_jwt_jwt_v4//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)

41
network/writer.go Normal file
View File

@@ -0,0 +1,41 @@
package network
import (
"bytes"
"encoding/json"
"io"
"net/http"
"strconv"
log "github.com/sirupsen/logrus"
)
// DefaultErrorJson is a JSON representation of a simple error value, containing only a message and an error code.
type DefaultErrorJson struct {
Message string `json:"message"`
Code int `json:"code"`
}
// WriteJson writes the response message in JSON format.
func WriteJson(w http.ResponseWriter, v any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(v); err != nil {
log.WithError(err).Error("Could not write response message")
}
}
// WriteError writes the error by manipulating headers and the body of the final response.
func WriteError(w http.ResponseWriter, errJson *DefaultErrorJson) {
j, err := json.Marshal(errJson)
if err != nil {
log.WithError(err).Error("Could not marshal error message")
return
}
w.Header().Set("Content-Length", strconv.Itoa(len(j)))
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(errJson.Code)
if _, err := io.Copy(w, io.NopCloser(bytes.NewReader(j))); err != nil {
log.WithError(err).Error("Could not write error message")
}
}

View File

@@ -69,6 +69,7 @@ go_library(
"//validator/web:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_gorilla_mux//:go_default_library",
"@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",

View File

@@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/gorilla/mux"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/pkg/errors"
fastssz "github.com/prysmaticlabs/fastssz"
@@ -764,6 +765,7 @@ func (c *ValidatorClient) registerRPCGatewayService(cliCtx *cli.Context) error {
Mux: gwmux,
}
opts := []gateway.Option{
gateway.WithRouter(mux.NewRouter()),
gateway.WithRemoteAddr(rpcAddr),
gateway.WithGatewayAddr(gatewayAddress),
gateway.WithMaxCallRecvMsgSize(maxCallSize),