Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ListPoolProposerSlashings and ListPoolVoluntaryExits in the beacon API #8508

Merged
merged 6 commits into from
Feb 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions beacon-chain/blockchain/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type Service struct {
chainStartFetcher powchain.ChainStartFetcher
attPool attestations.Pool
slashingPool slashings.PoolManager
exitPool *voluntaryexits.Pool
exitPool voluntaryexits.PoolManager
genesisTime time.Time
p2p p2p.Broadcaster
maxRoutines int
Expand Down Expand Up @@ -88,7 +88,7 @@ type Config struct {
BeaconDB db.HeadAccessDatabase
DepositCache *depositcache.DepositCache
AttPool attestations.Pool
ExitPool *voluntaryexits.Pool
ExitPool voluntaryexits.PoolManager
SlashingPool slashings.PoolManager
P2p p2p.Broadcaster
MaxRoutines int
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ type BeaconNode struct {
stop chan struct{} // Channel to wait for termination notifications.
db db.Database
attestationPool attestations.Pool
exitPool *voluntaryexits.Pool
exitPool voluntaryexits.PoolManager
slashingsPool slashings.PoolManager
depositCache *depositcache.DepositCache
stateFeed *event.Feed
Expand Down
5 changes: 3 additions & 2 deletions beacon-chain/operations/slashings/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import (

// PoolMock is a fake implementation of PoolManager.
type PoolMock struct {
PendingAttSlashings []*ethpb.AttesterSlashing
PendingAttSlashings []*ethpb.AttesterSlashing
PendingPropSlashings []*ethpb.ProposerSlashing
}

// PendingAttesterSlashings --
Expand All @@ -19,7 +20,7 @@ func (m *PoolMock) PendingAttesterSlashings(ctx context.Context, state *state.Be

// PendingProposerSlashings --
func (m *PoolMock) PendingProposerSlashings(ctx context.Context, state *state.BeaconState, noLimit bool) []*ethpb.ProposerSlashing {
panic("implement me")
return m.PendingPropSlashings
}

// InsertAttesterSlashing --
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/operations/voluntaryexits/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go_library(
name = "go_default_library",
srcs = [
"doc.go",
"mock.go",
"service.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits",
Expand Down
29 changes: 29 additions & 0 deletions beacon-chain/operations/voluntaryexits/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package voluntaryexits

import (
"context"

types "github.com/prysmaticlabs/eth2-types"
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
)

// PoolMock is a fake implementation of PoolManager.
type PoolMock struct {
Exits []*eth.SignedVoluntaryExit
}

// PendingExits --
func (m *PoolMock) PendingExits(_ *beaconstate.BeaconState, _ types.Slot, _ bool) []*eth.SignedVoluntaryExit {
return m.Exits
}

// InsertVoluntaryExit --
func (*PoolMock) InsertVoluntaryExit(_ context.Context, _ *beaconstate.BeaconState, _ *eth.SignedVoluntaryExit) {
panic("implement me")
}

// MarkIncluded --
func (*PoolMock) MarkIncluded(_ *eth.SignedVoluntaryExit) {
panic("implement me")
}
11 changes: 9 additions & 2 deletions beacon-chain/operations/voluntaryexits/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,15 @@ import (
"go.opencensus.io/trace"
)

// Pool implements a struct to maintain pending and seen voluntary exits. This pool
// is used by proposers to insert into new blocks.
// PoolManager maintains pending and seen voluntary exits.
// This pool is used by proposers to insert voluntary exits into new blocks.
type PoolManager interface {
PendingExits(state *beaconstate.BeaconState, slot types.Slot, noLimit bool) []*ethpb.SignedVoluntaryExit
InsertVoluntaryExit(ctx context.Context, state *beaconstate.BeaconState, exit *ethpb.SignedVoluntaryExit)
MarkIncluded(exit *ethpb.SignedVoluntaryExit)
}

// Pool is a concrete implementation of PoolManager.
type Pool struct {
lock sync.RWMutex
pending []*ethpb.SignedVoluntaryExit
Expand Down
2 changes: 2 additions & 0 deletions beacon-chain/rpc/beaconv1/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ go_library(
"//beacon-chain/db/filters:go_default_library",
"//beacon-chain/operations/attestations:go_default_library",
"//beacon-chain/operations/slashings:go_default_library",
"//beacon-chain/operations/voluntaryexits:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/state:go_default_library",
Expand Down Expand Up @@ -63,6 +64,7 @@ go_test(
"//beacon-chain/db:go_default_library",
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/operations/slashings:go_default_library",
"//beacon-chain/operations/voluntaryexits:go_default_library",
"//beacon-chain/p2p/testing:go_default_library",
"//beacon-chain/powchain/testing:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
Expand Down
39 changes: 36 additions & 3 deletions beacon-chain/rpc/beaconv1/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (bs *Server) ListPoolAttesterSlashings(ctx context.Context, req *ptypes.Emp
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
}
sourceSlashings := bs.SlashingsPool.PendingAttesterSlashings(ctx, headState, true)
sourceSlashings := bs.SlashingsPool.PendingAttesterSlashings(ctx, headState, true /* return unlimited slashings */)

slashings := make([]*ethpb.AttesterSlashing, len(sourceSlashings))
for i, s := range sourceSlashings {
Expand All @@ -55,7 +55,23 @@ func (bs *Server) SubmitAttesterSlashing(ctx context.Context, req *ethpb.Atteste
// ListPoolProposerSlashings retrieves proposer slashings known by the node
// but not necessarily incorporated into any block.
func (bs *Server) ListPoolProposerSlashings(ctx context.Context, req *ptypes.Empty) (*ethpb.ProposerSlashingPoolResponse, error) {
return nil, errors.New("unimplemented")
ctx, span := trace.StartSpan(ctx, "beaconv1.ListPoolProposerSlashings")
defer span.End()

headState, err := bs.ChainInfoFetcher.HeadState(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
}
sourceSlashings := bs.SlashingsPool.PendingProposerSlashings(ctx, headState, true /* return unlimited slashings */)

slashings := make([]*ethpb.ProposerSlashing, len(sourceSlashings))
for i, s := range sourceSlashings {
slashings[i] = migration.V1Alpha1ProposerSlashingToV1(s)
}

return &ethpb.ProposerSlashingPoolResponse{
Data: slashings,
}, nil
}

// SubmitProposerSlashing submits AttesterSlashing object to node's pool and if
Expand All @@ -67,7 +83,24 @@ func (bs *Server) SubmitProposerSlashing(ctx context.Context, req *ethpb.Propose
// ListPoolVoluntaryExits retrieves voluntary exits known by the node but
// not necessarily incorporated into any block.
func (bs *Server) ListPoolVoluntaryExits(ctx context.Context, req *ptypes.Empty) (*ethpb.VoluntaryExitsPoolResponse, error) {
return nil, errors.New("unimplemented")
ctx, span := trace.StartSpan(ctx, "beaconv1.ListPoolVoluntaryExits")
defer span.End()

headState, err := bs.ChainInfoFetcher.HeadState(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
}

sourceExits := bs.VoluntaryExitsPool.PendingExits(headState, headState.Slot(), true /* return unlimited exits */)

exits := make([]*ethpb.SignedVoluntaryExit, len(sourceExits))
for i, s := range sourceExits {
exits[i] = migration.V1Alpha1ExitToV1(s)
}

return &ethpb.VoluntaryExitsPoolResponse{
Data: exits,
}, nil
}

// SubmitVoluntaryExit submits SignedVoluntaryExit object to node's pool
Expand Down
91 changes: 91 additions & 0 deletions beacon-chain/rpc/beaconv1/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/proto/migration"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil"
Expand Down Expand Up @@ -102,3 +103,93 @@ func TestListPoolAttesterSlashings(t *testing.T) {
assert.DeepEqual(t, migration.V1Alpha1AttSlashingToV1(slashing1), resp.Data[0])
assert.DeepEqual(t, migration.V1Alpha1AttSlashingToV1(slashing2), resp.Data[1])
}

func TestListPoolProposerSlashings(t *testing.T) {
state, err := testutil.NewBeaconState()
require.NoError(t, err)
slashing1 := &eth.ProposerSlashing{
Header_1: &eth.SignedBeaconBlockHeader{
Header: &eth.BeaconBlockHeader{
Slot: 1,
ProposerIndex: 1,
ParentRoot: bytesutil.PadTo([]byte("parentroot1"), 32),
StateRoot: bytesutil.PadTo([]byte("stateroot1"), 32),
BodyRoot: bytesutil.PadTo([]byte("bodyroot1"), 32),
},
Signature: bytesutil.PadTo([]byte("signature1"), 96),
},
Header_2: &eth.SignedBeaconBlockHeader{
Header: &eth.BeaconBlockHeader{
Slot: 2,
ProposerIndex: 2,
ParentRoot: bytesutil.PadTo([]byte("parentroot2"), 32),
StateRoot: bytesutil.PadTo([]byte("stateroot2"), 32),
BodyRoot: bytesutil.PadTo([]byte("bodyroot2"), 32),
},
Signature: bytesutil.PadTo([]byte("signature2"), 96),
},
}
slashing2 := &eth.ProposerSlashing{
Header_1: &eth.SignedBeaconBlockHeader{
Header: &eth.BeaconBlockHeader{
Slot: 3,
ProposerIndex: 3,
ParentRoot: bytesutil.PadTo([]byte("parentroot3"), 32),
StateRoot: bytesutil.PadTo([]byte("stateroot3"), 32),
BodyRoot: bytesutil.PadTo([]byte("bodyroot3"), 32),
},
Signature: bytesutil.PadTo([]byte("signature3"), 96),
},
Header_2: &eth.SignedBeaconBlockHeader{
Header: &eth.BeaconBlockHeader{
Slot: 4,
ProposerIndex: 4,
ParentRoot: bytesutil.PadTo([]byte("parentroot4"), 32),
StateRoot: bytesutil.PadTo([]byte("stateroot4"), 32),
BodyRoot: bytesutil.PadTo([]byte("bodyroot4"), 32),
},
Signature: bytesutil.PadTo([]byte("signature4"), 96),
},
}

s := &Server{
ChainInfoFetcher: &chainMock.ChainService{State: state},
SlashingsPool: &slashings.PoolMock{PendingPropSlashings: []*eth.ProposerSlashing{slashing1, slashing2}},
}

resp, err := s.ListPoolProposerSlashings(context.Background(), &types.Empty{})
require.NoError(t, err)
require.Equal(t, 2, len(resp.Data))
assert.DeepEqual(t, migration.V1Alpha1ProposerSlashingToV1(slashing1), resp.Data[0])
assert.DeepEqual(t, migration.V1Alpha1ProposerSlashingToV1(slashing2), resp.Data[1])
}

func TestListPoolVoluntaryExits(t *testing.T) {
state, err := testutil.NewBeaconState()
require.NoError(t, err)
exit1 := &eth.SignedVoluntaryExit{
Exit: &eth.VoluntaryExit{
Epoch: 1,
ValidatorIndex: 1,
},
Signature: bytesutil.PadTo([]byte("signature1"), 96),
}
exit2 := &eth.SignedVoluntaryExit{
Exit: &eth.VoluntaryExit{
Epoch: 2,
ValidatorIndex: 2,
},
Signature: bytesutil.PadTo([]byte("signature2"), 96),
}

s := &Server{
ChainInfoFetcher: &chainMock.ChainService{State: state},
VoluntaryExitsPool: &voluntaryexits.PoolMock{Exits: []*eth.SignedVoluntaryExit{exit1, exit2}},
}

resp, err := s.ListPoolVoluntaryExits(context.Background(), &types.Empty{})
require.NoError(t, err)
require.Equal(t, 2, len(resp.Data))
assert.DeepEqual(t, migration.V1Alpha1ExitToV1(exit1), resp.Data[0])
assert.DeepEqual(t, migration.V1Alpha1ExitToV1(exit2), resp.Data[1])
}
2 changes: 2 additions & 0 deletions beacon-chain/rpc/beaconv1/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
Expand All @@ -40,6 +41,7 @@ type Server struct {
Broadcaster p2p.Broadcaster
AttestationsPool attestations.Pool
SlashingsPool slashings.PoolManager
VoluntaryExitsPool voluntaryexits.PoolManager
CanonicalStateChan chan *pbp2p.BeaconState
ChainStartChan chan time.Time
StateGenService stategen.StateManager
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/rpc/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type Service struct {
mockEth1Votes bool
enableDebugRPCEndpoints bool
attestationsPool attestations.Pool
exitPool *voluntaryexits.Pool
exitPool voluntaryexits.PoolManager
slashingsPool slashings.PoolManager
syncService chainSync.Checker
host string
Expand Down Expand Up @@ -122,7 +122,7 @@ type Config struct {
EnableDebugRPCEndpoints bool
MockEth1Votes bool
AttestationsPool attestations.Pool
ExitPool *voluntaryexits.Pool
ExitPool voluntaryexits.PoolManager
SlashingsPool slashings.PoolManager
SyncService chainSync.Checker
Broadcaster p2p.Broadcaster
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/rpc/validator/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type Server struct {
P2P p2p.Broadcaster
AttPool attestations.Pool
SlashingsPool slashings.PoolManager
ExitPool *voluntaryexits.Pool
ExitPool voluntaryexits.PoolManager
BlockReceiver blockchain.BlockReceiver
MockEth1Votes bool
Eth1BlockFetcher powchain.POWBlockFetcher
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/sync/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type Config struct {
P2P p2p.P2P
DB db.NoHeadAccessDatabase
AttPool attestations.Pool
ExitPool *voluntaryexits.Pool
ExitPool voluntaryexits.PoolManager
SlashingPool slashings.PoolManager
Chain blockchainService
InitialSync Checker
Expand Down Expand Up @@ -83,7 +83,7 @@ type Service struct {
p2p p2p.P2P
db db.NoHeadAccessDatabase
attPool attestations.Pool
exitPool *voluntaryexits.Pool
exitPool voluntaryexits.PoolManager
slashingPool slashings.PoolManager
chain blockchainService
slotToPendingBlocks *gcache.Cache
Expand Down
42 changes: 42 additions & 0 deletions proto/migration/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,45 @@ func V1Alpha1AttSlashingToV1(v1alpha1Slashing *ethpb_alpha.AttesterSlashing) *et
Attestation_2: V1Alpha1IndexedAttToV1(v1alpha1Slashing.Attestation_2),
}
}

Copy link
Member

@terencechain terencechain Feb 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some tests for the new functions below this line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the migration package doesn't have any tests... Would it be OK if I create a separate PR with tests for the whole package?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good 👍

// V1Alpha1SignedHeaderToV1 converts a v1alpha1 signed beacon block header to v1.
func V1Alpha1SignedHeaderToV1(v1alpha1Hdr *ethpb_alpha.SignedBeaconBlockHeader) *ethpb.SignedBeaconBlockHeader {
if v1alpha1Hdr == nil || v1alpha1Hdr.Header == nil {
return &ethpb.SignedBeaconBlockHeader{}
}
return &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: v1alpha1Hdr.Header.Slot,
ProposerIndex: v1alpha1Hdr.Header.ProposerIndex,
ParentRoot: v1alpha1Hdr.Header.ParentRoot,
StateRoot: v1alpha1Hdr.Header.StateRoot,
BodyRoot: v1alpha1Hdr.Header.BodyRoot,
},
Signature: v1alpha1Hdr.Signature,
}
}

// V1Alpha1ProposerSlashingToV1 converts a v1alpha1 proposer slashing to v1.
func V1Alpha1ProposerSlashingToV1(v1alpha1Slashing *ethpb_alpha.ProposerSlashing) *ethpb.ProposerSlashing {
if v1alpha1Slashing == nil {
return &ethpb.ProposerSlashing{}
}
return &ethpb.ProposerSlashing{
Header_1: V1Alpha1SignedHeaderToV1(v1alpha1Slashing.Header_1),
Header_2: V1Alpha1SignedHeaderToV1(v1alpha1Slashing.Header_2),
}
}

// V1Alpha1ExitToV1 converts a v1alpha1 SignedVoluntaryExit to v1.
func V1Alpha1ExitToV1(v1alpha1Exit *ethpb_alpha.SignedVoluntaryExit) *ethpb.SignedVoluntaryExit {
if v1alpha1Exit == nil || v1alpha1Exit.Exit == nil {
return &ethpb.SignedVoluntaryExit{}
}
return &ethpb.SignedVoluntaryExit{
Exit: &ethpb.VoluntaryExit{
Epoch: v1alpha1Exit.Exit.Epoch,
ValidatorIndex: v1alpha1Exit.Exit.ValidatorIndex,
},
Signature: v1alpha1Exit.Signature,
}
}