diff --git a/api/client/beacon/client.go b/api/client/beacon/client.go index dcb7877487e7..5ff6e7a5f9bd 100644 --- a/api/client/beacon/client.go +++ b/api/client/beacon/client.go @@ -46,10 +46,8 @@ const ( type StateOrBlockId string const ( - IdFinalized StateOrBlockId = "finalized" - IdGenesis StateOrBlockId = "genesis" - IdHead StateOrBlockId = "head" - IdJustified StateOrBlockId = "justified" + IdGenesis StateOrBlockId = "genesis" + IdHead StateOrBlockId = "head" ) var ErrMalformedHostname = errors.New("hostname must include port, separated by one colon, like example.com:3500") @@ -60,7 +58,7 @@ func IdFromRoot(r [32]byte) StateOrBlockId { return StateOrBlockId(fmt.Sprintf("%#x", r)) } -// IdFromRoot encodes a Slot in the format expected by the API in places where a slot can be used to identify +// IdFromSlot encodes a Slot in the format expected by the API in places where a slot can be used to identify // a BeaconState or SignedBeaconBlock. func IdFromSlot(s types.Slot) StateOrBlockId { return StateOrBlockId(strconv.FormatUint(uint64(s), 10)) diff --git a/beacon-chain/blockchain/BUILD.bazel b/beacon-chain/blockchain/BUILD.bazel index f21e55b54b99..0452008a44b4 100644 --- a/beacon-chain/blockchain/BUILD.bazel +++ b/beacon-chain/blockchain/BUILD.bazel @@ -137,6 +137,7 @@ go_test( "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/wrapper:go_default_library", + "//container/trie:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", @@ -188,6 +189,7 @@ go_test( "//beacon-chain/powchain/testing:go_default_library", "//config/params:go_default_library", "//consensus-types/wrapper:go_default_library", + "//container/trie:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", diff --git a/beacon-chain/blockchain/chain_info.go b/beacon-chain/blockchain/chain_info.go index 49b49e56bbc3..122737e304a9 100644 --- a/beacon-chain/blockchain/chain_info.go +++ b/beacon-chain/blockchain/chain_info.go @@ -20,7 +20,7 @@ import ( ) // ChainInfoFetcher defines a common interface for methods in blockchain service which -// directly retrieves chain info related data. +// directly retrieve chain info related data. type ChainInfoFetcher interface { HeadFetcher FinalizationFetcher @@ -49,7 +49,7 @@ type GenesisFetcher interface { } // HeadFetcher defines a common interface for methods in blockchain service which -// directly retrieves head related data. +// directly retrieve head related data. type HeadFetcher interface { HeadSlot() types.Slot HeadRoot(ctx context.Context) ([]byte, error) @@ -61,8 +61,6 @@ type HeadFetcher interface { HeadPublicKeyToValidatorIndex(pubKey [fieldparams.BLSPubkeyLength]byte) (types.ValidatorIndex, bool) HeadValidatorIndexToPublicKey(ctx context.Context, index types.ValidatorIndex) ([fieldparams.BLSPubkeyLength]byte, error) ChainHeads() ([][32]byte, []types.Slot) - IsOptimistic(ctx context.Context) (bool, error) - IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool, error) HeadSyncCommitteeFetcher HeadDomainFetcher } @@ -79,7 +77,7 @@ type CanonicalFetcher interface { } // FinalizationFetcher defines a common interface for methods in blockchain service which -// directly retrieves finalization and justification related data. +// directly retrieve finalization and justification related data. type FinalizationFetcher interface { FinalizedCheckpt() *ethpb.Checkpoint CurrentJustifiedCheckpt() *ethpb.Checkpoint @@ -87,6 +85,12 @@ type FinalizationFetcher interface { VerifyFinalizedBlkDescendant(ctx context.Context, blockRoot [32]byte) error } +// OptimisticModeFetcher retrieves information about optimistic status of the node. +type OptimisticModeFetcher interface { + IsOptimistic(ctx context.Context) (bool, error) + IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool, error) +} + // FinalizedCheckpt returns the latest finalized checkpoint from chain store. func (s *Service) FinalizedCheckpt() *ethpb.Checkpoint { cp := s.store.FinalizedCheckpt() @@ -238,7 +242,7 @@ func (s *Service) GenesisTime() time.Time { return s.genesisTime } -// GenesisValidatorsRoot returns the genesis validator +// GenesisValidatorsRoot returns the genesis validators // root of the chain. func (s *Service) GenesisValidatorsRoot() [32]byte { s.headLock.RLock() @@ -305,7 +309,7 @@ func (s *Service) HeadValidatorIndexToPublicKey(_ context.Context, index types.V return v.PublicKey(), nil } -// ForkChoicer returns the forkchoice interface +// ForkChoicer returns the forkchoice interface. func (s *Service) ForkChoicer() forkchoice.ForkChoicer { return s.cfg.ForkChoiceStore } @@ -321,7 +325,7 @@ func (s *Service) IsOptimistic(ctx context.Context) (bool, error) { return s.IsOptimisticForRoot(ctx, s.head.root) } -// IsOptimisticForRoot takes the root and slot as arguments instead of the current head +// IsOptimisticForRoot takes the root as argument instead of the current head // and returns true if it is optimistic. func (s *Service) IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool, error) { optimistic, err := s.cfg.ForkChoiceStore.IsOptimistic(root) @@ -351,7 +355,7 @@ func (s *Service) IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool, return false, nil } - // checkpoint root could be zeros before the first finalized epoch. Use genesis root if the case. + // Checkpoint root could be zeros before the first finalized epoch. Use genesis root if the case. lastValidated, err := s.cfg.BeaconDB.StateSummary(ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(validatedCheckpoint.Root))) if err != nil { return false, err @@ -369,7 +373,7 @@ func (s *Service) IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool, return false, err } - // historical non-canonical blocks here are returned as optimistic for safety. + // Historical non-canonical blocks here are returned as optimistic for safety. return !isCanonical, nil } @@ -378,7 +382,7 @@ func (s *Service) SetGenesisTime(t time.Time) { s.genesisTime = t } -// ForkChoiceStore returns the fork choice store in the service +// ForkChoiceStore returns the fork choice store in the service. func (s *Service) ForkChoiceStore() forkchoice.ForkChoicer { return s.cfg.ForkChoiceStore } diff --git a/beacon-chain/blockchain/chain_info_test.go b/beacon-chain/blockchain/chain_info_test.go index b2bfb74852f2..f5570c71e194 100644 --- a/beacon-chain/blockchain/chain_info_test.go +++ b/beacon-chain/blockchain/chain_info_test.go @@ -51,7 +51,7 @@ func TestFinalizedCheckpt_CanRetrieve(t *testing.T) { cp := ðpb.Checkpoint{Epoch: 5, Root: bytesutil.PadTo([]byte("foo"), 32)} c := setupBeaconChain(t, beaconDB) - c.store.SetFinalizedCheckpt(cp) + c.store.SetFinalizedCheckptAndPayloadHash(cp, [32]byte{'a'}) assert.Equal(t, cp.Epoch, c.FinalizedCheckpt().Epoch, "Unexpected finalized epoch") } @@ -62,7 +62,7 @@ func TestFinalizedCheckpt_GenesisRootOk(t *testing.T) { genesisRoot := [32]byte{'A'} cp := ðpb.Checkpoint{Root: genesisRoot[:]} c := setupBeaconChain(t, beaconDB) - c.store.SetFinalizedCheckpt(cp) + c.store.SetFinalizedCheckptAndPayloadHash(cp, [32]byte{'a'}) c.originBlockRoot = genesisRoot assert.DeepEqual(t, c.originBlockRoot[:], c.FinalizedCheckpt().Root) } @@ -73,7 +73,7 @@ func TestCurrentJustifiedCheckpt_CanRetrieve(t *testing.T) { c := setupBeaconChain(t, beaconDB) assert.Equal(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(c.CurrentJustifiedCheckpt().Root), "Unexpected justified epoch") cp := ðpb.Checkpoint{Epoch: 6, Root: bytesutil.PadTo([]byte("foo"), 32)} - c.store.SetJustifiedCheckpt(cp) + c.store.SetJustifiedCheckptAndPayloadHash(cp, [32]byte{}) assert.Equal(t, cp.Epoch, c.CurrentJustifiedCheckpt().Epoch, "Unexpected justified epoch") } @@ -83,7 +83,7 @@ func TestJustifiedCheckpt_GenesisRootOk(t *testing.T) { c := setupBeaconChain(t, beaconDB) genesisRoot := [32]byte{'B'} cp := ðpb.Checkpoint{Root: genesisRoot[:]} - c.store.SetJustifiedCheckpt(cp) + c.store.SetJustifiedCheckptAndPayloadHash(cp, [32]byte{}) c.originBlockRoot = genesisRoot assert.DeepEqual(t, c.originBlockRoot[:], c.CurrentJustifiedCheckpt().Root) } diff --git a/beacon-chain/blockchain/error.go b/beacon-chain/blockchain/error.go index 7cb99ae0e822..7e64ccc346d2 100644 --- a/beacon-chain/blockchain/error.go +++ b/beacon-chain/blockchain/error.go @@ -11,8 +11,6 @@ var ( errNilFinalizedInStore = errors.New("nil finalized checkpoint returned from store") // errInvalidNilSummary is returned when a nil summary is returned from the DB. errInvalidNilSummary = errors.New("nil summary returned from the DB") - // errNilParentInDB is returned when a nil parent block is returned from the DB. - errNilParentInDB = errors.New("nil parent block in DB") // errWrongBlockCount is returned when the wrong number of blocks or // block roots is used errWrongBlockCount = errors.New("wrong number of blocks or block roots") diff --git a/beacon-chain/blockchain/execution_engine.go b/beacon-chain/blockchain/execution_engine.go index a9295aecbb0f..4eef5a66241d 100644 --- a/beacon-chain/blockchain/execution_engine.go +++ b/beacon-chain/blockchain/execution_engine.go @@ -31,11 +31,9 @@ var ( // notifyForkchoiceUpdateArg is the argument for the forkchoice update notification `notifyForkchoiceUpdate`. type notifyForkchoiceUpdateArg struct { - headState state.BeaconState - headRoot [32]byte - headBlock interfaces.BeaconBlock - finalizedRoot [32]byte - justifiedRoot [32]byte + headState state.BeaconState + headRoot [32]byte + headBlock interfaces.BeaconBlock } // notifyForkchoiceUpdate signals execution engine the fork choice updates. Execution engine should: @@ -61,18 +59,12 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho if err != nil { return nil, errors.Wrap(err, "could not get execution payload") } - finalizedHash, err := s.getPayloadHash(ctx, arg.finalizedRoot) - if err != nil { - return nil, errors.Wrap(err, "could not get finalized block hash") - } - justifiedHash, err := s.getPayloadHash(ctx, arg.justifiedRoot) - if err != nil { - return nil, errors.Wrap(err, "could not get justified block hash") - } + finalizedHash := s.store.FinalizedPayloadBlockHash() + justifiedHash := s.store.JustifiedPayloadBlockHash() fcs := &enginev1.ForkchoiceState{ HeadBlockHash: headPayload.BlockHash, - SafeBlockHash: justifiedHash, - FinalizedBlockHash: finalizedHash, + SafeBlockHash: justifiedHash[:], + FinalizedBlockHash: finalizedHash[:], } nextSlot := s.CurrentSlot() + 1 // Cache payload ID for next slot proposer. @@ -89,10 +81,11 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho log.WithFields(logrus.Fields{ "headSlot": headBlk.Slot(), "headPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(headPayload.BlockHash)), - "finalizedPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(finalizedHash)), + "finalizedPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(finalizedHash[:])), }).Info("Called fork choice updated with optimistic block") return payloadID, s.optimisticCandidateBlock(ctx, headBlk) case powchain.ErrInvalidPayloadStatus: + newPayloadInvalidNodeCount.Inc() headRoot := arg.headRoot invalidRoots, err := s.ForkChoicer().SetOptimisticToInvalid(ctx, headRoot, bytesutil.ToBytes32(headBlk.ParentRoot()), bytesutil.ToBytes32(lastValidHash)) if err != nil { @@ -101,12 +94,35 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho if err := s.removeInvalidBlockAndState(ctx, invalidRoots); err != nil { return nil, err } + + r, err := s.updateHead(ctx, s.justifiedBalances.balances) + if err != nil { + return nil, err + } + b, err := s.getBlock(ctx, r) + if err != nil { + return nil, err + } + st, err := s.cfg.StateGen.StateByRoot(ctx, r) + if err != nil { + return nil, err + } + pid, err := s.notifyForkchoiceUpdate(ctx, ¬ifyForkchoiceUpdateArg{ + headState: st, + headRoot: r, + headBlock: b.Block(), + }) + if err != nil { + return nil, err + } + log.WithFields(logrus.Fields{ "slot": headBlk.Slot(), "blockRoot": fmt.Sprintf("%#x", headRoot), "invalidCount": len(invalidRoots), }).Warn("Pruned invalid blocks") - return nil, ErrInvalidPayload + return pid, ErrInvalidPayload + default: return nil, errors.WithMessage(ErrUndefinedExecutionEngineError, err.Error()) } @@ -125,19 +141,19 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho // getPayloadHash returns the payload hash given the block root. // if the block is before bellatrix fork epoch, it returns the zero hash. -func (s *Service) getPayloadHash(ctx context.Context, root [32]byte) ([]byte, error) { - finalizedBlock, err := s.getBlock(ctx, s.ensureRootNotZeros(root)) +func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, error) { + blk, err := s.getBlock(ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(root))) if err != nil { - return nil, err + return [32]byte{}, err } - if blocks.IsPreBellatrixVersion(finalizedBlock.Block().Version()) { - return params.BeaconConfig().ZeroHash[:], nil + if blocks.IsPreBellatrixVersion(blk.Block().Version()) { + return params.BeaconConfig().ZeroHash, nil } - payload, err := finalizedBlock.Block().Body().ExecutionPayload() + payload, err := blk.Block().Body().ExecutionPayload() if err != nil { - return nil, errors.Wrap(err, "could not get execution payload") + return [32]byte{}, errors.Wrap(err, "could not get execution payload") } - return payload.BlockHash, nil + return bytesutil.ToBytes32(payload.BlockHash), nil } // notifyForkchoiceUpdate signals execution engine on a new payload. @@ -219,14 +235,10 @@ func (s *Service) optimisticCandidateBlock(ctx context.Context, blk interfaces.B if blk.Slot()+params.BeaconConfig().SafeSlotsToImportOptimistically <= s.CurrentSlot() { return nil } - - parent, err := s.cfg.BeaconDB.Block(ctx, bytesutil.ToBytes32(blk.ParentRoot())) + parent, err := s.getBlock(ctx, bytesutil.ToBytes32(blk.ParentRoot())) if err != nil { return err } - if parent == nil || parent.IsNil() { - return errNilParentInDB - } parentIsExecutionBlock, err := blocks.IsExecutionBlock(parent.Block().Body()) if err != nil { return err @@ -266,7 +278,10 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, logrus.WithFields(logrus.Fields{ "validatorIndex": proposerID, "burnAddress": fieldparams.EthBurnAddressHex, - }).Error("Fee recipient not set. Using burn address") + }).Warn("Fee recipient is currently using the burn address, " + + "you will not be rewarded transaction fees on this setting. " + + "Please set a different eth address as the fee recipient. " + + "Please refer to our documentation for instructions") } case err != nil: return false, nil, 0, errors.Wrap(err, "could not get fee recipient in db") diff --git a/beacon-chain/blockchain/execution_engine_test.go b/beacon-chain/blockchain/execution_engine_test.go index c8c6cb93a529..31934eabfadb 100644 --- a/beacon-chain/blockchain/execution_engine_test.go +++ b/beacon-chain/blockchain/execution_engine_test.go @@ -9,6 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/cache" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" + doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree" "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" "github.com/prysmaticlabs/prysm/beacon-chain/powchain" mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing" @@ -174,12 +175,15 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) { t.Run(tt.name, func(t *testing.T) { service.cfg.ExecutionEngineCaller = &mockPOW.EngineClient{ErrForkchoiceUpdated: tt.newForkchoiceErr} st, _ := util.DeterministicGenesisState(t, 1) + require.NoError(t, beaconDB.SaveState(ctx, st, tt.finalizedRoot)) + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, tt.finalizedRoot)) + fc := ðpb.Checkpoint{Epoch: 1, Root: tt.finalizedRoot[:]} + service.store.SetFinalizedCheckptAndPayloadHash(fc, [32]byte{'a'}) + service.store.SetJustifiedCheckptAndPayloadHash(fc, [32]byte{'b'}) arg := ¬ifyForkchoiceUpdateArg{ - headState: st, - headRoot: tt.headRoot, - headBlock: tt.blk, - finalizedRoot: tt.finalizedRoot, - justifiedRoot: tt.justifiedRoot, + headState: st, + headRoot: tt.headRoot, + headBlock: tt.blk, } _, err := service.notifyForkchoiceUpdate(ctx, arg) if tt.errString != "" { @@ -191,6 +195,147 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) { } } +// +// +// A <- B <- C <- D +// \ +// ---------- E <- F +// \ +// ------ G +// D is the current head, attestations for F and G come late, both are invalid. +// We switch recursively to F then G and finally to D. +// +// We test: +// 1. forkchoice removes blocks F and G from the forkchoice implementation +// 2. forkchoice removes the weights of these blocks +// 3. the blockchain package calls fcu to obtain heads G -> F -> D. + +func Test_NotifyForkchoiceUpdateRecursive(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + + // Prepare blocks + ba := util.NewBeaconBlockBellatrix() + ba.Block.Body.ExecutionPayload.BlockNumber = 1 + wba, err := wrapper.WrappedSignedBeaconBlock(ba) + require.NoError(t, err) + bra, err := wba.Block().HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wba)) + + bb := util.NewBeaconBlockBellatrix() + bb.Block.Body.ExecutionPayload.BlockNumber = 2 + wbb, err := wrapper.WrappedSignedBeaconBlock(bb) + require.NoError(t, err) + brb, err := wbb.Block().HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wbb)) + + bc := util.NewBeaconBlockBellatrix() + bc.Block.Body.ExecutionPayload.BlockNumber = 3 + wbc, err := wrapper.WrappedSignedBeaconBlock(bc) + require.NoError(t, err) + brc, err := wbc.Block().HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wbc)) + + bd := util.NewBeaconBlockBellatrix() + pd := [32]byte{'D'} + bd.Block.Body.ExecutionPayload.BlockHash = pd[:] + bd.Block.Body.ExecutionPayload.BlockNumber = 4 + wbd, err := wrapper.WrappedSignedBeaconBlock(bd) + require.NoError(t, err) + brd, err := wbd.Block().HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wbd)) + + be := util.NewBeaconBlockBellatrix() + pe := [32]byte{'E'} + be.Block.Body.ExecutionPayload.BlockHash = pe[:] + be.Block.Body.ExecutionPayload.BlockNumber = 5 + wbe, err := wrapper.WrappedSignedBeaconBlock(be) + require.NoError(t, err) + bre, err := wbe.Block().HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wbe)) + + bf := util.NewBeaconBlockBellatrix() + pf := [32]byte{'F'} + bf.Block.Body.ExecutionPayload.BlockHash = pf[:] + bf.Block.Body.ExecutionPayload.BlockNumber = 6 + bf.Block.ParentRoot = bre[:] + wbf, err := wrapper.WrappedSignedBeaconBlock(bf) + require.NoError(t, err) + brf, err := wbf.Block().HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wbf)) + + bg := util.NewBeaconBlockBellatrix() + bg.Block.Body.ExecutionPayload.BlockNumber = 7 + pg := [32]byte{'G'} + bg.Block.Body.ExecutionPayload.BlockHash = pg[:] + bg.Block.ParentRoot = bre[:] + wbg, err := wrapper.WrappedSignedBeaconBlock(bg) + require.NoError(t, err) + brg, err := wbg.Block().HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wbg)) + + // Insert blocks into forkchoice + fcs := doublylinkedtree.New(0, 0) + opts := []Option{ + WithDatabase(beaconDB), + WithStateGen(stategen.New(beaconDB)), + WithForkChoiceStore(fcs), + WithProposerIdsCache(cache.NewProposerPayloadIDsCache()), + } + service, err := NewService(ctx, opts...) + service.justifiedBalances.balances = []uint64{50, 100, 200} + require.NoError(t, err) + require.NoError(t, fcs.InsertOptimisticBlock(ctx, 1, bra, [32]byte{}, [32]byte{'A'}, 0, 0)) + require.NoError(t, fcs.InsertOptimisticBlock(ctx, 2, brb, bra, [32]byte{'B'}, 0, 0)) + require.NoError(t, fcs.InsertOptimisticBlock(ctx, 3, brc, brb, [32]byte{'C'}, 0, 0)) + require.NoError(t, fcs.InsertOptimisticBlock(ctx, 4, brd, brc, [32]byte{'D'}, 0, 0)) + require.NoError(t, fcs.InsertOptimisticBlock(ctx, 5, bre, brb, [32]byte{'E'}, 0, 0)) + require.NoError(t, fcs.InsertOptimisticBlock(ctx, 6, brf, bre, [32]byte{'F'}, 0, 0)) + require.NoError(t, fcs.InsertOptimisticBlock(ctx, 7, brg, bre, [32]byte{'G'}, 0, 0)) + + // Insert Attestations to D, F and G so that they have higher weight than D + // Ensure G is head + fcs.ProcessAttestation(ctx, []uint64{0}, brd, 1) + fcs.ProcessAttestation(ctx, []uint64{1}, brf, 1) + fcs.ProcessAttestation(ctx, []uint64{2}, brg, 1) + headRoot, err := fcs.Head(ctx, 0, bra, []uint64{50, 100, 200}, 0) + require.NoError(t, err) + require.Equal(t, brg, headRoot) + + // Prepare Engine Mock to return invalid unless head is D, LVH = E + service.cfg.ExecutionEngineCaller = &mockPOW.EngineClient{ErrForkchoiceUpdated: powchain.ErrInvalidPayloadStatus, ForkChoiceUpdatedResp: pe[:], OverrideValidHash: [32]byte{'D'}} + st, _ := util.DeterministicGenesisState(t, 1) + + require.NoError(t, beaconDB.SaveState(ctx, st, bra)) + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bra)) + fc := ðpb.Checkpoint{Epoch: 0, Root: bra[:]} + service.store.SetFinalizedCheckptAndPayloadHash(fc, [32]byte{'a'}) + service.store.SetJustifiedCheckptAndPayloadHash(fc, [32]byte{'b'}) + a := ¬ifyForkchoiceUpdateArg{ + headState: st, + headBlock: wbg.Block(), + headRoot: brg, + } + _, err = service.notifyForkchoiceUpdate(ctx, a) + require.ErrorIs(t, ErrInvalidPayload, err) + // Ensure Head is D + headRoot, err = fcs.Head(ctx, 0, bra, service.justifiedBalances.balances, 0) + require.NoError(t, err) + require.Equal(t, brd, headRoot) + + // Ensure F and G where removed but their parent E wasn't + require.Equal(t, false, fcs.HasNode(brf)) + require.Equal(t, false, fcs.HasNode(brg)) + require.Equal(t, true, fcs.HasNode(bre)) +} + func Test_NotifyNewPayload(t *testing.T) { cfg := params.BeaconConfig() cfg.TerminalTotalDifficulty = "2" @@ -537,11 +682,11 @@ func Test_IsOptimisticCandidateBlock(t *testing.T) { jRoot, err := tt.justified.Block().HashTreeRoot() require.NoError(t, err) require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, tt.justified)) - service.store.SetJustifiedCheckpt( + service.store.SetJustifiedCheckptAndPayloadHash( ðpb.Checkpoint{ Root: jRoot[:], Epoch: slots.ToEpoch(tt.justified.Block().Slot()), - }) + }, [32]byte{'a'}) require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrappedParentBlock)) err = service.optimisticCandidateBlock(ctx, tt.blk) @@ -625,7 +770,7 @@ func Test_GetPayloadAttribute(t *testing.T) { require.Equal(t, true, hasPayload) require.Equal(t, suggestedVid, vId) require.Equal(t, fieldparams.EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient).String()) - require.LogsContain(t, hook, "Fee recipient not set. Using burn address") + require.LogsContain(t, hook, "Fee recipient is currently using the burn address") // Cache hit, advance state, has fee recipient suggestedAddr := common.HexToAddress("123") @@ -803,7 +948,7 @@ func TestService_getPayloadHash(t *testing.T) { service, err := NewService(ctx, opts...) require.NoError(t, err) - _, err = service.getPayloadHash(ctx, [32]byte{}) + _, err = service.getPayloadHash(ctx, []byte{}) require.ErrorIs(t, errBlockNotFoundInCacheOrDB, err) b := util.NewBeaconBlock() @@ -813,20 +958,20 @@ func TestService_getPayloadHash(t *testing.T) { require.NoError(t, err) service.saveInitSyncBlock(r, wsb) - h, err := service.getPayloadHash(ctx, r) + h, err := service.getPayloadHash(ctx, r[:]) require.NoError(t, err) - require.DeepEqual(t, params.BeaconConfig().ZeroHash[:], h) + require.DeepEqual(t, params.BeaconConfig().ZeroHash, h) bb := util.NewBeaconBlockBellatrix() - h = []byte{'a'} - bb.Block.Body.ExecutionPayload.BlockHash = h + h = [32]byte{'a'} + bb.Block.Body.ExecutionPayload.BlockHash = h[:] r, err = b.Block.HashTreeRoot() require.NoError(t, err) wsb, err = wrapper.WrappedSignedBeaconBlock(bb) require.NoError(t, err) service.saveInitSyncBlock(r, wsb) - h, err = service.getPayloadHash(ctx, r) + h, err = service.getPayloadHash(ctx, r[:]) require.NoError(t, err) - require.DeepEqual(t, []byte{'a'}, h) + require.DeepEqual(t, [32]byte{'a'}, h) } diff --git a/beacon-chain/blockchain/head.go b/beacon-chain/blockchain/head.go index a47191e2359e..f817e180b25f 100644 --- a/beacon-chain/blockchain/head.go +++ b/beacon-chain/blockchain/head.go @@ -40,7 +40,7 @@ func (s *Service) UpdateAndSaveHeadWithBalances(ctx context.Context) error { if err != nil { return errors.Wrap(err, "could not update head") } - headBlock, err := s.cfg.BeaconDB.Block(ctx, headRoot) + headBlock, err := s.getBlock(ctx, headRoot) if err != nil { return err } @@ -86,7 +86,7 @@ func (s *Service) updateHead(ctx context.Context, balances []uint64) ([32]byte, // re-initiate fork choice store using the latest justified info. // This recovers a fatal condition and should not happen in run time. if !s.cfg.ForkChoiceStore.HasNode(headStartRoot) { - jb, err := s.cfg.BeaconDB.Block(ctx, headStartRoot) + jb, err := s.getBlock(ctx, headStartRoot) if err != nil { return [32]byte{}, err } @@ -355,7 +355,7 @@ func (s *Service) notifyNewHeadEvent( // attestation pool. It also filters out the attestations that is one epoch older as a // defense so invalid attestations don't flow into the attestation pool. func (s *Service) saveOrphanedAtts(ctx context.Context, orphanedRoot [32]byte) error { - orphanedBlk, err := s.cfg.BeaconDB.Block(ctx, orphanedRoot) + orphanedBlk, err := s.getBlock(ctx, orphanedRoot) if err != nil { return err } diff --git a/beacon-chain/blockchain/head_test.go b/beacon-chain/blockchain/head_test.go index 8ff1cd455ebb..10ff99417559 100644 --- a/beacon-chain/blockchain/head_test.go +++ b/beacon-chain/blockchain/head_test.go @@ -154,8 +154,8 @@ func TestUpdateHead_MissingJustifiedRoot(t *testing.T) { r, err := b.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]}) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{'b'}) service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{}) headRoot, err := service.updateHead(context.Background(), []uint64{}) require.NoError(t, err) @@ -298,8 +298,8 @@ func TestUpdateHead_noSavedChanges(t *testing.T) { Root: bellatrixBlkRoot[:], Epoch: 1, } - service.store.SetFinalizedCheckpt(fcp) - service.store.SetJustifiedCheckpt(fcp) + service.store.SetFinalizedCheckptAndPayloadHash(fcp, [32]byte{'a'}) + service.store.SetJustifiedCheckptAndPayloadHash(fcp, [32]byte{'b'}) require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bellatrixBlkRoot)) bellatrixState, _ := util.DeterministicGenesisStateBellatrix(t, 2) diff --git a/beacon-chain/blockchain/mock_test.go b/beacon-chain/blockchain/mock_test.go index 8a6cf27f76b3..8c0abd2d3450 100644 --- a/beacon-chain/blockchain/mock_test.go +++ b/beacon-chain/blockchain/mock_test.go @@ -21,7 +21,7 @@ func testServiceOptsWithDB(t *testing.T) []Option { } } -// warning: only use these opts when you are certain there are no db calls +// WARNING: only use these opts when you are certain there are no db calls // in your code path. this is a lightweight way to satisfy the stategen/beacondb // initialization requirements w/o the overhead of db init. func testServiceOptsNoDB() []Option { diff --git a/beacon-chain/blockchain/new_slot.go b/beacon-chain/blockchain/new_slot.go index fcd765c87cb8..0c64c24551c7 100644 --- a/beacon-chain/blockchain/new_slot.go +++ b/beacon-chain/blockchain/new_slot.go @@ -64,7 +64,11 @@ func (s *Service) NewSlot(ctx context.Context, slot types.Slot) error { return err } if bytes.Equal(r, f.Root) { - s.store.SetJustifiedCheckpt(bj) + h, err := s.getPayloadHash(ctx, bj.Root) + if err != nil { + return err + } + s.store.SetJustifiedCheckptAndPayloadHash(bj, h) } } return nil diff --git a/beacon-chain/blockchain/process_attestation_test.go b/beacon-chain/blockchain/process_attestation_test.go index e22c3f6354ff..97daef0d6ffa 100644 --- a/beacon-chain/blockchain/process_attestation_test.go +++ b/beacon-chain/blockchain/process_attestation_test.go @@ -324,9 +324,9 @@ func TestStore_SaveCheckpointState(t *testing.T) { r := [32]byte{'g'} require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, r)) - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'}) service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]}) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: r[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'b'}) service.store.SetPrevFinalizedCheckpt(ðpb.Checkpoint{Root: r[:]}) r = bytesutil.ToBytes32([]byte{'A'}) @@ -358,9 +358,9 @@ func TestStore_SaveCheckpointState(t *testing.T) { assert.Equal(t, 2*params.BeaconConfig().SlotsPerEpoch, s2.Slot(), "Unexpected state slot") require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'}) service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]}) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: r[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'b'}) service.store.SetPrevFinalizedCheckpt(ðpb.Checkpoint{Root: r[:]}) cp3 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'C'}, fieldparams.RootLength)} require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'}))) @@ -500,7 +500,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_ProtoArray(t *testing.T) { r32, err := b32.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 1}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{}) b33 := util.NewBeaconBlock() b33.Block.Slot = 33 b33.Block.ParentRoot = r32[:] @@ -535,7 +535,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_DoublyLinkedTree(t *testing r32, err := b32.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 1}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{}) b33 := util.NewBeaconBlock() b33.Block.Slot = 33 b33.Block.ParentRoot = r32[:] @@ -564,7 +564,7 @@ func TestVerifyFinalizedConsistency_OK(t *testing.T) { r32, err := b32.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: r32[:], Epoch: 1}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r32[:], Epoch: 1}, [32]byte{}) b33 := util.NewBeaconBlock() b33.Block.Slot = 33 @@ -591,7 +591,7 @@ func TestVerifyFinalizedConsistency_IsCanonical(t *testing.T) { r32, err := b32.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: r32[:], Epoch: 1}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r32[:], Epoch: 1}, [32]byte{}) b33 := util.NewBeaconBlock() b33.Block.Slot = 33 diff --git a/beacon-chain/blockchain/process_block.go b/beacon-chain/blockchain/process_block.go index e6db77c0321d..7afccf2fc9af 100644 --- a/beacon-chain/blockchain/process_block.go +++ b/beacon-chain/blockchain/process_block.go @@ -123,7 +123,9 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo return err } } - + if err := s.savePostStateInfo(ctx, blockRoot, signed, postState); err != nil { + return err + } if err := s.insertBlockAndAttestationsToForkChoiceStore(ctx, signed.Block(), blockRoot, postState); err != nil { return errors.Wrapf(err, "could not insert block %d to fork choice store", signed.Block().Slot()) } @@ -146,9 +148,6 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo return err } - if err := s.savePostStateInfo(ctx, blockRoot, signed, postState); err != nil { - return err - } // If slasher is configured, forward the attestations in the block via // an event feed for processing. if features.Get().EnableSlasher { @@ -195,9 +194,19 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo newFinalized := postState.FinalizedCheckpointEpoch() > finalized.Epoch if newFinalized { s.store.SetPrevFinalizedCheckpt(finalized) - s.store.SetFinalizedCheckpt(postState.FinalizedCheckpoint()) + cp := postState.FinalizedCheckpoint() + h, err := s.getPayloadHash(ctx, cp.Root) + if err != nil { + return err + } + s.store.SetFinalizedCheckptAndPayloadHash(cp, h) s.store.SetPrevJustifiedCheckpt(justified) - s.store.SetJustifiedCheckpt(postState.CurrentJustifiedCheckpoint()) + cp = postState.CurrentJustifiedCheckpoint() + h, err = s.getPayloadHash(ctx, cp.Root) + if err != nil { + return err + } + s.store.SetJustifiedCheckptAndPayloadHash(postState.CurrentJustifiedCheckpoint(), h) } balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(justified.Root)) @@ -413,6 +422,10 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac } } s.saveInitSyncBlock(blockRoots[i], b) + if err = s.handleBlockAfterBatchVerify(ctx, b, blockRoots[i], fCheckpoints[i], jCheckpoints[i]); err != nil { + tracing.AnnotateError(span, err) + return nil, nil, err + } } for r, st := range boundaries { @@ -426,14 +439,10 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac if err := s.cfg.StateGen.SaveState(ctx, lastBR, preState); err != nil { return nil, nil, err } - f := fCheckpoints[len(fCheckpoints)-1] - j := jCheckpoints[len(jCheckpoints)-1] arg := ¬ifyForkchoiceUpdateArg{ - headState: preState, - headRoot: lastBR, - headBlock: lastB.Block(), - finalizedRoot: bytesutil.ToBytes32(f.Root), - justifiedRoot: bytesutil.ToBytes32(j.Root), + headState: preState, + headRoot: lastBR, + headBlock: lastB.Block(), } if _, err := s.notifyForkchoiceUpdate(ctx, arg); err != nil { return nil, nil, err @@ -484,7 +493,11 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interf return err } s.store.SetPrevFinalizedCheckpt(finalized) - s.store.SetFinalizedCheckpt(fCheckpoint) + h, err := s.getPayloadHash(ctx, fCheckpoint.Root) + if err != nil { + return err + } + s.store.SetFinalizedCheckptAndPayloadHash(fCheckpoint, h) } return nil } diff --git a/beacon-chain/blockchain/process_block_helpers.go b/beacon-chain/blockchain/process_block_helpers.go index 345c7b3a8e4b..e03dca2cd722 100644 --- a/beacon-chain/blockchain/process_block_helpers.go +++ b/beacon-chain/blockchain/process_block_helpers.go @@ -97,13 +97,10 @@ func (s *Service) VerifyFinalizedBlkDescendant(ctx context.Context, root [32]byt return errNilFinalizedInStore } fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root)) - finalizedBlkSigned, err := s.cfg.BeaconDB.Block(ctx, fRoot) + finalizedBlkSigned, err := s.getBlock(ctx, fRoot) if err != nil { return err } - if finalizedBlkSigned == nil || finalizedBlkSigned.IsNil() || finalizedBlkSigned.Block().IsNil() { - return errors.New("nil finalized block") - } finalizedBlk := finalizedBlkSigned.Block() bFinalizedRoot, err := s.ancestor(ctx, root[:], finalizedBlk.Slot()) if err != nil { @@ -208,7 +205,11 @@ func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaco return errNilJustifiedInStore } s.store.SetPrevJustifiedCheckpt(justified) - s.store.SetJustifiedCheckpt(cpt) + h, err := s.getPayloadHash(ctx, cpt.Root) + if err != nil { + return err + } + s.store.SetJustifiedCheckptAndPayloadHash(cpt, h) } return nil @@ -227,7 +228,11 @@ func (s *Service) updateJustifiedInitSync(ctx context.Context, cp *ethpb.Checkpo if err := s.cfg.BeaconDB.SaveJustifiedCheckpoint(ctx, cp); err != nil { return err } - s.store.SetJustifiedCheckpt(cp) + h, err := s.getPayloadHash(ctx, cp.Root) + if err != nil { + return err + } + s.store.SetJustifiedCheckptAndPayloadHash(cp, h) return nil } @@ -350,7 +355,7 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa higherThanFinalized := slot > fSlot // As long as parent node is not in fork choice store, and parent node is in DB. for !s.cfg.ForkChoiceStore.HasNode(parentRoot) && s.cfg.BeaconDB.HasBlock(ctx, parentRoot) && higherThanFinalized { - b, err := s.cfg.BeaconDB.Block(ctx, parentRoot) + b, err := s.getBlock(ctx, parentRoot) if err != nil { return err } diff --git a/beacon-chain/blockchain/process_block_test.go b/beacon-chain/blockchain/process_block_test.go index 9134933a6503..e139687eef97 100644 --- a/beacon-chain/blockchain/process_block_test.go +++ b/beacon-chain/blockchain/process_block_test.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" "strconv" + "sync" "testing" "time" @@ -39,6 +40,7 @@ import ( "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/util" prysmTime "github.com/prysmaticlabs/prysm/time" + logTest "github.com/sirupsen/logrus/hooks/test" ) func TestStore_OnBlock_ProtoArray(t *testing.T) { @@ -129,9 +131,9 @@ func TestStore_OnBlock_ProtoArray(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: validGenesisRoot[:]}, [32]byte{'a'}) service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]}) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: roots[0]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: roots[0]}, [32]byte{'b'}) service.store.SetPrevFinalizedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]}) root, err := tt.blk.Block.HashTreeRoot() @@ -232,9 +234,9 @@ func TestStore_OnBlock_DoublyLinkedTree(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: validGenesisRoot[:]}, [32]byte{'a'}) service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]}) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: roots[0]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: roots[0]}, [32]byte{'b'}) service.store.SetPrevFinalizedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]}) root, err := tt.blk.Block.HashTreeRoot() @@ -289,7 +291,8 @@ func TestStore_OnBlockBatch_ProtoArray(t *testing.T) { assert.NoError(t, beaconDB.SaveBlock(ctx, wsb)) gRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'}) service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{}) wsb, err = wrapper.WrappedSignedBeaconBlock(genesis) @@ -353,7 +356,8 @@ func TestStore_OnBlockBatch_DoublyLinkedTree(t *testing.T) { assert.NoError(t, beaconDB.SaveBlock(ctx, wsb)) gRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'}) service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0) wsb, err = wrapper.WrappedSignedBeaconBlock(genesis) @@ -415,7 +419,9 @@ func TestStore_OnBlockBatch_NotifyNewPayload(t *testing.T) { assert.NoError(t, beaconDB.SaveBlock(ctx, wsb)) gRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'}) + service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0) service.saveInitSyncBlock(gRoot, wsb) st, keys := util.DeterministicGenesisState(t, 64) @@ -484,7 +490,7 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) { diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot) service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0) - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}, [32]byte{'a'}) update, err = service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]}) require.NoError(t, err) assert.Equal(t, true, update, "Should be able to update justified") @@ -516,7 +522,7 @@ func TestShouldUpdateJustified_ReturnFalse_ProtoArray(t *testing.T) { diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot) service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0) - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}, [32]byte{'a'}) update, err := service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]}) require.NoError(t, err) @@ -549,7 +555,7 @@ func TestShouldUpdateJustified_ReturnFalse_DoublyLinkedTree(t *testing.T) { diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot) service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0) - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}, [32]byte{'a'}) update, err := service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]}) require.NoError(t, err) @@ -577,7 +583,7 @@ func TestCachedPreState_CanGetFromStateSummary_ProtoArray(t *testing.T) { assert.NoError(t, beaconDB.SaveBlock(ctx, wsb)) gRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{}) service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{}) wsb, err = wrapper.WrappedSignedBeaconBlock(genesis) require.NoError(t, err) @@ -614,7 +620,7 @@ func TestCachedPreState_CanGetFromStateSummary_DoublyLinkedTree(t *testing.T) { assert.NoError(t, beaconDB.SaveBlock(ctx, wsb)) gRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{}) service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0) wsb, err = wrapper.WrappedSignedBeaconBlock(genesis) require.NoError(t, err) @@ -648,7 +654,7 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) { assert.NoError(t, beaconDB.SaveBlock(ctx, wsb)) gRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{}) service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{}) wsb, err = wrapper.WrappedSignedBeaconBlock(genesis) require.NoError(t, err) @@ -656,7 +662,7 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) { b := util.NewBeaconBlock() b.Block.Slot = 1 - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{}) wb, err := wrapper.WrappedBeaconBlock(b.Block) require.NoError(t, err) err = service.verifyBlkPreState(ctx, wb) @@ -691,7 +697,7 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) { require.NoError(t, beaconDB.SaveBlock(ctx, wsb)) r, err := signedBlock.Block.HashTreeRoot() require.NoError(t, err) - service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: []byte{'A'}}) + service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: []byte{'A'}}, [32]byte{'a'}) service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: []byte{'A'}}) st, err := util.NewBeaconState() require.NoError(t, err) @@ -723,7 +729,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_ProtoArray(t *testing.T) { service, err := NewService(ctx, opts...) require.NoError(t, err) service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'}) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: make([]byte, 32)}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{}) genesisStateRoot := [32]byte{} genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) @@ -768,7 +774,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_DoublyLinkedTree(t *testing.T) { service, err := NewService(ctx, opts...) require.NoError(t, err) service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: make([]byte, 32)}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{}) genesisStateRoot := [32]byte{} genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) @@ -814,7 +820,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_ProtoArray(t *testing.T) { service, err := NewService(ctx, opts...) require.NoError(t, err) service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'}) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: make([]byte, 32)}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{}) genesisStateRoot := [32]byte{} genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) @@ -863,7 +869,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_DoublyLinkedTree(t *testing.T) { service, err := NewService(ctx, opts...) require.NoError(t, err) service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: make([]byte, 32)}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{}) genesisStateRoot := [32]byte{} genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) @@ -913,7 +919,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_ProtoArray(t *testing.T) { require.NoError(t, err) service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'}) // Set finalized epoch to 1. - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 1}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{}) genesisStateRoot := [32]byte{} genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) @@ -974,7 +980,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_DoublyLinkedTree(t *testing require.NoError(t, err) service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0) // Set finalized epoch to 1. - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 1}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{}) genesisStateRoot := [32]byte{} genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) @@ -1321,7 +1327,7 @@ func TestVerifyBlkDescendant(t *testing.T) { args: args{ finalizedRoot: [32]byte{'a'}, }, - wantedErr: "nil finalized block", + wantedErr: "block not found in cache or db", }, { name: "could not get finalized block root in DB", @@ -1350,7 +1356,7 @@ func TestVerifyBlkDescendant(t *testing.T) { for _, tt := range tests { service, err := NewService(ctx, opts...) require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: tt.args.finalizedRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: tt.args.finalizedRoot[:]}, [32]byte{}) err = service.VerifyFinalizedBlkDescendant(ctx, tt.args.parentRoot) if tt.wantedErr != "" { assert.ErrorContains(t, tt.wantedErr, err) @@ -1378,7 +1384,7 @@ func TestUpdateJustifiedInitSync(t *testing.T) { require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, beaconState, gRoot)) service.originBlockRoot = gRoot currentCp := ðpb.Checkpoint{Epoch: 1} - service.store.SetJustifiedCheckpt(currentCp) + service.store.SetJustifiedCheckptAndPayloadHash(currentCp, [32]byte{'a'}) newCp := ðpb.Checkpoint{Epoch: 2, Root: gRoot[:]} require.NoError(t, service.updateJustifiedInitSync(ctx, newCp)) @@ -1439,7 +1445,7 @@ func TestOnBlock_CanFinalize(t *testing.T) { require.NoError(t, err) gRoot, err := gBlk.Block().HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{}) testState := gs.Copy() for i := types.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ { @@ -1493,7 +1499,7 @@ func TestOnBlock_CallNewPayloadAndForkchoiceUpdated(t *testing.T) { require.NoError(t, err) gRoot, err := gBlk.Block().HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{}) testState := gs.Copy() for i := types.Slot(1); i < params.BeaconConfig().SlotsPerEpoch; i++ { @@ -1524,7 +1530,7 @@ func TestInsertFinalizedDeposits(t *testing.T) { require.NoError(t, err) gRoot, err := gBlk.Block().HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{}) gs = gs.Copy() assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 10})) assert.NoError(t, gs.SetEth1DepositIndex(8)) @@ -1563,7 +1569,7 @@ func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) { require.NoError(t, err) gRoot, err := gBlk.Block().HashTreeRoot() require.NoError(t, err) - service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{}) gs = gs.Copy() assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 7})) assert.NoError(t, gs.SetEth1DepositIndex(6)) @@ -1887,3 +1893,82 @@ func TestService_insertSlashingsToForkChoiceStore(t *testing.T) { require.NoError(t, err) service.insertSlashingsToForkChoiceStore(ctx, wb.Block().Body().AttesterSlashings()) } + +func TestOnBlock_ProcessBlocksParallel(t *testing.T) { + ctx := context.Background() + beaconDB := testDB.SetupDB(t) + fcs := protoarray.New(0, 0, [32]byte{'a'}) + depositCache, err := depositcache.New() + require.NoError(t, err) + opts := []Option{ + WithDatabase(beaconDB), + WithStateGen(stategen.New(beaconDB)), + WithForkChoiceStore(fcs), + WithDepositCache(depositCache), + WithStateNotifier(&mock.MockStateNotifier{}), + } + service, err := NewService(ctx, opts...) + require.NoError(t, err) + + gs, keys := util.DeterministicGenesisState(t, 32) + require.NoError(t, service.saveGenesisData(ctx, gs)) + gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx) + require.NoError(t, err) + gRoot, err := gBlk.Block().HashTreeRoot() + require.NoError(t, err) + service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'}) + + blk1, err := util.GenerateFullBlock(gs, keys, util.DefaultBlockGenConfig(), 1) + require.NoError(t, err) + r1, err := blk1.Block.HashTreeRoot() + require.NoError(t, err) + wsb1, err := wrapper.WrappedSignedBeaconBlock(blk1) + require.NoError(t, err) + blk2, err := util.GenerateFullBlock(gs, keys, util.DefaultBlockGenConfig(), 2) + require.NoError(t, err) + r2, err := blk2.Block.HashTreeRoot() + require.NoError(t, err) + wsb2, err := wrapper.WrappedSignedBeaconBlock(blk2) + require.NoError(t, err) + blk3, err := util.GenerateFullBlock(gs, keys, util.DefaultBlockGenConfig(), 3) + require.NoError(t, err) + r3, err := blk3.Block.HashTreeRoot() + require.NoError(t, err) + wsb3, err := wrapper.WrappedSignedBeaconBlock(blk3) + require.NoError(t, err) + blk4, err := util.GenerateFullBlock(gs, keys, util.DefaultBlockGenConfig(), 4) + require.NoError(t, err) + r4, err := blk4.Block.HashTreeRoot() + require.NoError(t, err) + wsb4, err := wrapper.WrappedSignedBeaconBlock(blk4) + require.NoError(t, err) + + logHook := logTest.NewGlobal() + for i := 0; i < 10; i++ { + var wg sync.WaitGroup + wg.Add(4) + go func() { + require.NoError(t, service.onBlock(ctx, wsb1, r1)) + wg.Done() + }() + go func() { + require.NoError(t, service.onBlock(ctx, wsb2, r2)) + wg.Done() + }() + go func() { + require.NoError(t, service.onBlock(ctx, wsb3, r3)) + wg.Done() + }() + go func() { + require.NoError(t, service.onBlock(ctx, wsb4, r4)) + wg.Done() + }() + wg.Wait() + require.LogsDoNotContain(t, logHook, "New head does not exist in DB. Do nothing") + require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r1)) + require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r2)) + require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r3)) + require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r4)) + service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'a'}) + } +} diff --git a/beacon-chain/blockchain/receive_attestation.go b/beacon-chain/blockchain/receive_attestation.go index 52f964916cab..58d2b804f35c 100644 --- a/beacon-chain/blockchain/receive_attestation.go +++ b/beacon-chain/blockchain/receive_attestation.go @@ -176,7 +176,7 @@ func (s *Service) UpdateHead(ctx context.Context) error { // This calls notify Forkchoice Update in the event that the head has changed func (s *Service) notifyEngineIfChangedHead(ctx context.Context, newHeadRoot [32]byte) { - if s.headRoot() == newHeadRoot { + if newHeadRoot == [32]byte{} || s.headRoot() == newHeadRoot { return } @@ -185,12 +185,6 @@ func (s *Service) notifyEngineIfChangedHead(ctx context.Context, newHeadRoot [32 return // We don't have the block, don't notify the engine and update head. } - finalized := s.store.FinalizedCheckpt() - if finalized == nil { - log.WithError(errNilFinalizedInStore).Error("could not get finalized checkpoint") - return - } - newHeadBlock, err := s.getBlock(ctx, newHeadRoot) if err != nil { log.WithError(err).Error("Could not get new head block") @@ -202,11 +196,9 @@ func (s *Service) notifyEngineIfChangedHead(ctx context.Context, newHeadRoot [32 return } arg := ¬ifyForkchoiceUpdateArg{ - headState: headState, - headRoot: newHeadRoot, - headBlock: newHeadBlock.Block(), - finalizedRoot: bytesutil.ToBytes32(finalized.Root), - justifiedRoot: bytesutil.ToBytes32(s.store.JustifiedCheckpt().Root), + headState: headState, + headRoot: newHeadRoot, + headBlock: newHeadBlock.Block(), } _, err = s.notifyForkchoiceUpdate(s.ctx, arg) if err != nil { diff --git a/beacon-chain/blockchain/receive_attestation_test.go b/beacon-chain/blockchain/receive_attestation_test.go index 5594752fb9e4..e3551367e0df 100644 --- a/beacon-chain/blockchain/receive_attestation_test.go +++ b/beacon-chain/blockchain/receive_attestation_test.go @@ -137,14 +137,14 @@ func TestNotifyEngineIfChangedHead(t *testing.T) { service.cfg.ProposerSlotIndexCache = cache.NewProposerPayloadIDsCache() service.notifyEngineIfChangedHead(ctx, service.headRoot()) hookErr := "could not notify forkchoice update" - finalizedErr := "could not get finalized checkpoint" - require.LogsDoNotContain(t, hook, finalizedErr) + invalidStateErr := "Could not get state from db" + require.LogsDoNotContain(t, hook, invalidStateErr) require.LogsDoNotContain(t, hook, hookErr) gb, err := wrapper.WrappedSignedBeaconBlock(util.NewBeaconBlock()) require.NoError(t, err) service.saveInitSyncBlock([32]byte{'a'}, gb) service.notifyEngineIfChangedHead(ctx, [32]byte{'a'}) - require.LogsContain(t, hook, finalizedErr) + require.LogsContain(t, hook, invalidStateErr) hook.Reset() service.head = &head{ @@ -169,9 +169,9 @@ func TestNotifyEngineIfChangedHead(t *testing.T) { state: st, } service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(2, 1, [8]byte{1}) - service.store.SetFinalizedCheckpt(finalized) + service.store.SetFinalizedCheckptAndPayloadHash(finalized, [32]byte{}) service.notifyEngineIfChangedHead(ctx, r1) - require.LogsDoNotContain(t, hook, finalizedErr) + require.LogsDoNotContain(t, hook, invalidStateErr) require.LogsDoNotContain(t, hook, hookErr) // Block in DB @@ -191,14 +191,19 @@ func TestNotifyEngineIfChangedHead(t *testing.T) { state: st, } service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(2, 1, [8]byte{1}) - service.store.SetFinalizedCheckpt(finalized) + service.store.SetFinalizedCheckptAndPayloadHash(finalized, [32]byte{}) service.notifyEngineIfChangedHead(ctx, r1) - require.LogsDoNotContain(t, hook, finalizedErr) + require.LogsDoNotContain(t, hook, invalidStateErr) require.LogsDoNotContain(t, hook, hookErr) vId, payloadID, has := service.cfg.ProposerSlotIndexCache.GetProposerPayloadIDs(2) require.Equal(t, true, has) require.Equal(t, types.ValidatorIndex(1), vId) require.Equal(t, [8]byte{1}, payloadID) + + // Test zero headRoot returns immediately. + headRoot := service.headRoot() + service.notifyEngineIfChangedHead(ctx, [32]byte{}) + require.Equal(t, service.headRoot(), headRoot) } func TestService_ProcessAttestationsAndUpdateHead(t *testing.T) { diff --git a/beacon-chain/blockchain/receive_block.go b/beacon-chain/blockchain/receive_block.go index fd2dcb52c603..efbdd3c30930 100644 --- a/beacon-chain/blockchain/receive_block.go +++ b/beacon-chain/blockchain/receive_block.go @@ -30,9 +30,9 @@ type SlashingReceiver interface { ReceiveAttesterSlashing(ctx context.Context, slashings *ethpb.AttesterSlashing) } -// ReceiveBlock is a function that defines the the operations (minus pubsub) -// that are performed on blocks that is received from regular sync service. The operations consists of: -// 1. Validate block, apply state transition and update check points +// ReceiveBlock is a function that defines the operations (minus pubsub) +// that are performed on a received block. The operations consist of: +// 1. Validate block, apply state transition and update checkpoints // 2. Apply fork choice to the processed block // 3. Save latest head info func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaconBlock, blockRoot [32]byte) error { @@ -85,7 +85,7 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []interfaces.Sig defer span.End() // Apply state transition on the incoming newly received block batches, one by one. - fCheckpoints, jCheckpoints, err := s.onBlockBatch(ctx, blocks, blkRoots) + _, _, err := s.onBlockBatch(ctx, blocks, blkRoots) if err != nil { err := errors.Wrap(err, "could not process block in batch") tracing.AnnotateError(span, err) @@ -94,10 +94,6 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []interfaces.Sig for i, b := range blocks { blockCopy := b.Copy() - if err = s.handleBlockAfterBatchVerify(ctx, blockCopy, blkRoots[i], fCheckpoints[i], jCheckpoints[i]); err != nil { - tracing.AnnotateError(span, err) - return err - } // Send notification of the processed block to the state feed. s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ Type: statefeed.BlockProcessed, diff --git a/beacon-chain/blockchain/receive_block_test.go b/beacon-chain/blockchain/receive_block_test.go index 678dc4a5d80c..a77b3549deef 100644 --- a/beacon-chain/blockchain/receive_block_test.go +++ b/beacon-chain/blockchain/receive_block_test.go @@ -141,7 +141,8 @@ func TestService_ReceiveBlock(t *testing.T) { require.NoError(t, err) gRoot, err := gBlk.Block().HashTreeRoot() require.NoError(t, err) - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + h := [32]byte{'a'} + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, h) root, err := tt.args.block.Block.HashTreeRoot() require.NoError(t, err) wsb, err := wrapper.WrappedSignedBeaconBlock(tt.args.block) @@ -181,7 +182,7 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) { require.NoError(t, err) gRoot, err := gBlk.Block().HashTreeRoot() require.NoError(t, err) - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'}) root, err := b.Block.HashTreeRoot() require.NoError(t, err) wg := sync.WaitGroup{} @@ -262,7 +263,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) { gRoot, err := gBlk.Block().HashTreeRoot() require.NoError(t, err) - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'}) root, err := tt.args.block.Block.HashTreeRoot() require.NoError(t, err) wsb, err := wrapper.WrappedSignedBeaconBlock(tt.args.block) @@ -312,7 +313,7 @@ func TestCheckSaveHotStateDB_Enabling(t *testing.T) { require.NoError(t, err) st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB)) s.genesisTime = time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second) - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{}) require.NoError(t, s.checkSaveHotStateDB(context.Background())) assert.LogsContain(t, hook, "Entering mode to save hot states in DB") @@ -323,7 +324,7 @@ func TestCheckSaveHotStateDB_Disabling(t *testing.T) { opts := testServiceOptsWithDB(t) s, err := NewService(context.Background(), opts...) require.NoError(t, err) - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{}) require.NoError(t, s.checkSaveHotStateDB(context.Background())) s.genesisTime = time.Now() @@ -336,7 +337,7 @@ func TestCheckSaveHotStateDB_Overflow(t *testing.T) { opts := testServiceOptsWithDB(t) s, err := NewService(context.Background(), opts...) require.NoError(t, err) - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 10000000}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{}) s.genesisTime = time.Now() require.NoError(t, s.checkSaveHotStateDB(context.Background())) diff --git a/beacon-chain/blockchain/service.go b/beacon-chain/blockchain/service.go index 72970463a3f2..cb094cf9fd55 100644 --- a/beacon-chain/blockchain/service.go +++ b/beacon-chain/blockchain/service.go @@ -201,13 +201,10 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error { forkChoicer = protoarray.New(justified.Epoch, finalized.Epoch, fRoot) } s.cfg.ForkChoiceStore = forkChoicer - fb, err := s.cfg.BeaconDB.Block(s.ctx, s.ensureRootNotZeros(fRoot)) + fb, err := s.getBlock(s.ctx, s.ensureRootNotZeros(fRoot)) if err != nil { return errors.Wrap(err, "could not get finalized checkpoint block") } - if fb == nil || fb.IsNil() { - return errNilFinalizedInStore - } payloadHash, err := getBlockPayloadHash(fb.Block()) if err != nil { return errors.Wrap(err, "could not get execution payload hash") @@ -339,14 +336,13 @@ func (s *Service) initializeHeadFromDB(ctx context.Context) error { finalizedState.Slot(), flags.HeadSync.Name) } } - - finalizedBlock, err := s.cfg.BeaconDB.Block(ctx, finalizedRoot) - if err != nil { - return errors.Wrap(err, "could not get finalized block from db") + if finalizedState == nil || finalizedState.IsNil() { + return errors.New("finalized state can't be nil") } - if finalizedState == nil || finalizedState.IsNil() || finalizedBlock == nil || finalizedBlock.IsNil() { - return errors.New("finalized state and block can't be nil") + finalizedBlock, err := s.getBlock(ctx, finalizedRoot) + if err != nil { + return errors.Wrap(err, "could not get finalized block") } s.setHead(finalizedRoot, finalizedBlock, finalizedState) diff --git a/beacon-chain/blockchain/service_test.go b/beacon-chain/blockchain/service_test.go index 4cadd4e8c892..869c7a2039d1 100644 --- a/beacon-chain/blockchain/service_test.go +++ b/beacon-chain/blockchain/service_test.go @@ -31,6 +31,7 @@ import ( "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/consensus-types/wrapper" + "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" @@ -86,9 +87,11 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service { bState, _ := util.DeterministicGenesisState(t, 10) pbState, err := v1.ProtobufBeaconState(bState.InnerStateUnsafe()) require.NoError(t, err) + mockTrie, err := trie.NewTrie(0) + require.NoError(t, err) err = beaconDB.SavePowchainData(ctx, ðpb.ETH1ChainData{ BeaconState: pbState, - Trie: ðpb.SparseMerkleTrie{}, + Trie: mockTrie.ToProto(), CurrentEth1Data: ðpb.LatestETH1Data{ BlockHash: make([]byte, 32), }, @@ -501,7 +504,7 @@ func TestHasBlock_ForkChoiceAndDB_ProtoArray(t *testing.T) { cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB}, store: &store.Store{}, } - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{}) b := util.NewBeaconBlock() r, err := b.Block.HashTreeRoot() require.NoError(t, err) @@ -522,7 +525,7 @@ func TestHasBlock_ForkChoiceAndDB_DoublyLinkedTree(t *testing.T) { cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0), BeaconDB: beaconDB}, store: &store.Store{}, } - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{}) b := util.NewBeaconBlock() r, err := b.Block.HashTreeRoot() require.NoError(t, err) @@ -595,7 +598,7 @@ func BenchmarkHasBlockForkChoiceStore_ProtoArray(b *testing.B) { cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB}, store: &store.Store{}, } - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{}) blk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}} r, err := blk.Block.HashTreeRoot() require.NoError(b, err) @@ -618,7 +621,7 @@ func BenchmarkHasBlockForkChoiceStore_DoublyLinkedTree(b *testing.B) { cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0), BeaconDB: beaconDB}, store: &store.Store{}, } - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{}) blk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}} r, err := blk.Block.HashTreeRoot() require.NoError(b, err) diff --git a/beacon-chain/blockchain/state_balance_cache.go b/beacon-chain/blockchain/state_balance_cache.go index 57e7c3679c60..17ffec2ccd6d 100644 --- a/beacon-chain/blockchain/state_balance_cache.go +++ b/beacon-chain/blockchain/state_balance_cache.go @@ -37,7 +37,7 @@ func newStateBalanceCache(sg *stategen.State) (*stateBalanceCache, error) { // the previously read value. This cache assumes we only want to cache one // set of balances for a single root (the current justified root). // -// warning: this is not thread-safe on its own, relies on get() for locking +// WARNING: this is not thread-safe on its own, relies on get() for locking func (c *stateBalanceCache) update(ctx context.Context, justifiedRoot [32]byte) ([]uint64, error) { stateBalanceCacheMiss.Inc() justifiedState, err := c.stateGen.StateByRoot(ctx, justifiedRoot) diff --git a/beacon-chain/blockchain/store/setter_getter.go b/beacon-chain/blockchain/store/setter_getter.go index 2d2e1b96bf51..857af7703fbd 100644 --- a/beacon-chain/blockchain/store/setter_getter.go +++ b/beacon-chain/blockchain/store/setter_getter.go @@ -23,6 +23,13 @@ func (s *Store) JustifiedCheckpt() *ethpb.Checkpoint { return s.justifiedCheckpt } +// JustifiedPayloadBlockHash returns the justified payload block hash reflecting justified check point. +func (s *Store) JustifiedPayloadBlockHash() [32]byte { + s.RLock() + defer s.RUnlock() + return s.justifiedPayloadBlockHash +} + // PrevFinalizedCheckpt returns the previous finalized checkpoint in the Store. func (s *Store) PrevFinalizedCheckpt() *ethpb.Checkpoint { s.RLock() @@ -37,6 +44,13 @@ func (s *Store) FinalizedCheckpt() *ethpb.Checkpoint { return s.finalizedCheckpt } +// FinalizedPayloadBlockHash returns the finalized payload block hash reflecting finalized check point. +func (s *Store) FinalizedPayloadBlockHash() [32]byte { + s.RLock() + defer s.RUnlock() + return s.finalizedPayloadBlockHash +} + // SetPrevJustifiedCheckpt sets the previous justified checkpoint in the Store. func (s *Store) SetPrevJustifiedCheckpt(cp *ethpb.Checkpoint) { s.Lock() @@ -51,18 +65,20 @@ func (s *Store) SetBestJustifiedCheckpt(cp *ethpb.Checkpoint) { s.bestJustifiedCheckpt = cp } -// SetJustifiedCheckpt sets the justified checkpoint in the Store. -func (s *Store) SetJustifiedCheckpt(cp *ethpb.Checkpoint) { +// SetJustifiedCheckptAndPayloadHash sets the justified checkpoint and blockhash in the Store. +func (s *Store) SetJustifiedCheckptAndPayloadHash(cp *ethpb.Checkpoint, h [32]byte) { s.Lock() defer s.Unlock() s.justifiedCheckpt = cp + s.justifiedPayloadBlockHash = h } -// SetFinalizedCheckpt sets the finalized checkpoint in the Store. -func (s *Store) SetFinalizedCheckpt(cp *ethpb.Checkpoint) { +// SetFinalizedCheckptAndPayloadHash sets the finalized checkpoint and blockhash in the Store. +func (s *Store) SetFinalizedCheckptAndPayloadHash(cp *ethpb.Checkpoint, h [32]byte) { s.Lock() defer s.Unlock() s.finalizedCheckpt = cp + s.finalizedPayloadBlockHash = h } // SetPrevFinalizedCheckpt sets the previous finalized checkpoint in the Store. diff --git a/beacon-chain/blockchain/store/setter_getter_test.go b/beacon-chain/blockchain/store/setter_getter_test.go index 5009779c3bdc..2c6174fd1c44 100644 --- a/beacon-chain/blockchain/store/setter_getter_test.go +++ b/beacon-chain/blockchain/store/setter_getter_test.go @@ -30,8 +30,10 @@ func Test_store_JustifiedCheckpt(t *testing.T) { var cp *ethpb.Checkpoint require.Equal(t, cp, s.JustifiedCheckpt()) cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}} - s.SetJustifiedCheckpt(cp) + h := [32]byte{'b'} + s.SetJustifiedCheckptAndPayloadHash(cp, h) require.Equal(t, cp, s.JustifiedCheckpt()) + require.Equal(t, h, s.JustifiedPayloadBlockHash()) } func Test_store_FinalizedCheckpt(t *testing.T) { @@ -39,8 +41,10 @@ func Test_store_FinalizedCheckpt(t *testing.T) { var cp *ethpb.Checkpoint require.Equal(t, cp, s.FinalizedCheckpt()) cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}} - s.SetFinalizedCheckpt(cp) + h := [32]byte{'b'} + s.SetFinalizedCheckptAndPayloadHash(cp, h) require.Equal(t, cp, s.FinalizedCheckpt()) + require.Equal(t, h, s.FinalizedPayloadBlockHash()) } func Test_store_PrevFinalizedCheckpt(t *testing.T) { diff --git a/beacon-chain/blockchain/store/type.go b/beacon-chain/blockchain/store/type.go index ef5e7e60abdf..ba9d2b2d9eba 100644 --- a/beacon-chain/blockchain/store/type.go +++ b/beacon-chain/blockchain/store/type.go @@ -17,9 +17,11 @@ import ( // best_justified_checkpoint: Checkpoint // proposerBoostRoot: Root type Store struct { - justifiedCheckpt *ethpb.Checkpoint - finalizedCheckpt *ethpb.Checkpoint - bestJustifiedCheckpt *ethpb.Checkpoint + justifiedCheckpt *ethpb.Checkpoint + justifiedPayloadBlockHash [32]byte + finalizedCheckpt *ethpb.Checkpoint + finalizedPayloadBlockHash [32]byte + bestJustifiedCheckpt *ethpb.Checkpoint sync.RWMutex // These are not part of the consensus spec, but we do use them to return gRPC API requests. // TODO(10094): Consider removing in v3. diff --git a/beacon-chain/blockchain/testing/mock.go b/beacon-chain/blockchain/testing/mock.go index 9907ea104c30..d6fb68175c56 100644 --- a/beacon-chain/blockchain/testing/mock.go +++ b/beacon-chain/blockchain/testing/mock.go @@ -376,7 +376,7 @@ func (_ *ChainService) HeadGenesisValidatorsRoot() [32]byte { return [32]byte{} } -// VerifyBlkDescendant mocks VerifyBlkDescendant and always returns nil. +// VerifyFinalizedBlkDescendant mocks VerifyBlkDescendant and always returns nil. func (s *ChainService) VerifyFinalizedBlkDescendant(_ context.Context, _ [32]byte) error { return s.VerifyBlkDescendantErr } @@ -451,7 +451,7 @@ func (s *ChainService) IsOptimisticForRoot(_ context.Context, _ [32]byte) (bool, return s.Optimistic, nil } -// ProcessAttestationsAndUpdateHead mocks the same method in the chain service. +// UpdateHead mocks the same method in the chain service. func (s *ChainService) UpdateHead(_ context.Context) error { return nil } // ReceiveAttesterSlashing mocks the same method in the chain service. diff --git a/beacon-chain/blockchain/weak_subjectivity_checks.go b/beacon-chain/blockchain/weak_subjectivity_checks.go index 1267e876a92a..aa3c781a6399 100644 --- a/beacon-chain/blockchain/weak_subjectivity_checks.go +++ b/beacon-chain/blockchain/weak_subjectivity_checks.go @@ -30,10 +30,11 @@ type WeakSubjectivityVerifier struct { db weakSubjectivityDB } -// NewWeakSubjectivityVerifier validates a checkpoint, and if valid, uses it to initialize a weak subjectivity verifier +// NewWeakSubjectivityVerifier validates a checkpoint, and if valid, uses it to initialize a weak subjectivity verifier. func NewWeakSubjectivityVerifier(wsc *ethpb.Checkpoint, db weakSubjectivityDB) (*WeakSubjectivityVerifier, error) { if wsc == nil || len(wsc.Root) == 0 || wsc.Epoch == 0 { - log.Warn("No valid weak subjectivity checkpoint specified, running without weak subjectivity verification") + log.Info("No checkpoint for syncing provided, node will begin syncing from genesis. Checkpoint Sync is an optional feature that allows your node to sync from a more recent checkpoint, " + + "which enhances the security of your local beacon node and the broader network. See https://docs.prylabs.network/docs/next/prysm-usage/checkpoint-sync/ to learn how to configure Checkpoint Sync.") return &WeakSubjectivityVerifier{ enabled: false, }, nil @@ -58,7 +59,6 @@ func (v *WeakSubjectivityVerifier) VerifyWeakSubjectivity(ctx context.Context, f if v.verified || !v.enabled { return nil } - // Two conditions are described in the specs: // IF epoch_number > store.finalized_checkpoint.epoch, // then ASSERT during block sync that block with root block_root @@ -92,6 +92,5 @@ func (v *WeakSubjectivityVerifier) VerifyWeakSubjectivity(ctx context.Context, f return nil } } - return errors.Wrap(errWSBlockNotFoundInEpoch, fmt.Sprintf("root=%#x, epoch=%d", v.root, v.epoch)) } diff --git a/beacon-chain/blockchain/weak_subjectivity_checks_test.go b/beacon-chain/blockchain/weak_subjectivity_checks_test.go index 18a2f58d6711..19585c06a391 100644 --- a/beacon-chain/blockchain/weak_subjectivity_checks_test.go +++ b/beacon-chain/blockchain/weak_subjectivity_checks_test.go @@ -79,7 +79,7 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) { store: &store.Store{}, wsVerifier: wv, } - s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: tt.finalizedEpoch}) + s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: tt.finalizedEpoch}, [32]byte{}) err = s.wsVerifier.VerifyWeakSubjectivity(context.Background(), s.store.FinalizedCheckpt().Epoch) if tt.wantErr == nil { require.NoError(t, err) diff --git a/beacon-chain/cache/committee_test.go b/beacon-chain/cache/committee_test.go index 76006f3ecb5f..c02840eab629 100644 --- a/beacon-chain/cache/committee_test.go +++ b/beacon-chain/cache/committee_test.go @@ -110,7 +110,7 @@ func TestCommitteeCache_CanRotate(t *testing.T) { sort.Slice(k, func(i, j int) bool { return k[i].(string) < k[j].(string) }) - wanted := end - int(maxCommitteesCacheSize) + wanted := end - maxCommitteesCacheSize s := bytesutil.ToBytes32([]byte(strconv.Itoa(wanted))) assert.Equal(t, key(s), k[0], "incorrect key received for slot 190") diff --git a/beacon-chain/db/errors.go b/beacon-chain/db/errors.go index 1b632b207941..b1f5aef946da 100644 --- a/beacon-chain/db/errors.go +++ b/beacon-chain/db/errors.go @@ -14,7 +14,7 @@ var ErrNotFoundState = kv.ErrNotFoundState // ErrNotFoundOriginBlockRoot wraps ErrNotFound for an error specific to the origin block root. var ErrNotFoundOriginBlockRoot = kv.ErrNotFoundOriginBlockRoot -// ErrNotFoundOriginBlockRoot wraps ErrNotFound for an error specific to the origin block root. +// ErrNotFoundBackfillBlockRoot wraps ErrNotFound for an error specific to the backfill block root. var ErrNotFoundBackfillBlockRoot = kv.ErrNotFoundBackfillBlockRoot // ErrNotFoundGenesisBlockRoot means no genesis block root was found, indicating the db was not initialized with genesis diff --git a/beacon-chain/db/kv/error.go b/beacon-chain/db/kv/error.go index 4841d42dc517..29dd336ffeb4 100644 --- a/beacon-chain/db/kv/error.go +++ b/beacon-chain/db/kv/error.go @@ -16,7 +16,7 @@ var ErrNotFoundOriginBlockRoot = errors.Wrap(ErrNotFound, "OriginBlockRoot") // ErrNotFoundGenesisBlockRoot means no genesis block root was found, indicating the db was not initialized with genesis var ErrNotFoundGenesisBlockRoot = errors.Wrap(ErrNotFound, "OriginGenesisRoot") -// ErrNotFoundOriginBlockRoot is an error specifically for the origin block root getter +// ErrNotFoundBackfillBlockRoot is an error specifically for the origin block root getter var ErrNotFoundBackfillBlockRoot = errors.Wrap(ErrNotFound, "BackfillBlockRoot") // ErrNotFoundFeeRecipient is a not found error specifically for the fee recipient getter diff --git a/beacon-chain/forkchoice/doubly-linked-tree/optimistic_sync.go b/beacon-chain/forkchoice/doubly-linked-tree/optimistic_sync.go index b264723110f1..a5b9bf83c8e2 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/optimistic_sync.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/optimistic_sync.go @@ -81,7 +81,7 @@ func (s *Store) removeNode(ctx context.Context, node *Node) ([][32]byte, error) if i != len(children)-1 { children[i] = children[len(children)-1] } - node.parent.children = children[:len(children)-2] + node.parent.children = children[:len(children)-1] break } } diff --git a/beacon-chain/forkchoice/doubly-linked-tree/optimistic_sync_test.go b/beacon-chain/forkchoice/doubly-linked-tree/optimistic_sync_test.go index 2a753a1fc0d1..941484589c26 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/optimistic_sync_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/optimistic_sync_test.go @@ -203,3 +203,26 @@ func TestSetOptimisticToInvalid_ProposerBoost(t *testing.T) { require.DeepEqual(t, params.BeaconConfig().ZeroHash, f.store.previousProposerBoostRoot) f.store.proposerBoostLock.RUnlock() } + +// This is a regression test (10565) +// ----- C +// / +// A <- B +// \ +// ----------D +// D is invalid + +func TestSetOptimisticToInvalid_CorrectChildren(t *testing.T) { + ctx := context.Background() + f := setup(1, 1) + + require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)) + require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1)) + require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1)) + require.NoError(t, f.InsertOptimisticBlock(ctx, 103, [32]byte{'d'}, [32]byte{'a'}, [32]byte{'D'}, 1, 1)) + + _, err := f.store.setOptimisticToInvalid(ctx, [32]byte{'d'}, [32]byte{'a'}, [32]byte{'A'}) + require.NoError(t, err) + require.Equal(t, 2, len(f.store.nodeByRoot[[32]byte{'a'}].children)) + +} diff --git a/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost_test.go b/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost_test.go index e5bae806b6d0..c2322c01ab4f 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost_test.go @@ -51,7 +51,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { slot, newRoot, headRoot, - params.BeaconConfig().ZeroHash, + zeroHash, jEpoch, fEpoch, ), @@ -75,7 +75,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { slot, newRoot, headRoot, - params.BeaconConfig().ZeroHash, + zeroHash, jEpoch, fEpoch, ), @@ -101,7 +101,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { slot, newRoot, headRoot, - params.BeaconConfig().ZeroHash, + zeroHash, jEpoch, fEpoch, ), @@ -111,35 +111,37 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { require.NoError(t, err) assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3") - // Insert a second block at slot 3 into the tree and boost its score. + // Insert a second block at slot 4 into the tree and boost its score. // 0 // | // 1 // | // 2 // / \ - // 3 4 <- HEAD - slot = types.Slot(3) + // 3 | + // 4 <- HEAD + slot = types.Slot(4) newRoot = indexToHash(4) require.NoError(t, f.InsertOptimisticBlock( ctx, slot, newRoot, - headRoot, - params.BeaconConfig().ZeroHash, + indexToHash(2), + zeroHash, jEpoch, fEpoch, ), ) f.ProcessAttestation(ctx, []uint64{3}, newRoot, fEpoch) - clockSlot := types.Slot(3) + clockSlot := types.Slot(4) args := &forkchoicetypes.ProposerBoostRootArgs{ BlockRoot: newRoot, BlockSlot: slot, CurrentSlot: clockSlot, SecondsIntoSlot: 0, } + require.NoError(t, f.BoostProposerRoot(ctx, args)) headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch) require.NoError(t, err) @@ -166,17 +168,27 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { // // In this case, we have a small fork: // - // (A: 54) -> (B: 44) -> (C: 34) + // (A: 54) -> (B: 44) -> (C: 10) // \_->(D: 24) // // So B has its own weight, 10, and the sum of both C and D. That's why we see weight 54 in the - // middle instead of the normal progression of (44 -> 34 -> 24). + // middle instead of the normal progression of (54 -> 44 -> 24). node1 := f.store.nodeByRoot[indexToHash(1)] require.Equal(t, node1.weight, uint64(54)) node2 := f.store.nodeByRoot[indexToHash(2)] require.Equal(t, node2.weight, uint64(44)) - node3 := f.store.nodeByRoot[indexToHash(4)] - require.Equal(t, node3.weight, uint64(24)) + node3 := f.store.nodeByRoot[indexToHash(3)] + require.Equal(t, node3.weight, uint64(10)) + node4 := f.store.nodeByRoot[indexToHash(4)] + require.Equal(t, node4.weight, uint64(24)) + + // Regression: process attestations for C, check that it + // becomes head, we need two attestations to have C.weight = 30 > 24 = D.weight + f.ProcessAttestation(ctx, []uint64{4, 5}, indexToHash(3), fEpoch) + headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch) + require.NoError(t, err) + assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4") + }) t.Run("vanilla ex ante attack", func(t *testing.T) { f := setup(jEpoch, fEpoch) diff --git a/beacon-chain/forkchoice/protoarray/optimistic_sync.go b/beacon-chain/forkchoice/protoarray/optimistic_sync.go index 92eec31ab8df..21584380ed32 100644 --- a/beacon-chain/forkchoice/protoarray/optimistic_sync.go +++ b/beacon-chain/forkchoice/protoarray/optimistic_sync.go @@ -24,6 +24,7 @@ func (f *ForkChoice) IsOptimistic(root [32]byte) (bool, error) { // SetOptimisticToValid is called with the root of a block that was returned as // VALID by the EL. +// // WARNING: This method returns an error if the root is not found in forkchoice func (f *ForkChoice) SetOptimisticToValid(ctx context.Context, root [32]byte) error { f.store.nodesLock.Lock() diff --git a/beacon-chain/forkchoice/protoarray/proposer_boost_test.go b/beacon-chain/forkchoice/protoarray/proposer_boost_test.go index 3ddd394db654..006468ae968a 100644 --- a/beacon-chain/forkchoice/protoarray/proposer_boost_test.go +++ b/beacon-chain/forkchoice/protoarray/proposer_boost_test.go @@ -51,7 +51,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { slot, newRoot, headRoot, - params.BeaconConfig().ZeroHash, + zeroHash, jEpoch, fEpoch, ), @@ -75,7 +75,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { slot, newRoot, headRoot, - params.BeaconConfig().ZeroHash, + zeroHash, jEpoch, fEpoch, ), @@ -101,7 +101,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { slot, newRoot, headRoot, - params.BeaconConfig().ZeroHash, + zeroHash, jEpoch, fEpoch, ), @@ -111,29 +111,30 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { require.NoError(t, err) assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3") - // Insert a second block at slot 3 into the tree and boost its score. + // Insert a second block at slot 4 into the tree and boost its score. // 0 // | // 1 // | // 2 // / \ - // 3 4 <- HEAD - slot = types.Slot(3) + // 3 | + // 4 <- HEAD + slot = types.Slot(4) newRoot = indexToHash(4) require.NoError(t, f.InsertOptimisticBlock( ctx, slot, newRoot, - headRoot, - params.BeaconConfig().ZeroHash, + indexToHash(2), + zeroHash, jEpoch, fEpoch, ), ) f.ProcessAttestation(ctx, []uint64{3}, newRoot, fEpoch) - clockSlot := types.Slot(3) + clockSlot := types.Slot(4) args := &forkchoicetypes.ProposerBoostRootArgs{ BlockRoot: newRoot, BlockSlot: slot, @@ -166,14 +167,22 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) { // // In this case, we have a small fork: // - // (A: 54) -> (B: 44) -> (C: 24) - // \_->(D: 10) + // (A: 54) -> (B: 44) -> (C: 10) + // \_->(D: 24) // // So B has its own weight, 10, and the sum of both C and D. That's why we see weight 54 in the - // middle instead of the normal progression of (44 -> 34 -> 24). + // middle instead of the normal progression of (54 -> 44 -> 24). require.Equal(t, f.store.nodes[1].weight, uint64(54)) require.Equal(t, f.store.nodes[2].weight, uint64(44)) - require.Equal(t, f.store.nodes[3].weight, uint64(34)) + require.Equal(t, f.store.nodes[3].weight, uint64(10)) + require.Equal(t, f.store.nodes[4].weight, uint64(24)) + + // Regression: process attestations for C, check that it + // becomes head, we need two attestations to have C.weight = 30 > 24 = D.weight + f.ProcessAttestation(ctx, []uint64{4, 5}, indexToHash(3), fEpoch) + headRoot, err = f.Head(ctx, jEpoch, zeroHash, balances, fEpoch) + require.NoError(t, err) + assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4") }) t.Run("vanilla ex ante attack", func(t *testing.T) { f := setup(jEpoch, fEpoch) diff --git a/beacon-chain/monitor/service_test.go b/beacon-chain/monitor/service_test.go index 2a42f43e5d54..d447a76b880f 100644 --- a/beacon-chain/monitor/service_test.go +++ b/beacon-chain/monitor/service_test.go @@ -130,7 +130,7 @@ func TestUpdateSyncCommitteeTrackedVals(t *testing.T) { func TestNewService(t *testing.T) { config := &ValidatorMonitorConfig{} - tracked := []types.ValidatorIndex{} + var tracked []types.ValidatorIndex ctx := context.Background() _, err := NewService(ctx, config, tracked) require.NoError(t, err) diff --git a/beacon-chain/node/config.go b/beacon-chain/node/config.go index 1d795aadda4e..a11b4bdf97d9 100644 --- a/beacon-chain/node/config.go +++ b/beacon-chain/node/config.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/cmd" "github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/config/params" @@ -117,7 +118,18 @@ func configureExecutionSetting(cliCtx *cli.Context) error { if !common.IsHexAddress(ha) { return fmt.Errorf("%s is not a valid fee recipient address", ha) } - c.DefaultFeeRecipient = common.HexToAddress(ha) + mixedcaseAddress, err := common.NewMixedcaseAddressFromString(ha) + if err != nil { + return errors.Wrapf(err, "could not decode fee recipient %s", ha) + } + checksumAddress := common.HexToAddress(ha) + if !mixedcaseAddress.ValidChecksum() { + log.Warnf("Fee recipient %s is not a checksum Ethereum address. "+ + "The checksummed address is %s and will be used as the fee recipient. "+ + "We recommend using a mixed-case address (checksum) "+ + "to prevent spelling mistakes in your fee recipient Ethereum address", ha, checksumAddress.Hex()) + } + c.DefaultFeeRecipient = checksumAddress params.OverrideBeaconConfig(c) return nil } diff --git a/beacon-chain/node/config_test.go b/beacon-chain/node/config_test.go index 2699df1e774d..26e13f1e3107 100644 --- a/beacon-chain/node/config_test.go +++ b/beacon-chain/node/config_test.go @@ -87,6 +87,7 @@ func TestConfigureProofOfWork(t *testing.T) { func TestConfigureExecutionSetting(t *testing.T) { params.SetupTestConfigCleanup(t) + hook := logTest.NewGlobal() app := cli.App{} set := flag.NewFlagSet("test", 0) @@ -102,11 +103,15 @@ func TestConfigureExecutionSetting(t *testing.T) { require.NoError(t, err) assert.Equal(t, common.HexToAddress("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), params.BeaconConfig().DefaultFeeRecipient) - require.NoError(t, set.Set(flags.SuggestedFeeRecipient.Name, "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) + assert.LogsContain(t, hook, + "is not a checksum Ethereum address", + ) + require.NoError(t, set.Set(flags.SuggestedFeeRecipient.Name, "0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa")) cliCtx = cli.NewContext(&app, set, nil) err = configureExecutionSetting(cliCtx) require.NoError(t, err) - assert.Equal(t, common.HexToAddress("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), params.BeaconConfig().DefaultFeeRecipient) + assert.Equal(t, common.HexToAddress("0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa"), params.BeaconConfig().DefaultFeeRecipient) + } func TestConfigureNetwork(t *testing.T) { diff --git a/beacon-chain/node/node.go b/beacon-chain/node/node.go index c83f946d7488..de8baabec3b4 100644 --- a/beacon-chain/node/node.go +++ b/beacon-chain/node/node.go @@ -804,6 +804,7 @@ func (b *BeaconNode) registerRPCService() error { GenesisTimeFetcher: chainService, GenesisFetcher: chainService, BlockBuilder: b.fetchBuilderService(), + OptimisticModeFetcher: chainService, AttestationsPool: b.attestationPool, ExitPool: b.exitPool, SlashingsPool: b.slashingsPool, diff --git a/beacon-chain/p2p/gossip_topic_mappings.go b/beacon-chain/p2p/gossip_topic_mappings.go index 2a763b256050..9aba63458336 100644 --- a/beacon-chain/p2p/gossip_topic_mappings.go +++ b/beacon-chain/p2p/gossip_topic_mappings.go @@ -54,7 +54,9 @@ func init() { for k, v := range gossipTopicMappings { GossipTypeMapping[reflect.TypeOf(v)] = k } - // Specially handle Altair Objects. + // Specially handle Altair objects. GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockAltair{})] = BlockSubnetTopicFormat + // Specially handle Bellatrix objects. GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockBellatrix{})] = BlockSubnetTopicFormat + GossipTypeMapping[reflect.TypeOf(ðpb.SignedBlindedBeaconBlockBellatrix{})] = BlockSubnetTopicFormat } diff --git a/beacon-chain/powchain/engine_client.go b/beacon-chain/powchain/engine_client.go index 08331828c987..2670d5403877 100644 --- a/beacon-chain/powchain/engine_client.go +++ b/beacon-chain/powchain/engine_client.go @@ -81,8 +81,6 @@ func (s *Service) NewPayload(ctx context.Context, payload *pb.ExecutionPayload) switch result.Status { case pb.PayloadStatus_INVALID_BLOCK_HASH: return nil, fmt.Errorf("could not validate block hash: %v", result.ValidationError) - case pb.PayloadStatus_INVALID_TERMINAL_BLOCK: - return nil, fmt.Errorf("could not satisfy terminal block condition: %v", result.ValidationError) case pb.PayloadStatus_ACCEPTED, pb.PayloadStatus_SYNCING: return nil, ErrAcceptedSyncingPayloadStatus case pb.PayloadStatus_INVALID: @@ -119,8 +117,6 @@ func (s *Service) ForkchoiceUpdated( } resp := result.Status switch resp.Status { - case pb.PayloadStatus_INVALID_TERMINAL_BLOCK: - return nil, nil, fmt.Errorf("could not satisfy terminal block condition: %v", resp.ValidationError) case pb.PayloadStatus_SYNCING: return nil, nil, ErrAcceptedSyncingPayloadStatus case pb.PayloadStatus_INVALID: diff --git a/beacon-chain/powchain/engine_client_test.go b/beacon-chain/powchain/engine_client_test.go index 62524a8b845f..5ca8908d43d7 100644 --- a/beacon-chain/powchain/engine_client_test.go +++ b/beacon-chain/powchain/engine_client_test.go @@ -217,27 +217,6 @@ func TestClient_HTTP(t *testing.T) { require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID) require.DeepEqual(t, []byte(nil), validHash) }) - t.Run(ForkchoiceUpdatedMethod+" INVALID_TERMINAL_BLOCK status", func(t *testing.T) { - forkChoiceState := &pb.ForkchoiceState{ - HeadBlockHash: []byte("head"), - SafeBlockHash: []byte("safe"), - FinalizedBlockHash: []byte("finalized"), - } - payloadAttributes := &pb.PayloadAttributes{ - Timestamp: 1, - PrevRandao: []byte("random"), - SuggestedFeeRecipient: []byte("suggestedFeeRecipient"), - } - want, ok := fix["ForkchoiceUpdatedInvalidTerminalBlockResponse"].(*ForkchoiceUpdatedResponse) - require.Equal(t, true, ok) - client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want) - - // We call the RPC method via HTTP and expect a proper result. - payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes) - require.ErrorContains(t, "could not satisfy terminal block condition", err) - require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID) - require.DeepEqual(t, []byte(nil), validHash) - }) t.Run(NewPayloadMethod+" VALID status", func(t *testing.T) { execPayload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload) require.Equal(t, true, ok) @@ -274,18 +253,6 @@ func TestClient_HTTP(t *testing.T) { require.ErrorContains(t, "could not validate block hash", err) require.DeepEqual(t, []uint8(nil), resp) }) - t.Run(NewPayloadMethod+" INVALID_TERMINAL_BLOCK status", func(t *testing.T) { - execPayload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload) - require.Equal(t, true, ok) - want, ok := fix["InvalidTerminalBlockStatus"].(*pb.PayloadStatus) - require.Equal(t, true, ok) - client := newPayloadSetup(t, want, execPayload) - - // We call the RPC method via HTTP and expect a proper result. - resp, err := client.NewPayload(ctx, execPayload) - require.ErrorContains(t, "could not satisfy terminal block condition", err) - require.DeepEqual(t, []uint8(nil), resp) - }) t.Run(NewPayloadMethod+" INVALID status", func(t *testing.T) { execPayload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload) require.Equal(t, true, ok) @@ -819,13 +786,6 @@ func fixtures() map[string]interface{} { }, PayloadId: &id, } - forkChoiceInvalidTerminalBlockResp := &ForkchoiceUpdatedResponse{ - Status: &pb.PayloadStatus{ - Status: pb.PayloadStatus_INVALID_TERMINAL_BLOCK, - LatestValidHash: nil, - }, - PayloadId: &id, - } forkChoiceAcceptedResp := &ForkchoiceUpdatedResponse{ Status: &pb.PayloadStatus{ Status: pb.PayloadStatus_ACCEPTED, @@ -856,10 +816,6 @@ func fixtures() map[string]interface{} { Status: pb.PayloadStatus_INVALID_BLOCK_HASH, LatestValidHash: nil, } - inValidTerminalBlockStatus := &pb.PayloadStatus{ - Status: pb.PayloadStatus_INVALID_TERMINAL_BLOCK, - LatestValidHash: nil, - } acceptedStatus := &pb.PayloadStatus{ Status: pb.PayloadStatus_ACCEPTED, LatestValidHash: nil, @@ -877,21 +833,19 @@ func fixtures() map[string]interface{} { LatestValidHash: foo[:], } return map[string]interface{}{ - "ExecutionBlock": executionBlock, - "ExecutionPayload": executionPayloadFixture, - "ValidPayloadStatus": validStatus, - "InvalidBlockHashStatus": inValidBlockHashStatus, - "InvalidTerminalBlockStatus": inValidTerminalBlockStatus, - "AcceptedStatus": acceptedStatus, - "SyncingStatus": syncingStatus, - "InvalidStatus": invalidStatus, - "UnknownStatus": unknownStatus, - "ForkchoiceUpdatedResponse": forkChoiceResp, - "ForkchoiceUpdatedSyncingResponse": forkChoiceSyncingResp, - "ForkchoiceUpdatedInvalidTerminalBlockResponse": forkChoiceInvalidTerminalBlockResp, - "ForkchoiceUpdatedAcceptedResponse": forkChoiceAcceptedResp, - "ForkchoiceUpdatedInvalidResponse": forkChoiceInvalidResp, - "TransitionConfiguration": transitionCfg, + "ExecutionBlock": executionBlock, + "ExecutionPayload": executionPayloadFixture, + "ValidPayloadStatus": validStatus, + "InvalidBlockHashStatus": inValidBlockHashStatus, + "AcceptedStatus": acceptedStatus, + "SyncingStatus": syncingStatus, + "InvalidStatus": invalidStatus, + "UnknownStatus": unknownStatus, + "ForkchoiceUpdatedResponse": forkChoiceResp, + "ForkchoiceUpdatedSyncingResponse": forkChoiceSyncingResp, + "ForkchoiceUpdatedAcceptedResponse": forkChoiceAcceptedResp, + "ForkchoiceUpdatedInvalidResponse": forkChoiceInvalidResp, + "TransitionConfiguration": transitionCfg, } } diff --git a/beacon-chain/powchain/rpc_connection.go b/beacon-chain/powchain/rpc_connection.go index be739951be7d..46970944307a 100644 --- a/beacon-chain/powchain/rpc_connection.go +++ b/beacon-chain/powchain/rpc_connection.go @@ -70,7 +70,9 @@ func (s *Service) pollConnectionStatus(ctx context.Context) { continue } // Close previous client, if connection was successful. - currClient.Close() + if currClient != nil { + currClient.Close() + } log.Infof("Connected to new endpoint: %s", logs.MaskCredentialsLogging(s.cfg.currHttpEndpoint.Url)) return case <-s.ctx.Done(): @@ -92,7 +94,9 @@ func (s *Service) retryExecutionClientConnection(ctx context.Context, err error) return } // Close previous client, if connection was successful. - currClient.Close() + if currClient != nil { + currClient.Close() + } // Reset run error in the event of a successful connection. s.runError = nil } @@ -114,7 +118,9 @@ func (s *Service) checkDefaultEndpoint(ctx context.Context) { return } // Close previous client, if connection was successful. - currClient.Close() + if currClient != nil { + currClient.Close() + } s.updateCurrHttpEndpoint(primaryEndpoint) } diff --git a/beacon-chain/powchain/service.go b/beacon-chain/powchain/service.go index 1c62c9a7f9af..3a3dc8034c7b 100644 --- a/beacon-chain/powchain/service.go +++ b/beacon-chain/powchain/service.go @@ -767,9 +767,12 @@ func (s *Service) initializeEth1Data(ctx context.Context, eth1DataInDB *ethpb.ET if eth1DataInDB == nil { return nil } - s.depositTrie = trie.CreateTrieFromProto(eth1DataInDB.Trie) - s.chainStartData = eth1DataInDB.ChainstartData var err error + s.depositTrie, err = trie.CreateTrieFromProto(eth1DataInDB.Trie) + if err != nil { + return err + } + s.chainStartData = eth1DataInDB.ChainstartData if !reflect.ValueOf(eth1DataInDB.BeaconState).IsZero() { s.preGenesisState, err = v1.InitializeFromProto(eth1DataInDB.BeaconState) if err != nil { diff --git a/beacon-chain/powchain/testing/mock_engine_client.go b/beacon-chain/powchain/testing/mock_engine_client.go index 9b23306b963a..7c8a9cd5cae1 100644 --- a/beacon-chain/powchain/testing/mock_engine_client.go +++ b/beacon-chain/powchain/testing/mock_engine_client.go @@ -28,6 +28,7 @@ type EngineClient struct { BlockByHashMap map[[32]byte]*pb.ExecutionBlock TerminalBlockHash []byte TerminalBlockHashExists bool + OverrideValidHash [32]byte } // NewPayload -- @@ -37,8 +38,11 @@ func (e *EngineClient) NewPayload(_ context.Context, _ *pb.ExecutionPayload) ([] // ForkchoiceUpdated -- func (e *EngineClient) ForkchoiceUpdated( - _ context.Context, _ *pb.ForkchoiceState, _ *pb.PayloadAttributes, + _ context.Context, fcs *pb.ForkchoiceState, _ *pb.PayloadAttributes, ) (*pb.PayloadIDBytes, []byte, error) { + if e.OverrideValidHash != [32]byte{} && bytesutil.ToBytes32(fcs.HeadBlockHash) == e.OverrideValidHash { + return e.PayloadIDBytes, e.ForkChoiceUpdatedResp, nil + } return e.PayloadIDBytes, e.ForkChoiceUpdatedResp, e.ErrForkchoiceUpdated } diff --git a/beacon-chain/rpc/apimiddleware/custom_handlers.go b/beacon-chain/rpc/apimiddleware/custom_handlers.go index 341194ad5aee..24d5b6937328 100644 --- a/beacon-chain/rpc/apimiddleware/custom_handlers.go +++ b/beacon-chain/rpc/apimiddleware/custom_handlers.go @@ -16,44 +16,78 @@ import ( "github.com/r3labs/sse" ) +const ( + versionHeader = "Eth-Consensus-Version" + grpcVersionHeader = "Grpc-metadata-Eth-Consensus-Version" +) + type sszConfig struct { - sszPath string fileName string - responseJson sszResponseJson + responseJson sszResponse } func handleGetBeaconStateSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) { config := sszConfig{ - sszPath: "/eth/v1/debug/beacon/states/{state_id}/ssz", fileName: "beacon_state.ssz", - responseJson: &beaconStateSSZResponseJson{}, + responseJson: &sszResponseJson{}, } return handleGetSSZ(m, endpoint, w, req, config) } func handleGetBeaconBlockSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) { config := sszConfig{ - sszPath: "/eth/v1/beacon/blocks/{block_id}/ssz", fileName: "beacon_block.ssz", - responseJson: &blockSSZResponseJson{}, + responseJson: &sszResponseJson{}, } return handleGetSSZ(m, endpoint, w, req, config) } func handleGetBeaconStateSSZV2(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) { config := sszConfig{ - sszPath: "/eth/v2/debug/beacon/states/{state_id}/ssz", fileName: "beacon_state.ssz", - responseJson: &beaconStateSSZResponseV2Json{}, + responseJson: &versionedSSZResponseJson{}, } return handleGetSSZ(m, endpoint, w, req, config) } func handleGetBeaconBlockSSZV2(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) { config := sszConfig{ - sszPath: "/eth/v2/beacon/blocks/{block_id}/ssz", fileName: "beacon_block.ssz", - responseJson: &blockSSZResponseV2Json{}, + responseJson: &versionedSSZResponseJson{}, + } + return handleGetSSZ(m, endpoint, w, req, config) +} + +func handleSubmitBlockSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) { + return handlePostSSZ(m, endpoint, w, req, sszConfig{}) +} + +func handleSubmitBlindedBlockSSZ( + m *apimiddleware.ApiProxyMiddleware, + endpoint apimiddleware.Endpoint, + w http.ResponseWriter, + req *http.Request, +) (handled bool) { + return handlePostSSZ(m, endpoint, w, req, sszConfig{}) +} + +func handleProduceBlockSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) { + config := sszConfig{ + fileName: "produce_beacon_block.ssz", + responseJson: &versionedSSZResponseJson{}, + } + return handleGetSSZ(m, endpoint, w, req, config) +} + +func handleProduceBlindedBlockSSZ( + m *apimiddleware.ApiProxyMiddleware, + endpoint apimiddleware.Endpoint, + w http.ResponseWriter, + req *http.Request, +) (handled bool) { + config := sszConfig{ + fileName: "produce_blinded_beacon_block.ssz", + responseJson: &versionedSSZResponseJson{}, } return handleGetSSZ(m, endpoint, w, req, config) } @@ -69,7 +103,7 @@ func handleGetSSZ( return false } - if errJson := prepareSSZRequestForProxying(m, endpoint, req, config.sszPath); errJson != nil { + if errJson := prepareSSZRequestForProxying(m, endpoint, req); errJson != nil { apimiddleware.WriteError(w, errJson, nil) return true } @@ -112,6 +146,53 @@ func handleGetSSZ( return true } +func handlePostSSZ( + m *apimiddleware.ApiProxyMiddleware, + endpoint apimiddleware.Endpoint, + w http.ResponseWriter, + req *http.Request, + config sszConfig, +) (handled bool) { + if !sszPosted(req) { + return false + } + + if errJson := prepareSSZRequestForProxying(m, endpoint, req); errJson != nil { + apimiddleware.WriteError(w, errJson, nil) + return true + } + prepareCustomHeaders(req) + if errJson := preparePostedSSZData(req); errJson != nil { + apimiddleware.WriteError(w, errJson, nil) + return true + } + + grpcResponse, errJson := m.ProxyRequest(req) + if errJson != nil { + apimiddleware.WriteError(w, errJson, nil) + return true + } + grpcResponseBody, errJson := apimiddleware.ReadGrpcResponseBody(grpcResponse.Body) + if errJson != nil { + apimiddleware.WriteError(w, errJson, nil) + return true + } + respHasError, errJson := apimiddleware.HandleGrpcResponseError(endpoint.Err, grpcResponse, grpcResponseBody, w) + if errJson != nil { + apimiddleware.WriteError(w, errJson, nil) + return + } + if respHasError { + return + } + if errJson := apimiddleware.Cleanup(grpcResponse.Body); errJson != nil { + apimiddleware.WriteError(w, errJson, nil) + return true + } + + return true +} + func sszRequested(req *http.Request) bool { accept, ok := req.Header["Accept"] if !ok { @@ -125,24 +206,57 @@ func sszRequested(req *http.Request) bool { return false } -func prepareSSZRequestForProxying( - m *apimiddleware.ApiProxyMiddleware, - endpoint apimiddleware.Endpoint, - req *http.Request, sszPath string, -) apimiddleware.ErrorJson { +func sszPosted(req *http.Request) bool { + ct, ok := req.Header["Content-Type"] + if !ok { + return false + } + if len(ct) != 1 { + return false + } + return ct[0] == "application/octet-stream" +} + +func prepareSSZRequestForProxying(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, req *http.Request) apimiddleware.ErrorJson { req.URL.Scheme = "http" req.URL.Host = m.GatewayAddress req.RequestURI = "" - req.URL.Path = sszPath - if errJson := apimiddleware.HandleURLParameters(endpoint.Path, req, []string{}); errJson != nil { + if errJson := apimiddleware.HandleURLParameters(endpoint.Path, req, endpoint.RequestURLLiterals); errJson != nil { + return errJson + } + if errJson := apimiddleware.HandleQueryParameters(req, endpoint.RequestQueryParams); errJson != nil { return errJson } - // We have to add the prefix after handling parameters because adding the prefix changes URL segment indexing. - req.URL.Path = "/internal" + req.URL.Path + // We have to add new segments after handling parameters because it changes URL segment indexing. + req.URL.Path = "/internal" + req.URL.Path + "/ssz" + return nil +} + +func prepareCustomHeaders(req *http.Request) { + ver := req.Header.Get(versionHeader) + if ver != "" { + req.Header.Del(versionHeader) + req.Header.Add(grpcVersionHeader, ver) + } +} + +func preparePostedSSZData(req *http.Request) apimiddleware.ErrorJson { + buf, err := io.ReadAll(req.Body) + if err != nil { + return apimiddleware.InternalServerErrorWithMessage(err, "could not read body") + } + j := sszRequestJson{Data: base64.StdEncoding.EncodeToString(buf)} + data, err := json.Marshal(j) + if err != nil { + return apimiddleware.InternalServerErrorWithMessage(err, "could not prepare POST data") + } + req.Body = io.NopCloser(bytes.NewBuffer(data)) + req.ContentLength = int64(len(data)) + req.Header.Set("Content-Type", "application/json") return nil } -func serializeMiddlewareResponseIntoSSZ(respJson sszResponseJson) (version string, ssz []byte, errJson apimiddleware.ErrorJson) { +func serializeMiddlewareResponseIntoSSZ(respJson sszResponse) (version string, ssz []byte, errJson apimiddleware.ErrorJson) { // Serialize the SSZ part of the deserialized value. data, err := base64.StdEncoding.DecodeString(respJson.SSZData()) if err != nil { @@ -168,7 +282,7 @@ func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWrite w.Header().Set("Content-Length", strconv.Itoa(len(respSsz))) w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Disposition", "attachment; filename="+fileName) - w.Header().Set("Eth-Consensus-Version", respVersion) + w.Header().Set(versionHeader, respVersion) if statusCodeHeader != "" { code, err := strconv.Atoi(statusCodeHeader) if err != nil { diff --git a/beacon-chain/rpc/apimiddleware/custom_handlers_test.go b/beacon-chain/rpc/apimiddleware/custom_handlers_test.go index 9809a81b640b..b8e6fa35b973 100644 --- a/beacon-chain/rpc/apimiddleware/custom_handlers_test.go +++ b/beacon-chain/rpc/apimiddleware/custom_handlers_test.go @@ -70,11 +70,21 @@ func TestPrepareSSZRequestForProxying(t *testing.T) { var body bytes.Buffer request := httptest.NewRequest("GET", "http://foo.example", &body) - errJson := prepareSSZRequestForProxying(middleware, endpoint, request, "/ssz") + errJson := prepareSSZRequestForProxying(middleware, endpoint, request) require.Equal(t, true, errJson == nil) assert.Equal(t, "/internal/ssz", request.URL.Path) } +func TestPreparePostedSszData(t *testing.T) { + var body bytes.Buffer + body.Write([]byte("body")) + request := httptest.NewRequest("POST", "http://foo.example", &body) + + preparePostedSSZData(request) + assert.Equal(t, int64(19), request.ContentLength) + assert.Equal(t, "application/json", request.Header.Get("Content-Type")) +} + func TestSerializeMiddlewareResponseIntoSSZ(t *testing.T) { t.Run("ok", func(t *testing.T) { j := testSSZResponseJson{ @@ -133,7 +143,7 @@ func TestWriteSSZResponseHeaderAndBody(t *testing.T) { require.Equal(t, true, ok, "header not found") require.Equal(t, 1, len(v), "wrong number of header values") assert.Equal(t, "attachment; filename=test.ssz", v[0]) - v, ok = writer.Header()["Eth-Consensus-Version"] + v, ok = writer.Header()[versionHeader] require.Equal(t, true, ok, "header not found") require.Equal(t, 1, len(v), "wrong number of header values") assert.Equal(t, "version", v[0]) diff --git a/beacon-chain/rpc/apimiddleware/endpoint_factory.go b/beacon-chain/rpc/apimiddleware/endpoint_factory.go index 5b1ef48cd840..7f3d34758d1e 100644 --- a/beacon-chain/rpc/apimiddleware/endpoint_factory.go +++ b/beacon-chain/rpc/apimiddleware/endpoint_factory.go @@ -110,11 +110,13 @@ func (_ *BeaconEndpointFactory) Create(path string) (*apimiddleware.Endpoint, er OnPreDeserializeRequestBodyIntoContainer: setInitialPublishBlockPostRequest, OnPostDeserializeRequestBodyIntoContainer: preparePublishedBlock, } + endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleSubmitBlockSSZ} case "/eth/v1/beacon/blinded_blocks": endpoint.Hooks = apimiddleware.HookCollection{ OnPreDeserializeRequestBodyIntoContainer: setInitialPublishBlindedBlockPostRequest, OnPostDeserializeRequestBodyIntoContainer: preparePublishedBlindedBlock, } + endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleSubmitBlindedBlockSSZ} case "/eth/v1/beacon/blocks/{block_id}": endpoint.GetResponse = &blockResponseJson{} endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleGetBeaconBlockSSZ} @@ -221,6 +223,7 @@ func (_ *BeaconEndpointFactory) Create(path string) (*apimiddleware.Endpoint, er endpoint.Hooks = apimiddleware.HookCollection{ OnPreSerializeMiddlewareResponseIntoJson: serializeProducedV2Block, } + endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleProduceBlockSSZ} case "/eth/v1/validator/blinded_blocks/{slot}": endpoint.GetResponse = &produceBlindedBlockResponseJson{} endpoint.RequestURLLiterals = []string{"slot"} @@ -228,6 +231,7 @@ func (_ *BeaconEndpointFactory) Create(path string) (*apimiddleware.Endpoint, er endpoint.Hooks = apimiddleware.HookCollection{ OnPreSerializeMiddlewareResponseIntoJson: serializeProducedBlindedBlock, } + endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleProduceBlindedBlockSSZ} case "/eth/v1/validator/attestation_data": endpoint.GetResponse = &produceAttestationDataResponseJson{} endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "slot"}, {Name: "committee_index"}} diff --git a/beacon-chain/rpc/apimiddleware/structs.go b/beacon-chain/rpc/apimiddleware/structs.go index 2e1570bbade8..245075f9796d 100644 --- a/beacon-chain/rpc/apimiddleware/structs.go +++ b/beacon-chain/rpc/apimiddleware/structs.go @@ -7,6 +7,10 @@ import ( ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2" ) +//---------------- +// Requests and responses. +//---------------- + // genesisResponseJson is used in /beacon/genesis API endpoint. type genesisResponseJson struct { Data *genesisResponse_GenesisJson `json:"data"` @@ -457,7 +461,7 @@ type blindedBeaconBlockBodyBellatrixJson struct { Deposits []*depositJson `json:"deposits"` VoluntaryExits []*signedVoluntaryExitJson `json:"voluntary_exits"` SyncAggregate *syncAggregateJson `json:"sync_aggregate"` - ExecutionPayloadHeader *executionPayloadHeaderJson `json:"execution_payload"` + ExecutionPayloadHeader *executionPayloadHeaderJson `json:"execution_payload_header"` } type executionPayloadJson struct { @@ -489,7 +493,7 @@ type executionPayloadHeaderJson struct { GasUsed string `json:"gas_used"` TimeStamp string `json:"timestamp"` ExtraData string `json:"extra_data" hex:"true"` - BaseFeePerGas string `json:"base_fee_per_gas" hex:"true"` + BaseFeePerGas string `json:"base_fee_per_gas" uint256:"true"` BlockHash string `json:"block_hash" hex:"true"` TransactionsRoot string `json:"transactions_root" hex:"true"` } @@ -833,63 +837,38 @@ type syncCommitteeContributionJson struct { // SSZ // --------------- -// sszResponseJson is a common abstraction over all SSZ responses. -type sszResponseJson interface { - SSZVersion() string - SSZData() string -} - -// blockSSZResponseJson is used in /beacon/blocks/{block_id} API endpoint. -type blockSSZResponseJson struct { +type sszRequestJson struct { Data string `json:"data"` } -func (ssz *blockSSZResponseJson) SSZData() string { - return ssz.Data -} - -func (*blockSSZResponseJson) SSZVersion() string { - return strings.ToLower(ethpbv2.Version_PHASE0.String()) -} - -// blockSSZResponseV2Json is used in /v2/beacon/blocks/{block_id} API endpoint. -type blockSSZResponseV2Json struct { - Version string `json:"version"` - Data string `json:"data"` -} - -func (ssz *blockSSZResponseV2Json) SSZData() string { - return ssz.Data -} - -func (ssz *blockSSZResponseV2Json) SSZVersion() string { - return ssz.Version +// sszResponse is a common abstraction over all SSZ responses. +type sszResponse interface { + SSZVersion() string + SSZData() string } -// beaconStateSSZResponseJson is used in /debug/beacon/states/{state_id} API endpoint. -type beaconStateSSZResponseJson struct { +type sszResponseJson struct { Data string `json:"data"` } -func (ssz *beaconStateSSZResponseJson) SSZData() string { +func (ssz *sszResponseJson) SSZData() string { return ssz.Data } -func (*beaconStateSSZResponseJson) SSZVersion() string { +func (*sszResponseJson) SSZVersion() string { return strings.ToLower(ethpbv2.Version_PHASE0.String()) } -// beaconStateSSZResponseV2Json is used in /v2/debug/beacon/states/{state_id} API endpoint. -type beaconStateSSZResponseV2Json struct { +type versionedSSZResponseJson struct { Version string `json:"version"` Data string `json:"data"` } -func (ssz *beaconStateSSZResponseV2Json) SSZData() string { +func (ssz *versionedSSZResponseJson) SSZData() string { return ssz.Data } -func (ssz *beaconStateSSZResponseV2Json) SSZVersion() string { +func (ssz *versionedSSZResponseJson) SSZVersion() string { return ssz.Version } diff --git a/beacon-chain/rpc/eth/beacon/BUILD.bazel b/beacon-chain/rpc/eth/beacon/BUILD.bazel index f490d733b253..e527709cc09c 100644 --- a/beacon-chain/rpc/eth/beacon/BUILD.bazel +++ b/beacon-chain/rpc/eth/beacon/BUILD.bazel @@ -44,6 +44,7 @@ go_library( "//consensus-types/wrapper:go_default_library", "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", + "//encoding/ssz/detect:go_default_library", "//network/forks:go_default_library", "//proto/eth/v1:go_default_library", "//proto/eth/v2:go_default_library", @@ -56,6 +57,7 @@ go_library( "@io_bazel_rules_go//proto/wkt:empty_go_proto", "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//codes:go_default_library", + "@org_golang_google_grpc//metadata:go_default_library", "@org_golang_google_grpc//status:go_default_library", "@org_golang_google_protobuf//types/known/emptypb:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", @@ -114,6 +116,7 @@ go_test( "@com_github_wealdtech_go_bytesutil//:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//codes:go_default_library", + "@org_golang_google_grpc//metadata:go_default_library", "@org_golang_google_grpc//status:go_default_library", "@org_golang_google_protobuf//types/known/emptypb:go_default_library", ], diff --git a/beacon-chain/rpc/eth/beacon/blocks.go b/beacon-chain/rpc/eth/beacon/blocks.go index 3fccd3ed22fb..706a68a091f5 100644 --- a/beacon-chain/rpc/eth/beacon/blocks.go +++ b/beacon-chain/rpc/eth/beacon/blocks.go @@ -18,16 +18,21 @@ import ( types "github.com/prysmaticlabs/prysm/consensus-types/primitives" "github.com/prysmaticlabs/prysm/consensus-types/wrapper" "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz/detect" + "github.com/prysmaticlabs/prysm/network/forks" ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1" ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2" "github.com/prysmaticlabs/prysm/proto/migration" "github.com/prysmaticlabs/prysm/time/slots" "go.opencensus.io/trace" "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" ) +const versionHeader = "eth-consensus-version" + // blockIdParseError represents an error scenario where a block ID could not be parsed. type blockIdParseError struct { message string @@ -109,7 +114,7 @@ func (bs *Server) GetBlockHeader(ctx context.Context, req *ethpbv1.BlockRequest) if err != nil { return nil, status.Errorf(codes.Internal, "Could not determine if block root is canonical: %v", err) } - isOptimistic, err := bs.HeadFetcher.IsOptimisticForRoot(ctx, blkRoot) + isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, blkRoot) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if block is optimistic: %v", err) } @@ -175,7 +180,7 @@ func (bs *Server) ListBlockHeaders(ctx context.Context, req *ethpbv1.BlockHeader return nil, status.Errorf(codes.Internal, "Could not determine if block root is canonical: %v", err) } if !isOptimistic { - isOptimistic, err = bs.HeadFetcher.IsOptimisticForRoot(ctx, blkRoots[i]) + isOptimistic, err = bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, blkRoots[i]) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if block is optimistic: %v", err) } @@ -223,6 +228,45 @@ func (bs *Server) SubmitBlock(ctx context.Context, req *ethpbv2.SignedBeaconBloc return &emptypb.Empty{}, nil } +// SubmitBlockSSZ instructs the beacon node to broadcast a newly signed beacon block to the beacon network, to be +// included in the beacon chain. The beacon node is not required to validate the signed BeaconBlock, and a successful +// response (20X) only indicates that the broadcast has been successful. The beacon node is expected to integrate the +// new block into its state, and therefore validate the block internally, however blocks which fail the validation are +// still broadcast but a different status code is returned (202). +// +// The provided block must be SSZ-serialized. +func (bs *Server) SubmitBlockSSZ(ctx context.Context, req *ethpbv2.SSZContainer) (*emptypb.Empty, error) { + ctx, span := trace.StartSpan(ctx, "beacon.SubmitBlockSSZ") + defer span.End() + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not read "+versionHeader+" header") + } + ver := md.Get(versionHeader) + if len(ver) == 0 { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not read "+versionHeader+" header") + } + schedule := forks.NewOrderedSchedule(params.BeaconConfig()) + forkVer, err := schedule.VersionForName(ver[0]) + if err != nil { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not determine fork version: %v", err) + } + unmarshaler, err := detect.FromForkVersion(forkVer) + if err != nil { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not create unmarshaler: %v", err) + } + block, err := unmarshaler.UnmarshalBeaconBlock(req.Data) + if err != nil { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not unmarshal request data into block: %v", err) + } + root, err := block.Block().HashTreeRoot() + if err != nil { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not compute block's hash tree root: %v", err) + } + return &emptypb.Empty{}, bs.submitBlock(ctx, root, block) +} + // SubmitBlindedBlock instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct // and publish a `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`. // The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network, @@ -259,6 +303,48 @@ func (bs *Server) SubmitBlindedBlock(ctx context.Context, req *ethpbv2.SignedBli return &emptypb.Empty{}, nil } +// SubmitBlindedBlockSSZ instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct +// and publish a `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`. +// The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network, +// to be included in the beacon chain. The beacon node is not required to validate the signed +// `BeaconBlock`, and a successful response (20X) only indicates that the broadcast has been +// successful. The beacon node is expected to integrate the new block into its state, and +// therefore validate the block internally, however blocks which fail the validation are still +// broadcast but a different status code is returned (202). +// +// The provided block must be SSZ-serialized. +func (bs *Server) SubmitBlindedBlockSSZ(ctx context.Context, req *ethpbv2.SSZContainer) (*emptypb.Empty, error) { + ctx, span := trace.StartSpan(ctx, "beacon.SubmitBlindedBlockSSZ") + defer span.End() + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not read"+versionHeader+" header") + } + ver := md.Get(versionHeader) + if len(ver) == 0 { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not read"+versionHeader+" header") + } + schedule := forks.NewOrderedSchedule(params.BeaconConfig()) + forkVer, err := schedule.VersionForName(ver[0]) + if err != nil { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not determine fork version: %v", err) + } + unmarshaler, err := detect.FromForkVersion(forkVer) + if err != nil { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not create unmarshaler: %v", err) + } + block, err := unmarshaler.UnmarshalBlindedBeaconBlock(req.Data) + if err != nil { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not unmarshal request data into block: %v", err) + } + root, err := block.Block().HashTreeRoot() + if err != nil { + return &emptypb.Empty{}, status.Errorf(codes.Internal, "Could not compute block's hash tree root: %v", err) + } + return &emptypb.Empty{}, bs.submitBlock(ctx, root, block) +} + // GetBlock retrieves block details for given block ID. func (bs *Server) GetBlock(ctx context.Context, req *ethpbv1.BlockRequest) (*ethpbv1.BlockResponse, error) { ctx, span := trace.StartSpan(ctx, "beacon.GetBlock") @@ -371,7 +457,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) ( if err != nil { return nil, status.Errorf(codes.Internal, "Could not get block root: %v", err) } - isOptimistic, err := bs.HeadFetcher.IsOptimisticForRoot(ctx, root) + isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if block is optimistic: %v", err) } @@ -393,7 +479,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) ( } // GetBlockSSZV2 returns the SSZ-serialized version of the beacon block for given block ID. -func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (*ethpbv2.BlockSSZResponseV2, error) { +func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (*ethpbv2.SSZContainer, error) { ctx, span := trace.StartSpan(ctx, "beacon.GetBlockSSZV2") defer span.End() @@ -413,7 +499,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2 if err != nil { return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err) } - return ðpbv2.BlockSSZResponseV2{Version: ethpbv2.Version_PHASE0, Data: sszBlock}, nil + return ðpbv2.SSZContainer{Version: ethpbv2.Version_PHASE0, Data: sszBlock}, nil } // ErrUnsupportedPhase0Block means that we have another block type if !errors.Is(err, wrapper.ErrUnsupportedPhase0Block) { @@ -437,7 +523,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2 if err != nil { return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err) } - return ðpbv2.BlockSSZResponseV2{Version: ethpbv2.Version_ALTAIR, Data: sszData}, nil + return ðpbv2.SSZContainer{Version: ethpbv2.Version_ALTAIR, Data: sszData}, nil } // ErrUnsupportedAltairBlock means that we have another block type if !errors.Is(err, wrapper.ErrUnsupportedAltairBlock) { @@ -461,7 +547,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2 if err != nil { return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ: %v", err) } - return ðpbv2.BlockSSZResponseV2{Version: ethpbv2.Version_BELLATRIX, Data: sszData}, nil + return ðpbv2.SSZContainer{Version: ethpbv2.Version_BELLATRIX, Data: sszData}, nil } // ErrUnsupportedBellatrixBlock means that we have another block type if !errors.Is(err, wrapper.ErrUnsupportedBellatrixBlock) { @@ -543,7 +629,7 @@ func (bs *Server) GetBlockRoot(ctx context.Context, req *ethpbv1.BlockRequest) ( } } - isOptimistic, err := bs.HeadFetcher.IsOptimisticForRoot(ctx, bytesutil.ToBytes32(root)) + isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, bytesutil.ToBytes32(root)) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if block is optimistic: %v", err) } @@ -616,7 +702,7 @@ func (bs *Server) ListBlockAttestations(ctx context.Context, req *ethpbv1.BlockR if err != nil { return nil, status.Errorf(codes.Internal, "Could not get block root: %v", err) } - isOptimistic, err := bs.HeadFetcher.IsOptimisticForRoot(ctx, root) + isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if block is optimistic: %v", err) } diff --git a/beacon-chain/rpc/eth/beacon/blocks_test.go b/beacon-chain/rpc/eth/beacon/blocks_test.go index e565f462b64a..dacb0eddc751 100644 --- a/beacon-chain/rpc/eth/beacon/blocks_test.go +++ b/beacon-chain/rpc/eth/beacon/blocks_test.go @@ -9,6 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/db" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" + "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/consensus-types/interfaces" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" "github.com/prysmaticlabs/prysm/consensus-types/wrapper" @@ -21,6 +22,7 @@ import ( "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/util" + "google.golang.org/grpc/metadata" ) func fillDBTestBlocks(ctx context.Context, t *testing.T, beaconDB db.Database) (*ethpbalpha.SignedBeaconBlock, []*ethpbalpha.BeaconBlockContainer) { @@ -187,9 +189,10 @@ func TestServer_GetBlockHeader(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } tests := []struct { @@ -287,9 +290,10 @@ func TestServer_GetBlockHeader(t *testing.T) { Optimistic: true, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } header, err := bs.GetBlockHeader(ctx, ðpbv1.BlockRequest{BlockId: []byte("head")}) require.NoError(t, err) @@ -312,9 +316,10 @@ func TestServer_ListBlockHeaders(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainFetcher, - HeadFetcher: mockChainFetcher, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainFetcher, + HeadFetcher: mockChainFetcher, + OptimisticModeFetcher: mockChainFetcher, } b2 := util.NewBeaconBlock() @@ -416,9 +421,10 @@ func TestServer_ListBlockHeaders(t *testing.T) { Optimistic: true, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainFetcher, - HeadFetcher: mockChainFetcher, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainFetcher, + HeadFetcher: mockChainFetcher, + OptimisticModeFetcher: mockChainFetcher, } slot := types.Slot(30) headers, err := bs.ListBlockHeaders(ctx, ðpbv1.BlockHeadersRequest{ @@ -557,6 +563,289 @@ func TestServer_SubmitBlock_OK(t *testing.T) { }) } +func TestServer_SubmitBlockSSZ_OK(t *testing.T) { + t.Run("Phase 0", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + genesis := util.NewBeaconBlock() + wsb, err := wrapper.WrappedSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(context.Background(), wsb), "Could not save genesis block") + + numDeposits := uint64(64) + beaconState, _ := util.DeterministicGenesisState(t, numDeposits) + bsRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesisRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state") + + c := &mock.ChainService{Root: bsRoot[:], State: beaconState} + beaconChainServer := &Server{ + BeaconDB: beaconDB, + BlockReceiver: c, + ChainInfoFetcher: c, + BlockNotifier: c.BlockNotifier(), + Broadcaster: mockp2p.NewTestP2P(t), + HeadFetcher: c, + } + req := util.NewBeaconBlock() + req.Block.Slot = 5 + req.Block.ParentRoot = bsRoot[:] + wsb, err = wrapper.WrappedSignedBeaconBlock(req) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wsb)) + blockSsz, err := req.MarshalSSZ() + require.NoError(t, err) + blockReq := ðpbv2.SSZContainer{ + Data: blockSsz, + } + md := metadata.MD{} + md.Set(versionHeader, "phase0") + sszCtx := metadata.NewIncomingContext(ctx, md) + _, err = beaconChainServer.SubmitBlockSSZ(sszCtx, blockReq) + assert.NoError(t, err, "Could not propose block correctly") + }) + + t.Run("Altair", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + genesis := util.NewBeaconBlockAltair() + wrapped, err := wrapper.WrappedSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapped), "Could not save genesis block") + + numDeposits := uint64(64) + beaconState, _ := util.DeterministicGenesisState(t, numDeposits) + bsRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesisRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state") + + c := &mock.ChainService{Root: bsRoot[:], State: beaconState} + beaconChainServer := &Server{ + BeaconDB: beaconDB, + BlockReceiver: c, + ChainInfoFetcher: c, + BlockNotifier: c.BlockNotifier(), + Broadcaster: mockp2p.NewTestP2P(t), + HeadFetcher: c, + } + req := util.NewBeaconBlockAltair() + req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().AltairForkEpoch)) + req.Block.ParentRoot = bsRoot[:] + wrapped, err = wrapper.WrappedSignedBeaconBlock(req) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapped)) + blockSsz, err := req.MarshalSSZ() + require.NoError(t, err) + blockReq := ðpbv2.SSZContainer{ + Data: blockSsz, + } + md := metadata.MD{} + md.Set(versionHeader, "altair") + sszCtx := metadata.NewIncomingContext(ctx, md) + _, err = beaconChainServer.SubmitBlockSSZ(sszCtx, blockReq) + assert.NoError(t, err, "Could not propose block correctly") + }) + + t.Run("Bellatrix", func(t *testing.T) { + // INFO: This code block can be removed once Bellatrix + // fork epoch is set to a value other than math.MaxUint64 + cfg := params.BeaconConfig() + cfg.BellatrixForkEpoch = cfg.AltairForkEpoch + 1000 + cfg.ForkVersionSchedule[bytesutil.ToBytes4(cfg.BellatrixForkVersion)] = cfg.AltairForkEpoch + 1000 + params.OverrideBeaconConfig(cfg) + + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + genesis := util.NewBeaconBlockBellatrix() + wrapped, err := wrapper.WrappedSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapped), "Could not save genesis block") + + numDeposits := uint64(64) + beaconState, _ := util.DeterministicGenesisState(t, numDeposits) + bsRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesisRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state") + + c := &mock.ChainService{Root: bsRoot[:], State: beaconState} + beaconChainServer := &Server{ + BeaconDB: beaconDB, + BlockReceiver: c, + ChainInfoFetcher: c, + BlockNotifier: c.BlockNotifier(), + Broadcaster: mockp2p.NewTestP2P(t), + HeadFetcher: c, + } + req := util.NewBeaconBlockBellatrix() + req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().BellatrixForkEpoch)) + req.Block.ParentRoot = bsRoot[:] + wrapped, err = wrapper.WrappedSignedBeaconBlock(req) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapped)) + blockSsz, err := req.MarshalSSZ() + require.NoError(t, err) + blockReq := ðpbv2.SSZContainer{ + Data: blockSsz, + } + md := metadata.MD{} + md.Set(versionHeader, "bellatrix") + sszCtx := metadata.NewIncomingContext(ctx, md) + _, err = beaconChainServer.SubmitBlockSSZ(sszCtx, blockReq) + assert.NoError(t, err, "Could not propose block correctly") + }) +} + +func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) { + t.Run("Phase 0", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + genesis := util.NewBeaconBlock() + wsb, err := wrapper.WrappedSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(context.Background(), wsb), "Could not save genesis block") + + numDeposits := uint64(64) + beaconState, _ := util.DeterministicGenesisState(t, numDeposits) + bsRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesisRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state") + + c := &mock.ChainService{Root: bsRoot[:], State: beaconState} + beaconChainServer := &Server{ + BeaconDB: beaconDB, + BlockReceiver: c, + ChainInfoFetcher: c, + BlockNotifier: c.BlockNotifier(), + Broadcaster: mockp2p.NewTestP2P(t), + HeadFetcher: c, + } + req := util.NewBeaconBlock() + req.Block.Slot = 5 + req.Block.ParentRoot = bsRoot[:] + wsb, err = wrapper.WrappedSignedBeaconBlock(req) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wsb)) + blockSsz, err := req.MarshalSSZ() + require.NoError(t, err) + blockReq := ðpbv2.SSZContainer{ + Data: blockSsz, + } + md := metadata.MD{} + md.Set(versionHeader, "phase0") + sszCtx := metadata.NewIncomingContext(ctx, md) + _, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq) + assert.NoError(t, err, "Could not propose block correctly") + }) + + t.Run("Altair", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + genesis := util.NewBeaconBlockAltair() + wrapped, err := wrapper.WrappedSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapped), "Could not save genesis block") + + numDeposits := uint64(64) + beaconState, _ := util.DeterministicGenesisState(t, numDeposits) + bsRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesisRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state") + + c := &mock.ChainService{Root: bsRoot[:], State: beaconState} + beaconChainServer := &Server{ + BeaconDB: beaconDB, + BlockReceiver: c, + ChainInfoFetcher: c, + BlockNotifier: c.BlockNotifier(), + Broadcaster: mockp2p.NewTestP2P(t), + HeadFetcher: c, + } + req := util.NewBeaconBlockAltair() + req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().AltairForkEpoch)) + req.Block.ParentRoot = bsRoot[:] + wrapped, err = wrapper.WrappedSignedBeaconBlock(req) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapped)) + blockSsz, err := req.MarshalSSZ() + require.NoError(t, err) + blockReq := ðpbv2.SSZContainer{ + Data: blockSsz, + } + md := metadata.MD{} + md.Set(versionHeader, "altair") + sszCtx := metadata.NewIncomingContext(ctx, md) + _, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq) + assert.NoError(t, err, "Could not propose block correctly") + }) + + t.Run("Bellatrix", func(t *testing.T) { + // INFO: This code block can be removed once Bellatrix + // fork epoch is set to a value other than math.MaxUint64 + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + cfg.BellatrixForkEpoch = cfg.AltairForkEpoch + 1000 + cfg.ForkVersionSchedule[bytesutil.ToBytes4(cfg.BellatrixForkVersion)] = cfg.AltairForkEpoch + 1000 + params.OverrideBeaconConfig(cfg) + + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + genesis := util.NewBeaconBlockBellatrix() + wrapped, err := wrapper.WrappedSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapped), "Could not save genesis block") + + numDeposits := uint64(64) + beaconState, _ := util.DeterministicGenesisState(t, numDeposits) + bsRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err) + genesisRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state") + + c := &mock.ChainService{Root: bsRoot[:], State: beaconState} + beaconChainServer := &Server{ + BeaconDB: beaconDB, + BlockReceiver: c, + ChainInfoFetcher: c, + BlockNotifier: c.BlockNotifier(), + Broadcaster: mockp2p.NewTestP2P(t), + HeadFetcher: c, + } + req := util.NewBlindedBeaconBlockBellatrix() + req.Block.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().BellatrixForkEpoch)) + req.Block.ParentRoot = bsRoot[:] + wrapped, err = wrapper.WrappedSignedBeaconBlock(req) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wrapped)) + blockSsz, err := req.MarshalSSZ() + require.NoError(t, err) + blockReq := ðpbv2.SSZContainer{ + Data: blockSsz, + } + md := metadata.MD{} + md.Set(versionHeader, "bellatrix") + sszCtx := metadata.NewIncomingContext(ctx, md) + _, err = beaconChainServer.SubmitBlindedBlockSSZ(sszCtx, blockReq) + assert.NoError(t, err, "Could not propose block correctly") + }) +} + func TestSubmitBlindedBlock(t *testing.T) { t.Run("Phase 0", func(t *testing.T) { beaconDB := dbTest.SetupDB(t) @@ -836,9 +1125,10 @@ func TestServer_GetBlockV2(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) @@ -955,9 +1245,10 @@ func TestServer_GetBlockV2(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } genBlk, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB) @@ -1074,9 +1365,10 @@ func TestServer_GetBlockV2(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } genBlk, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB) @@ -1194,9 +1486,10 @@ func TestServer_GetBlockV2(t *testing.T) { Optimistic: true, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } blk, err := bs.GetBlockV2(ctx, ðpbv2.BlockRequestV2{ @@ -1395,9 +1688,10 @@ func TestServer_GetBlockRoot(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainFetcher, - HeadFetcher: mockChainFetcher, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainFetcher, + HeadFetcher: mockChainFetcher, + OptimisticModeFetcher: mockChainFetcher, } root, err := genBlk.Block.HashTreeRoot() @@ -1485,9 +1779,10 @@ func TestServer_GetBlockRoot(t *testing.T) { Optimistic: true, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainFetcher, - HeadFetcher: mockChainFetcher, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainFetcher, + HeadFetcher: mockChainFetcher, + OptimisticModeFetcher: mockChainFetcher, } blockRootResp, err := bs.GetBlockRoot(ctx, ðpbv1.BlockRequest{ BlockId: []byte("head"), @@ -1513,9 +1808,10 @@ func TestServer_ListBlockAttestations(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) @@ -1615,9 +1911,10 @@ func TestServer_ListBlockAttestations(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } genBlk, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB) @@ -1717,9 +2014,10 @@ func TestServer_ListBlockAttestations(t *testing.T) { FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } genBlk, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB) @@ -1820,9 +2118,10 @@ func TestServer_ListBlockAttestations(t *testing.T) { Optimistic: true, } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: mockChainService, - HeadFetcher: mockChainService, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } resp, err := bs.ListBlockAttestations(ctx, ðpbv1.BlockRequest{ BlockId: []byte("head"), diff --git a/beacon-chain/rpc/eth/beacon/server.go b/beacon-chain/rpc/eth/beacon/server.go index dcd59663a2a0..388b4fdfb074 100644 --- a/beacon-chain/rpc/eth/beacon/server.go +++ b/beacon-chain/rpc/eth/beacon/server.go @@ -34,6 +34,7 @@ type Server struct { StateGenService stategen.StateManager StateFetcher statefetcher.Fetcher HeadFetcher blockchain.HeadFetcher + OptimisticModeFetcher blockchain.OptimisticModeFetcher V1Alpha1ValidatorServer *v1alpha1validator.Server SyncChecker sync.Checker CanonicalHistory *stategen.CanonicalHistory diff --git a/beacon-chain/rpc/eth/beacon/state.go b/beacon-chain/rpc/eth/beacon/state.go index b6504c9e27a8..089ae35ffc17 100644 --- a/beacon-chain/rpc/eth/beacon/state.go +++ b/beacon-chain/rpc/eth/beacon/state.go @@ -75,7 +75,7 @@ func (bs *Server) GetStateRoot(ctx context.Context, req *ethpb.StateRequest) (*e if err != nil { return nil, status.Errorf(codes.Internal, "Could not get state: %v", err) } - isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -103,7 +103,7 @@ func (bs *Server) GetStateFork(ctx context.Context, req *ethpb.StateRequest) (*e return nil, helpers.PrepareStateFetchGRPCError(err) } fork := st.Fork() - isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -133,7 +133,7 @@ func (bs *Server) GetFinalityCheckpoints(ctx context.Context, req *ethpb.StateRe if err != nil { return nil, helpers.PrepareStateFetchGRPCError(err) } - isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } diff --git a/beacon-chain/rpc/eth/beacon/state_test.go b/beacon-chain/rpc/eth/beacon/state_test.go index fdc11e10d197..86c94dca9506 100644 --- a/beacon-chain/rpc/eth/beacon/state_test.go +++ b/beacon-chain/rpc/eth/beacon/state_test.go @@ -80,13 +80,15 @@ func TestGetStateRoot(t *testing.T) { require.NoError(t, err) db := dbTest.SetupDB(t) + chainService := &chainMock.ChainService{} server := &Server{ StateFetcher: &testutil.MockFetcher{ BeaconStateRoot: stateRoot[:], BeaconState: fakeState, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := server.GetStateRoot(context.Background(), ð.StateRequest{ @@ -107,13 +109,15 @@ func TestGetStateRoot(t *testing.T) { require.NoError(t, db.SaveBlock(ctx, wsb)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, root)) + chainService := &chainMock.ChainService{Optimistic: true} server := &Server{ StateFetcher: &testutil.MockFetcher{ BeaconStateRoot: stateRoot[:], BeaconState: fakeState, }, - HeadFetcher: &chainMock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := server.GetStateRoot(context.Background(), ð.StateRequest{ StateId: make([]byte, 0), @@ -138,12 +142,14 @@ func TestGetStateFork(t *testing.T) { require.NoError(t, err) db := dbTest.SetupDB(t) + chainService := &chainMock.ChainService{} server := &Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: fakeState, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := server.GetStateFork(ctx, ð.StateRequest{ @@ -167,12 +173,14 @@ func TestGetStateFork(t *testing.T) { require.NoError(t, db.SaveBlock(ctx, wsb)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, root)) + chainService := &chainMock.ChainService{Optimistic: true} server := &Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: fakeState, }, - HeadFetcher: &chainMock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := server.GetStateFork(context.Background(), ð.StateRequest{ StateId: make([]byte, 0), @@ -204,12 +212,14 @@ func TestGetFinalityCheckpoints(t *testing.T) { require.NoError(t, err) db := dbTest.SetupDB(t) + chainService := &chainMock.ChainService{} server := &Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: fakeState, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := server.GetFinalityCheckpoints(ctx, ð.StateRequest{ @@ -235,12 +245,14 @@ func TestGetFinalityCheckpoints(t *testing.T) { require.NoError(t, db.SaveBlock(ctx, wsb)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, root)) + chainService := &chainMock.ChainService{Optimistic: true} server := &Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: fakeState, }, - HeadFetcher: &chainMock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := server.GetFinalityCheckpoints(context.Background(), ð.StateRequest{ StateId: make([]byte, 0), diff --git a/beacon-chain/rpc/eth/beacon/sync_committee.go b/beacon-chain/rpc/eth/beacon/sync_committee.go index a7071aff2115..39f3c3d72e7b 100644 --- a/beacon-chain/rpc/eth/beacon/sync_committee.go +++ b/beacon-chain/rpc/eth/beacon/sync_committee.go @@ -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, st, bs.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } diff --git a/beacon-chain/rpc/eth/beacon/sync_committee_test.go b/beacon-chain/rpc/eth/beacon/sync_committee_test.go index b81bd42b31cd..ba1fb5a56f96 100644 --- a/beacon-chain/rpc/eth/beacon/sync_committee_test.go +++ b/beacon-chain/rpc/eth/beacon/sync_committee_test.go @@ -162,6 +162,7 @@ func TestListSyncCommittees(t *testing.T) { require.NoError(t, err) db := dbTest.SetupDB(t) + chainService := &mock.ChainService{} s := &Server{ GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), @@ -169,8 +170,9 @@ func TestListSyncCommittees(t *testing.T) { StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &mock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } req := ðpbv2.StateSyncCommitteesRequest{StateId: stRoot[:]} resp, err := s.ListSyncCommittees(ctx, req) @@ -205,6 +207,7 @@ func TestListSyncCommittees(t *testing.T) { require.NoError(t, db.SaveBlock(ctx, wsb)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, root)) + chainService := &mock.ChainService{Optimistic: true} s := &Server{ GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), @@ -212,8 +215,9 @@ func TestListSyncCommittees(t *testing.T) { StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &mock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListSyncCommittees(ctx, req) require.NoError(t, err) @@ -261,6 +265,7 @@ func TestListSyncCommitteesFuture(t *testing.T) { })) db := dbTest.SetupDB(t) + chainService := &mock.ChainService{} s := &Server{ GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), @@ -268,8 +273,9 @@ func TestListSyncCommitteesFuture(t *testing.T) { StateFetcher: &futureSyncMockFetcher{ BeaconState: st, }, - HeadFetcher: &mock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } req := ðpbv2.StateSyncCommitteesRequest{} epoch := 2 * params.BeaconConfig().EpochsPerSyncCommitteePeriod diff --git a/beacon-chain/rpc/eth/beacon/validator.go b/beacon-chain/rpc/eth/beacon/validator.go index 24ee3ee08d1e..f6e5f2e4bdf1 100644 --- a/beacon-chain/rpc/eth/beacon/validator.go +++ b/beacon-chain/rpc/eth/beacon/validator.go @@ -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, st, bs.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -80,7 +80,7 @@ func (bs *Server) ListValidators(ctx context.Context, req *ethpb.StateValidators return nil, handleValContainerErr(err) } - isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -143,7 +143,7 @@ func (bs *Server) ListValidatorBalances(ctx context.Context, req *ethpb.Validato } } - isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -202,7 +202,7 @@ func (bs *Server) ListCommittees(ctx context.Context, req *ethpb.StateCommittees } } - isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, st, bs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } diff --git a/beacon-chain/rpc/eth/beacon/validator_test.go b/beacon-chain/rpc/eth/beacon/validator_test.go index d84549930d31..8b7cc0c363d7 100644 --- a/beacon-chain/rpc/eth/beacon/validator_test.go +++ b/beacon-chain/rpc/eth/beacon/validator_test.go @@ -33,12 +33,14 @@ func TestGetValidator(t *testing.T) { st, _ = util.DeterministicGenesisState(t, 8192) t.Run("Head Get Validator by index", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.GetValidator(ctx, ðpb.StateValidatorRequest{ @@ -50,12 +52,14 @@ func TestGetValidator(t *testing.T) { }) t.Run("Head Get Validator by pubkey", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } pubKey := st.PubkeyAtIndex(types.ValidatorIndex(20)) @@ -93,12 +97,14 @@ func TestGetValidator(t *testing.T) { require.NoError(t, db.SaveBlock(ctx, wsb)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, root)) + chainService := &chainMock.ChainService{Optimistic: true} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.GetValidator(ctx, ðpb.StateValidatorRequest{ StateId: []byte("head"), @@ -117,12 +123,14 @@ func TestListValidators(t *testing.T) { st, _ = util.DeterministicGenesisState(t, 8192) t.Run("Head List All Validators", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{ @@ -136,12 +144,14 @@ func TestListValidators(t *testing.T) { }) t.Run("Head List Validators by index", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } ids := [][]byte{[]byte("15"), []byte("26"), []byte("400")} @@ -158,12 +168,14 @@ func TestListValidators(t *testing.T) { }) t.Run("Head List Validators by pubkey", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } idNums := []types.ValidatorIndex{20, 66, 90, 100} pubkey1 := st.PubkeyAtIndex(types.ValidatorIndex(20)) @@ -184,12 +196,14 @@ 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{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } idNums := []types.ValidatorIndex{20, 90, 170, 129} @@ -212,12 +226,14 @@ func TestListValidators(t *testing.T) { }) t.Run("Unknown public key is ignored", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } existingKey := st.PubkeyAtIndex(types.ValidatorIndex(1)) @@ -232,12 +248,14 @@ func TestListValidators(t *testing.T) { }) t.Run("Unknown index is ignored", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } ids := [][]byte{[]byte("1"), []byte("99999")} @@ -261,12 +279,14 @@ func TestListValidators(t *testing.T) { require.NoError(t, db.SaveBlock(ctx, wsb)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, root)) + chainService := &chainMock.ChainService{Optimistic: true} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{ StateId: []byte("head"), @@ -349,12 +369,14 @@ 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{ ChainInfoFetcher: &chainMock.ChainService{State: st}, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{ @@ -384,12 +406,14 @@ 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{ ChainInfoFetcher: &chainMock.ChainService{State: st}, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{ @@ -418,12 +442,14 @@ func TestListValidators_Status(t *testing.T) { require.NoError(t, st.SetSlot(params.BeaconConfig().SlotsPerEpoch*35)) t.Run("Head List All EXITED Validators", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &statefetcher.StateProvider{ ChainInfoFetcher: &chainMock.ChainService{State: st}, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{ @@ -451,12 +477,14 @@ 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{ ChainInfoFetcher: &chainMock.ChainService{State: st}, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{ @@ -484,12 +512,14 @@ 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{ ChainInfoFetcher: &chainMock.ChainService{State: st}, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{ @@ -532,12 +562,14 @@ func TestListValidatorBalances(t *testing.T) { require.NoError(t, st.SetBalances(balances)) t.Run("Head List Validators Balance by index", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } ids := [][]byte{[]byte("15"), []byte("26"), []byte("400")} @@ -554,12 +586,14 @@ 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{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } idNums := []types.ValidatorIndex{20, 66, 90, 100} pubkey1 := st.PubkeyAtIndex(types.ValidatorIndex(20)) @@ -579,12 +613,14 @@ 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{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } idNums := []types.ValidatorIndex{20, 90, 170, 129} @@ -613,12 +649,14 @@ func TestListValidatorBalances(t *testing.T) { require.NoError(t, db.SaveBlock(ctx, wsb)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, root)) + chainService := &chainMock.ChainService{Optimistic: true} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } ids := [][]byte{[]byte("15"), []byte("26"), []byte("400")} @@ -640,12 +678,14 @@ func TestListCommittees(t *testing.T) { epoch := slots.ToEpoch(st.Slot()) t.Run("Head All Committees", func(t *testing.T) { + chainService := &chainMock.ChainService{} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListCommittees(ctx, ðpb.StateCommitteesRequest{ @@ -660,12 +700,14 @@ 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{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } epoch := types.Epoch(10) resp, err := s.ListCommittees(ctx, ðpb.StateCommitteesRequest{ @@ -679,12 +721,14 @@ 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{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } slot := types.Slot(4) @@ -704,12 +748,14 @@ 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{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } index := types.CommitteeIndex(1) @@ -729,12 +775,14 @@ 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{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } index := types.CommitteeIndex(1) @@ -764,12 +812,14 @@ func TestListCommittees(t *testing.T) { require.NoError(t, db.SaveBlock(ctx, wsb)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, root)) + chainService := &chainMock.ChainService{Optimistic: true} s := Server{ StateFetcher: &testutil.MockFetcher{ BeaconState: st, }, - HeadFetcher: &chainMock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + BeaconDB: db, } resp, err := s.ListCommittees(ctx, ðpb.StateCommitteesRequest{ diff --git a/beacon-chain/rpc/eth/debug/debug.go b/beacon-chain/rpc/eth/debug/debug.go index 686138304a29..a3b260283505 100644 --- a/beacon-chain/rpc/eth/debug/debug.go +++ b/beacon-chain/rpc/eth/debug/debug.go @@ -39,7 +39,7 @@ func (ds *Server) GetBeaconState(ctx context.Context, req *ethpbv1.StateRequest) } // GetBeaconStateSSZ returns the SSZ-serialized version of the full beacon state object for given state ID. -func (ds *Server) GetBeaconStateSSZ(ctx context.Context, req *ethpbv1.StateRequest) (*ethpbv1.BeaconStateSSZResponse, error) { +func (ds *Server) GetBeaconStateSSZ(ctx context.Context, req *ethpbv1.StateRequest) (*ethpbv2.SSZContainer, error) { ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateSSZ") defer span.End() @@ -53,7 +53,7 @@ func (ds *Server) GetBeaconStateSSZ(ctx context.Context, req *ethpbv1.StateReque return nil, status.Errorf(codes.Internal, "Could not marshal state into SSZ: %v", err) } - return ðpbv1.BeaconStateSSZResponse{Data: sszState}, nil + return ðpbv2.SSZContainer{Data: sszState}, nil } // GetBeaconStateV2 returns the full beacon state for a given state ID. @@ -65,7 +65,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques if err != nil { return nil, helpers.PrepareStateFetchGRPCError(err) } - isOptimistic, err := helpers.IsOptimistic(ctx, beaconSt, ds.HeadFetcher) + isOptimistic, err := helpers.IsOptimistic(ctx, beaconSt, ds.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -121,21 +121,32 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques } // GetBeaconStateSSZV2 returns the SSZ-serialized version of the full beacon state object for given state ID. -func (ds *Server) GetBeaconStateSSZV2(ctx context.Context, req *ethpbv2.StateRequestV2) (*ethpbv2.BeaconStateSSZResponseV2, error) { +func (ds *Server) GetBeaconStateSSZV2(ctx context.Context, req *ethpbv2.StateRequestV2) (*ethpbv2.SSZContainer, error) { ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateSSZV2") defer span.End() - state, err := ds.StateFetcher.State(ctx, req.StateId) + st, err := ds.StateFetcher.State(ctx, req.StateId) if err != nil { return nil, helpers.PrepareStateFetchGRPCError(err) } - sszState, err := state.MarshalSSZ() + sszState, err := st.MarshalSSZ() if err != nil { return nil, status.Errorf(codes.Internal, "Could not marshal state into SSZ: %v", err) } + var ver ethpbv2.Version + switch st.Version() { + case version.Phase0: + ver = ethpbv2.Version_PHASE0 + case version.Altair: + ver = ethpbv2.Version_ALTAIR + case version.Bellatrix: + ver = ethpbv2.Version_BELLATRIX + default: + return nil, status.Error(codes.Internal, "Unsupported state version") + } - return ðpbv2.BeaconStateSSZResponseV2{Data: sszState}, nil + return ðpbv2.SSZContainer{Data: sszState, Version: ver}, nil } // ListForkChoiceHeads retrieves the leaves of the current fork choice tree. @@ -167,7 +178,7 @@ func (ds *Server) ListForkChoiceHeadsV2(ctx context.Context, _ *emptypb.Empty) ( Data: make([]*ethpbv2.ForkChoiceHead, len(headRoots)), } for i := range headRoots { - isOptimistic, err := ds.HeadFetcher.IsOptimisticForRoot(ctx, headRoots[i]) + isOptimistic, err := ds.OptimisticModeFetcher.IsOptimisticForRoot(ctx, headRoots[i]) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if head is optimistic: %v", err) } diff --git a/beacon-chain/rpc/eth/debug/debug_test.go b/beacon-chain/rpc/eth/debug/debug_test.go index 365cfce75f93..11c5191544f6 100644 --- a/beacon-chain/rpc/eth/debug/debug_test.go +++ b/beacon-chain/rpc/eth/debug/debug_test.go @@ -44,8 +44,9 @@ func TestGetBeaconStateV2(t *testing.T) { StateFetcher: &testutil.MockFetcher{ BeaconState: fakeState, }, - HeadFetcher: &blockchainmock.ChainService{}, - BeaconDB: db, + HeadFetcher: &blockchainmock.ChainService{}, + OptimisticModeFetcher: &blockchainmock.ChainService{}, + BeaconDB: db, } resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.StateRequestV2{ StateId: make([]byte, 0), @@ -60,8 +61,9 @@ func TestGetBeaconStateV2(t *testing.T) { StateFetcher: &testutil.MockFetcher{ BeaconState: fakeState, }, - HeadFetcher: &blockchainmock.ChainService{}, - BeaconDB: db, + HeadFetcher: &blockchainmock.ChainService{}, + OptimisticModeFetcher: &blockchainmock.ChainService{}, + BeaconDB: db, } resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.StateRequestV2{ StateId: make([]byte, 0), @@ -76,8 +78,9 @@ func TestGetBeaconStateV2(t *testing.T) { StateFetcher: &testutil.MockFetcher{ BeaconState: fakeState, }, - HeadFetcher: &blockchainmock.ChainService{}, - BeaconDB: db, + HeadFetcher: &blockchainmock.ChainService{}, + OptimisticModeFetcher: &blockchainmock.ChainService{}, + BeaconDB: db, } resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.StateRequestV2{ StateId: make([]byte, 0), @@ -102,8 +105,9 @@ func TestGetBeaconStateV2(t *testing.T) { StateFetcher: &testutil.MockFetcher{ BeaconState: fakeState, }, - HeadFetcher: &blockchainmock.ChainService{Optimistic: true}, - BeaconDB: db, + HeadFetcher: &blockchainmock.ChainService{}, + OptimisticModeFetcher: &blockchainmock.ChainService{Optimistic: true}, + BeaconDB: db, } resp, err := server.GetBeaconStateV2(context.Background(), ðpbv2.StateRequestV2{ StateId: make([]byte, 0), @@ -153,6 +157,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) { assert.NotNil(t, resp) assert.DeepEqual(t, sszState, resp.Data) + assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version) }) t.Run("Altair", func(t *testing.T) { fakeState, _ := util.DeterministicGenesisStateAltair(t, 1) @@ -171,6 +176,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) { assert.NotNil(t, resp) assert.DeepEqual(t, sszState, resp.Data) + assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version) }) t.Run("Bellatrix", func(t *testing.T) { fakeState, _ := util.DeterministicGenesisStateBellatrix(t, 1) @@ -189,6 +195,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) { assert.NotNil(t, resp) assert.DeepEqual(t, sszState, resp.Data) + assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version) }) } @@ -238,8 +245,10 @@ func TestListForkChoiceHeadsV2(t *testing.T) { Root: bytesutil.ToBytes32(bytesutil.PadTo([]byte("bar"), 32)), }} + chainService := &blockchainmock.ChainService{} server := &Server{ - HeadFetcher: &blockchainmock.ChainService{}, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, } resp, err := server.ListForkChoiceHeadsV2(ctx, &emptypb.Empty{}) require.NoError(t, err) @@ -257,8 +266,10 @@ func TestListForkChoiceHeadsV2(t *testing.T) { } t.Run("optimistic head", func(t *testing.T) { + chainService := &blockchainmock.ChainService{Optimistic: true} server := &Server{ - HeadFetcher: &blockchainmock.ChainService{Optimistic: true}, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, } resp, err := server.ListForkChoiceHeadsV2(ctx, &emptypb.Empty{}) require.NoError(t, err) diff --git a/beacon-chain/rpc/eth/debug/server.go b/beacon-chain/rpc/eth/debug/server.go index 9ca2275533b1..19e46f09842a 100644 --- a/beacon-chain/rpc/eth/debug/server.go +++ b/beacon-chain/rpc/eth/debug/server.go @@ -12,7 +12,8 @@ import ( // Server defines a server implementation of the gRPC Beacon Chain service, // providing RPC endpoints to access data relevant to the Ethereum Beacon Chain. type Server struct { - BeaconDB db.ReadOnlyDatabase - HeadFetcher blockchain.HeadFetcher - StateFetcher statefetcher.Fetcher + BeaconDB db.ReadOnlyDatabase + HeadFetcher blockchain.HeadFetcher + StateFetcher statefetcher.Fetcher + OptimisticModeFetcher blockchain.OptimisticModeFetcher } diff --git a/beacon-chain/rpc/eth/helpers/sync.go b/beacon-chain/rpc/eth/helpers/sync.go index 5484c5771cca..9ac04d408ab3 100644 --- a/beacon-chain/rpc/eth/helpers/sync.go +++ b/beacon-chain/rpc/eth/helpers/sync.go @@ -39,7 +39,7 @@ func ValidateSync(ctx context.Context, syncChecker sync.Checker, headFetcher blo } // IsOptimistic checks whether the latest block header of the passed in beacon state is the header of an optimistic block. -func IsOptimistic(ctx context.Context, st state.BeaconState, headFetcher blockchain.HeadFetcher) (bool, error) { +func IsOptimistic(ctx context.Context, st state.BeaconState, optimisticSyncFetcher blockchain.OptimisticModeFetcher) (bool, error) { root, err := st.HashTreeRoot(ctx) if err != nil { return false, errors.Wrap(err, "could not get state root") @@ -50,7 +50,7 @@ func IsOptimistic(ctx context.Context, st state.BeaconState, headFetcher blockch if err != nil { return false, errors.Wrap(err, "could not get header root") } - isOptimistic, err := headFetcher.IsOptimisticForRoot(ctx, headRoot) + isOptimistic, err := optimisticSyncFetcher.IsOptimisticForRoot(ctx, headRoot) if err != nil { return false, errors.Wrap(err, "could not check if block is optimistic") } diff --git a/beacon-chain/rpc/eth/helpers/sync_test.go b/beacon-chain/rpc/eth/helpers/sync_test.go index 013233e2cd1e..044fe1728f95 100644 --- a/beacon-chain/rpc/eth/helpers/sync_test.go +++ b/beacon-chain/rpc/eth/helpers/sync_test.go @@ -58,14 +58,14 @@ func TestIsOptimistic(t *testing.T) { require.NoError(t, err) t.Run("optimistic", func(t *testing.T) { - mockHeadFetcher := &chainmock.ChainService{Optimistic: true} - o, err := IsOptimistic(ctx, st, mockHeadFetcher) + mockOptSyncFetcher := &chainmock.ChainService{Optimistic: true} + o, err := IsOptimistic(ctx, st, mockOptSyncFetcher) require.NoError(t, err) assert.Equal(t, true, o) }) t.Run("not optimistic", func(t *testing.T) { - mockHeadFetcher := &chainmock.ChainService{Optimistic: false} - o, err := IsOptimistic(ctx, st, mockHeadFetcher) + mockOptSyncFetcher := &chainmock.ChainService{Optimistic: false} + o, err := IsOptimistic(ctx, st, mockOptSyncFetcher) require.NoError(t, err) assert.Equal(t, false, o) }) diff --git a/beacon-chain/rpc/eth/validator/server.go b/beacon-chain/rpc/eth/validator/server.go index 37802ad8f219..40c7f2323619 100644 --- a/beacon-chain/rpc/eth/validator/server.go +++ b/beacon-chain/rpc/eth/validator/server.go @@ -13,14 +13,15 @@ import ( // Server defines a server implementation of the gRPC Validator service, // providing RPC endpoints intended for validator clients. type Server struct { - HeadFetcher blockchain.HeadFetcher - HeadUpdater blockchain.HeadUpdater - TimeFetcher blockchain.TimeFetcher - SyncChecker sync.Checker - AttestationsPool attestations.Pool - PeerManager p2p.PeerManager - Broadcaster p2p.Broadcaster - StateFetcher statefetcher.Fetcher - SyncCommitteePool synccommittee.Pool - V1Alpha1Server *v1alpha1validator.Server + HeadFetcher blockchain.HeadFetcher + HeadUpdater blockchain.HeadUpdater + TimeFetcher blockchain.TimeFetcher + SyncChecker sync.Checker + AttestationsPool attestations.Pool + PeerManager p2p.PeerManager + Broadcaster p2p.Broadcaster + StateFetcher statefetcher.Fetcher + OptimisticModeFetcher blockchain.OptimisticModeFetcher + SyncCommitteePool synccommittee.Pool + V1Alpha1Server *v1alpha1validator.Server } diff --git a/beacon-chain/rpc/eth/validator/validator.go b/beacon-chain/rpc/eth/validator/validator.go index 1f9a42dcc749..f684cc0ee8e2 100644 --- a/beacon-chain/rpc/eth/validator/validator.go +++ b/beacon-chain/rpc/eth/validator/validator.go @@ -58,7 +58,7 @@ func (vs *Server) GetAttesterDuties(ctx context.Context, req *ethpbv1.AttesterDu return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err) } - isOptimistic, err := rpchelpers.IsOptimistic(ctx, s, vs.HeadFetcher) + isOptimistic, err := rpchelpers.IsOptimistic(ctx, s, vs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -142,7 +142,7 @@ func (vs *Server) GetProposerDuties(ctx context.Context, req *ethpbv1.ProposerDu return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err) } - isOptimistic, err := rpchelpers.IsOptimistic(ctx, s, vs.HeadFetcher) + isOptimistic, err := rpchelpers.IsOptimistic(ctx, s, vs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -258,7 +258,7 @@ func (vs *Server) GetSyncCommitteeDuties(ctx context.Context, req *ethpbv2.SyncC return nil, status.Errorf(codes.Internal, "Could not get duties: %v", err) } - isOptimistic, err := rpchelpers.IsOptimistic(ctx, st, vs.HeadFetcher) + isOptimistic, err := rpchelpers.IsOptimistic(ctx, st, vs.OptimisticModeFetcher) if err != nil { return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) } @@ -348,6 +348,76 @@ func (vs *Server) ProduceBlockV2(ctx context.Context, req *ethpbv1.ProduceBlockR return nil, status.Error(codes.InvalidArgument, "Unsupported block type") } +// ProduceBlockV2SSZ requests the beacon node to produce a valid unsigned beacon block, which can then be signed by a proposer and submitted. +// +// The produced block is in SSZ form. +func (vs *Server) ProduceBlockV2SSZ(ctx context.Context, req *ethpbv1.ProduceBlockRequest) (*ethpbv2.SSZContainer, error) { + _, span := trace.StartSpan(ctx, "validator.ProduceBlockV2SSZ") + defer span.End() + + if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher); err != nil { + // We simply return the error because it's already a gRPC error. + return nil, err + } + + v1alpha1req := ðpbalpha.BlockRequest{ + Slot: req.Slot, + RandaoReveal: req.RandaoReveal, + Graffiti: req.Graffiti, + } + v1alpha1resp, err := vs.V1Alpha1Server.GetBeaconBlock(ctx, v1alpha1req) + if err != nil { + // We simply return err because it's already of a gRPC error type. + return nil, err + } + phase0Block, ok := v1alpha1resp.Block.(*ethpbalpha.GenericBeaconBlock_Phase0) + if ok { + block, err := migration.V1Alpha1ToV1Block(phase0Block.Phase0) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not prepare beacon block: %v", err) + } + sszBlock, err := block.MarshalSSZ() + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ format: %v", err) + } + return ðpbv2.SSZContainer{ + Version: ethpbv2.Version_PHASE0, + Data: sszBlock, + }, nil + } + altairBlock, ok := v1alpha1resp.Block.(*ethpbalpha.GenericBeaconBlock_Altair) + if ok { + block, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlock.Altair) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not prepare beacon block: %v", err) + } + sszBlock, err := block.MarshalSSZ() + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ format: %v", err) + } + return ðpbv2.SSZContainer{ + Version: ethpbv2.Version_ALTAIR, + Data: sszBlock, + }, nil + } + bellatrixBlock, ok := v1alpha1resp.Block.(*ethpbalpha.GenericBeaconBlock_Bellatrix) + if ok { + block, err := migration.V1Alpha1BeaconBlockBellatrixToV2(bellatrixBlock.Bellatrix) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not prepare beacon block: %v", err) + } + sszBlock, err := block.MarshalSSZ() + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ format: %v", err) + } + return ðpbv2.SSZContainer{ + Version: ethpbv2.Version_BELLATRIX, + Data: sszBlock, + }, nil + } + return nil, status.Error(codes.InvalidArgument, "Unsupported block type") +} + // ProduceBlindedBlock requests the beacon node to produce a valid unsigned blinded beacon block, // which can then be signed by a proposer and submitted. // @@ -413,6 +483,79 @@ func (vs *Server) ProduceBlindedBlock(ctx context.Context, req *ethpbv1.ProduceB return nil, status.Error(codes.InvalidArgument, "Unsupported block type") } +// ProduceBlindedBlockSSZ requests the beacon node to produce a valid unsigned blinded beacon block, +// which can then be signed by a proposer and submitted. +// +// The produced block is in SSZ form. +// +// Pre-Bellatrix, this endpoint will return a regular block. +func (vs *Server) ProduceBlindedBlockSSZ(ctx context.Context, req *ethpbv1.ProduceBlockRequest) (*ethpbv2.SSZContainer, error) { + ctx, span := trace.StartSpan(ctx, "validator.ProduceBlindedBlockSSZ") + defer span.End() + + if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher); err != nil { + // We simply return the error because it's already a gRPC error. + return nil, err + } + + v1alpha1req := ðpbalpha.BlockRequest{ + Slot: req.Slot, + RandaoReveal: req.RandaoReveal, + Graffiti: req.Graffiti, + } + v1alpha1resp, err := vs.V1Alpha1Server.GetBeaconBlock(ctx, v1alpha1req) + if err != nil { + // We simply return err because it's already of a gRPC error type. + return nil, err + } + phase0Block, ok := v1alpha1resp.Block.(*ethpbalpha.GenericBeaconBlock_Phase0) + if ok { + block, err := migration.V1Alpha1ToV1Block(phase0Block.Phase0) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not prepare beacon block: %v", err) + } + sszBlock, err := block.MarshalSSZ() + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ format: %v", err) + } + return ðpbv2.SSZContainer{ + Version: ethpbv2.Version_PHASE0, + Data: sszBlock, + }, nil + } + altairBlock, ok := v1alpha1resp.Block.(*ethpbalpha.GenericBeaconBlock_Altair) + if ok { + block, err := migration.V1Alpha1BeaconBlockAltairToV2(altairBlock.Altair) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not prepare beacon block: %v", err) + } + sszBlock, err := block.MarshalSSZ() + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ format: %v", err) + } + return ðpbv2.SSZContainer{ + Version: ethpbv2.Version_ALTAIR, + Data: sszBlock, + }, nil + } + bellatrixBlock, ok := v1alpha1resp.Block.(*ethpbalpha.GenericBeaconBlock_Bellatrix) + if ok { + block, err := migration.V1Alpha1BeaconBlockBellatrixToV2Blinded(bellatrixBlock.Bellatrix) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not prepare beacon block: %v", err) + } + sszBlock, err := block.MarshalSSZ() + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not marshal block into SSZ format: %v", err) + } + return ðpbv2.SSZContainer{ + Version: ethpbv2.Version_BELLATRIX, + Data: sszBlock, + }, nil + } + return nil, status.Error(codes.InvalidArgument, "Unsupported block type") +} + // PrepareBeaconProposer caches and updates the fee recipient for the given proposer. func (vs *Server) PrepareBeaconProposer( ctx context.Context, request *ethpbv1.PrepareBeaconProposerRequest, diff --git a/beacon-chain/rpc/eth/validator/validator_test.go b/beacon-chain/rpc/eth/validator/validator_test.go index 041e9718360b..4b554096e18d 100644 --- a/beacon-chain/rpc/eth/validator/validator_test.go +++ b/beacon-chain/rpc/eth/validator/validator_test.go @@ -82,9 +82,10 @@ func TestGetAttesterDuties(t *testing.T) { State: bs, Root: genesisRoot[:], Slot: &chainSlot, } vs := &Server{ - HeadFetcher: chain, - TimeFetcher: chain, - SyncChecker: &mockSync.Sync{IsSyncing: false}, + HeadFetcher: chain, + TimeFetcher: chain, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + OptimisticModeFetcher: chain, } t.Run("Single validator", func(t *testing.T) { @@ -160,9 +161,10 @@ func TestGetAttesterDuties(t *testing.T) { State: bs, Root: genesisRoot[:], Slot: &chainSlot, } vs := &Server{ - HeadFetcher: chain, - TimeFetcher: chain, - SyncChecker: &mockSync.Sync{IsSyncing: false}, + HeadFetcher: chain, + TimeFetcher: chain, + OptimisticModeFetcher: chain, + SyncChecker: &mockSync.Sync{IsSyncing: false}, } req := ðpbv1.AttesterDutiesRequest{ @@ -231,9 +233,10 @@ func TestGetAttesterDuties(t *testing.T) { State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true, } vs := &Server{ - HeadFetcher: chain, - TimeFetcher: chain, - SyncChecker: &mockSync.Sync{IsSyncing: false}, + HeadFetcher: chain, + TimeFetcher: chain, + OptimisticModeFetcher: chain, + SyncChecker: &mockSync.Sync{IsSyncing: false}, } req := ðpbv1.AttesterDutiesRequest{ Epoch: 0, @@ -285,9 +288,10 @@ func TestGetProposerDuties(t *testing.T) { State: bs, Root: genesisRoot[:], Slot: &chainSlot, } vs := &Server{ - HeadFetcher: chain, - TimeFetcher: chain, - SyncChecker: &mockSync.Sync{IsSyncing: false}, + HeadFetcher: chain, + TimeFetcher: chain, + OptimisticModeFetcher: chain, + SyncChecker: &mockSync.Sync{IsSyncing: false}, } t.Run("Ok", func(t *testing.T) { @@ -335,9 +339,10 @@ func TestGetProposerDuties(t *testing.T) { State: bs, Root: genesisRoot[:], Slot: &chainSlot, } vs := &Server{ - HeadFetcher: chain, - TimeFetcher: chain, - SyncChecker: &mockSync.Sync{IsSyncing: false}, + HeadFetcher: chain, + TimeFetcher: chain, + OptimisticModeFetcher: chain, + SyncChecker: &mockSync.Sync{IsSyncing: false}, } req := ðpbv1.ProposerDutiesRequest{ @@ -386,9 +391,10 @@ func TestGetProposerDuties(t *testing.T) { State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true, } vs := &Server{ - HeadFetcher: chain, - TimeFetcher: chain, - SyncChecker: &mockSync.Sync{IsSyncing: false}, + HeadFetcher: chain, + TimeFetcher: chain, + OptimisticModeFetcher: chain, + SyncChecker: &mockSync.Sync{IsSyncing: false}, } req := ðpbv1.ProposerDutiesRequest{ Epoch: 0, @@ -433,10 +439,11 @@ func TestGetSyncCommitteeDuties(t *testing.T) { mockChainService := &mockChain.ChainService{Genesis: genesisTime} vs := &Server{ - StateFetcher: &testutil.MockFetcher{BeaconState: st}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - TimeFetcher: mockChainService, - HeadFetcher: mockChainService, + StateFetcher: &testutil.MockFetcher{BeaconState: st}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + TimeFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } t.Run("Single validator", func(t *testing.T) { @@ -571,10 +578,11 @@ func TestGetSyncCommitteeDuties(t *testing.T) { } mockChainService := &mockChain.ChainService{Genesis: genesisTime, Slot: &newSyncPeriodStartSlot} vs := &Server{ - StateFetcher: &testutil.MockFetcher{BeaconState: stateFetchFn(newSyncPeriodStartSlot)}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - TimeFetcher: mockChainService, - HeadFetcher: mockChainService, + StateFetcher: &testutil.MockFetcher{BeaconState: stateFetchFn(newSyncPeriodStartSlot)}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + TimeFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } req := ðpbv2.SyncCommitteeDutiesRequest{ @@ -606,10 +614,11 @@ func TestGetSyncCommitteeDuties(t *testing.T) { mockChainService := &mockChain.ChainService{Genesis: genesisTime, Optimistic: true} vs := &Server{ - StateFetcher: &testutil.MockFetcher{BeaconState: st}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - TimeFetcher: mockChainService, - HeadFetcher: mockChainService, + StateFetcher: &testutil.MockFetcher{BeaconState: st}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + TimeFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } req := ðpbv2.SyncCommitteeDutiesRequest{ Epoch: 0, @@ -624,9 +633,10 @@ func TestGetSyncCommitteeDuties(t *testing.T) { func TestGetSyncCommitteeDuties_SyncNotReady(t *testing.T) { chainService := &mockChain.ChainService{} vs := &Server{ - SyncChecker: &mockSync.Sync{IsSyncing: true}, - HeadFetcher: chainService, - TimeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: true}, + HeadFetcher: chainService, + TimeFetcher: chainService, + OptimisticModeFetcher: chainService, } _, err := vs.GetSyncCommitteeDuties(context.Background(), ðpbv2.SyncCommitteeDutiesRequest{}) assert.ErrorContains(t, "Syncing to latest head, not ready to respond", err) @@ -1029,6 +1039,7 @@ func TestProduceBlockV2(t *testing.T) { }, TimeFetcher: &mockChain.ChainService{}, HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]}, + OptimisticModeFetcher: &mockChain.ChainService{}, SyncChecker: &mockSync.Sync{IsSyncing: false}, BlockReceiver: &mockChain.ChainService{}, HeadUpdater: &mockChain.ChainService{}, @@ -1143,39 +1154,29 @@ func TestProduceBlockV2(t *testing.T) { }) } -func TestProduceBlockV2_SyncNotReady(t *testing.T) { - chainService := &mockChain.ChainService{} - vs := &Server{ - SyncChecker: &mockSync.Sync{IsSyncing: true}, - HeadFetcher: chainService, - TimeFetcher: chainService, - } - _, err := vs.ProduceBlockV2(context.Background(), ðpbv1.ProduceBlockRequest{}) - assert.ErrorContains(t, "Syncing to latest head, not ready to respond", err) -} - -func TestProduceBlindedBlock(t *testing.T) { +func TestProduceBlockV2SSZ(t *testing.T) { t.Run("Phase 0", func(t *testing.T) { - db := dbutil.SetupDB(t) ctx := context.Background() - beaconState, privKeys := util.DeterministicGenesisState(t, 64) + db := dbutil.SetupDB(t) - stateRoot, err := beaconState.HashTreeRoot(ctx) + bs, privKeys := util.DeterministicGenesisState(t, 2) + + stateRoot, err := bs.HashTreeRoot(ctx) require.NoError(t, err, "Could not hash genesis state") genesis := blocks.NewGenesisBlock(stateRoot[:]) - wrapped, err := wrapper.WrappedSignedBeaconBlock(genesis) + wsb, err := wrapper.WrappedSignedBeaconBlock(genesis) require.NoError(t, err) - require.NoError(t, db.SaveBlock(ctx, wrapped), "Could not save genesis block") + require.NoError(t, db.SaveBlock(ctx, wsb), "Could not save genesis block") parentRoot, err := genesis.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveState(ctx, bs, parentRoot), "Could not save genesis state") require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") v1Alpha1Server := &v1alpha1validator.Server{ - HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]}, + HeadFetcher: &mockChain.ChainService{State: bs, Root: parentRoot[:]}, SyncChecker: &mockSync.Sync{IsSyncing: false}, BlockReceiver: &mockChain.ChainService{}, HeadUpdater: &mockChain.ChainService{}, @@ -1189,37 +1190,1022 @@ func TestProduceBlindedBlock(t *testing.T) { StateGen: stategen.New(db), } - proposerSlashings := make([]*ethpbalpha.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) - for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { - proposerSlashing, err := util.GenerateProposerSlashingForValidator( - beaconState, - privKeys[i], - i, /* validator index */ - ) - require.NoError(t, err) - proposerSlashings[i] = proposerSlashing - err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing) - require.NoError(t, err) + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, 1) + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + bs, + privKeys[0], + 0, + ) + require.NoError(t, err) + proposerSlashings[0] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), bs, proposerSlashing) + require.NoError(t, err) + + attSlashings := make([]*ethpbalpha.AttesterSlashing, 1) + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + bs, + privKeys[1], + 1, + ) + require.NoError(t, err) + attSlashings[0] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), bs, attesterSlashing) + require.NoError(t, err) + + v1Server := &Server{ + V1Alpha1Server: v1Alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + randaoReveal, err := util.RandaoReveal(bs, 0, privKeys) + require.NoError(t, err) + graffiti := bytesutil.ToBytes32([]byte("eth2")) + req := ðpbv1.ProduceBlockRequest{ + Slot: 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + resp, err := v1Server.ProduceBlockV2SSZ(ctx, req) + require.NoError(t, err) + assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version) + + expectedBlock := ðpbv1.BeaconBlock{ + Slot: 1, + ProposerIndex: 0, + ParentRoot: []byte{164, 47, 20, 157, 2, 202, 58, 173, 57, 154, 254, 181, 153, 74, 40, 89, 159, 74, 62, 247, 28, 222, 153, 182, 168, 79, 170, 149, 80, 99, 97, 32}, + StateRoot: []byte{224, 94, 112, 87, 163, 57, 192, 233, 181, 179, 212, 9, 226, 214, 65, 238, 189, 114, 223, 101, 215, 146, 163, 140, 92, 242, 35, 82, 222, 154, 127, 136}, + Body: ðpbv1.BeaconBlockBody{ + RandaoReveal: randaoReveal, + Eth1Data: ðpbv1.Eth1Data{ + DepositRoot: []byte{124, 159, 161, 54, 212, 65, 63, 166, 23, 54, 55, 232, 131, 182, 153, 141, 50, 225, 214, 117, 248, 140, 221, 255, 157, 203, 207, 51, 24, 32, 244, 184}, + DepositCount: 2, + BlockHash: []byte{8, 83, 63, 107, 189, 73, 117, 17, 62, 79, 12, 177, 4, 171, 205, 236, 29, 134, 217, 157, 87, 130, 180, 169, 167, 246, 39, 12, 14, 187, 106, 39}, + }, + Graffiti: graffiti[:], + ProposerSlashings: []*ethpbv1.ProposerSlashing{ + { + SignedHeader_1: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_1.Header.Slot, + ProposerIndex: proposerSlashing.Header_1.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_1.Header.ParentRoot, + StateRoot: proposerSlashing.Header_1.Header.StateRoot, + BodyRoot: proposerSlashing.Header_1.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_1.Signature, + }, + SignedHeader_2: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_2.Header.Slot, + ProposerIndex: proposerSlashing.Header_2.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_2.Header.ParentRoot, + StateRoot: proposerSlashing.Header_2.Header.StateRoot, + BodyRoot: proposerSlashing.Header_2.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_2.Signature, + }, + }, + }, + AttesterSlashings: []*ethpbv1.AttesterSlashing{ + { + Attestation_1: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_1.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_1.Data.Slot, + Index: attesterSlashing.Attestation_1.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_1.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Source.Epoch, + Root: attesterSlashing.Attestation_1.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Target.Epoch, + Root: attesterSlashing.Attestation_1.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_1.Signature, + }, + Attestation_2: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_2.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_2.Data.Slot, + Index: attesterSlashing.Attestation_2.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_2.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Source.Epoch, + Root: attesterSlashing.Attestation_2.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Target.Epoch, + Root: attesterSlashing.Attestation_2.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_2.Signature, + }, + }, + }, + }, + } + expectedData, err := expectedBlock.MarshalSSZ() + assert.NoError(t, err) + assert.DeepEqual(t, expectedData, resp.Data) + }) + + t.Run("Altair", func(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + + params.SetupTestConfigCleanup(t) + bc := params.BeaconConfig() + bc.AltairForkEpoch = types.Epoch(0) + params.OverrideBeaconConfig(bc) + + bs, privKeys := util.DeterministicGenesisStateAltair(t, params.BeaconConfig().SyncCommitteeSize) + syncCommittee, err := altair.NextSyncCommittee(context.Background(), bs) + require.NoError(t, err) + require.NoError(t, bs.SetCurrentSyncCommittee(syncCommittee)) + require.NoError(t, bs.SetNextSyncCommittee(syncCommittee)) + + stateRoot, err := bs.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + genesisBlock := util.NewBeaconBlockAltair() + genesisBlock.Block.StateRoot = stateRoot[:] + wrappedAltairBlock, err := wrapper.WrappedSignedBeaconBlock(genesisBlock) + require.NoError(t, err) + require.NoError(t, db.SaveBlock(ctx, wrappedAltairBlock)) + parentRoot, err := genesisBlock.Block.HashTreeRoot() + require.NoError(t, err) + + require.NoError(t, db.SaveState(ctx, bs, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + v1Alpha1Server := &v1alpha1validator.Server{ + HeadFetcher: &mockChain.ChainService{State: bs, Root: parentRoot[:]}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: &mockChain.ChainService{}, + HeadUpdater: &mockChain.ChainService{}, + ChainStartFetcher: &mockPOW.POWChain{}, + Eth1InfoFetcher: &mockPOW.POWChain{}, + Eth1BlockFetcher: &mockPOW.POWChain{}, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db), + SyncCommitteePool: synccommittee.NewStore(), } + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, 1) + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + bs, + privKeys[0], + 0, + ) + require.NoError(t, err) + proposerSlashings[0] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), bs, proposerSlashing) + require.NoError(t, err) + attSlashings := make([]*ethpbalpha.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) - for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { - attesterSlashing, err := util.GenerateAttesterSlashingForValidator( - beaconState, - privKeys[i+params.BeaconConfig().MaxProposerSlashings], - types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings), /* validator index */ - ) - require.NoError(t, err) - attSlashings[i] = attesterSlashing - err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing) - require.NoError(t, err) + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + bs, + privKeys[1], + 1, + ) + require.NoError(t, err) + attSlashings[0] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), bs, attesterSlashing) + require.NoError(t, err) + + aggregationBits := bitfield.NewBitvector128() + for i := range aggregationBits { + aggregationBits[i] = 0xAA + } + + syncCommitteeIndices, err := altair.NextSyncCommitteeIndices(context.Background(), bs) + require.NoError(t, err) + sigs := make([]bls.Signature, 0, len(syncCommitteeIndices)) + for i, indice := range syncCommitteeIndices { + if aggregationBits.BitAt(uint64(i)) { + b := p2pType.SSZBytes(parentRoot[:]) + sb, err := signing.ComputeDomainAndSign(bs, coreTime.CurrentEpoch(bs), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice]) + require.NoError(t, err) + sig, err := bls.SignatureFromBytes(sb) + require.NoError(t, err) + sigs = append(sigs, sig) + } + } + aggregatedSig := bls.AggregateSignatures(sigs).Marshal() + contribution := ðpbalpha.SyncCommitteeContribution{ + Slot: 0, + BlockRoot: parentRoot[:], + SubcommitteeIndex: 0, + AggregationBits: aggregationBits, + Signature: aggregatedSig, + } + require.NoError(t, v1Alpha1Server.SyncCommitteePool.SaveSyncCommitteeContribution(contribution)) + + v1Server := &Server{ + V1Alpha1Server: v1Alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + randaoReveal, err := util.RandaoReveal(bs, 0, privKeys) + require.NoError(t, err) + graffiti := bytesutil.ToBytes32([]byte("eth2")) + + req := ðpbv1.ProduceBlockRequest{ + Slot: 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + resp, err := v1Server.ProduceBlockV2SSZ(ctx, req) + require.NoError(t, err) + assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version) + + expectedBlock := ðpbv2.BeaconBlockAltair{ + Slot: 1, + ProposerIndex: 19, + ParentRoot: []byte{162, 206, 194, 54, 242, 248, 88, 148, 193, 141, 39, 23, 91, 116, 219, 219, 2, 248, 4, 155, 159, 201, 41, 156, 130, 57, 167, 176, 153, 18, 73, 148}, + StateRoot: []byte{144, 220, 158, 2, 142, 57, 111, 170, 148, 225, 129, 23, 103, 232, 44, 1, 222, 77, 36, 110, 118, 237, 184, 77, 253, 182, 0, 62, 168, 56, 105, 95}, + Body: ðpbv2.BeaconBlockBodyAltair{ + RandaoReveal: randaoReveal, + Eth1Data: ðpbv1.Eth1Data{ + DepositRoot: []byte{124, 159, 161, 54, 212, 65, 63, 166, 23, 54, 55, 232, 131, 182, 153, 141, 50, 225, 214, 117, 248, 140, 221, 255, 157, 203, 207, 51, 24, 32, 244, 184}, + DepositCount: params.BeaconConfig().SyncCommitteeSize, + BlockHash: []byte{8, 83, 63, 107, 189, 73, 117, 17, 62, 79, 12, 177, 4, 171, 205, 236, 29, 134, 217, 157, 87, 130, 180, 169, 167, 246, 39, 12, 14, 187, 106, 39}, + }, + Graffiti: graffiti[:], + ProposerSlashings: []*ethpbv1.ProposerSlashing{ + { + SignedHeader_1: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_1.Header.Slot, + ProposerIndex: proposerSlashing.Header_1.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_1.Header.ParentRoot, + StateRoot: proposerSlashing.Header_1.Header.StateRoot, + BodyRoot: proposerSlashing.Header_1.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_1.Signature, + }, + SignedHeader_2: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_2.Header.Slot, + ProposerIndex: proposerSlashing.Header_2.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_2.Header.ParentRoot, + StateRoot: proposerSlashing.Header_2.Header.StateRoot, + BodyRoot: proposerSlashing.Header_2.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_2.Signature, + }, + }, + }, + AttesterSlashings: []*ethpbv1.AttesterSlashing{ + { + Attestation_1: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_1.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_1.Data.Slot, + Index: attesterSlashing.Attestation_1.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_1.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Source.Epoch, + Root: attesterSlashing.Attestation_1.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Target.Epoch, + Root: attesterSlashing.Attestation_1.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_1.Signature, + }, + Attestation_2: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_2.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_2.Data.Slot, + Index: attesterSlashing.Attestation_2.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_2.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Source.Epoch, + Root: attesterSlashing.Attestation_2.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Target.Epoch, + Root: attesterSlashing.Attestation_2.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_2.Signature, + }, + }, + }, + SyncAggregate: ðpbv1.SyncAggregate{ + SyncCommitteeBits: []byte{170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + SyncCommitteeSignature: []byte{130, 228, 60, 221, 180, 9, 29, 148, 136, 255, 135, 183, 146, 130, 88, 240, 116, 219, 183, 208, 148, 211, 202, 78, 240, 120, 60, 99, 77, 76, 109, 210, 163, 243, 244, 25, 70, 184, 29, 252, 138, 128, 202, 173, 1, 166, 48, 49, 11, 136, 42, 124, 163, 187, 206, 253, 214, 149, 114, 137, 146, 123, 197, 187, 250, 204, 59, 196, 87, 195, 48, 11, 116, 123, 58, 49, 62, 98, 193, 166, 0, 172, 15, 253, 130, 88, 46, 110, 45, 84, 57, 107, 83, 182, 127, 105}, + }, + }, + } + expectedData, err := expectedBlock.MarshalSSZ() + assert.NoError(t, err) + assert.DeepEqual(t, expectedData, resp.Data) + }) + + t.Run("Bellatrix", func(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + + params.SetupTestConfigCleanup(t) + bc := params.BeaconConfig() + bc.AltairForkEpoch = types.Epoch(0) + bc.BellatrixForkEpoch = types.Epoch(1) + params.OverrideBeaconConfig(bc) + + bs, privKeys := util.DeterministicGenesisStateBellatrix(t, params.BeaconConfig().SyncCommitteeSize) + require.NoError(t, bs.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + syncCommittee, err := altair.NextSyncCommittee(context.Background(), bs) + require.NoError(t, err) + require.NoError(t, bs.SetCurrentSyncCommittee(syncCommittee)) + require.NoError(t, bs.SetNextSyncCommittee(syncCommittee)) + + stateRoot, err := bs.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + genesisBlock := util.NewBeaconBlockBellatrix() + genesisBlock.Block.StateRoot = stateRoot[:] + wrappedBellatrixBlock, err := wrapper.WrappedSignedBeaconBlock(genesisBlock) + require.NoError(t, err) + require.NoError(t, db.SaveBlock(ctx, wrappedBellatrixBlock)) + parentRoot, err := genesisBlock.Block.HashTreeRoot() + require.NoError(t, err) + + require.NoError(t, db.SaveState(ctx, bs, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + v1Alpha1Server := &v1alpha1validator.Server{ + ExecutionEngineCaller: &mockPOW.EngineClient{ + ExecutionBlock: &enginev1.ExecutionBlock{ + TotalDifficulty: "0x1", + }, + }, + TimeFetcher: &mockChain.ChainService{}, + HeadFetcher: &mockChain.ChainService{State: bs, Root: parentRoot[:]}, + OptimisticModeFetcher: &mockChain.ChainService{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: &mockChain.ChainService{}, + HeadUpdater: &mockChain.ChainService{}, + ChainStartFetcher: &mockPOW.POWChain{}, + Eth1InfoFetcher: &mockPOW.POWChain{}, + Eth1BlockFetcher: &mockPOW.POWChain{}, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db), + SyncCommitteePool: synccommittee.NewStore(), + ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), + } + + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, 1) + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + bs, + privKeys[0], + 0, + ) + require.NoError(t, err) + proposerSlashings[0] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), bs, proposerSlashing) + require.NoError(t, err) + + attSlashings := make([]*ethpbalpha.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + bs, + privKeys[1], + 1, + ) + require.NoError(t, err) + attSlashings[0] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), bs, attesterSlashing) + require.NoError(t, err) + + aggregationBits := bitfield.NewBitvector128() + for i := range aggregationBits { + aggregationBits[i] = 0xAA + } + + syncCommitteeIndices, err := altair.NextSyncCommitteeIndices(context.Background(), bs) + require.NoError(t, err) + sigs := make([]bls.Signature, 0, len(syncCommitteeIndices)) + for i, indice := range syncCommitteeIndices { + if aggregationBits.BitAt(uint64(i)) { + b := p2pType.SSZBytes(parentRoot[:]) + sb, err := signing.ComputeDomainAndSign(bs, coreTime.CurrentEpoch(bs), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice]) + require.NoError(t, err) + sig, err := bls.SignatureFromBytes(sb) + require.NoError(t, err) + sigs = append(sigs, sig) + } + } + aggregatedSig := bls.AggregateSignatures(sigs).Marshal() + contribution := ðpbalpha.SyncCommitteeContribution{ + Slot: params.BeaconConfig().SlotsPerEpoch, + BlockRoot: parentRoot[:], + SubcommitteeIndex: 0, + AggregationBits: aggregationBits, + Signature: aggregatedSig, + } + require.NoError(t, v1Alpha1Server.SyncCommitteePool.SaveSyncCommitteeContribution(contribution)) + + v1Server := &Server{ + V1Alpha1Server: v1Alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + randaoReveal, err := util.RandaoReveal(bs, 1, privKeys) + require.NoError(t, err) + graffiti := bytesutil.ToBytes32([]byte("eth2")) + + req := ðpbv1.ProduceBlockRequest{ + Slot: params.BeaconConfig().SlotsPerEpoch + 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + resp, err := v1Server.ProduceBlockV2SSZ(ctx, req) + require.NoError(t, err) + assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version) + + expectedBlock := ðpbv2.BeaconBlockBellatrix{ + Slot: 33, + ProposerIndex: 348, + ParentRoot: []byte{228, 15, 208, 120, 31, 194, 202, 144, 41, 107, 98, 126, 162, 234, 190, 94, 174, 176, 69, 177, 103, 82, 69, 254, 0, 230, 192, 67, 158, 29, 141, 85}, + StateRoot: []byte{143, 107, 161, 135, 58, 60, 195, 107, 55, 142, 122, 111, 184, 1, 19, 233, 145, 204, 160, 226, 148, 67, 194, 102, 79, 196, 74, 242, 174, 108, 68, 82}, + Body: ðpbv2.BeaconBlockBodyBellatrix{ + RandaoReveal: randaoReveal, + Eth1Data: ðpbv1.Eth1Data{ + DepositRoot: []byte{40, 2, 99, 184, 81, 91, 153, 196, 115, 217, 104, 93, 31, 202, 27, 153, 42, 224, 148, 156, 116, 43, 161, 28, 155, 166, 37, 217, 205, 152, 69, 6}, + DepositCount: params.BeaconConfig().SyncCommitteeSize, + BlockHash: []byte{226, 231, 104, 45, 7, 68, 48, 54, 228, 109, 84, 245, 125, 45, 227, 127, 135, 155, 63, 38, 241, 251, 129, 192, 248, 49, 9, 120, 146, 18, 34, 228}, + }, + Graffiti: graffiti[:], + ProposerSlashings: []*ethpbv1.ProposerSlashing{ + { + SignedHeader_1: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_1.Header.Slot, + ProposerIndex: proposerSlashing.Header_1.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_1.Header.ParentRoot, + StateRoot: proposerSlashing.Header_1.Header.StateRoot, + BodyRoot: proposerSlashing.Header_1.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_1.Signature, + }, + SignedHeader_2: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_2.Header.Slot, + ProposerIndex: proposerSlashing.Header_2.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_2.Header.ParentRoot, + StateRoot: proposerSlashing.Header_2.Header.StateRoot, + BodyRoot: proposerSlashing.Header_2.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_2.Signature, + }, + }, + }, + AttesterSlashings: []*ethpbv1.AttesterSlashing{ + { + Attestation_1: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_1.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_1.Data.Slot, + Index: attesterSlashing.Attestation_1.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_1.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Source.Epoch, + Root: attesterSlashing.Attestation_1.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Target.Epoch, + Root: attesterSlashing.Attestation_1.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_1.Signature, + }, + Attestation_2: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_2.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_2.Data.Slot, + Index: attesterSlashing.Attestation_2.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_2.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Source.Epoch, + Root: attesterSlashing.Attestation_2.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Target.Epoch, + Root: attesterSlashing.Attestation_2.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_2.Signature, + }, + }, + }, + SyncAggregate: ðpbv1.SyncAggregate{ + SyncCommitteeBits: []byte{170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + SyncCommitteeSignature: []byte{153, 51, 238, 112, 158, 23, 41, 26, 18, 53, 3, 111, 57, 180, 45, 131, 90, 249, 28, 23, 153, 188, 171, 204, 45, 180, 133, 236, 47, 203, 119, 132, 162, 17, 61, 60, 122, 161, 45, 136, 130, 174, 120, 60, 64, 144, 6, 34, 24, 87, 41, 77, 16, 223, 36, 125, 80, 185, 178, 234, 74, 184, 196, 45, 242, 47, 124, 178, 83, 65, 106, 26, 179, 178, 27, 4, 72, 79, 191, 128, 114, 51, 246, 147, 3, 55, 210, 64, 148, 78, 144, 45, 97, 182, 157, 206}, + }, + ExecutionPayload: &enginev1.ExecutionPayload{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: nil, + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + Transactions: nil, + }, + }, + } + expectedData, err := expectedBlock.MarshalSSZ() + assert.NoError(t, err) + assert.DeepEqual(t, expectedData, resp.Data) + }) +} + +func TestProduceBlockV2_SyncNotReady(t *testing.T) { + chainService := &mockChain.ChainService{} + vs := &Server{ + SyncChecker: &mockSync.Sync{IsSyncing: true}, + HeadFetcher: chainService, + TimeFetcher: chainService, + } + _, err := vs.ProduceBlockV2(context.Background(), ðpbv1.ProduceBlockRequest{}) + assert.ErrorContains(t, "Syncing to latest head, not ready to respond", err) +} + +func TestProduceBlockV2SSZ_SyncNotReady(t *testing.T) { + chainService := &mockChain.ChainService{} + vs := &Server{ + SyncChecker: &mockSync.Sync{IsSyncing: true}, + HeadFetcher: chainService, + TimeFetcher: chainService, + } + _, err := vs.ProduceBlockV2SSZ(context.Background(), ðpbv1.ProduceBlockRequest{}) + assert.ErrorContains(t, "Syncing to latest head, not ready to respond", err) +} + +func TestProduceBlindedBlock(t *testing.T) { + t.Run("Phase 0", func(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + + beaconState, privKeys := util.DeterministicGenesisState(t, 64) + + stateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + genesis := blocks.NewGenesisBlock(stateRoot[:]) + wrapped, err := wrapper.WrappedSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, db.SaveBlock(ctx, wrapped), "Could not save genesis block") + + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + v1Alpha1Server := &v1alpha1validator.Server{ + HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: &mockChain.ChainService{}, + HeadUpdater: &mockChain.ChainService{}, + ChainStartFetcher: &mockPOW.POWChain{}, + Eth1InfoFetcher: &mockPOW.POWChain{}, + Eth1BlockFetcher: &mockPOW.POWChain{}, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db), + } + + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) + for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + beaconState, + privKeys[i], + i, /* validator index */ + ) + require.NoError(t, err) + proposerSlashings[i] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing) + require.NoError(t, err) + } + + attSlashings := make([]*ethpbalpha.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) + for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + beaconState, + privKeys[i+params.BeaconConfig().MaxProposerSlashings], + types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings), /* validator index */ + ) + require.NoError(t, err) + attSlashings[i] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing) + require.NoError(t, err) + } + + v1Server := &Server{ + SyncChecker: &mockSync.Sync{IsSyncing: false}, + V1Alpha1Server: v1Alpha1Server, + } + randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + require.NoError(t, err) + graffiti := bytesutil.ToBytes32([]byte("eth2")) + req := ðpbv1.ProduceBlockRequest{ + Slot: 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + resp, err := v1Server.ProduceBlindedBlock(ctx, req) + require.NoError(t, err) + assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version) + + containerBlock, ok := resp.Data.Block.(*ethpbv2.BlindedBeaconBlockContainer_Phase0Block) + require.Equal(t, true, ok) + blk := containerBlock.Phase0Block + assert.Equal(t, req.Slot, blk.Slot, "Expected block to have slot of 1") + assert.DeepEqual(t, parentRoot[:], blk.ParentRoot, "Expected block to have correct parent root") + assert.DeepEqual(t, randaoReveal, blk.Body.RandaoReveal, "Expected block to have correct randao reveal") + assert.DeepEqual(t, req.Graffiti, blk.Body.Graffiti, "Expected block to have correct graffiti") + assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(blk.Body.ProposerSlashings))) + expectedPropSlashings := make([]*ethpbv1.ProposerSlashing, len(proposerSlashings)) + for i, slash := range proposerSlashings { + expectedPropSlashings[i] = migration.V1Alpha1ProposerSlashingToV1(slash) + } + assert.DeepEqual(t, expectedPropSlashings, blk.Body.ProposerSlashings) + assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(blk.Body.AttesterSlashings))) + expectedAttSlashings := make([]*ethpbv1.AttesterSlashing, len(attSlashings)) + for i, slash := range attSlashings { + expectedAttSlashings[i] = migration.V1Alpha1AttSlashingToV1(slash) + } + assert.DeepEqual(t, expectedAttSlashings, blk.Body.AttesterSlashings) + }) + + t.Run("Altair", func(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + + params.SetupTestConfigCleanup(t) + bc := params.BeaconConfig() + bc.AltairForkEpoch = types.Epoch(0) + params.OverrideBeaconConfig(bc) + + beaconState, privKeys := util.DeterministicGenesisStateAltair(t, params.BeaconConfig().SyncCommitteeSize) + syncCommittee, err := altair.NextSyncCommittee(context.Background(), beaconState) + require.NoError(t, err) + require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee)) + require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee)) + + stateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + genesisBlock := util.NewBeaconBlockAltair() + genesisBlock.Block.StateRoot = stateRoot[:] + wrappedAltairBlock, err := wrapper.WrappedSignedBeaconBlock(genesisBlock) + require.NoError(t, err) + require.NoError(t, err) + require.NoError(t, db.SaveBlock(ctx, wrappedAltairBlock)) + parentRoot, err := genesisBlock.Block.HashTreeRoot() + require.NoError(t, err) + + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + v1Alpha1Server := &v1alpha1validator.Server{ + HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: &mockChain.ChainService{}, + HeadUpdater: &mockChain.ChainService{}, + ChainStartFetcher: &mockPOW.POWChain{}, + Eth1InfoFetcher: &mockPOW.POWChain{}, + Eth1BlockFetcher: &mockPOW.POWChain{}, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db), + SyncCommitteePool: synccommittee.NewStore(), + } + + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) + for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + beaconState, + privKeys[i], + i, /* validator index */ + ) + require.NoError(t, err) + proposerSlashings[i] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing) + require.NoError(t, err) + } + + attSlashings := make([]*ethpbalpha.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) + for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + beaconState, + privKeys[i+params.BeaconConfig().MaxProposerSlashings], + types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings), /* validator index */ + ) + require.NoError(t, err) + attSlashings[i] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing) + require.NoError(t, err) + } + + aggregationBits := bitfield.NewBitvector128() + for i := range aggregationBits { + aggregationBits[i] = 0xAA + } + + syncCommitteeIndices, err := altair.NextSyncCommitteeIndices(context.Background(), beaconState) + require.NoError(t, err) + sigs := make([]bls.Signature, 0, len(syncCommitteeIndices)) + for i, indice := range syncCommitteeIndices { + if aggregationBits.BitAt(uint64(i)) { + b := p2pType.SSZBytes(parentRoot[:]) + sb, err := signing.ComputeDomainAndSign(beaconState, coreTime.CurrentEpoch(beaconState), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice]) + require.NoError(t, err) + sig, err := bls.SignatureFromBytes(sb) + require.NoError(t, err) + sigs = append(sigs, sig) + } + } + aggregatedSig := bls.AggregateSignatures(sigs).Marshal() + contribution := ðpbalpha.SyncCommitteeContribution{ + Slot: 0, + BlockRoot: parentRoot[:], + SubcommitteeIndex: 0, + AggregationBits: aggregationBits, + Signature: aggregatedSig, + } + require.NoError(t, v1Alpha1Server.SyncCommitteePool.SaveSyncCommitteeContribution(contribution)) + + v1Server := &Server{ + SyncChecker: &mockSync.Sync{IsSyncing: false}, + V1Alpha1Server: v1Alpha1Server, + } + randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + require.NoError(t, err) + graffiti := bytesutil.ToBytes32([]byte("eth2")) + + req := ðpbv1.ProduceBlockRequest{ + Slot: 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + resp, err := v1Server.ProduceBlindedBlock(ctx, req) + require.NoError(t, err) + assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version) + + containerBlock, ok := resp.Data.Block.(*ethpbv2.BlindedBeaconBlockContainer_AltairBlock) + require.Equal(t, true, ok) + blk := containerBlock.AltairBlock + assert.Equal(t, req.Slot, blk.Slot, "Expected block to have slot of 1") + assert.DeepEqual(t, parentRoot[:], blk.ParentRoot, "Expected block to have correct parent root") + assert.DeepEqual(t, randaoReveal, blk.Body.RandaoReveal, "Expected block to have correct randao reveal") + assert.DeepEqual(t, req.Graffiti, blk.Body.Graffiti, "Expected block to have correct graffiti") + assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(blk.Body.ProposerSlashings))) + expectedPropSlashings := make([]*ethpbv1.ProposerSlashing, len(proposerSlashings)) + for i, slash := range proposerSlashings { + expectedPropSlashings[i] = migration.V1Alpha1ProposerSlashingToV1(slash) + } + assert.DeepEqual(t, expectedPropSlashings, blk.Body.ProposerSlashings) + assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(blk.Body.AttesterSlashings))) + expectedAttSlashings := make([]*ethpbv1.AttesterSlashing, len(attSlashings)) + for i, slash := range attSlashings { + expectedAttSlashings[i] = migration.V1Alpha1AttSlashingToV1(slash) + } + assert.DeepEqual(t, expectedAttSlashings, blk.Body.AttesterSlashings) + expectedBits := bitfield.NewBitvector512() + for i := 0; i <= 15; i++ { + expectedBits[i] = 0xAA + } + assert.DeepEqual(t, expectedBits, blk.Body.SyncAggregate.SyncCommitteeBits) + assert.DeepEqual(t, aggregatedSig, blk.Body.SyncAggregate.SyncCommitteeSignature) + }) + + t.Run("Bellatrix", func(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + + params.SetupTestConfigCleanup(t) + bc := params.BeaconConfig() + bc.AltairForkEpoch = types.Epoch(0) + bc.BellatrixForkEpoch = types.Epoch(1) + params.OverrideBeaconConfig(bc) + + beaconState, privKeys := util.DeterministicGenesisStateBellatrix(t, params.BeaconConfig().SyncCommitteeSize) + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + syncCommittee, err := altair.NextSyncCommittee(context.Background(), beaconState) + require.NoError(t, err) + require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee)) + require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee)) + + stateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + genesisBlock := util.NewBeaconBlockBellatrix() + genesisBlock.Block.StateRoot = stateRoot[:] + wrappedBellatrixBlock, err := wrapper.WrappedSignedBeaconBlock(genesisBlock) + require.NoError(t, err) + require.NoError(t, db.SaveBlock(ctx, wrappedBellatrixBlock)) + parentRoot, err := genesisBlock.Block.HashTreeRoot() + require.NoError(t, err) + + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + v1Alpha1Server := &v1alpha1validator.Server{ + ExecutionEngineCaller: &mockPOW.EngineClient{ + ExecutionBlock: &enginev1.ExecutionBlock{ + TotalDifficulty: "0x1", + }, + }, + TimeFetcher: &mockChain.ChainService{}, + HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]}, + OptimisticModeFetcher: &mockChain.ChainService{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: &mockChain.ChainService{}, + HeadUpdater: &mockChain.ChainService{}, + ChainStartFetcher: &mockPOW.POWChain{}, + Eth1InfoFetcher: &mockPOW.POWChain{}, + Eth1BlockFetcher: &mockPOW.POWChain{}, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db), + SyncCommitteePool: synccommittee.NewStore(), + ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), + } + + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) + for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + beaconState, + privKeys[i], + i, + ) + require.NoError(t, err) + proposerSlashings[i] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing) + require.NoError(t, err) + } + + attSlashings := make([]*ethpbalpha.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) + for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + beaconState, + privKeys[i+params.BeaconConfig().MaxProposerSlashings], + types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings), /* validator index */ + ) + require.NoError(t, err) + attSlashings[i] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing) + require.NoError(t, err) + } + + aggregationBits := bitfield.NewBitvector128() + for i := range aggregationBits { + aggregationBits[i] = 0xAA + } + + syncCommitteeIndices, err := altair.NextSyncCommitteeIndices(context.Background(), beaconState) + require.NoError(t, err) + sigs := make([]bls.Signature, 0, len(syncCommitteeIndices)) + for i, indice := range syncCommitteeIndices { + if aggregationBits.BitAt(uint64(i)) { + b := p2pType.SSZBytes(parentRoot[:]) + sb, err := signing.ComputeDomainAndSign(beaconState, coreTime.CurrentEpoch(beaconState), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice]) + require.NoError(t, err) + sig, err := bls.SignatureFromBytes(sb) + require.NoError(t, err) + sigs = append(sigs, sig) + } + } + aggregatedSig := bls.AggregateSignatures(sigs).Marshal() + contribution := ðpbalpha.SyncCommitteeContribution{ + Slot: params.BeaconConfig().SlotsPerEpoch, + BlockRoot: parentRoot[:], + SubcommitteeIndex: 0, + AggregationBits: aggregationBits, + Signature: aggregatedSig, + } + require.NoError(t, v1Alpha1Server.SyncCommitteePool.SaveSyncCommitteeContribution(contribution)) + + v1Server := &Server{ + V1Alpha1Server: v1Alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + randaoReveal, err := util.RandaoReveal(beaconState, 1, privKeys) + require.NoError(t, err) + graffiti := bytesutil.ToBytes32([]byte("eth2")) + + req := ðpbv1.ProduceBlockRequest{ + Slot: params.BeaconConfig().SlotsPerEpoch + 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + resp, err := v1Server.ProduceBlindedBlock(ctx, req) + require.NoError(t, err) + assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version) + + containerBlock, ok := resp.Data.Block.(*ethpbv2.BlindedBeaconBlockContainer_BellatrixBlock) + require.Equal(t, true, ok) + blk := containerBlock.BellatrixBlock + assert.Equal(t, req.Slot, blk.Slot, "Expected block to have slot of 1") + assert.DeepEqual(t, parentRoot[:], blk.ParentRoot, "Expected block to have correct parent root") + assert.DeepEqual(t, randaoReveal, blk.Body.RandaoReveal, "Expected block to have correct randao reveal") + assert.DeepEqual(t, req.Graffiti, blk.Body.Graffiti, "Expected block to have correct graffiti") + assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(blk.Body.ProposerSlashings))) + expectedPropSlashings := make([]*ethpbv1.ProposerSlashing, len(proposerSlashings)) + for i, slash := range proposerSlashings { + expectedPropSlashings[i] = migration.V1Alpha1ProposerSlashingToV1(slash) + } + assert.DeepEqual(t, expectedPropSlashings, blk.Body.ProposerSlashings) + assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(blk.Body.AttesterSlashings))) + expectedAttSlashings := make([]*ethpbv1.AttesterSlashing, len(attSlashings)) + for i, slash := range attSlashings { + expectedAttSlashings[i] = migration.V1Alpha1AttSlashingToV1(slash) + } + assert.DeepEqual(t, expectedAttSlashings, blk.Body.AttesterSlashings) + expectedBits := bitfield.NewBitvector512() + for i := 0; i <= 15; i++ { + expectedBits[i] = 0xAA + } + assert.DeepEqual(t, expectedBits, blk.Body.SyncAggregate.SyncCommitteeBits) + assert.DeepEqual(t, aggregatedSig, blk.Body.SyncAggregate.SyncCommitteeSignature) + }) +} + +func TestProduceBlindedBlockSSZ(t *testing.T) { + t.Run("Phase 0", func(t *testing.T) { + ctx := context.Background() + + db := dbutil.SetupDB(t) + + bs, privKeys := util.DeterministicGenesisState(t, 2) + + stateRoot, err := bs.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + genesis := blocks.NewGenesisBlock(stateRoot[:]) + wsb, err := wrapper.WrappedSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, db.SaveBlock(ctx, wsb), "Could not save genesis block") + + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, bs, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + v1Alpha1Server := &v1alpha1validator.Server{ + HeadFetcher: &mockChain.ChainService{State: bs, Root: parentRoot[:]}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: &mockChain.ChainService{}, + HeadUpdater: &mockChain.ChainService{}, + ChainStartFetcher: &mockPOW.POWChain{}, + Eth1InfoFetcher: &mockPOW.POWChain{}, + Eth1BlockFetcher: &mockPOW.POWChain{}, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db), } + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, 1) + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + bs, + privKeys[0], + 0, + ) + require.NoError(t, err) + proposerSlashings[0] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), bs, proposerSlashing) + require.NoError(t, err) + + attSlashings := make([]*ethpbalpha.AttesterSlashing, 1) + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + bs, + privKeys[1], + 1, + ) + require.NoError(t, err) + attSlashings[0] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), bs, attesterSlashing) + require.NoError(t, err) + v1Server := &Server{ - SyncChecker: &mockSync.Sync{IsSyncing: false}, V1Alpha1Server: v1Alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, } - randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + randaoReveal, err := util.RandaoReveal(bs, 0, privKeys) require.NoError(t, err) graffiti := bytesutil.ToBytes32([]byte("eth2")) req := ðpbv1.ProduceBlockRequest{ @@ -1227,29 +2213,90 @@ func TestProduceBlindedBlock(t *testing.T) { RandaoReveal: randaoReveal, Graffiti: graffiti[:], } - resp, err := v1Server.ProduceBlindedBlock(ctx, req) + resp, err := v1Server.ProduceBlindedBlockSSZ(ctx, req) require.NoError(t, err) assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version) - containerBlock, ok := resp.Data.Block.(*ethpbv2.BlindedBeaconBlockContainer_Phase0Block) - require.Equal(t, true, ok) - blk := containerBlock.Phase0Block - assert.Equal(t, req.Slot, blk.Slot, "Expected block to have slot of 1") - assert.DeepEqual(t, parentRoot[:], blk.ParentRoot, "Expected block to have correct parent root") - assert.DeepEqual(t, randaoReveal, blk.Body.RandaoReveal, "Expected block to have correct randao reveal") - assert.DeepEqual(t, req.Graffiti, blk.Body.Graffiti, "Expected block to have correct graffiti") - assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(blk.Body.ProposerSlashings))) - expectedPropSlashings := make([]*ethpbv1.ProposerSlashing, len(proposerSlashings)) - for i, slash := range proposerSlashings { - expectedPropSlashings[i] = migration.V1Alpha1ProposerSlashingToV1(slash) - } - assert.DeepEqual(t, expectedPropSlashings, blk.Body.ProposerSlashings) - assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(blk.Body.AttesterSlashings))) - expectedAttSlashings := make([]*ethpbv1.AttesterSlashing, len(attSlashings)) - for i, slash := range attSlashings { - expectedAttSlashings[i] = migration.V1Alpha1AttSlashingToV1(slash) + expectedBlock := ðpbv1.BeaconBlock{ + Slot: 1, + ProposerIndex: 0, + ParentRoot: []byte{164, 47, 20, 157, 2, 202, 58, 173, 57, 154, 254, 181, 153, 74, 40, 89, 159, 74, 62, 247, 28, 222, 153, 182, 168, 79, 170, 149, 80, 99, 97, 32}, + StateRoot: []byte{224, 94, 112, 87, 163, 57, 192, 233, 181, 179, 212, 9, 226, 214, 65, 238, 189, 114, 223, 101, 215, 146, 163, 140, 92, 242, 35, 82, 222, 154, 127, 136}, + Body: ðpbv1.BeaconBlockBody{ + RandaoReveal: randaoReveal, + Eth1Data: ðpbv1.Eth1Data{ + DepositRoot: []byte{124, 159, 161, 54, 212, 65, 63, 166, 23, 54, 55, 232, 131, 182, 153, 141, 50, 225, 214, 117, 248, 140, 221, 255, 157, 203, 207, 51, 24, 32, 244, 184}, + DepositCount: 2, + BlockHash: []byte{8, 83, 63, 107, 189, 73, 117, 17, 62, 79, 12, 177, 4, 171, 205, 236, 29, 134, 217, 157, 87, 130, 180, 169, 167, 246, 39, 12, 14, 187, 106, 39}, + }, + Graffiti: graffiti[:], + ProposerSlashings: []*ethpbv1.ProposerSlashing{ + { + SignedHeader_1: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_1.Header.Slot, + ProposerIndex: proposerSlashing.Header_1.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_1.Header.ParentRoot, + StateRoot: proposerSlashing.Header_1.Header.StateRoot, + BodyRoot: proposerSlashing.Header_1.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_1.Signature, + }, + SignedHeader_2: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_2.Header.Slot, + ProposerIndex: proposerSlashing.Header_2.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_2.Header.ParentRoot, + StateRoot: proposerSlashing.Header_2.Header.StateRoot, + BodyRoot: proposerSlashing.Header_2.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_2.Signature, + }, + }, + }, + AttesterSlashings: []*ethpbv1.AttesterSlashing{ + { + Attestation_1: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_1.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_1.Data.Slot, + Index: attesterSlashing.Attestation_1.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_1.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Source.Epoch, + Root: attesterSlashing.Attestation_1.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Target.Epoch, + Root: attesterSlashing.Attestation_1.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_1.Signature, + }, + Attestation_2: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_2.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_2.Data.Slot, + Index: attesterSlashing.Attestation_2.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_2.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Source.Epoch, + Root: attesterSlashing.Attestation_2.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Target.Epoch, + Root: attesterSlashing.Attestation_2.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_2.Signature, + }, + }, + }, + }, } - assert.DeepEqual(t, expectedAttSlashings, blk.Body.AttesterSlashings) + expectedData, err := expectedBlock.MarshalSSZ() + assert.NoError(t, err) + assert.DeepEqual(t, expectedData, resp.Data) }) t.Run("Altair", func(t *testing.T) { @@ -1261,28 +2308,27 @@ func TestProduceBlindedBlock(t *testing.T) { bc.AltairForkEpoch = types.Epoch(0) params.OverrideBeaconConfig(bc) - beaconState, privKeys := util.DeterministicGenesisStateAltair(t, params.BeaconConfig().SyncCommitteeSize) - syncCommittee, err := altair.NextSyncCommittee(context.Background(), beaconState) + bs, privKeys := util.DeterministicGenesisStateAltair(t, params.BeaconConfig().SyncCommitteeSize) + syncCommittee, err := altair.NextSyncCommittee(context.Background(), bs) require.NoError(t, err) - require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee)) - require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee)) + require.NoError(t, bs.SetCurrentSyncCommittee(syncCommittee)) + require.NoError(t, bs.SetNextSyncCommittee(syncCommittee)) - stateRoot, err := beaconState.HashTreeRoot(ctx) + stateRoot, err := bs.HashTreeRoot(ctx) require.NoError(t, err, "Could not hash genesis state") genesisBlock := util.NewBeaconBlockAltair() genesisBlock.Block.StateRoot = stateRoot[:] wrappedAltairBlock, err := wrapper.WrappedSignedBeaconBlock(genesisBlock) require.NoError(t, err) - require.NoError(t, err) require.NoError(t, db.SaveBlock(ctx, wrappedAltairBlock)) parentRoot, err := genesisBlock.Block.HashTreeRoot() require.NoError(t, err) - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveState(ctx, bs, parentRoot), "Could not save genesis state") require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") v1Alpha1Server := &v1alpha1validator.Server{ - HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]}, + HeadFetcher: &mockChain.ChainService{State: bs, Root: parentRoot[:]}, SyncChecker: &mockSync.Sync{IsSyncing: false}, BlockReceiver: &mockChain.ChainService{}, HeadUpdater: &mockChain.ChainService{}, @@ -1297,44 +2343,40 @@ func TestProduceBlindedBlock(t *testing.T) { SyncCommitteePool: synccommittee.NewStore(), } - proposerSlashings := make([]*ethpbalpha.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) - for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { - proposerSlashing, err := util.GenerateProposerSlashingForValidator( - beaconState, - privKeys[i], - i, /* validator index */ - ) - require.NoError(t, err) - proposerSlashings[i] = proposerSlashing - err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing) - require.NoError(t, err) - } + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, 1) + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + bs, + privKeys[0], + 0, + ) + require.NoError(t, err) + proposerSlashings[0] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), bs, proposerSlashing) + require.NoError(t, err) attSlashings := make([]*ethpbalpha.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) - for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { - attesterSlashing, err := util.GenerateAttesterSlashingForValidator( - beaconState, - privKeys[i+params.BeaconConfig().MaxProposerSlashings], - types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings), /* validator index */ - ) - require.NoError(t, err) - attSlashings[i] = attesterSlashing - err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing) - require.NoError(t, err) - } + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + bs, + privKeys[1], + 1, + ) + require.NoError(t, err) + attSlashings[0] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), bs, attesterSlashing) + require.NoError(t, err) aggregationBits := bitfield.NewBitvector128() for i := range aggregationBits { aggregationBits[i] = 0xAA } - syncCommitteeIndices, err := altair.NextSyncCommitteeIndices(context.Background(), beaconState) + syncCommitteeIndices, err := altair.NextSyncCommitteeIndices(context.Background(), bs) require.NoError(t, err) sigs := make([]bls.Signature, 0, len(syncCommitteeIndices)) for i, indice := range syncCommitteeIndices { if aggregationBits.BitAt(uint64(i)) { b := p2pType.SSZBytes(parentRoot[:]) - sb, err := signing.ComputeDomainAndSign(beaconState, coreTime.CurrentEpoch(beaconState), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice]) + sb, err := signing.ComputeDomainAndSign(bs, coreTime.CurrentEpoch(bs), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice]) require.NoError(t, err) sig, err := bls.SignatureFromBytes(sb) require.NoError(t, err) @@ -1352,10 +2394,10 @@ func TestProduceBlindedBlock(t *testing.T) { require.NoError(t, v1Alpha1Server.SyncCommitteePool.SaveSyncCommitteeContribution(contribution)) v1Server := &Server{ - SyncChecker: &mockSync.Sync{IsSyncing: false}, V1Alpha1Server: v1Alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, } - randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + randaoReveal, err := util.RandaoReveal(bs, 0, privKeys) require.NoError(t, err) graffiti := bytesutil.ToBytes32([]byte("eth2")) @@ -1364,35 +2406,94 @@ func TestProduceBlindedBlock(t *testing.T) { RandaoReveal: randaoReveal, Graffiti: graffiti[:], } - resp, err := v1Server.ProduceBlindedBlock(ctx, req) + resp, err := v1Server.ProduceBlindedBlockSSZ(ctx, req) require.NoError(t, err) assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version) - containerBlock, ok := resp.Data.Block.(*ethpbv2.BlindedBeaconBlockContainer_AltairBlock) - require.Equal(t, true, ok) - blk := containerBlock.AltairBlock - assert.Equal(t, req.Slot, blk.Slot, "Expected block to have slot of 1") - assert.DeepEqual(t, parentRoot[:], blk.ParentRoot, "Expected block to have correct parent root") - assert.DeepEqual(t, randaoReveal, blk.Body.RandaoReveal, "Expected block to have correct randao reveal") - assert.DeepEqual(t, req.Graffiti, blk.Body.Graffiti, "Expected block to have correct graffiti") - assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(blk.Body.ProposerSlashings))) - expectedPropSlashings := make([]*ethpbv1.ProposerSlashing, len(proposerSlashings)) - for i, slash := range proposerSlashings { - expectedPropSlashings[i] = migration.V1Alpha1ProposerSlashingToV1(slash) - } - assert.DeepEqual(t, expectedPropSlashings, blk.Body.ProposerSlashings) - assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(blk.Body.AttesterSlashings))) - expectedAttSlashings := make([]*ethpbv1.AttesterSlashing, len(attSlashings)) - for i, slash := range attSlashings { - expectedAttSlashings[i] = migration.V1Alpha1AttSlashingToV1(slash) - } - assert.DeepEqual(t, expectedAttSlashings, blk.Body.AttesterSlashings) - expectedBits := bitfield.NewBitvector512() - for i := 0; i <= 15; i++ { - expectedBits[i] = 0xAA + expectedBlock := ðpbv2.BeaconBlockAltair{ + Slot: 1, + ProposerIndex: 19, + ParentRoot: []byte{162, 206, 194, 54, 242, 248, 88, 148, 193, 141, 39, 23, 91, 116, 219, 219, 2, 248, 4, 155, 159, 201, 41, 156, 130, 57, 167, 176, 153, 18, 73, 148}, + StateRoot: []byte{144, 220, 158, 2, 142, 57, 111, 170, 148, 225, 129, 23, 103, 232, 44, 1, 222, 77, 36, 110, 118, 237, 184, 77, 253, 182, 0, 62, 168, 56, 105, 95}, + Body: ðpbv2.BeaconBlockBodyAltair{ + RandaoReveal: randaoReveal, + Eth1Data: ðpbv1.Eth1Data{ + DepositRoot: []byte{124, 159, 161, 54, 212, 65, 63, 166, 23, 54, 55, 232, 131, 182, 153, 141, 50, 225, 214, 117, 248, 140, 221, 255, 157, 203, 207, 51, 24, 32, 244, 184}, + DepositCount: params.BeaconConfig().SyncCommitteeSize, + BlockHash: []byte{8, 83, 63, 107, 189, 73, 117, 17, 62, 79, 12, 177, 4, 171, 205, 236, 29, 134, 217, 157, 87, 130, 180, 169, 167, 246, 39, 12, 14, 187, 106, 39}, + }, + Graffiti: graffiti[:], + ProposerSlashings: []*ethpbv1.ProposerSlashing{ + { + SignedHeader_1: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_1.Header.Slot, + ProposerIndex: proposerSlashing.Header_1.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_1.Header.ParentRoot, + StateRoot: proposerSlashing.Header_1.Header.StateRoot, + BodyRoot: proposerSlashing.Header_1.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_1.Signature, + }, + SignedHeader_2: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_2.Header.Slot, + ProposerIndex: proposerSlashing.Header_2.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_2.Header.ParentRoot, + StateRoot: proposerSlashing.Header_2.Header.StateRoot, + BodyRoot: proposerSlashing.Header_2.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_2.Signature, + }, + }, + }, + AttesterSlashings: []*ethpbv1.AttesterSlashing{ + { + Attestation_1: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_1.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_1.Data.Slot, + Index: attesterSlashing.Attestation_1.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_1.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Source.Epoch, + Root: attesterSlashing.Attestation_1.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Target.Epoch, + Root: attesterSlashing.Attestation_1.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_1.Signature, + }, + Attestation_2: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_2.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_2.Data.Slot, + Index: attesterSlashing.Attestation_2.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_2.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Source.Epoch, + Root: attesterSlashing.Attestation_2.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Target.Epoch, + Root: attesterSlashing.Attestation_2.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_2.Signature, + }, + }, + }, + SyncAggregate: ðpbv1.SyncAggregate{ + SyncCommitteeBits: []byte{170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + SyncCommitteeSignature: []byte{130, 228, 60, 221, 180, 9, 29, 148, 136, 255, 135, 183, 146, 130, 88, 240, 116, 219, 183, 208, 148, 211, 202, 78, 240, 120, 60, 99, 77, 76, 109, 210, 163, 243, 244, 25, 70, 184, 29, 252, 138, 128, 202, 173, 1, 166, 48, 49, 11, 136, 42, 124, 163, 187, 206, 253, 214, 149, 114, 137, 146, 123, 197, 187, 250, 204, 59, 196, 87, 195, 48, 11, 116, 123, 58, 49, 62, 98, 193, 166, 0, 172, 15, 253, 130, 88, 46, 110, 45, 84, 57, 107, 83, 182, 127, 105}, + }, + }, } - assert.DeepEqual(t, expectedBits, blk.Body.SyncAggregate.SyncCommitteeBits) - assert.DeepEqual(t, aggregatedSig, blk.Body.SyncAggregate.SyncCommitteeSignature) + expectedData, err := expectedBlock.MarshalSSZ() + assert.NoError(t, err) + assert.DeepEqual(t, expectedData, resp.Data) }) t.Run("Bellatrix", func(t *testing.T) { @@ -1405,14 +2506,14 @@ func TestProduceBlindedBlock(t *testing.T) { bc.BellatrixForkEpoch = types.Epoch(1) params.OverrideBeaconConfig(bc) - beaconState, privKeys := util.DeterministicGenesisStateBellatrix(t, params.BeaconConfig().SyncCommitteeSize) - require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) - syncCommittee, err := altair.NextSyncCommittee(context.Background(), beaconState) + bs, privKeys := util.DeterministicGenesisStateBellatrix(t, params.BeaconConfig().SyncCommitteeSize) + require.NoError(t, bs.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + syncCommittee, err := altair.NextSyncCommittee(context.Background(), bs) require.NoError(t, err) - require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee)) - require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee)) + require.NoError(t, bs.SetCurrentSyncCommittee(syncCommittee)) + require.NoError(t, bs.SetNextSyncCommittee(syncCommittee)) - stateRoot, err := beaconState.HashTreeRoot(ctx) + stateRoot, err := bs.HashTreeRoot(ctx) require.NoError(t, err, "Could not hash genesis state") genesisBlock := util.NewBeaconBlockBellatrix() genesisBlock.Block.StateRoot = stateRoot[:] @@ -1422,7 +2523,7 @@ func TestProduceBlindedBlock(t *testing.T) { parentRoot, err := genesisBlock.Block.HashTreeRoot() require.NoError(t, err) - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveState(ctx, bs, parentRoot), "Could not save genesis state") require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") v1Alpha1Server := &v1alpha1validator.Server{ @@ -1432,7 +2533,8 @@ func TestProduceBlindedBlock(t *testing.T) { }, }, TimeFetcher: &mockChain.ChainService{}, - HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]}, + HeadFetcher: &mockChain.ChainService{State: bs, Root: parentRoot[:]}, + OptimisticModeFetcher: &mockChain.ChainService{}, SyncChecker: &mockSync.Sync{IsSyncing: false}, BlockReceiver: &mockChain.ChainService{}, HeadUpdater: &mockChain.ChainService{}, @@ -1448,44 +2550,40 @@ func TestProduceBlindedBlock(t *testing.T) { ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), } - proposerSlashings := make([]*ethpbalpha.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) - for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { - proposerSlashing, err := util.GenerateProposerSlashingForValidator( - beaconState, - privKeys[i], - i, - ) - require.NoError(t, err) - proposerSlashings[i] = proposerSlashing - err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing) - require.NoError(t, err) - } + proposerSlashings := make([]*ethpbalpha.ProposerSlashing, 1) + proposerSlashing, err := util.GenerateProposerSlashingForValidator( + bs, + privKeys[0], + 0, + ) + require.NoError(t, err) + proposerSlashings[0] = proposerSlashing + err = v1Alpha1Server.SlashingsPool.InsertProposerSlashing(context.Background(), bs, proposerSlashing) + require.NoError(t, err) attSlashings := make([]*ethpbalpha.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) - for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { - attesterSlashing, err := util.GenerateAttesterSlashingForValidator( - beaconState, - privKeys[i+params.BeaconConfig().MaxProposerSlashings], - types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings), /* validator index */ - ) - require.NoError(t, err) - attSlashings[i] = attesterSlashing - err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing) - require.NoError(t, err) - } + attesterSlashing, err := util.GenerateAttesterSlashingForValidator( + bs, + privKeys[1], + 1, + ) + require.NoError(t, err) + attSlashings[0] = attesterSlashing + err = v1Alpha1Server.SlashingsPool.InsertAttesterSlashing(context.Background(), bs, attesterSlashing) + require.NoError(t, err) aggregationBits := bitfield.NewBitvector128() for i := range aggregationBits { aggregationBits[i] = 0xAA } - syncCommitteeIndices, err := altair.NextSyncCommitteeIndices(context.Background(), beaconState) + syncCommitteeIndices, err := altair.NextSyncCommitteeIndices(context.Background(), bs) require.NoError(t, err) sigs := make([]bls.Signature, 0, len(syncCommitteeIndices)) for i, indice := range syncCommitteeIndices { if aggregationBits.BitAt(uint64(i)) { b := p2pType.SSZBytes(parentRoot[:]) - sb, err := signing.ComputeDomainAndSign(beaconState, coreTime.CurrentEpoch(beaconState), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice]) + sb, err := signing.ComputeDomainAndSign(bs, coreTime.CurrentEpoch(bs), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice]) require.NoError(t, err) sig, err := bls.SignatureFromBytes(sb) require.NoError(t, err) @@ -1506,7 +2604,7 @@ func TestProduceBlindedBlock(t *testing.T) { V1Alpha1Server: v1Alpha1Server, SyncChecker: &mockSync.Sync{IsSyncing: false}, } - randaoReveal, err := util.RandaoReveal(beaconState, 1, privKeys) + randaoReveal, err := util.RandaoReveal(bs, 1, privKeys) require.NoError(t, err) graffiti := bytesutil.ToBytes32([]byte("eth2")) @@ -1515,35 +2613,106 @@ func TestProduceBlindedBlock(t *testing.T) { RandaoReveal: randaoReveal, Graffiti: graffiti[:], } - resp, err := v1Server.ProduceBlindedBlock(ctx, req) + resp, err := v1Server.ProduceBlindedBlockSSZ(ctx, req) require.NoError(t, err) assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version) - containerBlock, ok := resp.Data.Block.(*ethpbv2.BlindedBeaconBlockContainer_BellatrixBlock) - require.Equal(t, true, ok) - blk := containerBlock.BellatrixBlock - assert.Equal(t, req.Slot, blk.Slot, "Expected block to have slot of 1") - assert.DeepEqual(t, parentRoot[:], blk.ParentRoot, "Expected block to have correct parent root") - assert.DeepEqual(t, randaoReveal, blk.Body.RandaoReveal, "Expected block to have correct randao reveal") - assert.DeepEqual(t, req.Graffiti, blk.Body.Graffiti, "Expected block to have correct graffiti") - assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(blk.Body.ProposerSlashings))) - expectedPropSlashings := make([]*ethpbv1.ProposerSlashing, len(proposerSlashings)) - for i, slash := range proposerSlashings { - expectedPropSlashings[i] = migration.V1Alpha1ProposerSlashingToV1(slash) - } - assert.DeepEqual(t, expectedPropSlashings, blk.Body.ProposerSlashings) - assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(blk.Body.AttesterSlashings))) - expectedAttSlashings := make([]*ethpbv1.AttesterSlashing, len(attSlashings)) - for i, slash := range attSlashings { - expectedAttSlashings[i] = migration.V1Alpha1AttSlashingToV1(slash) - } - assert.DeepEqual(t, expectedAttSlashings, blk.Body.AttesterSlashings) - expectedBits := bitfield.NewBitvector512() - for i := 0; i <= 15; i++ { - expectedBits[i] = 0xAA + expectedBlock := ðpbv2.BlindedBeaconBlockBellatrix{ + Slot: 33, + ProposerIndex: 348, + ParentRoot: []byte{228, 15, 208, 120, 31, 194, 202, 144, 41, 107, 98, 126, 162, 234, 190, 94, 174, 176, 69, 177, 103, 82, 69, 254, 0, 230, 192, 67, 158, 29, 141, 85}, + StateRoot: []byte{143, 107, 161, 135, 58, 60, 195, 107, 55, 142, 122, 111, 184, 1, 19, 233, 145, 204, 160, 226, 148, 67, 194, 102, 79, 196, 74, 242, 174, 108, 68, 82}, + Body: ðpbv2.BlindedBeaconBlockBodyBellatrix{ + RandaoReveal: randaoReveal, + Eth1Data: ðpbv1.Eth1Data{ + DepositRoot: []byte{40, 2, 99, 184, 81, 91, 153, 196, 115, 217, 104, 93, 31, 202, 27, 153, 42, 224, 148, 156, 116, 43, 161, 28, 155, 166, 37, 217, 205, 152, 69, 6}, + DepositCount: params.BeaconConfig().SyncCommitteeSize, + BlockHash: []byte{226, 231, 104, 45, 7, 68, 48, 54, 228, 109, 84, 245, 125, 45, 227, 127, 135, 155, 63, 38, 241, 251, 129, 192, 248, 49, 9, 120, 146, 18, 34, 228}, + }, + Graffiti: graffiti[:], + ProposerSlashings: []*ethpbv1.ProposerSlashing{ + { + SignedHeader_1: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_1.Header.Slot, + ProposerIndex: proposerSlashing.Header_1.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_1.Header.ParentRoot, + StateRoot: proposerSlashing.Header_1.Header.StateRoot, + BodyRoot: proposerSlashing.Header_1.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_1.Signature, + }, + SignedHeader_2: ðpbv1.SignedBeaconBlockHeader{ + Message: ðpbv1.BeaconBlockHeader{ + Slot: proposerSlashing.Header_2.Header.Slot, + ProposerIndex: proposerSlashing.Header_2.Header.ProposerIndex, + ParentRoot: proposerSlashing.Header_2.Header.ParentRoot, + StateRoot: proposerSlashing.Header_2.Header.StateRoot, + BodyRoot: proposerSlashing.Header_2.Header.BodyRoot, + }, + Signature: proposerSlashing.Header_2.Signature, + }, + }, + }, + AttesterSlashings: []*ethpbv1.AttesterSlashing{ + { + Attestation_1: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_1.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_1.Data.Slot, + Index: attesterSlashing.Attestation_1.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_1.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Source.Epoch, + Root: attesterSlashing.Attestation_1.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_1.Data.Target.Epoch, + Root: attesterSlashing.Attestation_1.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_1.Signature, + }, + Attestation_2: ðpbv1.IndexedAttestation{ + AttestingIndices: attesterSlashing.Attestation_2.AttestingIndices, + Data: ðpbv1.AttestationData{ + Slot: attesterSlashing.Attestation_2.Data.Slot, + Index: attesterSlashing.Attestation_2.Data.CommitteeIndex, + BeaconBlockRoot: attesterSlashing.Attestation_2.Data.BeaconBlockRoot, + Source: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Source.Epoch, + Root: attesterSlashing.Attestation_2.Data.Source.Root, + }, + Target: ðpbv1.Checkpoint{ + Epoch: attesterSlashing.Attestation_2.Data.Target.Epoch, + Root: attesterSlashing.Attestation_2.Data.Target.Root, + }, + }, + Signature: attesterSlashing.Attestation_2.Signature, + }, + }, + }, + SyncAggregate: ðpbv1.SyncAggregate{ + SyncCommitteeBits: []byte{170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + SyncCommitteeSignature: []byte{153, 51, 238, 112, 158, 23, 41, 26, 18, 53, 3, 111, 57, 180, 45, 131, 90, 249, 28, 23, 153, 188, 171, 204, 45, 180, 133, 236, 47, 203, 119, 132, 162, 17, 61, 60, 122, 161, 45, 136, 130, 174, 120, 60, 64, 144, 6, 34, 24, 87, 41, 77, 16, 223, 36, 125, 80, 185, 178, 234, 74, 184, 196, 45, 242, 47, 124, 178, 83, 65, 106, 26, 179, 178, 27, 4, 72, 79, 191, 128, 114, 51, 246, 147, 3, 55, 210, 64, 148, 78, 144, 45, 97, 182, 157, 206}, + }, + ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeader{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: nil, + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: []byte{127, 254, 36, 30, 166, 1, 135, 253, 176, 24, 123, 250, 34, 222, 53, 209, 249, 190, 215, 171, 6, 29, 148, 1, 253, 71, 227, 74, 84, 251, 237, 225}, + }, + }, } - assert.DeepEqual(t, expectedBits, blk.Body.SyncAggregate.SyncCommitteeBits) - assert.DeepEqual(t, aggregatedSig, blk.Body.SyncAggregate.SyncCommitteeSignature) + expectedData, err := expectedBlock.MarshalSSZ() + assert.NoError(t, err) + assert.DeepEqual(t, expectedData, resp.Data) }) } @@ -1558,6 +2727,17 @@ func TestProduceBlindedBlock_SyncNotReady(t *testing.T) { assert.ErrorContains(t, "Syncing to latest head, not ready to respond", err) } +func TestProduceBlindedBlockSSZ_SyncNotReady(t *testing.T) { + chainService := &mockChain.ChainService{} + vs := &Server{ + SyncChecker: &mockSync.Sync{IsSyncing: true}, + HeadFetcher: chainService, + TimeFetcher: chainService, + } + _, err := vs.ProduceBlindedBlockSSZ(context.Background(), ðpbv1.ProduceBlockRequest{}) + assert.ErrorContains(t, "Syncing to latest head, not ready to respond", err) +} + func TestProduceAttestationData(t *testing.T) { block := util.NewBeaconBlock() block.Block.Slot = 3*params.BeaconConfig().SlotsPerEpoch + 1 @@ -1655,50 +2835,50 @@ func TestGetAggregateAttestation(t *testing.T) { }, Signature: sig1, } - root2_1 := bytesutil.PadTo([]byte("root2_1"), 32) - sig2_1 := bytesutil.PadTo([]byte("sig2_1"), fieldparams.BLSSignatureLength) - attSlot2_1 := ðpbalpha.Attestation{ + root21 := bytesutil.PadTo([]byte("root2_1"), 32) + sig21 := bytesutil.PadTo([]byte("sig2_1"), fieldparams.BLSSignatureLength) + attslot21 := ðpbalpha.Attestation{ AggregationBits: []byte{0, 1, 1}, Data: ðpbalpha.AttestationData{ Slot: 2, CommitteeIndex: 2, - BeaconBlockRoot: root2_1, + BeaconBlockRoot: root21, Source: ðpbalpha.Checkpoint{ Epoch: 1, - Root: root2_1, + Root: root21, }, Target: ðpbalpha.Checkpoint{ Epoch: 1, - Root: root2_1, + Root: root21, }, }, - Signature: sig2_1, + Signature: sig21, } - root2_2 := bytesutil.PadTo([]byte("root2_2"), 32) - sig2_2 := bytesutil.PadTo([]byte("sig2_2"), fieldparams.BLSSignatureLength) - attSlot2_2 := ðpbalpha.Attestation{ + root22 := bytesutil.PadTo([]byte("root2_2"), 32) + sig22 := bytesutil.PadTo([]byte("sig2_2"), fieldparams.BLSSignatureLength) + attslot22 := ðpbalpha.Attestation{ AggregationBits: []byte{0, 1, 1, 1}, Data: ðpbalpha.AttestationData{ Slot: 2, CommitteeIndex: 3, - BeaconBlockRoot: root2_2, + BeaconBlockRoot: root22, Source: ðpbalpha.Checkpoint{ Epoch: 1, - Root: root2_2, + Root: root22, }, Target: ðpbalpha.Checkpoint{ Epoch: 1, - Root: root2_2, + Root: root22, }, }, - Signature: sig2_2, + Signature: sig22, } vs := &Server{ - AttestationsPool: &mock.PoolMock{AggregatedAtts: []*ethpbalpha.Attestation{attSlot1, attSlot2_1, attSlot2_2}}, + AttestationsPool: &mock.PoolMock{AggregatedAtts: []*ethpbalpha.Attestation{attSlot1, attslot21, attslot22}}, } t.Run("OK", func(t *testing.T) { - reqRoot, err := attSlot2_2.Data.HashTreeRoot() + reqRoot, err := attslot22.Data.HashTreeRoot() require.NoError(t, err) req := ðpbv1.AggregateAttestationRequest{ AttestationDataRoot: reqRoot[:], @@ -1709,16 +2889,16 @@ func TestGetAggregateAttestation(t *testing.T) { require.NotNil(t, att) require.NotNil(t, att.Data) assert.DeepEqual(t, bitfield.Bitlist{0, 1, 1, 1}, att.Data.AggregationBits) - assert.DeepEqual(t, sig2_2, att.Data.Signature) + assert.DeepEqual(t, sig22, att.Data.Signature) assert.Equal(t, types.Slot(2), att.Data.Data.Slot) assert.Equal(t, types.CommitteeIndex(3), att.Data.Data.Index) - assert.DeepEqual(t, root2_2, att.Data.Data.BeaconBlockRoot) + assert.DeepEqual(t, root22, att.Data.Data.BeaconBlockRoot) require.NotNil(t, att.Data.Data.Source) assert.Equal(t, types.Epoch(1), att.Data.Data.Source.Epoch) - assert.DeepEqual(t, root2_2, att.Data.Data.Source.Root) + assert.DeepEqual(t, root22, att.Data.Data.Source.Root) require.NotNil(t, att.Data.Data.Target) assert.Equal(t, types.Epoch(1), att.Data.Data.Target.Epoch) - assert.DeepEqual(t, root2_2, att.Data.Data.Target.Root) + assert.DeepEqual(t, root22, att.Data.Data.Target.Root) }) t.Run("No matching attestation", func(t *testing.T) { @@ -2596,5 +3776,4 @@ func TestPrepareBeaconProposer(t *testing.T) { require.Equal(t, common.BytesToAddress(tt.args.request.Recipients[0].FeeRecipient), address) }) } - } diff --git a/beacon-chain/rpc/prysm/v1alpha1/debug/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/debug/BUILD.bazel index 51c0e3544901..52792ed01265 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/debug/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/debug/BUILD.bazel @@ -50,7 +50,6 @@ go_test( "//beacon-chain/db/testing:go_default_library", "//beacon-chain/forkchoice/protoarray:go_default_library", "//beacon-chain/p2p/testing:go_default_library", - "//beacon-chain/state:go_default_library", "//beacon-chain/state/stategen:go_default_library", "//beacon-chain/state/stategen/mock:go_default_library", "//config/fieldparams:go_default_library", diff --git a/beacon-chain/rpc/prysm/v1alpha1/debug/state_test.go b/beacon-chain/rpc/prysm/v1alpha1/debug/state_test.go index d6cad2adc115..d8534d4faf54 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/debug/state_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/debug/state_test.go @@ -7,7 +7,6 @@ import ( mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" mockstategen "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen/mock" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" @@ -83,10 +82,9 @@ func TestServer_GetBeaconState(t *testing.T) { Slot: slot + 1, }, } - state := state.BeaconState(st) // since we are requesting a state at a skipped slot, use the same method as stategen // to advance to the pre-state for the subsequent slot - state, err = stategen.ReplayProcessSlots(ctx, state, slot+1) + state, err := stategen.ReplayProcessSlots(ctx, st, slot+1) require.NoError(t, err) wanted, err = state.MarshalSSZ() require.NoError(t, err) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go index 3614c1d5bd24..3637e7e2723e 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go @@ -178,9 +178,10 @@ func TestGetAttestationData_Optimistic(t *testing.T) { params.OverrideBeaconConfig(cfg) as := &Server{ - SyncChecker: &mockSync.Sync{}, - TimeFetcher: &mock.ChainService{Genesis: time.Now()}, - HeadFetcher: &mock.ChainService{Optimistic: true}, + SyncChecker: &mockSync.Sync{}, + TimeFetcher: &mock.ChainService{Genesis: time.Now()}, + HeadFetcher: &mock.ChainService{}, + OptimisticModeFetcher: &mock.ChainService{Optimistic: true}, } _, err := as.GetAttestationData(context.Background(), ðpb.AttestationDataRequest{}) s, ok := status.FromError(err) @@ -191,10 +192,11 @@ func TestGetAttestationData_Optimistic(t *testing.T) { beaconState, err := util.NewBeaconState() require.NoError(t, err) as = &Server{ - SyncChecker: &mockSync.Sync{}, - TimeFetcher: &mock.ChainService{Genesis: time.Now()}, - HeadFetcher: &mock.ChainService{Optimistic: false, State: beaconState}, - AttestationCache: cache.NewAttestationCache(), + SyncChecker: &mockSync.Sync{}, + TimeFetcher: &mock.ChainService{Genesis: time.Now()}, + HeadFetcher: &mock.ChainService{Optimistic: false, State: beaconState}, + OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, + AttestationCache: cache.NewAttestationCache(), } _, err = as.GetAttestationData(context.Background(), ðpb.AttestationDataRequest{}) require.NoError(t, err) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go index 8c25adaaf06a..bdedd0759dac 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go @@ -120,18 +120,20 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx feeRecipient := params.BeaconConfig().DefaultFeeRecipient recipient, err := vs.BeaconDB.FeeRecipientByValidatorID(ctx, vIdx) - burnAddr := bytesutil.PadTo([]byte{}, fieldparams.FeeRecipientLength) switch err == nil { case true: feeRecipient = recipient case errors.As(err, kv.ErrNotFoundFeeRecipient): // If fee recipient is not found in DB and not set from beacon node CLI, // use the burn address. - if bytes.Equal(feeRecipient.Bytes(), burnAddr) { + if feeRecipient.String() == fieldparams.EthBurnAddressHex { logrus.WithFields(logrus.Fields{ "validatorIndex": vIdx, - "burnAddress": burnAddr, - }).Error("Fee recipient not set. Using burn address") + "burnAddress": fieldparams.EthBurnAddressHex, + }).Warn("Fee recipient is currently using the burn address, " + + "you will not be rewarded transaction fees on this setting. " + + "Please set a different eth address as the fee recipient. " + + "Please refer to our documentation for instructions") } default: return nil, errors.Wrap(err, "could not get fee recipient in db") diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index 913beb9dcbb4..fac0e4d2bae5 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -2413,7 +2413,7 @@ func TestProposer_GetBeaconBlock_BellatrixEpoch(t *testing.T) { assert.DeepEqual(t, randaoReveal, bellatrixBlk.Bellatrix.Body.RandaoReveal, "Expected block to have correct randao reveal") assert.DeepEqual(t, req.Graffiti, bellatrixBlk.Bellatrix.Body.Graffiti, "Expected block to have correct Graffiti") - require.LogsContain(t, hook, "Fee recipient not set. Using burn address") + require.LogsContain(t, hook, "Fee recipient is currently using the burn address") require.DeepEqual(t, payload, bellatrixBlk.Bellatrix.Body.ExecutionPayload) // Payload should equal. // Operator sets default fee recipient to not be burned through beacon node cli. @@ -2424,7 +2424,7 @@ func TestProposer_GetBeaconBlock_BellatrixEpoch(t *testing.T) { params.OverrideBeaconConfig(cfg) _, err = proposerServer.GetBeaconBlock(ctx, req) require.NoError(t, err) - require.LogsDoNotContain(t, newHook, "Fee recipient not set. Using burn address") + require.LogsDoNotContain(t, newHook, "Fee recipient is currently using the burn address") } func TestProposer_GetBeaconBlock_Optimistic(t *testing.T) { @@ -2437,7 +2437,7 @@ func TestProposer_GetBeaconBlock_Optimistic(t *testing.T) { bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) require.NoError(t, err) - proposerServer := &Server{HeadFetcher: &mock.ChainService{Optimistic: true}, TimeFetcher: &mock.ChainService{}} + proposerServer := &Server{OptimisticModeFetcher: &mock.ChainService{Optimistic: true}, TimeFetcher: &mock.ChainService{}} req := ðpb.BlockRequest{ Slot: bellatrixSlot + 1, } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go index 2d94b6f39480..80bad12ff7d8 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go @@ -52,6 +52,7 @@ type Server struct { DepositFetcher depositcache.DepositFetcher ChainStartFetcher powchain.ChainStartFetcher Eth1InfoFetcher powchain.ChainInfoFetcher + OptimisticModeFetcher blockchain.OptimisticModeFetcher SyncChecker sync.Checker StateNotifier statefeed.Notifier BlockNotifier blockfeed.Notifier diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/status.go b/beacon-chain/rpc/prysm/v1alpha1/validator/status.go index 3b0c6ebe4dc1..e74f76007741 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/status.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/status.go @@ -255,7 +255,7 @@ func (vs *Server) optimisticStatus(ctx context.Context) error { if slots.ToEpoch(vs.TimeFetcher.CurrentSlot()) < params.BeaconConfig().BellatrixForkEpoch { return nil } - optimistic, err := vs.HeadFetcher.IsOptimistic(ctx) + optimistic, err := vs.OptimisticModeFetcher.IsOptimistic(ctx) if err != nil { return status.Errorf(codes.Internal, "Could not determine if the node is a optimistic node: %v", err) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/status_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/status_test.go index c0a4764c8182..287df9b9258d 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/status_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/status_test.go @@ -603,7 +603,7 @@ func TestActivationStatus_OK(t *testing.T) { } func TestOptimisticStatus(t *testing.T) { - server := &Server{HeadFetcher: &mockChain.ChainService{}, TimeFetcher: &mockChain.ChainService{}} + server := &Server{OptimisticModeFetcher: &mockChain.ChainService{}, TimeFetcher: &mockChain.ChainService{}} err := server.optimisticStatus(context.Background()) require.NoError(t, err) @@ -612,14 +612,14 @@ func TestOptimisticStatus(t *testing.T) { cfg.BellatrixForkEpoch = 2 params.OverrideBeaconConfig(cfg) - server = &Server{HeadFetcher: &mockChain.ChainService{Optimistic: true}, TimeFetcher: &mockChain.ChainService{}} + server = &Server{OptimisticModeFetcher: &mockChain.ChainService{Optimistic: true}, TimeFetcher: &mockChain.ChainService{}} err = server.optimisticStatus(context.Background()) s, ok := status.FromError(err) require.Equal(t, true, ok) require.DeepEqual(t, codes.Unavailable, s.Code()) require.ErrorContains(t, errOptimisticMode.Error(), err) - server = &Server{HeadFetcher: &mockChain.ChainService{Optimistic: false}, TimeFetcher: &mockChain.ChainService{}} + server = &Server{OptimisticModeFetcher: &mockChain.ChainService{Optimistic: false}, TimeFetcher: &mockChain.ChainService{}} err = server.optimisticStatus(context.Background()) require.NoError(t, err) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/sync_committee_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/sync_committee_test.go index 208d6b66c94f..717d730cc87c 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/sync_committee_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/sync_committee_test.go @@ -42,8 +42,9 @@ func TestGetSyncMessageBlockRoot_Optimistic(t *testing.T) { params.OverrideBeaconConfig(cfg) server := &Server{ - HeadFetcher: &mock.ChainService{Optimistic: true}, - TimeFetcher: &mock.ChainService{Genesis: time.Now()}, + HeadFetcher: &mock.ChainService{}, + TimeFetcher: &mock.ChainService{Genesis: time.Now()}, + OptimisticModeFetcher: &mock.ChainService{Optimistic: true}, } _, err := server.GetSyncMessageBlockRoot(context.Background(), &emptypb.Empty{}) s, ok := status.FromError(err) @@ -52,8 +53,9 @@ func TestGetSyncMessageBlockRoot_Optimistic(t *testing.T) { require.ErrorContains(t, errOptimisticMode.Error(), err) server = &Server{ - HeadFetcher: &mock.ChainService{Optimistic: false}, - TimeFetcher: &mock.ChainService{Genesis: time.Now()}, + HeadFetcher: &mock.ChainService{}, + TimeFetcher: &mock.ChainService{Genesis: time.Now()}, + OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, } _, err = server.GetSyncMessageBlockRoot(context.Background(), &emptypb.Empty{}) require.NoError(t, err) diff --git a/beacon-chain/rpc/service.go b/beacon-chain/rpc/service.go index f5140d44e9aa..31b4e01fcf88 100644 --- a/beacon-chain/rpc/service.go +++ b/beacon-chain/rpc/service.go @@ -113,6 +113,7 @@ type Config struct { MaxMsgSize int ExecutionEngineCaller powchain.EngineCaller ProposerIdsCache *cache.ProposerPayloadIDsCache + OptimisticModeFetcher blockchain.OptimisticModeFetcher } // NewService instantiates a new RPC service instance that will @@ -200,6 +201,7 @@ func (s *Service) Start() { DepositFetcher: s.cfg.DepositFetcher, ChainStartFetcher: s.cfg.ChainStartFetcher, Eth1InfoFetcher: s.cfg.POWChainService, + OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, SyncChecker: s.cfg.SyncService, StateNotifier: s.cfg.StateNotifier, BlockNotifier: s.cfg.BlockNotifier, @@ -234,7 +236,8 @@ func (s *Service) Start() { StateGenService: s.cfg.StateGen, ReplayerBuilder: ch, }, - SyncCommitteePool: s.cfg.SyncCommitteeObjectPool, + OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, + SyncCommitteePool: s.cfg.SyncCommitteeObjectPool, } nodeServer := &nodev1alpha1.Server{ @@ -304,6 +307,7 @@ func (s *Service) Start() { StateGenService: s.cfg.StateGen, ReplayerBuilder: ch, }, + OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, HeadFetcher: s.cfg.HeadFetcher, VoluntaryExitsPool: s.cfg.ExitPool, V1Alpha1ValidatorServer: validatorServer, @@ -342,6 +346,7 @@ func (s *Service) Start() { StateGenService: s.cfg.StateGen, ReplayerBuilder: ch, }, + OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, } ethpbv1alpha1.RegisterDebugServer(s.grpcServer, debugServer) ethpbservice.RegisterBeaconDebugServer(s.grpcServer, debugServerV1) diff --git a/beacon-chain/rpc/testutil/mock_powchain_info_fetcher.go b/beacon-chain/rpc/testutil/mock_powchain_info_fetcher.go index 396b1388de26..e17dd86f55b8 100644 --- a/beacon-chain/rpc/testutil/mock_powchain_info_fetcher.go +++ b/beacon-chain/rpc/testutil/mock_powchain_info_fetcher.go @@ -4,7 +4,7 @@ import ( "math/big" ) -// MockGenesisTimeFetcher is a fake implementation of the powchain.ChainInfoFetcher +// MockPOWChainInfoFetcher is a fake implementation of the powchain.ChainInfoFetcher type MockPOWChainInfoFetcher struct { CurrEndpoint string CurrError error @@ -12,11 +12,11 @@ type MockPOWChainInfoFetcher struct { Errors []error } -func (m *MockPOWChainInfoFetcher) Eth2GenesisPowchainInfo() (uint64, *big.Int) { +func (*MockPOWChainInfoFetcher) Eth2GenesisPowchainInfo() (uint64, *big.Int) { return uint64(0), &big.Int{} } -func (m *MockPOWChainInfoFetcher) IsConnectedToETH1() bool { +func (*MockPOWChainInfoFetcher) IsConnectedToETH1() bool { return true } diff --git a/beacon-chain/slasher/service.go b/beacon-chain/slasher/service.go index 8425ccafff09..0c5f4dc2ac3b 100644 --- a/beacon-chain/slasher/service.go +++ b/beacon-chain/slasher/service.go @@ -175,7 +175,6 @@ func (s *Service) waitForChainInitialization() { stateChannel := make(chan *feed.Event, 1) stateSub := s.serviceCfg.StateNotifier.StateFeed().Subscribe(stateChannel) defer stateSub.Unsubscribe() - defer close(stateChannel) for { select { case stateEvent := <-stateChannel: diff --git a/beacon-chain/state/fieldtrie/field_trie.go b/beacon-chain/state/fieldtrie/field_trie.go index 62a713477cac..9932a0fac37d 100644 --- a/beacon-chain/state/fieldtrie/field_trie.go +++ b/beacon-chain/state/fieldtrie/field_trie.go @@ -134,7 +134,7 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b } // We remove the duplicates here in order to prevent // duplicated insertions into the trie. - newIndices := []uint64{} + var newIndices []uint64 indexExists := make(map[uint64]bool) newRoots := make([][32]byte, 0, len(fieldRoots)/iNumOfElems) for i, idx := range indices { diff --git a/beacon-chain/state/fieldtrie/field_trie_helpers.go b/beacon-chain/state/fieldtrie/field_trie_helpers.go index 63afe34feb9b..4b2aca6676a7 100644 --- a/beacon-chain/state/fieldtrie/field_trie_helpers.go +++ b/beacon-chain/state/fieldtrie/field_trie_helpers.go @@ -374,7 +374,7 @@ func handleBalanceSlice(val, indices []uint64, convertAll bool) ([][32]byte, err if err != nil { return nil, err } - roots := [][32]byte{} + var roots [][32]byte for _, idx := range indices { // We split the indexes into their relevant groups. Balances // are compressed according to 4 values -> 1 chunk. diff --git a/beacon-chain/state/state-native/BUILD.bazel b/beacon-chain/state/state-native/BUILD.bazel index 70508e05aff0..0b2f870ca37f 100644 --- a/beacon-chain/state/state-native/BUILD.bazel +++ b/beacon-chain/state/state-native/BUILD.bazel @@ -68,6 +68,7 @@ go_library( "//encoding/ssz:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", + "@com_github_ferranbt_fastssz//:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@io_opencensus_go//trace:go_default_library", diff --git a/beacon-chain/state/state-native/custom-types/historical_roots.go b/beacon-chain/state/state-native/custom-types/historical_roots.go index aea021fc44fa..5965bd70c581 100644 --- a/beacon-chain/state/state-native/custom-types/historical_roots.go +++ b/beacon-chain/state/state-native/custom-types/historical_roots.go @@ -10,7 +10,7 @@ var _ fssz.HashRoot = (HistoricalRoots)([][32]byte{}) var _ fssz.Marshaler = (*HistoricalRoots)(nil) var _ fssz.Unmarshaler = (*HistoricalRoots)(nil) -// Byte32 represents a 32 bytes HistoricalRoots object in Ethereum beacon chain consensus. +// HistoricalRoots represents a 32 bytes HistoricalRoots object in Ethereum beacon chain consensus. type HistoricalRoots [][32]byte // HashTreeRoot returns calculated hash root. diff --git a/beacon-chain/state/state-native/getters_validator.go b/beacon-chain/state/state-native/getters_validator.go index 9a2706e208c2..8f51d94f6ac7 100644 --- a/beacon-chain/state/state-native/getters_validator.go +++ b/beacon-chain/state/state-native/getters_validator.go @@ -154,7 +154,8 @@ func (b *BeaconState) NumValidators() int { } // ReadFromEveryValidator reads values from every validator and applies it to the provided function. -// Warning: This method is potentially unsafe, as it exposes the actual validator registry. +// +// WARNING: This method is potentially unsafe, as it exposes the actual validator registry. func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { if b.validators == nil { return errors.New("nil validators in state") diff --git a/beacon-chain/state/state-native/ssz.go b/beacon-chain/state/state-native/ssz.go index 1c3ab7ea4cfb..f7d998823926 100644 --- a/beacon-chain/state/state-native/ssz.go +++ b/beacon-chain/state/state-native/ssz.go @@ -1,36 +1,18 @@ package state_native import ( + ssz "github.com/ferranbt/fastssz" "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/runtime/version" ) var errAssertionFailed = errors.New("failed to convert interface to proto state") -var errUnsupportedVersion = errors.New("unsupported beacon state version") func (b *BeaconState) MarshalSSZ() ([]byte, error) { proto := b.ToProto() - switch b.Version() { - case version.Phase0: - s, ok := proto.(*ethpb.BeaconState) - if !ok { - return nil, errAssertionFailed - } - return s.MarshalSSZ() - case version.Altair: - s, ok := proto.(*ethpb.BeaconStateAltair) - if !ok { - return nil, errAssertionFailed - } - return s.MarshalSSZ() - case version.Bellatrix: - s, ok := proto.(*ethpb.BeaconStateBellatrix) - if !ok { - return nil, errAssertionFailed - } - return s.MarshalSSZ() - default: - return nil, errUnsupportedVersion + + s, ok := proto.(ssz.Marshaler) + if !ok { + return nil, errAssertionFailed } + return s.MarshalSSZ() } diff --git a/beacon-chain/state/state-native/state_trie.go b/beacon-chain/state/state-native/state_trie.go index bd88d3a947ea..87ac6f84e1cb 100644 --- a/beacon-chain/state/state-native/state_trie.go +++ b/beacon-chain/state/state-native/state_trie.go @@ -541,6 +541,7 @@ func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { } // Initializes the Merkle layers for the beacon state if they are empty. +// // WARNING: Caller must acquire the mutex before using. func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { if len(b.merkleLayers) > 0 { @@ -565,6 +566,7 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { } // Recomputes the Merkle layers for the dirty fields in the state. +// // WARNING: Caller must acquire the mutex before using. func (b *BeaconState) recomputeDirtyFields(ctx context.Context) error { for field := range b.dirtyFields { diff --git a/beacon-chain/state/stategen/mock/mock.go b/beacon-chain/state/stategen/mock/mock.go index ba99f895dbbc..0441e5841413 100644 --- a/beacon-chain/state/stategen/mock/mock.go +++ b/beacon-chain/state/stategen/mock/mock.go @@ -23,7 +23,7 @@ func NewMockService() *MockStateManager { } } -// StateByRootIfCachedNoCopy +// StateByRootIfCachedNoCopy -- func (_ *MockStateManager) StateByRootIfCachedNoCopy(_ [32]byte) state.BeaconState { panic("implement me") } diff --git a/beacon-chain/state/v1/BUILD.bazel b/beacon-chain/state/v1/BUILD.bazel index 61a333741874..cbd92af4f056 100644 --- a/beacon-chain/state/v1/BUILD.bazel +++ b/beacon-chain/state/v1/BUILD.bazel @@ -66,13 +66,16 @@ go_test( "readonly_validator_test.go", "references_test.go", "setters_attestation_test.go", + "state_fuzz_test.go", "state_test.go", "state_trie_test.go", "types_test.go", ], embed = [":go_default_library"], deps = [ + "//beacon-chain/core/transition:go_default_library", "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/testing:go_default_library", "//beacon-chain/state/types:go_default_library", @@ -80,6 +83,7 @@ go_test( "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//container/trie:go_default_library", + "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/interop:go_default_library", diff --git a/beacon-chain/state/v1/getters_attestation.go b/beacon-chain/state/v1/getters_attestation.go index e7e3bd6901d4..fbdde3cbc41c 100644 --- a/beacon-chain/state/v1/getters_attestation.go +++ b/beacon-chain/state/v1/getters_attestation.go @@ -7,7 +7,7 @@ import ( // PreviousEpochAttestations corresponding to blocks on the beacon chain. func (b *BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } if b.state.PreviousEpochAttestations == nil { return nil, nil @@ -32,7 +32,7 @@ func (b *BeaconState) previousEpochAttestations() []*ethpb.PendingAttestation { // CurrentEpochAttestations corresponding to blocks on the beacon chain. func (b *BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } if b.state.CurrentEpochAttestations == nil { return nil, nil diff --git a/beacon-chain/state/v1/getters_test.go b/beacon-chain/state/v1/getters_test.go index 205ca8e63129..474dbc503f7e 100644 --- a/beacon-chain/state/v1/getters_test.go +++ b/beacon-chain/state/v1/getters_test.go @@ -56,9 +56,9 @@ func TestNilState_NoPanic(t *testing.T) { _ = st.RandaoMixesLength() _ = st.Slashings() _, err = st.PreviousEpochAttestations() - require.NoError(t, err) + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.CurrentEpochAttestations() - require.NoError(t, err) + require.ErrorIs(t, ErrNilInnerState, err) _ = st.JustificationBits() _ = st.PreviousJustifiedCheckpoint() _ = st.CurrentJustifiedCheckpoint() diff --git a/beacon-chain/state/v1/getters_validator.go b/beacon-chain/state/v1/getters_validator.go index 74ef91a8abea..8e5c2d264658 100644 --- a/beacon-chain/state/v1/getters_validator.go +++ b/beacon-chain/state/v1/getters_validator.go @@ -174,7 +174,8 @@ func (b *BeaconState) NumValidators() int { } // ReadFromEveryValidator reads values from every validator and applies it to the provided function. -// Warning: This method is potentially unsafe, as it exposes the actual validator registry. +// +// WARNING: This method is potentially unsafe, as it exposes the actual validator registry. func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { if !b.hasInnerState() { return ErrNilInnerState diff --git a/beacon-chain/state/v1/state_fuzz_test.go b/beacon-chain/state/v1/state_fuzz_test.go new file mode 100644 index 000000000000..96ee9ae271b6 --- /dev/null +++ b/beacon-chain/state/v1/state_fuzz_test.go @@ -0,0 +1,88 @@ +//go:build go1.18 +// +build go1.18 + +package v1_test + +import ( + "context" + "testing" + + coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" + native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + types "github.com/prysmaticlabs/prysm/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/crypto/rand" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func FuzzV1StateHashTreeRoot(f *testing.F) { + gState, _ := util.DeterministicGenesisState(f, 100) + output, err := gState.MarshalSSZ() + assert.NoError(f, err) + randPool := make([]byte, 100) + _, err = rand.NewDeterministicGenerator().Read(randPool) + assert.NoError(f, err) + f.Add(randPool, uint64(10)) + f.Fuzz(func(t *testing.T, diffBuffer []byte, slotsToTransition uint64) { + stateSSZ := bytesutil.SafeCopyBytes(output) + for i := 0; i < len(diffBuffer); i += 9 { + if i+8 >= len(diffBuffer) { + return + } + num := bytesutil.BytesToUint64BigEndian(diffBuffer[i : i+8]) + num %= uint64(len(diffBuffer)) + // Perform a XOR on the byte of the selected index. + stateSSZ[num] ^= diffBuffer[i+8] + } + pbState := ðpb.BeaconState{} + err := pbState.UnmarshalSSZ(stateSSZ) + if err != nil { + return + } + nativeState, err := native.InitializeFromProtoPhase0(pbState) + assert.NoError(t, err) + + slotsToTransition %= 100 + stateObj, err := v1.InitializeFromProtoUnsafe(pbState) + assert.NoError(t, err) + for stateObj.Slot() < types.Slot(slotsToTransition) { + stateObj, err = coreState.ProcessSlots(context.Background(), stateObj, stateObj.Slot()+1) + assert.NoError(t, err) + stateObj.Copy() + + nativeState, err = coreState.ProcessSlots(context.Background(), nativeState, nativeState.Slot()+1) + assert.NoError(t, err) + nativeState.Copy() + } + assert.NoError(t, err) + // Perform a cold HTR calculation by initializing a new state. + innerState, ok := stateObj.InnerStateUnsafe().(*ethpb.BeaconState) + assert.Equal(t, true, ok, "inner state is a not a beacon state proto") + newState, err := v1.InitializeFromProtoUnsafe(innerState) + assert.NoError(t, err) + + newRt, newErr := newState.HashTreeRoot(context.Background()) + rt, err := stateObj.HashTreeRoot(context.Background()) + nativeRt, nativeErr := nativeState.HashTreeRoot(context.Background()) + + assert.Equal(t, newErr != nil, err != nil) + assert.Equal(t, newErr != nil, nativeErr != nil) + if err == nil { + assert.Equal(t, rt, newRt) + assert.Equal(t, rt, nativeRt) + } + + newSSZ, newErr := newState.MarshalSSZ() + stateObjSSZ, err := stateObj.MarshalSSZ() + nativeSSZ, nativeErr := nativeState.MarshalSSZ() + assert.Equal(t, newErr != nil, err != nil) + assert.Equal(t, newErr != nil, nativeErr != nil) + if err == nil { + assert.DeepEqual(t, newSSZ, stateObjSSZ) + assert.DeepEqual(t, newSSZ, nativeSSZ) + } + }) +} diff --git a/beacon-chain/state/v1/state_trie.go b/beacon-chain/state/v1/state_trie.go index c0060c0a4bc3..7e9039240b88 100644 --- a/beacon-chain/state/v1/state_trie.go +++ b/beacon-chain/state/v1/state_trie.go @@ -213,6 +213,7 @@ func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { } // Initializes the Merkle layers for the beacon state if they are empty. +// // WARNING: Caller must acquire the mutex before using. func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { if len(b.merkleLayers) > 0 { @@ -229,6 +230,7 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { } // Recomputes the Merkle layers for the dirty fields in the state. +// // WARNING: Caller must acquire the mutex before using. func (b *BeaconState) recomputeDirtyFields(ctx context.Context) error { for field := range b.dirtyFields { diff --git a/beacon-chain/state/v2/BUILD.bazel b/beacon-chain/state/v2/BUILD.bazel index 5a6cf84b1736..0e51337f311f 100644 --- a/beacon-chain/state/v2/BUILD.bazel +++ b/beacon-chain/state/v2/BUILD.bazel @@ -66,11 +66,15 @@ go_test( "proofs_test.go", "references_test.go", "setters_test.go", + "state_fuzz_test.go", "state_trie_test.go", ], + data = glob(["testdata/**"]), embed = [":go_default_library"], deps = [ + "//beacon-chain/core/transition:go_default_library", "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/testing:go_default_library", "//beacon-chain/state/types:go_default_library", @@ -79,6 +83,7 @@ go_test( "//consensus-types/primitives:go_default_library", "//container/trie:go_default_library", "//crypto/bls:go_default_library", + "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", diff --git a/beacon-chain/state/v2/getters_participation.go b/beacon-chain/state/v2/getters_participation.go index 9d62b0f20336..6c90e12cb78a 100644 --- a/beacon-chain/state/v2/getters_participation.go +++ b/beacon-chain/state/v2/getters_participation.go @@ -3,7 +3,7 @@ package v2 // CurrentEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } if b.state.CurrentEpochParticipation == nil { return nil, nil @@ -18,7 +18,7 @@ func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { // PreviousEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } if b.state.PreviousEpochParticipation == nil { return nil, nil diff --git a/beacon-chain/state/v2/getters_sync_committee.go b/beacon-chain/state/v2/getters_sync_committee.go index 7717cf2b2adc..084b7a19c3f8 100644 --- a/beacon-chain/state/v2/getters_sync_committee.go +++ b/beacon-chain/state/v2/getters_sync_committee.go @@ -28,7 +28,7 @@ func (b *BeaconState) nextSyncCommittee() *ethpb.SyncCommittee { // CurrentSyncCommittee of the current sync committee in beacon chain state. func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } b.lock.RLock() @@ -44,7 +44,7 @@ func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { // NextSyncCommittee of the next sync committee in beacon chain state. func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } b.lock.RLock() diff --git a/beacon-chain/state/v2/getters_test.go b/beacon-chain/state/v2/getters_test.go index b70398aa84fb..8ccff4e626e5 100644 --- a/beacon-chain/state/v2/getters_test.go +++ b/beacon-chain/state/v2/getters_test.go @@ -8,6 +8,7 @@ import ( testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" ) func TestBeaconState_SlotDataRace(t *testing.T) { @@ -51,28 +52,28 @@ func TestNilState_NoPanic(t *testing.T) { _ = st.BalancesLength() _ = st.RandaoMixes() _, err = st.RandaoMixAtIndex(0) - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _ = st.RandaoMixesLength() _ = st.Slashings() _, err = st.CurrentEpochParticipation() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.PreviousEpochParticipation() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _ = st.JustificationBits() _ = err _ = st.PreviousJustifiedCheckpoint() _ = st.CurrentJustifiedCheckpoint() _ = st.FinalizedCheckpoint() _, err = st.CurrentEpochParticipation() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.PreviousEpochParticipation() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.InactivityScores() _ = err _, err = st.CurrentSyncCommittee() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.NextSyncCommittee() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) } func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { diff --git a/beacon-chain/state/v2/getters_validator.go b/beacon-chain/state/v2/getters_validator.go index d137fa10c412..1edf411f1781 100644 --- a/beacon-chain/state/v2/getters_validator.go +++ b/beacon-chain/state/v2/getters_validator.go @@ -175,7 +175,8 @@ func (b *BeaconState) NumValidators() int { } // ReadFromEveryValidator reads values from every validator and applies it to the provided function. -// Warning: This method is potentially unsafe, as it exposes the actual validator registry. +// +// WARNING: This method is potentially unsafe, as it exposes the actual validator registry. func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { if !b.hasInnerState() { return ErrNilInnerState diff --git a/beacon-chain/state/v2/state_fuzz_test.go b/beacon-chain/state/v2/state_fuzz_test.go new file mode 100644 index 000000000000..6a7a623202d7 --- /dev/null +++ b/beacon-chain/state/v2/state_fuzz_test.go @@ -0,0 +1,90 @@ +//go:build go1.18 +// +build go1.18 + +package v2_test + +import ( + "context" + "testing" + + coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" + native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + types "github.com/prysmaticlabs/prysm/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/crypto/rand" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func FuzzV2StateHashTreeRoot(f *testing.F) { + gState, _ := util.DeterministicGenesisStateAltair(f, 100) + output, err := gState.MarshalSSZ() + assert.NoError(f, err) + randPool := make([]byte, 100) + _, err = rand.NewDeterministicGenerator().Read(randPool) + assert.NoError(f, err) + f.Add(randPool, uint64(10)) + f.Fuzz(func(t *testing.T, diffBuffer []byte, slotsToTransition uint64) { + stateSSZ := bytesutil.SafeCopyBytes(output) + for i := 0; i < len(diffBuffer); i += 9 { + if i+8 >= len(diffBuffer) { + return + } + num := bytesutil.BytesToUint64BigEndian(diffBuffer[i : i+8]) + num %= uint64(len(diffBuffer)) + // Perform a XOR on the byte of the selected index. + stateSSZ[num] ^= diffBuffer[i+8] + } + pbState := ðpb.BeaconStateAltair{} + err := pbState.UnmarshalSSZ(stateSSZ) + if err != nil { + return + } + nativeState, err := native.InitializeFromProtoAltair(pbState) + if err != nil { + return + } + + slotsToTransition %= 100 + stateObj, err := v2.InitializeFromProtoUnsafe(pbState) + assert.NoError(t, err) + for stateObj.Slot() < types.Slot(slotsToTransition) { + stateObj, err = coreState.ProcessSlots(context.Background(), stateObj, stateObj.Slot()+1) + assert.NoError(t, err) + stateObj.Copy() + + nativeState, err = coreState.ProcessSlots(context.Background(), nativeState, nativeState.Slot()+1) + assert.NoError(t, err) + nativeState.Copy() + } + assert.NoError(t, err) + // Perform a cold HTR calculation by initializing a new state. + innerState, ok := stateObj.InnerStateUnsafe().(*ethpb.BeaconStateAltair) + assert.Equal(t, true, ok, "inner state is a not a beacon state altair proto") + newState, err := v2.InitializeFromProtoUnsafe(innerState) + assert.NoError(t, err) + + newRt, newErr := newState.HashTreeRoot(context.Background()) + rt, err := stateObj.HashTreeRoot(context.Background()) + nativeRt, nativeErr := nativeState.HashTreeRoot(context.Background()) + assert.Equal(t, newErr != nil, err != nil) + assert.Equal(t, newErr != nil, nativeErr != nil) + if err == nil { + assert.Equal(t, rt, newRt) + assert.Equal(t, rt, nativeRt) + } + + newSSZ, newErr := newState.MarshalSSZ() + stateObjSSZ, err := stateObj.MarshalSSZ() + nativeSSZ, nativeErr := nativeState.MarshalSSZ() + assert.Equal(t, newErr != nil, err != nil) + assert.Equal(t, newErr != nil, nativeErr != nil) + if err == nil { + assert.DeepEqual(t, newSSZ, stateObjSSZ) + assert.DeepEqual(t, newSSZ, nativeSSZ) + } + + }) +} diff --git a/beacon-chain/state/v2/state_trie.go b/beacon-chain/state/v2/state_trie.go index de79d257ea78..2728ea164f4b 100644 --- a/beacon-chain/state/v2/state_trie.go +++ b/beacon-chain/state/v2/state_trie.go @@ -218,6 +218,7 @@ func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { } // Initializes the Merkle layers for the beacon state if they are empty. +// // WARNING: Caller must acquire the mutex before using. func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { if len(b.merkleLayers) > 0 { @@ -234,6 +235,7 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { } // Recomputes the Merkle layers for the dirty fields in the state. +// // WARNING: Caller must acquire the mutex before using. func (b *BeaconState) recomputeDirtyFields(ctx context.Context) error { for field := range b.dirtyFields { diff --git a/beacon-chain/state/v2/testdata/fuzz/FuzzV2StateHashTreeRoot/52875ab39ad0eeec927085f3330d00508d015fe3c204b6bc6607296f64ec221c b/beacon-chain/state/v2/testdata/fuzz/FuzzV2StateHashTreeRoot/52875ab39ad0eeec927085f3330d00508d015fe3c204b6bc6607296f64ec221c new file mode 100644 index 000000000000..609d1ea9875d --- /dev/null +++ b/beacon-chain/state/v2/testdata/fuzz/FuzzV2StateHashTreeRoot/52875ab39ad0eeec927085f3330d00508d015fe3c204b6bc6607296f64ec221c @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("") +uint64(117) diff --git a/beacon-chain/state/v3/BUILD.bazel b/beacon-chain/state/v3/BUILD.bazel index c92c85f71455..edcff6926070 100644 --- a/beacon-chain/state/v3/BUILD.bazel +++ b/beacon-chain/state/v3/BUILD.bazel @@ -68,11 +68,14 @@ go_test( "proofs_test.go", "references_test.go", "setters_test.go", + "state_fuzz_test.go", "state_trie_test.go", ], embed = [":go_default_library"], deps = [ + "//beacon-chain/core/transition:go_default_library", "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/testing:go_default_library", "//beacon-chain/state/types:go_default_library", @@ -81,6 +84,7 @@ go_test( "//consensus-types/primitives:go_default_library", "//container/trie:go_default_library", "//crypto/bls:go_default_library", + "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", diff --git a/beacon-chain/state/v3/getters_participation.go b/beacon-chain/state/v3/getters_participation.go index 42358b01de1f..48acdbde53e8 100644 --- a/beacon-chain/state/v3/getters_participation.go +++ b/beacon-chain/state/v3/getters_participation.go @@ -3,7 +3,7 @@ package v3 // CurrentEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } if b.state.CurrentEpochParticipation == nil { return nil, nil @@ -18,7 +18,7 @@ func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { // PreviousEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } if b.state.PreviousEpochParticipation == nil { return nil, nil diff --git a/beacon-chain/state/v3/getters_payload_header.go b/beacon-chain/state/v3/getters_payload_header.go index bfbd893f25ac..584123d3d7c0 100644 --- a/beacon-chain/state/v3/getters_payload_header.go +++ b/beacon-chain/state/v3/getters_payload_header.go @@ -7,7 +7,7 @@ import ( // LatestExecutionPayloadHeader of the beacon state. func (b *BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } if b.state.LatestExecutionPayloadHeader == nil { return nil, nil diff --git a/beacon-chain/state/v3/getters_sync_committee.go b/beacon-chain/state/v3/getters_sync_committee.go index 38faf4ac1991..c554b1f1d33d 100644 --- a/beacon-chain/state/v3/getters_sync_committee.go +++ b/beacon-chain/state/v3/getters_sync_committee.go @@ -28,7 +28,7 @@ func (b *BeaconState) nextSyncCommittee() *ethpb.SyncCommittee { // CurrentSyncCommittee of the current sync committee in beacon chain state. func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } b.lock.RLock() @@ -44,7 +44,7 @@ func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { // NextSyncCommittee of the next sync committee in beacon chain state. func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { if !b.hasInnerState() { - return nil, nil + return nil, ErrNilInnerState } b.lock.RLock() diff --git a/beacon-chain/state/v3/getters_test.go b/beacon-chain/state/v3/getters_test.go index e91755771afa..58928b423802 100644 --- a/beacon-chain/state/v3/getters_test.go +++ b/beacon-chain/state/v3/getters_test.go @@ -8,6 +8,7 @@ import ( testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" ) func TestBeaconState_SlotDataRace(t *testing.T) { @@ -55,23 +56,26 @@ func TestNilState_NoPanic(t *testing.T) { _ = st.RandaoMixesLength() _ = st.Slashings() _, err = st.CurrentEpochParticipation() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.PreviousEpochParticipation() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _ = st.JustificationBits() _ = st.PreviousJustifiedCheckpoint() _ = st.CurrentJustifiedCheckpoint() _ = st.FinalizedCheckpoint() _, err = st.CurrentEpochParticipation() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.PreviousEpochParticipation() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.InactivityScores() _ = err _, err = st.CurrentSyncCommittee() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) _, err = st.NextSyncCommittee() - _ = err + require.ErrorIs(t, ErrNilInnerState, err) + _, err = st.LatestExecutionPayloadHeader() + require.ErrorIs(t, ErrNilInnerState, err) + } func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { diff --git a/beacon-chain/state/v3/getters_validator.go b/beacon-chain/state/v3/getters_validator.go index 6810581f7050..a1605ce9e856 100644 --- a/beacon-chain/state/v3/getters_validator.go +++ b/beacon-chain/state/v3/getters_validator.go @@ -175,7 +175,8 @@ func (b *BeaconState) NumValidators() int { } // ReadFromEveryValidator reads values from every validator and applies it to the provided function. -// Warning: This method is potentially unsafe, as it exposes the actual validator registry. +// +// WARNING: This method is potentially unsafe, as it exposes the actual validator registry. func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { if !b.hasInnerState() { return ErrNilInnerState diff --git a/beacon-chain/state/v3/state_fuzz_test.go b/beacon-chain/state/v3/state_fuzz_test.go new file mode 100644 index 000000000000..01fe3b3a6121 --- /dev/null +++ b/beacon-chain/state/v3/state_fuzz_test.go @@ -0,0 +1,90 @@ +//go:build go1.18 +// +build go1.18 + +package v3_test + +import ( + "context" + "testing" + + coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" + native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" + types "github.com/prysmaticlabs/prysm/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/crypto/rand" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func FuzzV3StateHashTreeRoot(f *testing.F) { + gState, _ := util.DeterministicGenesisStateBellatrix(f, 100) + output, err := gState.MarshalSSZ() + assert.NoError(f, err) + randPool := make([]byte, 100) + _, err = rand.NewDeterministicGenerator().Read(randPool) + assert.NoError(f, err) + f.Add(randPool, uint64(10)) + f.Fuzz(func(t *testing.T, diffBuffer []byte, slotsToTransition uint64) { + stateSSZ := bytesutil.SafeCopyBytes(output) + for i := 0; i < len(diffBuffer); i += 9 { + if i+8 >= len(diffBuffer) { + return + } + num := bytesutil.BytesToUint64BigEndian(diffBuffer[i : i+8]) + num %= uint64(len(diffBuffer)) + // Perform a XOR on the byte of the selected index. + stateSSZ[num] ^= diffBuffer[i+8] + } + pbState := ðpb.BeaconStateBellatrix{} + err := pbState.UnmarshalSSZ(stateSSZ) + if err != nil { + return + } + nativeState, err := native.InitializeFromProtoBellatrix(pbState) + if err != nil { + return + } + + slotsToTransition %= 100 + stateObj, err := v3.InitializeFromProtoUnsafe(pbState) + assert.NoError(t, err) + for stateObj.Slot() < types.Slot(slotsToTransition) { + stateObj, err = coreState.ProcessSlots(context.Background(), stateObj, stateObj.Slot()+1) + assert.NoError(t, err) + stateObj.Copy() + + nativeState, err = coreState.ProcessSlots(context.Background(), nativeState, nativeState.Slot()+1) + assert.NoError(t, err) + nativeState.Copy() + } + assert.NoError(t, err) + // Perform a cold HTR calculation by initializing a new state. + innerState, ok := stateObj.InnerStateUnsafe().(*ethpb.BeaconStateBellatrix) + assert.Equal(t, true, ok, "inner state is a not a beacon state bellatrix proto") + newState, err := v3.InitializeFromProtoUnsafe(innerState) + assert.NoError(t, err) + + newRt, newErr := newState.HashTreeRoot(context.Background()) + rt, err := stateObj.HashTreeRoot(context.Background()) + nativeRt, nativeErr := nativeState.HashTreeRoot(context.Background()) + assert.Equal(t, newErr != nil, err != nil) + assert.Equal(t, newErr != nil, nativeErr != nil) + if err == nil { + assert.Equal(t, rt, newRt) + assert.Equal(t, rt, nativeRt) + } + + newSSZ, newErr := newState.MarshalSSZ() + stateObjSSZ, err := stateObj.MarshalSSZ() + nativeSSZ, nativeErr := nativeState.MarshalSSZ() + assert.Equal(t, newErr != nil, err != nil) + assert.Equal(t, newErr != nil, nativeErr != nil) + if err == nil { + assert.DeepEqual(t, newSSZ, stateObjSSZ) + assert.DeepEqual(t, newSSZ, nativeSSZ) + } + + }) +} diff --git a/beacon-chain/state/v3/state_trie.go b/beacon-chain/state/v3/state_trie.go index 962e56910f51..5a4958eb1380 100644 --- a/beacon-chain/state/v3/state_trie.go +++ b/beacon-chain/state/v3/state_trie.go @@ -218,6 +218,7 @@ func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { } // Initializes the Merkle layers for the beacon state if they are empty. +// // WARNING: Caller must acquire the mutex before using. func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { if len(b.merkleLayers) > 0 { @@ -234,6 +235,7 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { } // Recomputes the Merkle layers for the dirty fields in the state. +// // WARNING: Caller must acquire the mutex before using. func (b *BeaconState) recomputeDirtyFields(_ context.Context) error { for field := range b.dirtyFields { diff --git a/beacon-chain/sync/BUILD.bazel b/beacon-chain/sync/BUILD.bazel index 3c4e990754ab..e6149f374134 100644 --- a/beacon-chain/sync/BUILD.bazel +++ b/beacon-chain/sync/BUILD.bazel @@ -149,6 +149,7 @@ go_test( "subscriber_beacon_blocks_test.go", "subscriber_test.go", "subscription_topic_handler_test.go", + "sync_fuzz_test.go", "sync_test.go", "utils_test.go", "validate_aggregate_proof_test.go", @@ -222,6 +223,7 @@ go_test( "@com_github_libp2p_go_libp2p_pubsub//:go_default_library", "@com_github_libp2p_go_libp2p_pubsub//pb:go_default_library", "@com_github_patrickmn_go_cache//:go_default_library", + "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", diff --git a/beacon-chain/sync/initial-sync/round_robin.go b/beacon-chain/sync/initial-sync/round_robin.go index eebdf0057434..bd4757b3073f 100644 --- a/beacon-chain/sync/initial-sync/round_robin.go +++ b/beacon-chain/sync/initial-sync/round_robin.go @@ -142,6 +142,7 @@ func (s *Service) processFetchedDataRegSync( blockReceiver := s.cfg.Chain.ReceiveBlock invalidBlocks := 0 + blksWithoutParentCount := 0 for _, blk := range data.blocks { if err := s.processBlock(ctx, genesis, blk, blockReceiver); err != nil { switch { @@ -149,7 +150,7 @@ func (s *Service) processFetchedDataRegSync( log.WithError(err).Debug("Block is not processed") invalidBlocks++ case errors.Is(err, errParentDoesNotExist): - log.WithError(err).Debug("Block is not processed") + blksWithoutParentCount++ invalidBlocks++ default: log.WithError(err).Warn("Block is not processed") @@ -157,6 +158,13 @@ func (s *Service) processFetchedDataRegSync( continue } } + if blksWithoutParentCount > 0 { + log.WithFields(logrus.Fields{ + "missingParent": fmt.Sprintf("%#x", data.blocks[0].Block().ParentRoot()), + "firstSlot": data.blocks[0].Block().Slot(), + "lastSlot": data.blocks[blksWithoutParentCount-1].Block().Slot(), + }).Debug("Could not process batch blocks due to missing parent") + } // Add more visible logging if all blocks cannot be processed. if len(data.blocks) == invalidBlocks { log.WithField("error", "Range had no valid blocks to process").Warn("Range is not processed") diff --git a/beacon-chain/sync/service.go b/beacon-chain/sync/service.go index 6fafec4daeaa..2ba50617e3eb 100644 --- a/beacon-chain/sync/service.go +++ b/beacon-chain/sync/service.go @@ -95,6 +95,7 @@ type blockchainService interface { blockchain.TimeFetcher blockchain.GenesisFetcher blockchain.CanonicalFetcher + blockchain.OptimisticModeFetcher blockchain.SlashingReceiver } diff --git a/beacon-chain/sync/subscriber_beacon_blocks.go b/beacon-chain/sync/subscriber_beacon_blocks.go index b12bc98ff2d7..410b79d803b7 100644 --- a/beacon-chain/sync/subscriber_beacon_blocks.go +++ b/beacon-chain/sync/subscriber_beacon_blocks.go @@ -33,7 +33,7 @@ func (s *Service) beaconBlockSubscriber(ctx context.Context, msg proto.Message) } if err := s.cfg.chain.ReceiveBlock(ctx, signed, root); err != nil { - if !errors.Is(err, powchain.ErrHTTPTimeout) && !errors.Is(blockchain.ErrUndefinedExecutionEngineError, err) { + if !errors.Is(err, powchain.ErrHTTPTimeout) && !errors.Is(err, blockchain.ErrUndefinedExecutionEngineError) { interop.WriteBlockToDisk(signed, true /*failed*/) s.setBadBlock(ctx, root) } diff --git a/beacon-chain/sync/subscriber_beacon_blocks_test.go b/beacon-chain/sync/subscriber_beacon_blocks_test.go index e1285f3c641b..98de24ede886 100644 --- a/beacon-chain/sync/subscriber_beacon_blocks_test.go +++ b/beacon-chain/sync/subscriber_beacon_blocks_test.go @@ -4,7 +4,9 @@ import ( "context" "testing" + "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/blockchain" chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" @@ -125,3 +127,21 @@ func TestService_BeaconBlockSubscribe_ExecutionEngineTimesOut(t *testing.T) { require.Equal(t, 0, len(s.badBlockCache.Keys())) require.Equal(t, 1, len(s.seenBlockCache.Keys())) } + +func TestService_BeaconBlockSubscribe_UndefinedEeError(t *testing.T) { + msg := "timeout" + err := errors.WithMessage(blockchain.ErrUndefinedExecutionEngineError, msg) + + s := &Service{ + cfg: &config{ + chain: &chainMock.ChainService{ + ReceiveBlockMockErr: err, + }, + }, + seenBlockCache: lruwrpr.New(10), + badBlockCache: lruwrpr.New(10), + } + require.ErrorIs(t, s.beaconBlockSubscriber(context.Background(), util.NewBeaconBlock()), blockchain.ErrUndefinedExecutionEngineError) + require.Equal(t, 0, len(s.badBlockCache.Keys())) + require.Equal(t, 1, len(s.seenBlockCache.Keys())) +} diff --git a/beacon-chain/sync/sync_fuzz_test.go b/beacon-chain/sync/sync_fuzz_test.go new file mode 100644 index 000000000000..b8811f4c40fa --- /dev/null +++ b/beacon-chain/sync/sync_fuzz_test.go @@ -0,0 +1,281 @@ +//go:build go1.18 +// +build go1.18 + +package sync + +import ( + "bytes" + "context" + "reflect" + "testing" + "time" + + "github.com/libp2p/go-libp2p-core/peer" + pubsub "github.com/libp2p/go-libp2p-pubsub" + pb "github.com/libp2p/go-libp2p-pubsub/pb" + gcache "github.com/patrickmn/go-cache" + mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" + "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" + dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" + "github.com/prysmaticlabs/prysm/beacon-chain/p2p" + p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" + mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" + lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/consensus-types/wrapper" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func FuzzValidateBeaconBlockPubSub_Phase0(f *testing.F) { + db := dbtest.SetupDB(f) + p := p2ptest.NewFuzzTestP2P() + ctx := context.Background() + beaconState, privKeys := util.DeterministicGenesisState(f, 100) + parentBlock := util.NewBeaconBlock() + wsb, err := wrapper.WrappedSignedBeaconBlock(parentBlock) + require.NoError(f, err) + require.NoError(f, db.SaveBlock(ctx, wsb)) + bRoot, err := parentBlock.Block.HashTreeRoot() + require.NoError(f, err) + require.NoError(f, db.SaveState(ctx, beaconState, bRoot)) + require.NoError(f, db.SaveStateSummary(ctx, ðpb.StateSummary{Root: bRoot[:]})) + copied := beaconState.Copy() + require.NoError(f, copied.SetSlot(1)) + proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied) + require.NoError(f, err) + msg := util.NewBeaconBlock() + msg.Block.ParentRoot = bRoot[:] + msg.Block.Slot = 1 + msg.Block.ProposerIndex = proposerIdx + msg.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, msg.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx]) + require.NoError(f, err) + + stateGen := stategen.New(db) + chainService := &mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Epoch: 0, + Root: make([]byte, 32), + }, + DB: db, + } + r := &Service{ + cfg: &config{ + beaconDB: db, + p2p: p, + initialSync: &mockSync.Sync{IsSyncing: false}, + chain: chainService, + blockNotifier: chainService.BlockNotifier(), + stateGen: stateGen, + }, + seenBlockCache: lruwrpr.New(10), + badBlockCache: lruwrpr.New(10), + slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), + seenPendingBlocks: make(map[[32]byte]bool), + } + buf := new(bytes.Buffer) + _, err = p.Encoding().EncodeGossip(buf, msg) + require.NoError(f, err) + topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(f, err) + topic = r.addDigestToTopic(topic, digest) + + f.Add("junk", []byte("junk"), buf.Bytes(), []byte(topic)) + f.Fuzz(func(t *testing.T, pid string, from, data, topic []byte) { + r.cfg.p2p = p2ptest.NewFuzzTestP2P() + r.rateLimiter = newRateLimiter(r.cfg.p2p) + cService := &mock.ChainService{ + Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot*10000000), 0), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Epoch: 0, + Root: make([]byte, 32), + }, + DB: db, + } + r.cfg.chain = cService + r.cfg.blockNotifier = cService.BlockNotifier() + strTop := string(topic) + msg := &pubsub.Message{ + Message: &pb.Message{ + From: from, + Data: data, + Topic: &strTop, + }, + } + _, err := r.validateBeaconBlockPubSub(ctx, peer.ID(pid), msg) + _ = err + }) +} + +func FuzzValidateBeaconBlockPubSub_Altair(f *testing.F) { + db := dbtest.SetupDB(f) + p := p2ptest.NewFuzzTestP2P() + ctx := context.Background() + beaconState, privKeys := util.DeterministicGenesisStateAltair(f, 100) + parentBlock := util.NewBeaconBlockAltair() + wsb, err := wrapper.WrappedSignedBeaconBlock(parentBlock) + require.NoError(f, err) + require.NoError(f, db.SaveBlock(ctx, wsb)) + bRoot, err := parentBlock.Block.HashTreeRoot() + require.NoError(f, err) + require.NoError(f, db.SaveState(ctx, beaconState, bRoot)) + require.NoError(f, db.SaveStateSummary(ctx, ðpb.StateSummary{Root: bRoot[:]})) + copied := beaconState.Copy() + require.NoError(f, copied.SetSlot(1)) + proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied) + require.NoError(f, err) + msg := util.NewBeaconBlock() + msg.Block.ParentRoot = bRoot[:] + msg.Block.Slot = 1 + msg.Block.ProposerIndex = proposerIdx + msg.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, msg.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx]) + require.NoError(f, err) + + stateGen := stategen.New(db) + chainService := &mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Epoch: 0, + Root: make([]byte, 32), + }, + DB: db, + } + r := &Service{ + cfg: &config{ + beaconDB: db, + p2p: p, + initialSync: &mockSync.Sync{IsSyncing: false}, + chain: chainService, + blockNotifier: chainService.BlockNotifier(), + stateGen: stateGen, + }, + seenBlockCache: lruwrpr.New(10), + badBlockCache: lruwrpr.New(10), + slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), + seenPendingBlocks: make(map[[32]byte]bool), + } + buf := new(bytes.Buffer) + _, err = p.Encoding().EncodeGossip(buf, msg) + require.NoError(f, err) + topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(f, err) + topic = r.addDigestToTopic(topic, digest) + + f.Add("junk", []byte("junk"), buf.Bytes(), []byte(topic)) + f.Fuzz(func(t *testing.T, pid string, from, data, topic []byte) { + r.cfg.p2p = p2ptest.NewFuzzTestP2P() + r.rateLimiter = newRateLimiter(r.cfg.p2p) + cService := &mock.ChainService{ + Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot*10000000), 0), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Epoch: 0, + Root: make([]byte, 32), + }, + DB: db, + } + r.cfg.chain = cService + r.cfg.blockNotifier = cService.BlockNotifier() + strTop := string(topic) + msg := &pubsub.Message{ + Message: &pb.Message{ + From: from, + Data: data, + Topic: &strTop, + }, + } + _, err := r.validateBeaconBlockPubSub(ctx, peer.ID(pid), msg) + _ = err + }) +} + +func FuzzValidateBeaconBlockPubSub_Bellatrix(f *testing.F) { + db := dbtest.SetupDB(f) + p := p2ptest.NewFuzzTestP2P() + ctx := context.Background() + beaconState, privKeys := util.DeterministicGenesisStateBellatrix(f, 100) + parentBlock := util.NewBeaconBlockBellatrix() + wsb, err := wrapper.WrappedSignedBeaconBlock(parentBlock) + require.NoError(f, err) + require.NoError(f, db.SaveBlock(ctx, wsb)) + bRoot, err := parentBlock.Block.HashTreeRoot() + require.NoError(f, err) + require.NoError(f, db.SaveState(ctx, beaconState, bRoot)) + require.NoError(f, db.SaveStateSummary(ctx, ðpb.StateSummary{Root: bRoot[:]})) + copied := beaconState.Copy() + require.NoError(f, copied.SetSlot(1)) + proposerIdx, err := helpers.BeaconProposerIndex(ctx, copied) + require.NoError(f, err) + msg := util.NewBeaconBlock() + msg.Block.ParentRoot = bRoot[:] + msg.Block.Slot = 1 + msg.Block.ProposerIndex = proposerIdx + msg.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, msg.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx]) + require.NoError(f, err) + + stateGen := stategen.New(db) + chainService := &mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Epoch: 0, + Root: make([]byte, 32), + }, + DB: db, + } + r := &Service{ + cfg: &config{ + beaconDB: db, + p2p: p, + initialSync: &mockSync.Sync{IsSyncing: false}, + chain: chainService, + blockNotifier: chainService.BlockNotifier(), + stateGen: stateGen, + }, + seenBlockCache: lruwrpr.New(10), + badBlockCache: lruwrpr.New(10), + slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), + seenPendingBlocks: make(map[[32]byte]bool), + } + buf := new(bytes.Buffer) + _, err = p.Encoding().EncodeGossip(buf, msg) + require.NoError(f, err) + topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(f, err) + topic = r.addDigestToTopic(topic, digest) + + f.Add("junk", []byte("junk"), buf.Bytes(), []byte(topic)) + f.Fuzz(func(t *testing.T, pid string, from, data, topic []byte) { + r.cfg.p2p = p2ptest.NewFuzzTestP2P() + r.rateLimiter = newRateLimiter(r.cfg.p2p) + cService := &mock.ChainService{ + Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot*10000000), 0), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Epoch: 0, + Root: make([]byte, 32), + }, + DB: db, + } + r.cfg.chain = cService + r.cfg.blockNotifier = cService.BlockNotifier() + strTop := string(topic) + msg := &pubsub.Message{ + Message: &pb.Message{ + From: from, + Data: data, + Topic: &strTop, + }, + } + _, err := r.validateBeaconBlockPubSub(ctx, peer.ID(pid), msg) + _ = err + }) +} diff --git a/beacon-chain/sync/validate_beacon_blocks.go b/beacon-chain/sync/validate_beacon_blocks.go index e3f6b1e4e617..1a5df208a06a 100644 --- a/beacon-chain/sync/validate_beacon_blocks.go +++ b/beacon-chain/sync/validate_beacon_blocks.go @@ -96,7 +96,7 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms blockRoot, err := blk.Block().HashTreeRoot() if err != nil { - log.WithError(err).WithField("blockSlot", blk.Block().Slot()).Debug("Ignored block") + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Ignored block") return pubsub.ValidationIgnore, nil } if s.cfg.beaconDB.HasBlock(ctx, blockRoot) { @@ -105,8 +105,9 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms // Check if parent is a bad block and then reject the block. if s.hasBadBlock(bytesutil.ToBytes32(blk.Block().ParentRoot())) { s.setBadBlock(ctx, blockRoot) - e := fmt.Errorf("received block with root %#x that has an invalid parent %#x", blockRoot, blk.Block().ParentRoot()) - return pubsub.ValidationReject, e + err := fmt.Errorf("received block with root %#x that has an invalid parent %#x", blockRoot, blk.Block().ParentRoot()) + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Received block with an invalid parent") + return pubsub.ValidationReject, err } s.pendingQueueLock.RLock() @@ -121,24 +122,25 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms // earlier (SECONDS_PER_SLOT * 2 seconds). Queue such blocks and process them at the right slot. genesisTime := uint64(s.cfg.chain.GenesisTime().Unix()) if err := slots.VerifyTime(genesisTime, blk.Block().Slot(), earlyBlockProcessingTolerance); err != nil { - log.WithError(err).WithField("blockSlot", blk.Block().Slot()).Debug("Ignored block") + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Ignored block: could not verify slot time") return pubsub.ValidationIgnore, nil } // Add metrics for block arrival time subtracts slot start time. if err := captureArrivalTimeMetric(genesisTime, blk.Block().Slot()); err != nil { - log.WithError(err).WithField("blockSlot", blk.Block().Slot()).Debug("Ignored block") + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Ignored block: could not capture arrival time metric") return pubsub.ValidationIgnore, nil } startSlot, err := slots.EpochStart(s.cfg.chain.FinalizedCheckpt().Epoch) if err != nil { - log.WithError(err).WithField("blockSlot", blk.Block().Slot()).Debug("Ignored block") + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Ignored block: could not calculate epoch start slot") return pubsub.ValidationIgnore, nil } if startSlot >= blk.Block().Slot() { - e := fmt.Errorf("finalized slot %d greater or equal to block slot %d", startSlot, blk.Block().Slot()) - return pubsub.ValidationIgnore, e + err := fmt.Errorf("finalized slot %d greater or equal to block slot %d", startSlot, blk.Block().Slot()) + log.WithFields(getBlockFields(blk)).Debug(err) + return pubsub.ValidationIgnore, err } // Process the block if the clock jitter is less than MAXIMUM_GOSSIP_CLOCK_DISPARITY. @@ -147,11 +149,13 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms s.pendingQueueLock.Lock() if err := s.insertBlockToPendingQueue(blk.Block().Slot(), blk, blockRoot); err != nil { s.pendingQueueLock.Unlock() + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Could not insert block to pending queue") return pubsub.ValidationIgnore, err } s.pendingQueueLock.Unlock() - e := fmt.Errorf("early block, with current slot %d < block slot %d", s.cfg.chain.CurrentSlot(), blk.Block().Slot()) - return pubsub.ValidationIgnore, e + err := fmt.Errorf("early block, with current slot %d < block slot %d", s.cfg.chain.CurrentSlot(), blk.Block().Slot()) + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Could not process early block") + return pubsub.ValidationIgnore, err } // Handle block when the parent is unknown. @@ -159,10 +163,13 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms s.pendingQueueLock.Lock() if err := s.insertBlockToPendingQueue(blk.Block().Slot(), blk, blockRoot); err != nil { s.pendingQueueLock.Unlock() + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Could not insert block to pending queue") return pubsub.ValidationIgnore, err } s.pendingQueueLock.Unlock() - return pubsub.ValidationIgnore, errors.Errorf("unknown parent for block with slot %d and parent root %#x", blk.Block().Slot(), blk.Block().ParentRoot()) + err := errors.Errorf("unknown parent for block with slot %d and parent root %#x", blk.Block().Slot(), blk.Block().ParentRoot()) + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Could not identify parent for block") + return pubsub.ValidationIgnore, err } err = s.validateBeaconBlock(ctx, blk, blockRoot) @@ -170,6 +177,7 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms // If the parent is optimistic, process the block as usual // This also does not penalize a peer which sends optimistic blocks if !errors.Is(ErrOptimisticParent, err) { + log.WithError(err).WithFields(getBlockFields(blk)).Debug("Could not validate beacon block") return pubsub.ValidationReject, err } } @@ -328,6 +336,7 @@ func (s *Service) setBadBlock(ctx context.Context, root [32]byte) { if ctx.Err() != nil { // Do not mark block as bad if it was due to context error. return } + log.WithField("root", fmt.Sprintf("%#x", root)).Debug("Inserting in invalid block cache") s.badBlockCache.Add(string(root[:]), true) } @@ -356,3 +365,15 @@ func isBlockQueueable(genesisTime uint64, slot types.Slot, receivedTime time.Tim currentTimeWithDisparity := receivedTime.Add(params.BeaconNetworkConfig().MaximumGossipClockDisparity) return currentTimeWithDisparity.Unix() < slotTime.Unix() } + +func getBlockFields(b interfaces.SignedBeaconBlock) logrus.Fields { + if helpers.BeaconBlockIsNil(b) != nil { + return logrus.Fields{} + } + return logrus.Fields{ + "slot": b.Block().Slot(), + "proposerIndex": b.Block().ProposerIndex(), + "graffiti": string(b.Block().Body().Graffiti()), + "version": b.Block().Version(), + } +} diff --git a/beacon-chain/sync/validate_beacon_blocks_test.go b/beacon-chain/sync/validate_beacon_blocks_test.go index ef924217b4b0..e0cfd0105f76 100644 --- a/beacon-chain/sync/validate_beacon_blocks_test.go +++ b/beacon-chain/sync/validate_beacon_blocks_test.go @@ -25,7 +25,6 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" lruwrpr "github.com/prysmaticlabs/prysm/cache/lru" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" "github.com/prysmaticlabs/prysm/consensus-types/wrapper" @@ -46,7 +45,7 @@ func TestValidateBeaconBlockPubSub_InvalidSignature(t *testing.T) { db := dbtest.SetupDB(t) p := p2ptest.NewTestP2P(t) ctx := context.Background() - beaconState, _ := util.DeterministicGenesisState(t, 100) + beaconState, privKeys := util.DeterministicGenesisState(t, 100) parentBlock := util.NewBeaconBlock() wsb, err := wrapper.WrappedSignedBeaconBlock(parentBlock) require.NoError(t, err) @@ -63,14 +62,18 @@ func TestValidateBeaconBlockPubSub_InvalidSignature(t *testing.T) { msg.Block.ParentRoot = bRoot[:] msg.Block.Slot = 1 msg.Block.ProposerIndex = proposerIdx - msg.Signature = bytesutil.PadTo([]byte("fake"), fieldparams.BLSSignatureLength) + badPrivKeyIdx := proposerIdx + 1 // We generate a valid signature from a wrong private key which fails to verify + msg.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, msg.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[badPrivKeyIdx]) + require.NoError(t, err) stateGen := stategen.New(db) chainService := &mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0), FinalizedCheckPoint: ðpb.Checkpoint{ Epoch: 0, Root: make([]byte, 32), - }} + }, + DB: db, + } r := &Service{ cfg: &config{ beaconDB: db, @@ -88,6 +91,9 @@ func TestValidateBeaconBlockPubSub_InvalidSignature(t *testing.T) { _, err = p.Encoding().EncodeGossip(buf, msg) require.NoError(t, err) topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(t, err) + topic = r.addDigestToTopic(topic, digest) m := &pubsub.Message{ Message: &pubsubpb.Message{ Data: buf.Bytes(), @@ -95,7 +101,7 @@ func TestValidateBeaconBlockPubSub_InvalidSignature(t *testing.T) { }, } res, err := r.validateBeaconBlockPubSub(ctx, "", m) - assert.NotNil(t, err) + require.ErrorIs(t, err, signing.ErrSigFailedToVerify) result := res == pubsub.ValidationReject assert.Equal(t, true, result) } @@ -130,6 +136,9 @@ func TestValidateBeaconBlockPubSub_BlockAlreadyPresentInDB(t *testing.T) { require.NoError(t, err) topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(t, err) + topic = r.addDigestToTopic(topic, digest) m := &pubsub.Message{ Message: &pubsubpb.Message{ Data: buf.Bytes(), @@ -137,9 +146,8 @@ func TestValidateBeaconBlockPubSub_BlockAlreadyPresentInDB(t *testing.T) { }, } res, err := r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result := res == pubsub.ValidationAccept - assert.Equal(t, false, result) + assert.NoError(t, err) + assert.Equal(t, res, pubsub.ValidationIgnore, "block present in DB should be ignored") } func TestValidateBeaconBlockPubSub_CanRecoverStateSummary(t *testing.T) { @@ -516,12 +524,11 @@ func TestValidateBeaconBlockPubSub_Syncing(t *testing.T) { }, } res, err := r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result := res == pubsub.ValidationAccept - assert.Equal(t, false, result) + assert.NoError(t, err) + assert.Equal(t, res, pubsub.ValidationIgnore, "block is ignored until fully synced") } -func TestValidateBeaconBlockPubSub_AcceptBlocksFromNearFuture(t *testing.T) { +func TestValidateBeaconBlockPubSub_IgnoreAndQueueBlocksFromNearFuture(t *testing.T) { db := dbtest.SetupDB(t) p := p2ptest.NewTestP2P(t) ctx := context.Background() @@ -583,9 +590,8 @@ func TestValidateBeaconBlockPubSub_AcceptBlocksFromNearFuture(t *testing.T) { }, } res, err := r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result := res == pubsub.ValidationIgnore - assert.Equal(t, true, result) + require.ErrorContains(t, "early block, with current slot", err) + assert.Equal(t, res, pubsub.ValidationIgnore, "early block should be ignored and queued") // check if the block is inserted in the Queue assert.Equal(t, true, len(r.pendingBlocksInCache(msg.Block.Slot)) == 1) @@ -600,7 +606,7 @@ func TestValidateBeaconBlockPubSub_RejectBlocksFromFuture(t *testing.T) { sk, err := bls.SecretKeyFromBytes(b32[:]) require.NoError(t, err) msg := util.NewBeaconBlock() - msg.Block.Slot = 3 + msg.Block.Slot = 10 msg.Block.ParentRoot = util.Random32Bytes(t) msg.Signature = sk.Sign([]byte("data")).Marshal() @@ -624,6 +630,9 @@ func TestValidateBeaconBlockPubSub_RejectBlocksFromFuture(t *testing.T) { _, err = p.Encoding().EncodeGossip(buf, msg) require.NoError(t, err) topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(t, err) + topic = r.addDigestToTopic(topic, digest) m := &pubsub.Message{ Message: &pubsubpb.Message{ Data: buf.Bytes(), @@ -631,9 +640,8 @@ func TestValidateBeaconBlockPubSub_RejectBlocksFromFuture(t *testing.T) { }, } res, err := r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result := res == pubsub.ValidationAccept - assert.Equal(t, false, result) + assert.NoError(t, err) + assert.Equal(t, res, pubsub.ValidationIgnore, "block from the future should be ignored") } func TestValidateBeaconBlockPubSub_RejectBlocksFromThePast(t *testing.T) { @@ -672,6 +680,9 @@ func TestValidateBeaconBlockPubSub_RejectBlocksFromThePast(t *testing.T) { _, err = p.Encoding().EncodeGossip(buf, msg) require.NoError(t, err) topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(t, err) + topic = r.addDigestToTopic(topic, digest) m := &pubsub.Message{ Message: &pubsubpb.Message{ Data: buf.Bytes(), @@ -679,9 +690,8 @@ func TestValidateBeaconBlockPubSub_RejectBlocksFromThePast(t *testing.T) { }, } res, err := r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result := res == pubsub.ValidationAccept - assert.Equal(t, false, result) + require.ErrorContains(t, "greater or equal to block slot", err) + assert.Equal(t, res, pubsub.ValidationIgnore, "block from the past should be ignored") } func TestValidateBeaconBlockPubSub_SeenProposerSlot(t *testing.T) { @@ -731,6 +741,9 @@ func TestValidateBeaconBlockPubSub_SeenProposerSlot(t *testing.T) { _, err = p.Encoding().EncodeGossip(buf, msg) require.NoError(t, err) topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(t, err) + topic = r.addDigestToTopic(topic, digest) m := &pubsub.Message{ Message: &pubsubpb.Message{ Data: buf.Bytes(), @@ -740,9 +753,8 @@ func TestValidateBeaconBlockPubSub_SeenProposerSlot(t *testing.T) { r.setSeenBlockIndexSlot(msg.Block.Slot, msg.Block.ProposerIndex) time.Sleep(10 * time.Millisecond) // Wait for cached value to pass through buffers. res, err := r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result := res == pubsub.ValidationAccept - assert.Equal(t, false, result) + assert.NoError(t, err) + assert.Equal(t, res, pubsub.ValidationIgnore, "seen proposer block should be ignored") } func TestValidateBeaconBlockPubSub_FilterByFinalizedEpoch(t *testing.T) { @@ -932,6 +944,9 @@ func TestValidateBeaconBlockPubSub_InvalidParentBlock(t *testing.T) { _, err = p.Encoding().EncodeGossip(buf, msg) require.NoError(t, err) topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(t, err) + topic = r.addDigestToTopic(topic, digest) m := &pubsub.Message{ Message: &pubsubpb.Message{ Data: buf.Bytes(), @@ -939,9 +954,8 @@ func TestValidateBeaconBlockPubSub_InvalidParentBlock(t *testing.T) { }, } res, err := r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result := res == pubsub.ValidationAccept - assert.Equal(t, false, result) + require.ErrorContains(t, "unknown parent for block", err) + assert.Equal(t, res, pubsub.ValidationIgnore, "block with invalid parent should be ignored") require.NoError(t, copied.SetSlot(2)) proposerIdx, err = helpers.BeaconProposerIndex(ctx, copied) @@ -961,21 +975,27 @@ func TestValidateBeaconBlockPubSub_InvalidParentBlock(t *testing.T) { Topic: &topic, }, } + chainService = &mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(2*params.BeaconConfig().SecondsPerSlot), 0), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Epoch: 0, + }} + r.cfg.chain = chainService res, err = r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result = res == pubsub.ValidationAccept + require.ErrorContains(t, "unknown parent for block", err) // Expect block with bad parent to fail too - assert.Equal(t, false, result) + assert.Equal(t, res, pubsub.ValidationIgnore, "block with invalid parent should be ignored") } -func TestValidateBeaconBlockPubSub_RejectEvilBlocksFromFuture(t *testing.T) { +func TestValidateBeaconBlockPubSub_RejectBlocksFromBadParent(t *testing.T) { db := dbtest.SetupDB(t) p := p2ptest.NewTestP2P(t) ctx := context.Background() beaconState, privKeys := util.DeterministicGenesisState(t, 100) parentBlock := util.NewBeaconBlock() + parentBlock.Block.ParentRoot = bytesutil.PadTo([]byte("foo"), 32) wsb, err := wrapper.WrappedSignedBeaconBlock(parentBlock) require.NoError(t, err) require.NoError(t, db.SaveBlock(ctx, wsb)) @@ -1031,11 +1051,15 @@ func TestValidateBeaconBlockPubSub_RejectEvilBlocksFromFuture(t *testing.T) { slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), seenPendingBlocks: make(map[[32]byte]bool), } + r.setBadBlock(ctx, bytesutil.ToBytes32(msg.Block.ParentRoot)) buf := new(bytes.Buffer) _, err = p.Encoding().EncodeGossip(buf, msg) require.NoError(t, err) topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)] + digest, err := r.currentForkDigest() + assert.NoError(t, err) + topic = r.addDigestToTopic(topic, digest) m := &pubsub.Message{ Message: &pubsubpb.Message{ Data: buf.Bytes(), @@ -1043,9 +1067,8 @@ func TestValidateBeaconBlockPubSub_RejectEvilBlocksFromFuture(t *testing.T) { }, } res, err := r.validateBeaconBlockPubSub(ctx, "", m) - _ = err - result := res == pubsub.ValidationAccept - assert.Equal(t, false, result) + assert.ErrorContains(t, "invalid parent", err) + assert.Equal(t, res, pubsub.ValidationReject) } func TestService_setBadBlock_DoesntSetWithContextErr(t *testing.T) { @@ -1388,3 +1411,18 @@ func Test_validateBeaconBlockProcessingWhenParentIsOptimistic(t *testing.T) { result := res == pubsub.ValidationAccept assert.Equal(t, true, result) } + +func Test_getBlockFields(t *testing.T) { + hook := logTest.NewGlobal() + + // Nil + log.WithFields(getBlockFields(nil)).Info("nil block") + // Good block + b := util.NewBeaconBlockBellatrix() + wb, err := wrapper.WrappedSignedBeaconBlock(b) + require.NoError(t, err) + log.WithFields(getBlockFields(wb)).Info("bad block") + + require.LogsContain(t, hook, "nil block") + require.LogsContain(t, hook, "bad block") +} diff --git a/cmd/validator/accounts/BUILD.bazel b/cmd/validator/accounts/BUILD.bazel index 8b77ebb83e2c..6c349327497d 100644 --- a/cmd/validator/accounts/BUILD.bazel +++ b/cmd/validator/accounts/BUILD.bazel @@ -1,10 +1,12 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ "accounts.go", + "delete.go", "list.go", + "wallet_utils.go", ], importpath = "github.com/prysmaticlabs/prysm/cmd/validator/accounts", visibility = ["//visibility:public"], @@ -15,6 +17,7 @@ go_library( "//runtime/tos:go_default_library", "//validator/accounts:go_default_library", "//validator/accounts/iface:go_default_library", + "//validator/accounts/userprompt:go_default_library", "//validator/accounts/wallet:go_default_library", "//validator/client:go_default_library", "//validator/keymanager:go_default_library", @@ -23,3 +26,25 @@ go_library( "@com_github_urfave_cli_v2//:go_default_library", ], ) + +go_test( + name = "go_default_test", + srcs = ["delete_test.go"], + embed = [":go_default_library"], + deps = [ + "//cmd/validator/flags:go_default_library", + "//config/params:go_default_library", + "//crypto/bls:go_default_library", + "//encoding/bytesutil:go_default_library", + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + "//time:go_default_library", + "//validator/accounts:go_default_library", + "//validator/accounts/wallet:go_default_library", + "//validator/keymanager:go_default_library", + "//validator/keymanager/local:go_default_library", + "@com_github_google_uuid//:go_default_library", + "@com_github_urfave_cli_v2//:go_default_library", + "@com_github_wealdtech_go_eth2_wallet_encryptor_keystorev4//:go_default_library", + ], +) diff --git a/cmd/validator/accounts/accounts.go b/cmd/validator/accounts/accounts.go index 137f714099d9..38c64911c666 100644 --- a/cmd/validator/accounts/accounts.go +++ b/cmd/validator/accounts/accounts.go @@ -29,17 +29,21 @@ var Commands = &cli.Command{ flags.DeletePublicKeysFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { if err := cmd.LoadFlagsFromConfig(cliCtx, cliCtx.Command.Flags); err != nil { return err } - return tos.VerifyTosAcceptedOrPrompt(cliCtx) + if err := tos.VerifyTosAcceptedOrPrompt(cliCtx); err != nil { + return err + } + features.ConfigureValidator(cliCtx) + return nil }, Action: func(cliCtx *cli.Context) error { - features.ConfigureValidator(cliCtx) - if err := accounts.DeleteAccountCli(cliCtx); err != nil { + if err := accountsDelete(cliCtx); err != nil { log.Fatalf("Could not delete account: %v", err) } return nil @@ -62,6 +66,7 @@ var Commands = &cli.Command{ flags.GrpcRetryDelayFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { @@ -95,6 +100,7 @@ var Commands = &cli.Command{ flags.BackupPasswordFile, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { @@ -122,6 +128,7 @@ var Commands = &cli.Command{ flags.ImportPrivateKeyFileFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { @@ -155,6 +162,7 @@ var Commands = &cli.Command{ flags.ExitAllFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { diff --git a/cmd/validator/accounts/delete.go b/cmd/validator/accounts/delete.go new file mode 100644 index 000000000000..3d7525190cd8 --- /dev/null +++ b/cmd/validator/accounts/delete.go @@ -0,0 +1,63 @@ +package accounts + +import ( + "strings" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/cmd" + "github.com/prysmaticlabs/prysm/cmd/validator/flags" + "github.com/prysmaticlabs/prysm/validator/accounts" + "github.com/prysmaticlabs/prysm/validator/accounts/userprompt" + "github.com/prysmaticlabs/prysm/validator/client" + "github.com/urfave/cli/v2" +) + +func accountsDelete(c *cli.Context) error { + w, km, err := walletWithKeymanager(c) + if err != nil { + return err + } + dialOpts := client.ConstructDialOptions( + c.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name), + c.String(flags.CertFlag.Name), + c.Uint(flags.GrpcRetriesFlag.Name), + c.Duration(flags.GrpcRetryDelayFlag.Name), + ) + grpcHeaders := strings.Split(c.String(flags.GrpcHeadersFlag.Name), ",") + + opts := []accounts.Option{ + accounts.WithWallet(w), + accounts.WithKeymanager(km), + accounts.WithGRPCDialOpts(dialOpts), + accounts.WithBeaconRPCProvider(c.String(flags.BeaconRPCProviderFlag.Name)), + accounts.WithGRPCHeaders(grpcHeaders), + } + + // Get full set of public keys from the keymanager. + validatingPublicKeys, err := km.FetchValidatingPublicKeys(c.Context) + if err != nil { + return err + } + if len(validatingPublicKeys) == 0 { + return errors.New("wallet is empty, no accounts to delete") + } + // Filter keys either from CLI flag or from interactive session. + filteredPubKeys, err := accounts.FilterPublicKeysFromUserInput( + c, + flags.DeletePublicKeysFlag, + validatingPublicKeys, + userprompt.SelectAccountsDeletePromptText, + ) + if err != nil { + return errors.Wrap(err, "could not filter public keys for deletion") + } + opts = append(opts, accounts.WithFilteredPubKeys(filteredPubKeys)) + opts = append(opts, accounts.WithWalletKeyCount(len(validatingPublicKeys))) + opts = append(opts, accounts.WithDeletePublicKeys(c.IsSet(flags.DeletePublicKeysFlag.Name))) + + acc, err := accounts.NewCLIManager(opts...) + if err != nil { + return err + } + return acc.Delete(c.Context) +} diff --git a/cmd/validator/accounts/delete_test.go b/cmd/validator/accounts/delete_test.go new file mode 100644 index 000000000000..416aa75c265b --- /dev/null +++ b/cmd/validator/accounts/delete_test.go @@ -0,0 +1,191 @@ +package accounts + +import ( + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + "time" + + "github.com/google/uuid" + "github.com/prysmaticlabs/prysm/cmd/validator/flags" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/crypto/bls" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + prysmTime "github.com/prysmaticlabs/prysm/time" + "github.com/prysmaticlabs/prysm/validator/accounts" + "github.com/prysmaticlabs/prysm/validator/accounts/wallet" + "github.com/prysmaticlabs/prysm/validator/keymanager" + "github.com/prysmaticlabs/prysm/validator/keymanager/local" + "github.com/urfave/cli/v2" + keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4" +) + +const ( + passwordFileName = "password.txt" + password = "OhWOWthisisatest42!$" +) + +func setupWalletAndPasswordsDir(t testing.TB) (string, string, string) { + walletDir := filepath.Join(t.TempDir(), "wallet") + passwordsDir := filepath.Join(t.TempDir(), "passwords") + passwordFileDir := filepath.Join(t.TempDir(), "passwordFile") + require.NoError(t, os.MkdirAll(passwordFileDir, params.BeaconIoConfig().ReadWriteExecutePermissions)) + passwordFilePath := filepath.Join(passwordFileDir, passwordFileName) + require.NoError(t, os.WriteFile(passwordFilePath, []byte(password), os.ModePerm)) + return walletDir, passwordsDir, passwordFilePath +} + +// Returns the fullPath to the newly created keystore file. +func createKeystore(t *testing.T, path string) (*keymanager.Keystore, string) { + validatingKey, err := bls.RandKey() + require.NoError(t, err) + encryptor := keystorev4.New() + cryptoFields, err := encryptor.Encrypt(validatingKey.Marshal(), password) + require.NoError(t, err) + id, err := uuid.NewRandom() + require.NoError(t, err) + keystoreFile := &keymanager.Keystore{ + Crypto: cryptoFields, + ID: id.String(), + Pubkey: fmt.Sprintf("%x", validatingKey.PublicKey().Marshal()), + Version: encryptor.Version(), + Name: encryptor.Name(), + } + encoded, err := json.MarshalIndent(keystoreFile, "", "\t") + require.NoError(t, err) + // Write the encoded keystore to disk with the timestamp appended + createdAt := prysmTime.Now().Unix() + fullPath := filepath.Join(path, fmt.Sprintf(local.KeystoreFileNameFormat, createdAt)) + require.NoError(t, os.WriteFile(fullPath, encoded, os.ModePerm)) + return keystoreFile, fullPath +} + +type testWalletConfig struct { + exitAll bool + skipDepositConfirm bool + keymanagerKind keymanager.Kind + numAccounts int64 + grpcHeaders string + privateKeyFile string + accountPasswordFile string + walletPasswordFile string + backupPasswordFile string + backupPublicKeys string + voluntaryExitPublicKeys string + deletePublicKeys string + keysDir string + backupDir string + walletDir string +} + +func setupWalletCtx( + tb testing.TB, + cfg *testWalletConfig, +) *cli.Context { + app := cli.App{} + set := flag.NewFlagSet("test", 0) + set.String(flags.WalletDirFlag.Name, cfg.walletDir, "") + set.String(flags.KeysDirFlag.Name, cfg.keysDir, "") + set.String(flags.KeymanagerKindFlag.Name, cfg.keymanagerKind.String(), "") + set.String(flags.DeletePublicKeysFlag.Name, cfg.deletePublicKeys, "") + set.String(flags.VoluntaryExitPublicKeysFlag.Name, cfg.voluntaryExitPublicKeys, "") + set.String(flags.BackupDirFlag.Name, cfg.backupDir, "") + set.String(flags.BackupPasswordFile.Name, cfg.backupPasswordFile, "") + set.String(flags.BackupPublicKeysFlag.Name, cfg.backupPublicKeys, "") + set.String(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile, "") + set.String(flags.AccountPasswordFileFlag.Name, cfg.accountPasswordFile, "") + set.Int64(flags.NumAccountsFlag.Name, cfg.numAccounts, "") + set.Bool(flags.SkipDepositConfirmationFlag.Name, cfg.skipDepositConfirm, "") + set.Bool(flags.SkipMnemonic25thWordCheckFlag.Name, true, "") + set.Bool(flags.ExitAllFlag.Name, cfg.exitAll, "") + set.String(flags.GrpcHeadersFlag.Name, cfg.grpcHeaders, "") + + if cfg.privateKeyFile != "" { + set.String(flags.ImportPrivateKeyFileFlag.Name, cfg.privateKeyFile, "") + assert.NoError(tb, set.Set(flags.ImportPrivateKeyFileFlag.Name, cfg.privateKeyFile)) + } + assert.NoError(tb, set.Set(flags.WalletDirFlag.Name, cfg.walletDir)) + assert.NoError(tb, set.Set(flags.SkipMnemonic25thWordCheckFlag.Name, "true")) + assert.NoError(tb, set.Set(flags.KeysDirFlag.Name, cfg.keysDir)) + assert.NoError(tb, set.Set(flags.KeymanagerKindFlag.Name, cfg.keymanagerKind.String())) + assert.NoError(tb, set.Set(flags.DeletePublicKeysFlag.Name, cfg.deletePublicKeys)) + assert.NoError(tb, set.Set(flags.VoluntaryExitPublicKeysFlag.Name, cfg.voluntaryExitPublicKeys)) + assert.NoError(tb, set.Set(flags.BackupDirFlag.Name, cfg.backupDir)) + assert.NoError(tb, set.Set(flags.BackupPublicKeysFlag.Name, cfg.backupPublicKeys)) + assert.NoError(tb, set.Set(flags.BackupPasswordFile.Name, cfg.backupPasswordFile)) + assert.NoError(tb, set.Set(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile)) + assert.NoError(tb, set.Set(flags.AccountPasswordFileFlag.Name, cfg.accountPasswordFile)) + assert.NoError(tb, set.Set(flags.NumAccountsFlag.Name, strconv.Itoa(int(cfg.numAccounts)))) + assert.NoError(tb, set.Set(flags.SkipDepositConfirmationFlag.Name, strconv.FormatBool(cfg.skipDepositConfirm))) + assert.NoError(tb, set.Set(flags.ExitAllFlag.Name, strconv.FormatBool(cfg.exitAll))) + assert.NoError(tb, set.Set(flags.GrpcHeadersFlag.Name, cfg.grpcHeaders)) + return cli.NewContext(&app, set, nil) +} + +func TestDeleteAccounts_Noninteractive(t *testing.T) { + walletDir, _, passwordFilePath := setupWalletAndPasswordsDir(t) + // Write a directory where we will import keys from. + keysDir := filepath.Join(t.TempDir(), "keysDir") + require.NoError(t, os.MkdirAll(keysDir, os.ModePerm)) + + // Create 3 keystore files in the keys directory we can then + // import from in our wallet. + k1, _ := createKeystore(t, keysDir) + time.Sleep(time.Second) + k2, _ := createKeystore(t, keysDir) + time.Sleep(time.Second) + k3, _ := createKeystore(t, keysDir) + generatedPubKeys := []string{k1.Pubkey, k2.Pubkey, k3.Pubkey} + // Only delete keys 0 and 1. + deletePublicKeys := strings.Join(generatedPubKeys[0:2], ",") + + // We initialize a wallet with a local keymanager. + cliCtx := setupWalletCtx(t, &testWalletConfig{ + // Wallet configuration flags. + walletDir: walletDir, + keymanagerKind: keymanager.Local, + walletPasswordFile: passwordFilePath, + accountPasswordFile: passwordFilePath, + // Flags required for ImportAccounts to work. + keysDir: keysDir, + // Flags required for DeleteAccounts to work. + deletePublicKeys: deletePublicKeys, + }) + w, err := accounts.CreateWalletWithKeymanager(cliCtx.Context, &accounts.CreateWalletConfig{ + WalletCfg: &wallet.Config{ + WalletDir: walletDir, + KeymanagerKind: keymanager.Local, + WalletPassword: password, + }, + }) + require.NoError(t, err) + + // We attempt to import accounts. + require.NoError(t, accounts.ImportAccountsCli(cliCtx)) + + // We attempt to delete the accounts specified. + require.NoError(t, accountsDelete(cliCtx)) + + keymanager, err := local.NewKeymanager( + cliCtx.Context, + &local.SetupConfig{ + Wallet: w, + ListenForChanges: false, + }, + ) + require.NoError(t, err) + remainingAccounts, err := keymanager.FetchValidatingPublicKeys(cliCtx.Context) + require.NoError(t, err) + require.Equal(t, len(remainingAccounts), 1) + remainingPublicKey, err := hex.DecodeString(k3.Pubkey) + require.NoError(t, err) + assert.DeepEqual(t, remainingAccounts[0], bytesutil.ToBytes48(remainingPublicKey)) +} diff --git a/cmd/validator/accounts/list.go b/cmd/validator/accounts/list.go index 9ab44fdb853f..76ba4ca5411a 100644 --- a/cmd/validator/accounts/list.go +++ b/cmd/validator/accounts/list.go @@ -3,14 +3,10 @@ package accounts import ( "strings" - "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/cmd" "github.com/prysmaticlabs/prysm/cmd/validator/flags" "github.com/prysmaticlabs/prysm/validator/accounts" - "github.com/prysmaticlabs/prysm/validator/accounts/iface" - "github.com/prysmaticlabs/prysm/validator/accounts/wallet" "github.com/prysmaticlabs/prysm/validator/client" - "github.com/prysmaticlabs/prysm/validator/keymanager" "github.com/urfave/cli/v2" ) @@ -51,22 +47,3 @@ func accountsList(c *cli.Context) error { c.Context, ) } - -func walletWithKeymanager(c *cli.Context) (*wallet.Wallet, keymanager.IKeymanager, error) { - w, err := wallet.OpenWalletOrElseCli(c, func(cliCtx *cli.Context) (*wallet.Wallet, error) { - return nil, wallet.ErrNoWalletFound - }) - if err != nil { - return nil, nil, errors.Wrap(err, "could not open wallet") - } - // TODO(#9883) - Remove this when we have a better way to handle this. this is fine. - // genesis root is not set here which is used for sign function, but fetch keys should be fine. - km, err := w.InitializeKeymanager(c.Context, iface.InitKeymanagerConfig{ListenForChanges: false}) - if err != nil && strings.Contains(err.Error(), keymanager.IncorrectPasswordErrMsg) { - return nil, nil, errors.New("wrong wallet password entered") - } - if err != nil { - return nil, nil, errors.Wrap(err, accounts.ErrCouldNotInitializeKeymanager) - } - return w, km, nil -} diff --git a/cmd/validator/accounts/wallet_utils.go b/cmd/validator/accounts/wallet_utils.go new file mode 100644 index 000000000000..2055f25f5ea4 --- /dev/null +++ b/cmd/validator/accounts/wallet_utils.go @@ -0,0 +1,31 @@ +package accounts + +import ( + "strings" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/validator/accounts" + "github.com/prysmaticlabs/prysm/validator/accounts/iface" + "github.com/prysmaticlabs/prysm/validator/accounts/wallet" + "github.com/prysmaticlabs/prysm/validator/keymanager" + "github.com/urfave/cli/v2" +) + +func walletWithKeymanager(c *cli.Context) (*wallet.Wallet, keymanager.IKeymanager, error) { + w, err := wallet.OpenWalletOrElseCli(c, func(cliCtx *cli.Context) (*wallet.Wallet, error) { + return nil, wallet.ErrNoWalletFound + }) + if err != nil { + return nil, nil, errors.Wrap(err, "could not open wallet") + } + // TODO(#9883) - Remove this when we have a better way to handle this. this is fine. + // genesis root is not set here which is used for sign function, but fetch keys should be fine. + km, err := w.InitializeKeymanager(c.Context, iface.InitKeymanagerConfig{ListenForChanges: false}) + if err != nil && strings.Contains(err.Error(), keymanager.IncorrectPasswordErrMsg) { + return nil, nil, errors.New("wrong wallet password entered") + } + if err != nil { + return nil, nil, errors.Wrap(err, accounts.ErrCouldNotInitializeKeymanager) + } + return w, km, nil +} diff --git a/cmd/validator/slashing-protection/slashing-protection.go b/cmd/validator/slashing-protection/slashing-protection.go index 7fd3eb0bbea7..45e0127bccf2 100644 --- a/cmd/validator/slashing-protection/slashing-protection.go +++ b/cmd/validator/slashing-protection/slashing-protection.go @@ -23,6 +23,7 @@ var Commands = &cli.Command{ flags.SlashingProtectionExportDirFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { @@ -47,6 +48,7 @@ var Commands = &cli.Command{ flags.SlashingProtectionJSONFileFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { diff --git a/cmd/validator/wallet/wallet.go b/cmd/validator/wallet/wallet.go index 2daea8164c0d..f6cd27b75a97 100644 --- a/cmd/validator/wallet/wallet.go +++ b/cmd/validator/wallet/wallet.go @@ -35,6 +35,7 @@ var Commands = &cli.Command{ flags.SkipMnemonic25thWordCheckFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { @@ -64,6 +65,7 @@ var Commands = &cli.Command{ flags.RemoteSignerCACertPathFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { @@ -92,6 +94,7 @@ var Commands = &cli.Command{ flags.SkipMnemonic25thWordCheckFlag, features.Mainnet, features.PraterTestnet, + features.RopstenTestnet, cmd.AcceptTosFlag, }), Before: func(cliCtx *cli.Context) error { diff --git a/config/features/config.go b/config/features/config.go index dbc8842fde42..4d2a518cee0c 100644 --- a/config/features/config.go +++ b/config/features/config.go @@ -115,6 +115,10 @@ func configureTestnet(ctx *cli.Context) { log.Warn("Running on the Prater Testnet") params.UsePraterConfig() params.UsePraterNetworkConfig() + } else if ctx.Bool(RopstenTestnet.Name) { + log.Warn("Running on the Ropsten Beacon Chain Testnet") + params.UseRopstenConfig() + params.UseRopstenNetworkConfig() } else { log.Warn("Running on Ethereum Consensus Mainnet") params.UseMainnetConfig() diff --git a/config/features/flags.go b/config/features/flags.go index 2bd65dbb0cbd..f788e6f3f8ab 100644 --- a/config/features/flags.go +++ b/config/features/flags.go @@ -12,6 +12,11 @@ var ( Name: "prater", Usage: "Run Prysm configured for the Prater test network", } + // RopstenTestnet flag for the multiclient Ethereum consensus testnet. + RopstenTestnet = &cli.BoolFlag{ + Name: "ropsten", + Usage: "Run Prysm configured for the Ropsten beacon chain test network", + } // Mainnet flag for easier tooling, no-op Mainnet = &cli.BoolFlag{ Value: true, @@ -128,6 +133,7 @@ var ValidatorFlags = append(deprecatedFlags, []cli.Flag{ enableExternalSlasherProtectionFlag, disableAttestingHistoryDBCache, PraterTestnet, + RopstenTestnet, Mainnet, dynamicKeyReloadDebounceInterval, attestTimely, @@ -146,6 +152,7 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{ writeSSZStateTransitionsFlag, disableGRPCConnectionLogging, PraterTestnet, + RopstenTestnet, Mainnet, enablePeerScorer, enableLargerGossipHistory, diff --git a/config/params/BUILD.bazel b/config/params/BUILD.bazel index a8fa15a4319a..eb18d65389d5 100644 --- a/config/params/BUILD.bazel +++ b/config/params/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "registry.go", "testnet_e2e_config.go", "testnet_prater_config.go", + "testnet_ropsten_config.go", "testutils.go", "values.go", ], diff --git a/config/params/config.go b/config/params/config.go index 5caaecc77938..9ab23d346167 100644 --- a/config/params/config.go +++ b/config/params/config.go @@ -144,6 +144,7 @@ type BeaconChainConfig struct { ShardingForkVersion []byte `yaml:"SHARDING_FORK_VERSION" spec:"true"` // ShardingForkVersion is used to represent the fork version for sharding. ShardingForkEpoch types.Epoch `yaml:"SHARDING_FORK_EPOCH" spec:"true"` // ShardingForkEpoch is used to represent the assigned fork epoch for sharding. ForkVersionSchedule map[[fieldparams.VersionLength]byte]types.Epoch // Schedule of fork epochs by version. + ForkVersionNames map[[fieldparams.VersionLength]byte]string // Human-readable names of fork versions. // Weak subjectivity values. SafetyDecay uint64 // SafetyDecay is defined as the loss in the 1/3 consensus safety margin of the casper FFG mechanism. @@ -195,6 +196,7 @@ type BeaconChainConfig struct { func (b *BeaconChainConfig) InitializeForkSchedule() { // Reset Fork Version Schedule. b.ForkVersionSchedule = configForkSchedule(b) + b.ForkVersionNames = configForkNames(b) } func configForkSchedule(b *BeaconChainConfig) map[[fieldparams.VersionLength]byte]types.Epoch { @@ -207,3 +209,14 @@ func configForkSchedule(b *BeaconChainConfig) map[[fieldparams.VersionLength]byt fvs[bytesutil.ToBytes4(b.BellatrixForkVersion)] = b.BellatrixForkEpoch return fvs } + +func configForkNames(b *BeaconChainConfig) map[[fieldparams.VersionLength]byte]string { + fvn := map[[fieldparams.VersionLength]byte]string{} + // Set Genesis fork data. + fvn[bytesutil.ToBytes4(b.GenesisForkVersion)] = "phase0" + // Set Altair fork data. + fvn[bytesutil.ToBytes4(b.AltairForkVersion)] = "altair" + // Set Bellatrix fork data. + fvn[bytesutil.ToBytes4(b.BellatrixForkVersion)] = "bellatrix" + return fvn +} diff --git a/config/params/testnet_e2e_config.go b/config/params/testnet_e2e_config.go index 7d70a2d06c28..9c82e4acf476 100644 --- a/config/params/testnet_e2e_config.go +++ b/config/params/testnet_e2e_config.go @@ -22,7 +22,8 @@ func UseE2EMainnetConfig() { } // E2ETestConfig retrieves the configurations made specifically for E2E testing. -// Warning: This config is only for testing, it is not meant for use outside of E2E. +// +// WARNING: This config is only for testing, it is not meant for use outside of E2E. func E2ETestConfig() *BeaconChainConfig { e2eConfig := MinimalSpecConfig() diff --git a/config/params/testnet_ropsten_config.go b/config/params/testnet_ropsten_config.go new file mode 100644 index 000000000000..cf54bbb99c1b --- /dev/null +++ b/config/params/testnet_ropsten_config.go @@ -0,0 +1,44 @@ +package params + +import ( + eth1Params "github.com/ethereum/go-ethereum/params" +) + +// UseRopstenNetworkConfig uses the Ropsten beacon chain specific network config. +func UseRopstenNetworkConfig() { + cfg := BeaconNetworkConfig().Copy() + cfg.ContractDeploymentBlock = 12269949 + cfg.BootstrapNodes = []string{ + // EF boot node + "enr:-Iq4QMCTfIMXnow27baRUb35Q8iiFHSIDBJh6hQM5Axohhf4b6Kr_cOCu0htQ5WvVqKvFgY28893DHAg8gnBAXsAVqmGAX53x8JggmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk", + // Teku boot node + "enr:-KG4QMJSJ7DHk6v2p-W8zQ3Xv7FfssZ_1E3p2eY6kN13staMObUonAurqyWhODoeY6edXtV8e9eL9RnhgZ9va2SMDRQMhGV0aDKQS-iVMYAAAHD0AQAAAAAAAIJpZIJ2NIJpcIQDhAAhiXNlY3AyNTZrMaEDXBVUZhhmdy1MYor1eGdRJ4vHYghFKDgjyHgt6sJ-IlCDdGNwgiMog3VkcIIjKA", + } + OverrideBeaconNetworkConfig(cfg) +} + +// UseRopstenConfig sets the main beacon chain config for Ropsten beacon chain. +func UseRopstenConfig() { + beaconConfig = RopstenConfig() +} + +// RopstenConfig defines the config for the Ropsten beacon chain testnet. +func RopstenConfig() *BeaconChainConfig { + cfg := MainnetConfig().Copy() + cfg.MinGenesisTime = 1653318000 + cfg.GenesisDelay = 604800 + cfg.MinGenesisActiveValidatorCount = 100000 + cfg.ConfigName = RopstenName + cfg.GenesisForkVersion = []byte{0x80, 0x00, 0x00, 0x69} + cfg.SecondsPerETH1Block = 14 + cfg.DepositChainID = eth1Params.RopstenChainConfig.ChainID.Uint64() + cfg.DepositNetworkID = eth1Params.RopstenChainConfig.ChainID.Uint64() + cfg.AltairForkEpoch = 500 + cfg.AltairForkVersion = []byte{0x80, 0x00, 0x00, 0x70} + cfg.BellatrixForkEpoch = 750 + cfg.BellatrixForkVersion = []byte{0x80, 0x00, 0x00, 0x71} + cfg.TerminalTotalDifficulty = "43531756765713534" + cfg.DepositContractAddress = "0x6f22fFbC56eFF051aECF839396DD1eD9aD6BBA9D" + cfg.InitializeForkSchedule() + return cfg +} diff --git a/config/params/values.go b/config/params/values.go index 271b2895e63c..6c51c59d80ef 100644 --- a/config/params/values.go +++ b/config/params/values.go @@ -14,6 +14,7 @@ const ( MainnetName = "mainnet" MinimalName = "minimal" PraterName = "prater" + RopstenName = "ropsten" ) // KnownConfigs provides an index of all known BeaconChainConfig values. diff --git a/consensus-types/primitives/committee_index_test.go b/consensus-types/primitives/committee_index_test.go index 087e283bc23f..6ef20b0d9a40 100644 --- a/consensus-types/primitives/committee_index_test.go +++ b/consensus-types/primitives/committee_index_test.go @@ -13,14 +13,14 @@ func TestCommitteeIndex_Casting(t *testing.T) { t.Errorf("Unequal: %v = %v", CommitteeIndex(x1), committeeIdx) } - var x2 float64 = 42.2 + var x2 = 42.2 if CommitteeIndex(x2) != committeeIdx { t.Errorf("Unequal: %v = %v", CommitteeIndex(x2), committeeIdx) } }) t.Run("int", func(t *testing.T) { - var x int = 42 + var x = 42 if CommitteeIndex(x) != committeeIdx { t.Errorf("Unequal: %v = %v", CommitteeIndex(x), committeeIdx) } diff --git a/consensus-types/primitives/slot_test.go b/consensus-types/primitives/slot_test.go index e6d57a2a8309..7977213cb352 100644 --- a/consensus-types/primitives/slot_test.go +++ b/consensus-types/primitives/slot_test.go @@ -25,14 +25,14 @@ func TestSlot_Casting(t *testing.T) { t.Errorf("Unequal: %v = %v", types.Slot(x1), slot) } - var x2 float64 = 42.2 + var x2 = 42.2 if types.Slot(x2) != slot { t.Errorf("Unequal: %v = %v", types.Slot(x2), slot) } }) t.Run("int", func(t *testing.T) { - var x int = 42 + var x = 42 if types.Slot(x) != slot { t.Errorf("Unequal: %v = %v", types.Slot(x), slot) } diff --git a/consensus-types/primitives/validator_test.go b/consensus-types/primitives/validator_test.go index e08d57fe1e44..548c10b23bba 100644 --- a/consensus-types/primitives/validator_test.go +++ b/consensus-types/primitives/validator_test.go @@ -20,14 +20,14 @@ func TestValidatorIndex_Casting(t *testing.T) { t.Errorf("Unequal: %v = %v", ValidatorIndex(x1), valIdx) } - var x2 float64 = 42.2 + var x2 = 42.2 if ValidatorIndex(x2) != valIdx { t.Errorf("Unequal: %v = %v", ValidatorIndex(x2), valIdx) } }) t.Run("int", func(t *testing.T) { - var x int = 42 + var x = 42 if ValidatorIndex(x) != valIdx { t.Errorf("Unequal: %v = %v", ValidatorIndex(x), valIdx) } diff --git a/consensus-types/wrapper/beacon_block_bellatrix_test.go b/consensus-types/wrapper/beacon_block_bellatrix_test.go index db421b7e9e03..86e664d7cb12 100644 --- a/consensus-types/wrapper/beacon_block_bellatrix_test.go +++ b/consensus-types/wrapper/beacon_block_bellatrix_test.go @@ -191,7 +191,7 @@ func TestBellatrixBeaconBlock_IsNil(t *testing.T) { assert.Equal(t, false, wb.IsNil()) } -func TesTBellatrixBeaconBlock_IsBlinded(t *testing.T) { +func TestBellatrixBeaconBlock_IsBlinded(t *testing.T) { wsb, err := wrapper.WrappedBeaconBlock(ðpb.BeaconBlockBellatrix{}) require.NoError(t, err) require.Equal(t, false, wsb.IsNil()) diff --git a/container/trie/BUILD.bazel b/container/trie/BUILD.bazel index 62489a5c7a8e..fc91b8c58479 100644 --- a/container/trie/BUILD.bazel +++ b/container/trie/BUILD.bazel @@ -13,6 +13,7 @@ go_library( "//encoding/bytesutil:go_default_library", "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "@com_github_pkg_errors//:go_default_library", ], ) diff --git a/container/trie/sparse_merkle.go b/container/trie/sparse_merkle.go index 5507c8f05534..54d6975c09c8 100644 --- a/container/trie/sparse_merkle.go +++ b/container/trie/sparse_merkle.go @@ -4,9 +4,9 @@ package trie import ( "bytes" "encoding/binary" - "errors" "fmt" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/math" @@ -29,7 +29,7 @@ func NewTrie(depth uint64) (*SparseMerkleTrie, error) { } // CreateTrieFromProto creates a Sparse Merkle Trie from its corresponding merkle trie. -func CreateTrieFromProto(trieObj *protodb.SparseMerkleTrie) *SparseMerkleTrie { +func CreateTrieFromProto(trieObj *protodb.SparseMerkleTrie) (*SparseMerkleTrie, error) { trie := &SparseMerkleTrie{ depth: uint(trieObj.Depth), originalItems: trieObj.OriginalItems, @@ -39,7 +39,29 @@ func CreateTrieFromProto(trieObj *protodb.SparseMerkleTrie) *SparseMerkleTrie { branches[i] = layer.Layer } trie.branches = branches - return trie + + if err := trie.validate(); err != nil { + return nil, errors.Wrap(err, "invalid sparse merkle trie") + } + + return trie, nil +} + +func (m *SparseMerkleTrie) validate() error { + if len(m.branches) == 0 { + return errors.New("no branches") + } + if len(m.branches[len(m.branches)-1]) == 0 { + return errors.New("invalid branches provided") + } + if m.depth >= uint(len(m.branches)) { + return errors.New("depth is greater than or equal to number of branches") + } + if m.depth >= 64 { + return errors.New("depth exceeds 64") // PowerOf2 would overflow. + } + + return nil } // GenerateTrieFromItems constructs a Merkle trie from a sequence of byte slices. @@ -82,10 +104,6 @@ func (m *SparseMerkleTrie) Items() [][]byte { // Spec Definition: // sha256(concat(node, self.to_little_endian_64(self.deposit_count), slice(zero_bytes32, start=0, len=24))) func (m *SparseMerkleTrie) HashTreeRoot() ([32]byte, error) { - if len(m.branches) == 0 || len(m.branches[len(m.branches)-1]) == 0 { - return [32]byte{}, errors.New("invalid branches provided to compute root") - } - enc := [32]byte{} depositCount := uint64(len(m.originalItems)) if len(m.originalItems) == 1 && bytes.Equal(m.originalItems[0], ZeroHashes[0][:]) { @@ -101,12 +119,6 @@ func (m *SparseMerkleTrie) Insert(item []byte, index int) error { if index < 0 { return fmt.Errorf("negative index provided: %d", index) } - if len(m.branches) == 0 { - return errors.New("invalid trie: no branches") - } - if m.depth > uint(len(m.branches)) { - return errors.New("invalid trie: depth is greater than number of branches") - } for index >= len(m.branches[0]) { m.branches[0] = append(m.branches[0], ZeroHashes[0][:]) } @@ -153,16 +165,10 @@ func (m *SparseMerkleTrie) MerkleProof(index int) ([][]byte, error) { if index < 0 { return nil, fmt.Errorf("merkle index is negative: %d", index) } - if len(m.branches) == 0 { - return nil, errors.New("invalid trie: no branches") - } leaves := m.branches[0] if index >= len(leaves) { return nil, fmt.Errorf("merkle index out of range in trie, max range: %d, received: %d", len(leaves), index) } - if m.depth > uint(len(m.branches)) { - return nil, errors.New("invalid trie: depth is greater than number of branches") - } merkleIndex := uint(index) proof := make([][]byte, m.depth+1) for i := uint(0); i < m.depth; i++ { diff --git a/container/trie/sparse_merkle_test.go b/container/trie/sparse_merkle_test.go index f0b12ba8576c..7d362431b502 100644 --- a/container/trie/sparse_merkle_test.go +++ b/container/trie/sparse_merkle_test.go @@ -16,6 +16,68 @@ import ( "github.com/prysmaticlabs/prysm/testing/require" ) +func TestCreateTrieFromProto_Validation(t *testing.T) { + h := hash.Hash([]byte("hi")) + genValidLayers := func(num int) []*ethpb.TrieLayer { + l := make([]*ethpb.TrieLayer, num) + for i := 0; i < num; i++ { + l[i] = ðpb.TrieLayer{ + Layer: [][]byte{h[:]}, + } + } + return l + } + tests := []struct { + trie *ethpb.SparseMerkleTrie + errString string + }{ + { + trie: ðpb.SparseMerkleTrie{ + Layers: []*ethpb.TrieLayer{}, + Depth: 0, + }, + errString: "no branches", + }, + { + trie: ðpb.SparseMerkleTrie{ + Layers: []*ethpb.TrieLayer{ + { + Layer: [][]byte{h[:]}, + }, + { + Layer: [][]byte{h[:]}, + }, + { + Layer: [][]byte{}, + }, + }, + Depth: 2, + }, + errString: "invalid branches provided", + }, + { + trie: ðpb.SparseMerkleTrie{ + Layers: genValidLayers(3), + Depth: 12, + }, + errString: "depth is greater than or equal to number of branches", + }, + { + trie: ðpb.SparseMerkleTrie{ + Layers: genValidLayers(66), + Depth: 65, + }, + errString: "depth exceeds 64", + }, + } + for _, tt := range tests { + t.Run(tt.errString, func(t *testing.T) { + _, err := trie.CreateTrieFromProto(tt.trie) + require.ErrorContains(t, tt.errString, err) + }) + } +} + func TestMarshalDepositWithProof(t *testing.T) { items := [][]byte{ []byte("A"), @@ -52,7 +114,7 @@ func TestMarshalDepositWithProof(t *testing.T) { func TestMerkleTrie_MerkleProofOutOfRange(t *testing.T) { h := hash.Hash([]byte("hi")) - m := trie.CreateTrieFromProto(ðpb.SparseMerkleTrie{ + m, err := trie.CreateTrieFromProto(ðpb.SparseMerkleTrie{ Layers: []*ethpb.TrieLayer{ { Layer: [][]byte{h[:]}, @@ -61,11 +123,12 @@ func TestMerkleTrie_MerkleProofOutOfRange(t *testing.T) { Layer: [][]byte{h[:]}, }, { - Layer: [][]byte{}, + Layer: [][]byte{h[:]}, }, }, - Depth: 4, + Depth: 2, }) + require.NoError(t, err) if _, err := m.MerkleProof(6); err == nil { t.Error("Expected out of range failure, received nil", err) } @@ -128,6 +191,7 @@ func TestMerkleTrie_VerifyMerkleProof(t *testing.T) { []byte("G"), []byte("H"), } + m, err := trie.GenerateTrieFromItems(items, params.BeaconConfig().DepositContractTreeDepth) require.NoError(t, err) proof, err := m.MerkleProof(0) @@ -209,7 +273,8 @@ func TestRoundtripProto_OK(t *testing.T) { depositRoot, err := m.HashTreeRoot() require.NoError(t, err) - newTrie := trie.CreateTrieFromProto(protoTrie) + newTrie, err := trie.CreateTrieFromProto(protoTrie) + require.NoError(t, err) root, err := newTrie.HashTreeRoot() require.NoError(t, err) require.DeepEqual(t, depositRoot, root) diff --git a/container/trie/sparse_merkle_trie_fuzz_test.go b/container/trie/sparse_merkle_trie_fuzz_test.go index 1845fdb0e503..4d03309ebdc7 100644 --- a/container/trie/sparse_merkle_trie_fuzz_test.go +++ b/container/trie/sparse_merkle_trie_fuzz_test.go @@ -22,10 +22,10 @@ func FuzzSparseMerkleTrie_HashTreeRoot(f *testing.F) { Layer: [][]byte{h[:]}, }, { - Layer: [][]byte{}, + Layer: [][]byte{h[:]}, }, }, - Depth: 4, + Depth: 2, } b, err := proto.Marshal(pb) require.NoError(f, err) @@ -36,10 +36,13 @@ func FuzzSparseMerkleTrie_HashTreeRoot(f *testing.F) { if err := proto.Unmarshal(b, pb); err != nil { return } - _, err := trie.CreateTrieFromProto(pb).HashTreeRoot() + smt, err := trie.CreateTrieFromProto(pb) if err != nil { return } + if _, err := smt.HashTreeRoot(); err != nil { + return + } }) } @@ -54,10 +57,10 @@ func FuzzSparseMerkleTrie_MerkleProof(f *testing.F) { Layer: [][]byte{h[:]}, }, { - Layer: [][]byte{}, + Layer: [][]byte{h[:]}, }, }, - Depth: 4, + Depth: 2, } b, err := proto.Marshal(pb) require.NoError(f, err) @@ -68,10 +71,13 @@ func FuzzSparseMerkleTrie_MerkleProof(f *testing.F) { if err := proto.Unmarshal(b, pb); err != nil { return } - _, err := trie.CreateTrieFromProto(pb).MerkleProof(i) + smt, err := trie.CreateTrieFromProto(pb) if err != nil { return } + if _, err := smt.MerkleProof(i); err != nil { + return + } }) } @@ -86,10 +92,10 @@ func FuzzSparseMerkleTrie_Insert(f *testing.F) { Layer: [][]byte{h[:]}, }, { - Layer: [][]byte{}, + Layer: [][]byte{h[:]}, }, }, - Depth: 4, + Depth: 2, } b, err := proto.Marshal(pb) require.NoError(f, err) @@ -100,7 +106,11 @@ func FuzzSparseMerkleTrie_Insert(f *testing.F) { if err := proto.Unmarshal(b, pb); err != nil { return } - if err := trie.CreateTrieFromProto(pb).Insert(item, i); err != nil { + smt, err := trie.CreateTrieFromProto(pb) + if err != nil { + return + } + if err := smt.Insert(item, i); err != nil { return } }) diff --git a/container/trie/testdata/fuzz/FuzzSparseMerkleTrie_Insert/fuzzbuzz-97663548a1e2280a081745e5fa25c289f7121c0b b/container/trie/testdata/fuzz/FuzzSparseMerkleTrie_Insert/fuzzbuzz-97663548a1e2280a081745e5fa25c289f7121c0b new file mode 100644 index 000000000000..7c5460c2276f --- /dev/null +++ b/container/trie/testdata/fuzz/FuzzSparseMerkleTrie_Insert/fuzzbuzz-97663548a1e2280a081745e5fa25c289f7121c0b @@ -0,0 +1,4 @@ +go test fuzz v1 +[]byte("\b\x03\x12\"2 00000000000000000000000000000000\x12\"2 00000000000000000000000000000000\x12\x00") +[]byte("") +int(0) diff --git a/contracts/deposit/helper.go b/contracts/deposit/helper.go index f69b5fef85e5..945f5a6ecad2 100644 --- a/contracts/deposit/helper.go +++ b/contracts/deposit/helper.go @@ -4,7 +4,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" ) -// NewDepositContractcallFromBoundContract creates a new instance of DepositContractCaller, bound to +// NewDepositContractCallerFromBoundContract creates a new instance of DepositContractCaller, bound to // a specific deployed contract. func NewDepositContractCallerFromBoundContract(contract *bind.BoundContract) DepositContractCaller { return DepositContractCaller{contract: contract} diff --git a/crypto/bls/blst/signature_test.go b/crypto/bls/blst/signature_test.go index 37f23020fc36..1a673f43b44b 100644 --- a/crypto/bls/blst/signature_test.go +++ b/crypto/bls/blst/signature_test.go @@ -44,7 +44,7 @@ func TestAggregateVerify(t *testing.T) { func TestAggregateVerify_CompressedSignatures(t *testing.T) { pubkeys := make([]common.PublicKey, 0, 100) sigs := make([]common.Signature, 0, 100) - sigBytes := [][]byte{} + var sigBytes [][]byte var msgs [][32]byte for i := 0; i < 100; i++ { msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)} diff --git a/crypto/bls/signature_batch_test.go b/crypto/bls/signature_batch_test.go index 07795bcd62b6..8c2df671a532 100644 --- a/crypto/bls/signature_batch_test.go +++ b/crypto/bls/signature_batch_test.go @@ -49,7 +49,7 @@ func TestCopySignatureSet(t *testing.T) { } func TestSignatureBatch_RemoveDuplicates(t *testing.T) { - keys := []SecretKey{} + var keys []SecretKey for i := 0; i < 100; i++ { key, err := RandKey() assert.NoError(t, err) @@ -73,9 +73,9 @@ func TestSignatureBatch_RemoveDuplicates(t *testing.T) { chosenKeys := keys[:20] msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -105,9 +105,9 @@ func TestSignatureBatch_RemoveDuplicates(t *testing.T) { msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys[:10] { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -149,9 +149,9 @@ func TestSignatureBatch_RemoveDuplicates(t *testing.T) { msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys[:10] { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -190,9 +190,9 @@ func TestSignatureBatch_RemoveDuplicates(t *testing.T) { msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys[:10] { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -242,9 +242,9 @@ func TestSignatureBatch_RemoveDuplicates(t *testing.T) { msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys[:10] { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -328,7 +328,7 @@ func TestSignatureBatch_RemoveDuplicates(t *testing.T) { } func TestSignatureBatch_AggregateBatch(t *testing.T) { - keys := []SecretKey{} + var keys []SecretKey for i := 0; i < 100; i++ { key, err := RandKey() assert.NoError(t, err) @@ -353,9 +353,9 @@ func TestSignatureBatch_AggregateBatch(t *testing.T) { chosenKeys := keys[:20] msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -383,9 +383,9 @@ func TestSignatureBatch_AggregateBatch(t *testing.T) { chosenKeys := keys[:20] msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -409,9 +409,9 @@ func TestSignatureBatch_AggregateBatch(t *testing.T) { msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys[:10] { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -459,9 +459,9 @@ func TestSignatureBatch_AggregateBatch(t *testing.T) { msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} - signatures := [][]byte{} - messages := [][32]byte{} - pubs := []PublicKey{} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey for _, k := range chosenKeys[:10] { s := k.Sign(msg[:]) signatures = append(signatures, s.Marshal()) @@ -485,7 +485,7 @@ func TestSignatureBatch_AggregateBatch(t *testing.T) { messages[15][31] ^= byte(100) messages[25][31] ^= byte(100) - newSigs := [][]byte{} + var newSigs [][]byte newSigs = append(newSigs, signatures[:5]...) newSigs = append(newSigs, signatures[6:10]...) @@ -504,7 +504,7 @@ func TestSignatureBatch_AggregateBatch(t *testing.T) { aggSig3, err := AggregateCompressedSignatures(newSigs) assert.NoError(t, err) - newPubs := []PublicKey{} + var newPubs []PublicKey newPubs = append(newPubs, pubs[:5]...) newPubs = append(newPubs, pubs[6:10]...) diff --git a/encoding/ssz/detect/BUILD.bazel b/encoding/ssz/detect/BUILD.bazel index 9d11e3fcd9b5..60d103b6a22f 100644 --- a/encoding/ssz/detect/BUILD.bazel +++ b/encoding/ssz/detect/BUILD.bazel @@ -42,7 +42,6 @@ go_test( "//consensus-types/primitives:go_default_library", "//consensus-types/wrapper:go_default_library", "//encoding/bytesutil:go_default_library", - "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "//testing/require:go_default_library", diff --git a/encoding/ssz/detect/configfork.go b/encoding/ssz/detect/configfork.go index 98cceadb1321..0149a7756ee9 100644 --- a/encoding/ssz/detect/configfork.go +++ b/encoding/ssz/detect/configfork.go @@ -136,7 +136,7 @@ func slotFromBlock(marshaled []byte) (types.Slot, error) { return types.Slot(slot), nil } -var errBlockForkMismatch = errors.New("fork or config detected from state is different than block") +var errBlockForkMismatch = errors.New("fork or config detected in unmarshaler is different than block") // UnmarshalBeaconBlock uses internal knowledge in the VersionedUnmarshaler to pick the right concrete SignedBeaconBlock type, // then Unmarshal()s the type and returns an instance of block.SignedBeaconBlock if successful. @@ -145,18 +145,39 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac if err != nil { return nil, err } + if err := cf.validateVersion(slot); err != nil { + return nil, err + } - // heuristic to make sure block is from the same version as the VersionedUnmarshaler. - // Look up the version for the epoch that the block is from, then ensure that it matches the Version in the - // VersionedUnmarshaler. - epoch := slots.ToEpoch(slot) - fs := forks.NewOrderedSchedule(cf.Config) - ver, err := fs.VersionForEpoch(epoch) + var blk ssz.Unmarshaler + switch cf.Fork { + case version.Phase0: + blk = ðpb.SignedBeaconBlock{} + case version.Altair: + blk = ðpb.SignedBeaconBlockAltair{} + case version.Bellatrix: + blk = ðpb.SignedBeaconBlockBellatrix{} + default: + forkName := version.String(cf.Fork) + return nil, fmt.Errorf("unable to initialize BeaconBlock for fork version=%s at slot=%d", forkName, slot) + } + err = blk.UnmarshalSSZ(marshaled) + if err != nil { + return nil, errors.Wrap(err, "failed to unmarshal SignedBeaconBlock in UnmarshalSSZ") + } + return wrapper.WrappedSignedBeaconBlock(blk) +} + +// UnmarshalBlindedBeaconBlock uses internal knowledge in the VersionedUnmarshaler to pick the right concrete blinded SignedBeaconBlock type, +// then Unmarshal()s the type and returns an instance of block.SignedBeaconBlock if successful. +// For Phase0 and Altair it works exactly line UnmarshalBeaconBlock. +func (cf *VersionedUnmarshaler) UnmarshalBlindedBeaconBlock(marshaled []byte) (interfaces.SignedBeaconBlock, error) { + slot, err := slotFromBlock(marshaled) if err != nil { return nil, err } - if ver != cf.Version { - return nil, errors.Wrapf(errBlockForkMismatch, "slot=%d, epoch=%d, version=%#x", slot, epoch, ver) + if err := cf.validateVersion(slot); err != nil { + return nil, err } var blk ssz.Unmarshaler @@ -166,7 +187,7 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac case version.Altair: blk = ðpb.SignedBeaconBlockAltair{} case version.Bellatrix: - blk = ðpb.SignedBeaconBlockBellatrix{} + blk = ðpb.SignedBlindedBeaconBlockBellatrix{} default: forkName := version.String(cf.Fork) return nil, fmt.Errorf("unable to initialize BeaconBlock for fork version=%s at slot=%d", forkName, slot) @@ -177,3 +198,19 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac } return wrapper.WrappedSignedBeaconBlock(blk) } + +// Heuristic to make sure block is from the same version as the VersionedUnmarshaler. +// Look up the version for the epoch that the block is from, then ensure that it matches the Version in the +// VersionedUnmarshaler. +func (cf *VersionedUnmarshaler) validateVersion(slot types.Slot) error { + epoch := slots.ToEpoch(slot) + fs := forks.NewOrderedSchedule(cf.Config) + ver, err := fs.VersionForEpoch(epoch) + if err != nil { + return err + } + if ver != cf.Version { + return errors.Wrapf(errBlockForkMismatch, "slot=%d, epoch=%d, version=%#x", slot, epoch, ver) + } + return nil +} diff --git a/encoding/ssz/detect/configfork_test.go b/encoding/ssz/detect/configfork_test.go index 440554918af4..d1d7566e1426 100644 --- a/encoding/ssz/detect/configfork_test.go +++ b/encoding/ssz/detect/configfork_test.go @@ -16,13 +16,12 @@ import ( "github.com/prysmaticlabs/prysm/time/slots" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - v1 "github.com/prysmaticlabs/prysm/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" ) func TestSlotFromBlock(t *testing.T) { - b := testBlockGenesis() + b := util.NewBeaconBlock() var slot types.Slot = 3 b.Block.Slot = slot bb, err := b.MarshalSSZ() @@ -31,7 +30,7 @@ func TestSlotFromBlock(t *testing.T) { require.NoError(t, err) require.Equal(t, slot, sfb) - ba := testBlockAltair() + ba := util.NewBeaconBlockAltair() ba.Block.Slot = slot bab, err := ba.MarshalSSZ() require.NoError(t, err) @@ -39,7 +38,7 @@ func TestSlotFromBlock(t *testing.T) { require.NoError(t, err) require.Equal(t, slot, sfba) - bm := testBlockBellatrix() + bm := util.NewBeaconBlockBellatrix() bm.Block.Slot = slot bmb, err := ba.MarshalSSZ() require.NoError(t, err) @@ -277,125 +276,123 @@ func TestUnmarshalBlock(t *testing.T) { } } +func TestUnmarshalBlindedBlock(t *testing.T) { + bc, cleanup := hackBellatrixMaxuint() + defer cleanup() + require.Equal(t, types.Epoch(math.MaxUint32), params.KnownConfigs[params.MainnetName]().BellatrixForkEpoch) + genv := bytesutil.ToBytes4(bc.GenesisForkVersion) + altairv := bytesutil.ToBytes4(bc.AltairForkVersion) + bellav := bytesutil.ToBytes4(bc.BellatrixForkVersion) + altairS, err := slots.EpochStart(bc.AltairForkEpoch) + bellaS, err := slots.EpochStart(bc.BellatrixForkEpoch) + require.NoError(t, err) + cases := []struct { + b func(*testing.T, types.Slot) interfaces.SignedBeaconBlock + name string + version [4]byte + slot types.Slot + err error + }{ + { + name: "genesis - slot 0", + b: signedTestBlockGenesis, + version: genv, + }, + { + name: "last slot of phase 0", + b: signedTestBlockGenesis, + version: genv, + slot: altairS - 1, + }, + { + name: "first slot of altair", + b: signedTestBlockAltair, + version: altairv, + slot: altairS, + }, + { + name: "last slot of altair", + b: signedTestBlockAltair, + version: altairv, + slot: bellaS - 1, + }, + { + name: "first slot of bellatrix", + b: signedTestBlindedBlockBellatrix, + version: bellav, + slot: bellaS, + }, + { + name: "bellatrix block in altair slot", + b: signedTestBlindedBlockBellatrix, + version: bellav, + slot: bellaS - 1, + err: errBlockForkMismatch, + }, + { + name: "genesis block in altair slot", + b: signedTestBlockGenesis, + version: genv, + slot: bellaS - 1, + err: errBlockForkMismatch, + }, + { + name: "altair block in genesis slot", + b: signedTestBlockAltair, + version: altairv, + err: errBlockForkMismatch, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + b := c.b(t, c.slot) + marshaled, err := b.MarshalSSZ() + require.NoError(t, err) + cf, err := FromForkVersion(c.version) + require.NoError(t, err) + bcf, err := cf.UnmarshalBlindedBeaconBlock(marshaled) + if c.err != nil { + require.ErrorIs(t, err, c.err) + return + } + require.NoError(t, err) + expected, err := b.Block().HashTreeRoot() + require.NoError(t, err) + actual, err := bcf.Block().HashTreeRoot() + require.NoError(t, err) + require.Equal(t, expected, actual) + }) + } +} + func signedTestBlockGenesis(t *testing.T, slot types.Slot) interfaces.SignedBeaconBlock { - b := testBlockGenesis() + b := util.NewBeaconBlock() b.Block.Slot = slot s, err := wrapper.WrappedSignedBeaconBlock(b) require.NoError(t, err) return s } -func testBlockGenesis() *ethpb.SignedBeaconBlock { - return ðpb.SignedBeaconBlock{ - Block: ðpb.BeaconBlock{ - ProposerIndex: types.ValidatorIndex(0), - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - Body: ðpb.BeaconBlockBody{ - RandaoReveal: make([]byte, 96), - Graffiti: make([]byte, 32), - ProposerSlashings: []*ethpb.ProposerSlashing{}, - AttesterSlashings: []*ethpb.AttesterSlashing{}, - Attestations: []*ethpb.Attestation{}, - Deposits: []*ethpb.Deposit{}, - VoluntaryExits: []*ethpb.SignedVoluntaryExit{}, - Eth1Data: ðpb.Eth1Data{ - DepositRoot: make([]byte, 32), - DepositCount: 0, - BlockHash: make([]byte, 32), - }, - }, - }, - Signature: make([]byte, 96), - } -} - func signedTestBlockAltair(t *testing.T, slot types.Slot) interfaces.SignedBeaconBlock { - b := testBlockAltair() + b := util.NewBeaconBlockAltair() b.Block.Slot = slot s, err := wrapper.WrappedSignedBeaconBlock(b) require.NoError(t, err) return s } -func testBlockAltair() *ethpb.SignedBeaconBlockAltair { - return ðpb.SignedBeaconBlockAltair{ - Block: ðpb.BeaconBlockAltair{ - ProposerIndex: types.ValidatorIndex(0), - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - Body: ðpb.BeaconBlockBodyAltair{ - RandaoReveal: make([]byte, 96), - Eth1Data: ðpb.Eth1Data{ - DepositRoot: make([]byte, 32), - DepositCount: 0, - BlockHash: make([]byte, 32), - }, - Graffiti: make([]byte, 32), - ProposerSlashings: []*ethpb.ProposerSlashing{}, - AttesterSlashings: []*ethpb.AttesterSlashing{}, - Attestations: []*ethpb.Attestation{}, - Deposits: []*ethpb.Deposit{}, - VoluntaryExits: []*ethpb.SignedVoluntaryExit{}, - SyncAggregate: ðpb.SyncAggregate{ - SyncCommitteeBits: make([]byte, 64), - SyncCommitteeSignature: make([]byte, 96), - }, - }, - }, - Signature: make([]byte, 96), - } -} - func signedTestBlockBellatrix(t *testing.T, slot types.Slot) interfaces.SignedBeaconBlock { - b := testBlockBellatrix() + b := util.NewBeaconBlockBellatrix() b.Block.Slot = slot s, err := wrapper.WrappedSignedBeaconBlock(b) require.NoError(t, err) return s } -func testBlockBellatrix() *ethpb.SignedBeaconBlockBellatrix { - return ðpb.SignedBeaconBlockBellatrix{ - Block: ðpb.BeaconBlockBellatrix{ - ProposerIndex: types.ValidatorIndex(0), - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - Body: ðpb.BeaconBlockBodyBellatrix{ - RandaoReveal: make([]byte, 96), - Eth1Data: ðpb.Eth1Data{ - DepositRoot: make([]byte, 32), - DepositCount: 0, - BlockHash: make([]byte, 32), - }, - Graffiti: make([]byte, 32), - ProposerSlashings: []*ethpb.ProposerSlashing{}, - AttesterSlashings: []*ethpb.AttesterSlashing{}, - Attestations: []*ethpb.Attestation{}, - Deposits: []*ethpb.Deposit{}, - VoluntaryExits: []*ethpb.SignedVoluntaryExit{}, - SyncAggregate: ðpb.SyncAggregate{ - SyncCommitteeBits: make([]byte, 64), - SyncCommitteeSignature: make([]byte, 96), - }, - ExecutionPayload: &v1.ExecutionPayload{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, 32), - ReceiptsRoot: make([]byte, 32), - LogsBloom: make([]byte, 256), - BlockNumber: 0, - GasLimit: 0, - GasUsed: 0, - Timestamp: 0, - ExtraData: make([]byte, 32), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - Transactions: make([][]byte, 0), - PrevRandao: make([]byte, 32), - }, - }, - }, - Signature: make([]byte, 96), - } +func signedTestBlindedBlockBellatrix(t *testing.T, slot types.Slot) interfaces.SignedBeaconBlock { + b := util.NewBlindedBeaconBlockBellatrix() + b.Block.Slot = slot + s, err := wrapper.WrappedSignedBeaconBlock(b) + require.NoError(t, err) + return s } diff --git a/network/forks/ordered.go b/network/forks/ordered.go index c644784b61d9..97fc63aec7c8 100644 --- a/network/forks/ordered.go +++ b/network/forks/ordered.go @@ -2,6 +2,7 @@ package forks import ( "sort" + "strings" "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" @@ -13,10 +14,11 @@ import ( type ForkScheduleEntry struct { Version [fieldparams.VersionLength]byte Epoch types.Epoch + Name string } // OrderedSchedule provides a type that can be used to sort the fork schedule and find the Version -// the chain should be at for a given epoch (via VersionForEpoch). +// the chain should be at for a given epoch (via VersionForEpoch) or name (via VersionForName). type OrderedSchedule []ForkScheduleEntry // Len implements the Len method of sort.Interface @@ -38,6 +40,17 @@ func (o OrderedSchedule) VersionForEpoch(epoch types.Epoch) ([fieldparams.Versio return [fieldparams.VersionLength]byte{}, errors.Wrapf(ErrVersionNotFound, "no epoch in list <= %d", epoch) } +// VersionForName finds the Version corresponding to the lowercase version of the provided name. +func (o OrderedSchedule) VersionForName(name string) ([fieldparams.VersionLength]byte, error) { + lower := strings.ToLower(name) + for _, e := range o { + if e.Name == lower { + return e.Version, nil + } + } + return [4]byte{}, errors.Wrapf(ErrVersionNotFound, "no version with name %s", lower) +} + func (o OrderedSchedule) Previous(version [fieldparams.VersionLength]byte) ([fieldparams.VersionLength]byte, error) { for i := len(o) - 1; i >= 0; i-- { if o[i].Version == version { @@ -51,7 +64,7 @@ func (o OrderedSchedule) Previous(version [fieldparams.VersionLength]byte) ([fie return [fieldparams.VersionLength]byte{}, errors.Wrapf(ErrVersionNotFound, "no version in list == %#x", version) } -// Converts the ForkVersionSchedule map into a list of Version+Epoch values, ordered by Epoch from lowest to highest. +// NewOrderedSchedule Converts fork version maps into a list of Version+Epoch+Name values, ordered by Epoch from lowest to highest. // See docs for OrderedSchedule for more detail on what you can do with this type. func NewOrderedSchedule(b *params.BeaconChainConfig) OrderedSchedule { ofs := make(OrderedSchedule, 0) @@ -59,6 +72,7 @@ func NewOrderedSchedule(b *params.BeaconChainConfig) OrderedSchedule { fse := ForkScheduleEntry{ Version: version, Epoch: epoch, + Name: b.ForkVersionNames[version], } ofs = append(ofs, fse) } diff --git a/network/forks/ordered_test.go b/network/forks/ordered_test.go index 4916f935b429..c372d4d61f25 100644 --- a/network/forks/ordered_test.go +++ b/network/forks/ordered_test.go @@ -35,7 +35,7 @@ func TestOrderedConfigSchedule(t *testing.T) { }) } - bc := testForkVersionScheduleBCC() + bc := testForkVersionBCC() ofs := NewOrderedSchedule(bc) for i := range ofs { if ofs[i].Epoch != types.Epoch(math.Pow(2, float64(i))) { @@ -45,7 +45,7 @@ func TestOrderedConfigSchedule(t *testing.T) { } func TestVersionForEpoch(t *testing.T) { - bc := testForkVersionScheduleBCC() + bc := testForkVersionBCC() ofs := NewOrderedSchedule(bc) testCases := []struct { name string @@ -92,7 +92,45 @@ func TestVersionForEpoch(t *testing.T) { } } -func testForkVersionScheduleBCC() *params.BeaconChainConfig { +func TestVersionForName(t *testing.T) { + bc := testForkVersionBCC() + ofs := NewOrderedSchedule(bc) + testCases := []struct { + testName string + version [4]byte + versionName string + err error + }{ + { + testName: "found", + version: [4]byte{2, 1, 2, 3}, + versionName: "third", + }, + { + testName: "found lowercase", + version: [4]byte{4, 1, 2, 3}, + versionName: "FiFtH", + }, + { + testName: "not found", + versionName: "nonexistent", + err: ErrVersionNotFound, + }, + } + for _, tc := range testCases { + t.Run(tc.testName, func(t *testing.T) { + v, err := ofs.VersionForName(tc.versionName) + if tc.err == nil { + require.NoError(t, err) + } else { + require.ErrorIs(t, err, tc.err) + } + require.Equal(t, tc.version, v) + }) + } +} + +func testForkVersionBCC() *params.BeaconChainConfig { return ¶ms.BeaconChainConfig{ ForkVersionSchedule: map[[4]byte]types.Epoch{ {1, 1, 2, 3}: types.Epoch(2), @@ -101,11 +139,18 @@ func testForkVersionScheduleBCC() *params.BeaconChainConfig { {3, 1, 2, 3}: types.Epoch(8), {2, 1, 2, 3}: types.Epoch(4), }, + ForkVersionNames: map[[4]byte]string{ + {1, 1, 2, 3}: "second", + {0, 1, 2, 3}: "first", + {4, 1, 2, 3}: "fifth", + {3, 1, 2, 3}: "fourth", + {2, 1, 2, 3}: "third", + }, } } func TestPrevious(t *testing.T) { - cfg := testForkVersionScheduleBCC() + cfg := testForkVersionBCC() os := NewOrderedSchedule(cfg) unreal := [4]byte{255, 255, 255, 255} _, err := os.Previous(unreal) diff --git a/proto/engine/v1/execution_engine.pb.go b/proto/engine/v1/execution_engine.pb.go index 7b5292017969..70f6d75407a1 100755 --- a/proto/engine/v1/execution_engine.pb.go +++ b/proto/engine/v1/execution_engine.pb.go @@ -25,13 +25,12 @@ const ( type PayloadStatus_Status int32 const ( - PayloadStatus_UNKNOWN PayloadStatus_Status = 0 - PayloadStatus_VALID PayloadStatus_Status = 1 - PayloadStatus_INVALID PayloadStatus_Status = 2 - PayloadStatus_SYNCING PayloadStatus_Status = 3 - PayloadStatus_ACCEPTED PayloadStatus_Status = 4 - PayloadStatus_INVALID_BLOCK_HASH PayloadStatus_Status = 5 - PayloadStatus_INVALID_TERMINAL_BLOCK PayloadStatus_Status = 6 + PayloadStatus_UNKNOWN PayloadStatus_Status = 0 + PayloadStatus_VALID PayloadStatus_Status = 1 + PayloadStatus_INVALID PayloadStatus_Status = 2 + PayloadStatus_SYNCING PayloadStatus_Status = 3 + PayloadStatus_ACCEPTED PayloadStatus_Status = 4 + PayloadStatus_INVALID_BLOCK_HASH PayloadStatus_Status = 5 ) // Enum value maps for PayloadStatus_Status. @@ -43,16 +42,14 @@ var ( 3: "SYNCING", 4: "ACCEPTED", 5: "INVALID_BLOCK_HASH", - 6: "INVALID_TERMINAL_BLOCK", } PayloadStatus_Status_value = map[string]int32{ - "UNKNOWN": 0, - "VALID": 1, - "INVALID": 2, - "SYNCING": 3, - "ACCEPTED": 4, - "INVALID_BLOCK_HASH": 5, - "INVALID_TERMINAL_BLOCK": 6, + "UNKNOWN": 0, + "VALID": 1, + "INVALID": 2, + "SYNCING": 3, + "ACCEPTED": 4, + "INVALID_BLOCK_HASH": 5, } ) @@ -988,7 +985,7 @@ var file_proto_engine_v1_execution_engine_proto_rawDesc = []byte{ 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x15, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, - 0x74, 0x22, 0xae, 0x02, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, + 0x74, 0x22, 0x92, 0x02, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x40, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, @@ -999,35 +996,34 @@ var file_proto_engine_v1_execution_engine_proto_rawDesc = []byte{ 0x56, 0x61, 0x6c, 0x69, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7c, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, + 0x72, 0x72, 0x6f, 0x72, 0x22, 0x60, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, - 0x48, 0x41, 0x53, 0x48, 0x10, 0x05, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, - 0x44, 0x5f, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, - 0x10, 0x06, 0x22, 0xab, 0x01, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x6b, 0x63, 0x68, 0x6f, 0x69, 0x63, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x68, 0x65, 0x61, 0x64, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x0f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x73, 0x61, 0x66, 0x65, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x38, 0x0a, 0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x12, 0x66, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, - 0x42, 0x93, 0x01, 0x0a, 0x16, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, - 0x2f, 0x76, 0x31, 0x3b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x76, 0x31, 0xaa, 0x02, 0x12, 0x45, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x56, - 0x31, 0xca, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x6e, 0x67, - 0x69, 0x6e, 0x65, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x48, 0x41, 0x53, 0x48, 0x10, 0x05, 0x22, 0xab, 0x01, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x6b, 0x63, + 0x68, 0x6f, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x0f, 0x68, 0x65, + 0x61, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x68, 0x65, 0x61, + 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x0f, 0x73, 0x61, + 0x66, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x73, 0x61, 0x66, + 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x38, 0x0a, 0x14, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x48, 0x61, 0x73, 0x68, 0x42, 0x93, 0x01, 0x0a, 0x16, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x42, + 0x14, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x76, 0x31, + 0xaa, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x5c, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/proto/engine/v1/execution_engine.proto b/proto/engine/v1/execution_engine.proto index a1251b5620cc..0c969c2afbb4 100644 --- a/proto/engine/v1/execution_engine.proto +++ b/proto/engine/v1/execution_engine.proto @@ -105,7 +105,6 @@ message PayloadStatus { SYNCING = 3; ACCEPTED = 4; INVALID_BLOCK_HASH = 5; - INVALID_TERMINAL_BLOCK = 6; } } diff --git a/proto/eth/service/beacon_chain_service.pb.go b/proto/eth/service/beacon_chain_service.pb.go index 00dd92c5e4fe..6a97a6cb322d 100755 --- a/proto/eth/service/beacon_chain_service.pb.go +++ b/proto/eth/service/beacon_chain_service.pb.go @@ -48,134 +48,143 @@ var file_proto_eth_service_beacon_chain_service_proto_rawDesc = []byte{ 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x32, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x8c, 0x25, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x6f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x47, 0x65, - 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x8b, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, - 0x57, 0x65, 0x61, 0x6b, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x65, 0x61, 0x6b, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x77, 0x65, 0x61, 0x6b, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x89, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, - 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, - 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x46, - 0x6f, 0x72, 0x6b, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, - 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, - 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0xb1, - 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x40, 0x12, 0x3e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, + 0x76, 0x32, 0x2f, 0x73, 0x73, 0x7a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, + 0x86, 0x27, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, + 0x6f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, + 0x1f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, + 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, + 0x12, 0x8b, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, 0x65, 0x61, 0x6b, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x57, 0x65, 0x61, 0x6b, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x77, 0x65, 0x61, + 0x6b, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x89, + 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, + 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, - 0x12, 0x34, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, - 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0xac, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x45, - 0x12, 0x43, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, - 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0xb4, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, - 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x12, 0x3c, - 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, - 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0xa1, 0x01, 0x0a, - 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, - 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x12, 0x34, 0x2f, 0x69, 0x6e, 0x74, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, - 0x12, 0xb2, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, - 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x41, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3b, 0x12, 0x39, 0x2f, 0x69, 0x6e, 0x74, + 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x0c, 0x47, + 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x1d, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0xb1, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x73, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x46, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x40, 0x12, 0x3e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, - 0x1f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, - 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x12, 0x89, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x0e, 0x4c, + 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x27, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x12, 0x34, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, + 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0xac, + 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, + 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x4b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x45, 0x12, 0x43, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, + 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0xb4, 0x01, + 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x12, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x36, 0x12, 0x34, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0xb2, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, + 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x41, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x3b, 0x12, 0x39, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x79, + 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x88, 0x01, + 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x73, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, - 0x12, 0x2a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x7f, 0x0a, 0x0b, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2d, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, 0x32, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x1e, 0x2f, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x93, 0x01, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x89, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1d, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x12, 0x2a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x7f, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x56, 0x32, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x23, 0x22, 0x1e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x76, 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x53, 0x5a, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x22, 0x22, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x73, 0x7a, 0x3a, 0x01, 0x2a, 0x12, 0x93, 0x01, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, @@ -185,179 +194,187 @@ var file_proto_eth_service_beacon_chain_service_proto_rawDesc = []byte{ 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x26, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, - 0x3a, 0x01, 0x2a, 0x12, 0x89, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, - 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, - 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, - 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x12, - 0x7c, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x86, 0x01, - 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x12, 0x1d, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x65, + 0x3a, 0x01, 0x2a, 0x12, 0x85, 0x01, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, + 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x12, 0x1d, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, + 0x53, 0x53, 0x5a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x22, 0x2a, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x73, 0x7a, 0x3a, 0x01, 0x2a, 0x12, 0x89, 0x01, 0x0a, 0x0c, + 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, - 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0x82, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x56, 0x32, 0x12, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x32, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, - 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, - 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x8c, 0x01, 0x0a, 0x0d, - 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x56, 0x32, 0x12, 0x1f, 0x2e, + 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x7c, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x86, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, + 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, + 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, + 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0x82, + 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x32, 0x12, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x1a, 0x23, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x56, 0x32, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0xa2, 0x01, 0x0a, 0x15, 0x4c, - 0x69, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x3e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x32, + 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, + 0x69, 0x64, 0x7d, 0x12, 0x86, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x53, 0x53, 0x5a, 0x56, 0x32, 0x12, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x1a, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x53, 0x5a, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, + 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0xa2, 0x01, 0x0a, + 0x15, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x3e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x9e, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, - 0x64, 0x7d, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x9e, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x34, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x22, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x8e, 0x01, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x34, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x2e, 0x22, 0x29, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, - 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x01, - 0x2a, 0x12, 0x9c, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, + 0x3a, 0x01, 0x2a, 0x12, 0x9c, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x6f, 0x6f, + 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x31, 0x12, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, + 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, + 0x22, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, + 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9b, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, + 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6f, + 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x31, 0x12, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, + 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, + 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, + 0x22, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, + 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x70, + 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x93, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, + 0x6c, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, - 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, - 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x8f, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x2f, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, + 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, + 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x13, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, + 0x69, 0x74, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, + 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x22, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, + 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xa8, 0x01, 0x0a, 0x21, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, + 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x32, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x79, 0x6e, 0x63, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x37, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x31, 0x22, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, + 0x6c, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, + 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x7f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x53, + 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, - 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x3a, - 0x01, 0x2a, 0x12, 0x9b, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x50, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, + 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x73, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6f, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, - 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, - 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x8f, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x2f, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x65, 0x63, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, + 0x1c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, + 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x12, 0x88, 0x01, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, - 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x70, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x3a, - 0x01, 0x2a, 0x12, 0x93, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x56, - 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, - 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, - 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, - 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, - 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x37, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x22, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, - 0x70, 0x6f, 0x6f, 0x6c, 0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, - 0x78, 0x69, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xa8, 0x01, 0x0a, 0x21, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x32, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x31, 0x22, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, - 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2f, - 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x3a, - 0x01, 0x2a, 0x12, 0x7f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x63, 0x68, - 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x25, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, - 0x75, 0x6c, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x12, 0x88, 0x01, 0x0a, 0x12, - 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x42, 0x95, 0x01, 0x0a, 0x18, 0x6f, 0x72, 0x67, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x42, 0x17, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x42, 0x95, 0x01, 0x0a, 0x18, 0x6f, 0x72, 0x67, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x17, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, + 0x68, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_proto_eth_service_beacon_chain_service_proto_goTypes = []interface{}{ @@ -371,31 +388,31 @@ var file_proto_eth_service_beacon_chain_service_proto_goTypes = []interface{}{ (*v1.BlockHeadersRequest)(nil), // 7: ethereum.eth.v1.BlockHeadersRequest (*v1.BlockRequest)(nil), // 8: ethereum.eth.v1.BlockRequest (*v2.SignedBeaconBlockContainerV2)(nil), // 9: ethereum.eth.v2.SignedBeaconBlockContainerV2 - (*v2.SignedBlindedBeaconBlockContainer)(nil), // 10: ethereum.eth.v2.SignedBlindedBeaconBlockContainer - (*v2.BlockRequestV2)(nil), // 11: ethereum.eth.v2.BlockRequestV2 - (*v1.AttestationsPoolRequest)(nil), // 12: ethereum.eth.v1.AttestationsPoolRequest - (*v1.SubmitAttestationsRequest)(nil), // 13: ethereum.eth.v1.SubmitAttestationsRequest - (*v1.AttesterSlashing)(nil), // 14: ethereum.eth.v1.AttesterSlashing - (*v1.ProposerSlashing)(nil), // 15: ethereum.eth.v1.ProposerSlashing - (*v1.SignedVoluntaryExit)(nil), // 16: ethereum.eth.v1.SignedVoluntaryExit - (*v2.SubmitPoolSyncCommitteeSignatures)(nil), // 17: ethereum.eth.v2.SubmitPoolSyncCommitteeSignatures - (*v1.GenesisResponse)(nil), // 18: ethereum.eth.v1.GenesisResponse - (*v1.WeakSubjectivityResponse)(nil), // 19: ethereum.eth.v1.WeakSubjectivityResponse - (*v1.StateRootResponse)(nil), // 20: ethereum.eth.v1.StateRootResponse - (*v1.StateForkResponse)(nil), // 21: ethereum.eth.v1.StateForkResponse - (*v1.StateFinalityCheckpointResponse)(nil), // 22: ethereum.eth.v1.StateFinalityCheckpointResponse - (*v1.StateValidatorsResponse)(nil), // 23: ethereum.eth.v1.StateValidatorsResponse - (*v1.StateValidatorResponse)(nil), // 24: ethereum.eth.v1.StateValidatorResponse - (*v1.ValidatorBalancesResponse)(nil), // 25: ethereum.eth.v1.ValidatorBalancesResponse - (*v1.StateCommitteesResponse)(nil), // 26: ethereum.eth.v1.StateCommitteesResponse - (*v2.StateSyncCommitteesResponse)(nil), // 27: ethereum.eth.v2.StateSyncCommitteesResponse - (*v1.BlockHeadersResponse)(nil), // 28: ethereum.eth.v1.BlockHeadersResponse - (*v1.BlockHeaderResponse)(nil), // 29: ethereum.eth.v1.BlockHeaderResponse - (*v1.BlockRootResponse)(nil), // 30: ethereum.eth.v1.BlockRootResponse - (*v1.BlockResponse)(nil), // 31: ethereum.eth.v1.BlockResponse - (*v1.BlockSSZResponse)(nil), // 32: ethereum.eth.v1.BlockSSZResponse - (*v2.BlockResponseV2)(nil), // 33: ethereum.eth.v2.BlockResponseV2 - (*v2.BlockSSZResponseV2)(nil), // 34: ethereum.eth.v2.BlockSSZResponseV2 + (*v2.SSZContainer)(nil), // 10: ethereum.eth.v2.SSZContainer + (*v2.SignedBlindedBeaconBlockContainer)(nil), // 11: ethereum.eth.v2.SignedBlindedBeaconBlockContainer + (*v2.BlockRequestV2)(nil), // 12: ethereum.eth.v2.BlockRequestV2 + (*v1.AttestationsPoolRequest)(nil), // 13: ethereum.eth.v1.AttestationsPoolRequest + (*v1.SubmitAttestationsRequest)(nil), // 14: ethereum.eth.v1.SubmitAttestationsRequest + (*v1.AttesterSlashing)(nil), // 15: ethereum.eth.v1.AttesterSlashing + (*v1.ProposerSlashing)(nil), // 16: ethereum.eth.v1.ProposerSlashing + (*v1.SignedVoluntaryExit)(nil), // 17: ethereum.eth.v1.SignedVoluntaryExit + (*v2.SubmitPoolSyncCommitteeSignatures)(nil), // 18: ethereum.eth.v2.SubmitPoolSyncCommitteeSignatures + (*v1.GenesisResponse)(nil), // 19: ethereum.eth.v1.GenesisResponse + (*v1.WeakSubjectivityResponse)(nil), // 20: ethereum.eth.v1.WeakSubjectivityResponse + (*v1.StateRootResponse)(nil), // 21: ethereum.eth.v1.StateRootResponse + (*v1.StateForkResponse)(nil), // 22: ethereum.eth.v1.StateForkResponse + (*v1.StateFinalityCheckpointResponse)(nil), // 23: ethereum.eth.v1.StateFinalityCheckpointResponse + (*v1.StateValidatorsResponse)(nil), // 24: ethereum.eth.v1.StateValidatorsResponse + (*v1.StateValidatorResponse)(nil), // 25: ethereum.eth.v1.StateValidatorResponse + (*v1.ValidatorBalancesResponse)(nil), // 26: ethereum.eth.v1.ValidatorBalancesResponse + (*v1.StateCommitteesResponse)(nil), // 27: ethereum.eth.v1.StateCommitteesResponse + (*v2.StateSyncCommitteesResponse)(nil), // 28: ethereum.eth.v2.StateSyncCommitteesResponse + (*v1.BlockHeadersResponse)(nil), // 29: ethereum.eth.v1.BlockHeadersResponse + (*v1.BlockHeaderResponse)(nil), // 30: ethereum.eth.v1.BlockHeaderResponse + (*v1.BlockRootResponse)(nil), // 31: ethereum.eth.v1.BlockRootResponse + (*v1.BlockResponse)(nil), // 32: ethereum.eth.v1.BlockResponse + (*v1.BlockSSZResponse)(nil), // 33: ethereum.eth.v1.BlockSSZResponse + (*v2.BlockResponseV2)(nil), // 34: ethereum.eth.v2.BlockResponseV2 (*v1.BlockAttestationsResponse)(nil), // 35: ethereum.eth.v1.BlockAttestationsResponse (*v1.AttestationsPoolResponse)(nil), // 36: ethereum.eth.v1.AttestationsPoolResponse (*v1.AttesterSlashingsPoolResponse)(nil), // 37: ethereum.eth.v1.AttesterSlashingsPoolResponse @@ -419,59 +436,63 @@ var file_proto_eth_service_beacon_chain_service_proto_depIdxs = []int32{ 7, // 10: ethereum.eth.service.BeaconChain.ListBlockHeaders:input_type -> ethereum.eth.v1.BlockHeadersRequest 8, // 11: ethereum.eth.service.BeaconChain.GetBlockHeader:input_type -> ethereum.eth.v1.BlockRequest 9, // 12: ethereum.eth.service.BeaconChain.SubmitBlock:input_type -> ethereum.eth.v2.SignedBeaconBlockContainerV2 - 10, // 13: ethereum.eth.service.BeaconChain.SubmitBlindedBlock:input_type -> ethereum.eth.v2.SignedBlindedBeaconBlockContainer - 8, // 14: ethereum.eth.service.BeaconChain.GetBlockRoot:input_type -> ethereum.eth.v1.BlockRequest - 8, // 15: ethereum.eth.service.BeaconChain.GetBlock:input_type -> ethereum.eth.v1.BlockRequest - 8, // 16: ethereum.eth.service.BeaconChain.GetBlockSSZ:input_type -> ethereum.eth.v1.BlockRequest - 11, // 17: ethereum.eth.service.BeaconChain.GetBlockV2:input_type -> ethereum.eth.v2.BlockRequestV2 - 11, // 18: ethereum.eth.service.BeaconChain.GetBlockSSZV2:input_type -> ethereum.eth.v2.BlockRequestV2 - 8, // 19: ethereum.eth.service.BeaconChain.ListBlockAttestations:input_type -> ethereum.eth.v1.BlockRequest - 12, // 20: ethereum.eth.service.BeaconChain.ListPoolAttestations:input_type -> ethereum.eth.v1.AttestationsPoolRequest - 13, // 21: ethereum.eth.service.BeaconChain.SubmitAttestations:input_type -> ethereum.eth.v1.SubmitAttestationsRequest - 0, // 22: ethereum.eth.service.BeaconChain.ListPoolAttesterSlashings:input_type -> google.protobuf.Empty - 14, // 23: ethereum.eth.service.BeaconChain.SubmitAttesterSlashing:input_type -> ethereum.eth.v1.AttesterSlashing - 0, // 24: ethereum.eth.service.BeaconChain.ListPoolProposerSlashings:input_type -> google.protobuf.Empty - 15, // 25: ethereum.eth.service.BeaconChain.SubmitProposerSlashing:input_type -> ethereum.eth.v1.ProposerSlashing - 0, // 26: ethereum.eth.service.BeaconChain.ListPoolVoluntaryExits:input_type -> google.protobuf.Empty - 16, // 27: ethereum.eth.service.BeaconChain.SubmitVoluntaryExit:input_type -> ethereum.eth.v1.SignedVoluntaryExit - 17, // 28: ethereum.eth.service.BeaconChain.SubmitPoolSyncCommitteeSignatures:input_type -> ethereum.eth.v2.SubmitPoolSyncCommitteeSignatures - 0, // 29: ethereum.eth.service.BeaconChain.GetForkSchedule:input_type -> google.protobuf.Empty - 0, // 30: ethereum.eth.service.BeaconChain.GetSpec:input_type -> google.protobuf.Empty - 0, // 31: ethereum.eth.service.BeaconChain.GetDepositContract:input_type -> google.protobuf.Empty - 18, // 32: ethereum.eth.service.BeaconChain.GetGenesis:output_type -> ethereum.eth.v1.GenesisResponse - 19, // 33: ethereum.eth.service.BeaconChain.GetWeakSubjectivity:output_type -> ethereum.eth.v1.WeakSubjectivityResponse - 20, // 34: ethereum.eth.service.BeaconChain.GetStateRoot:output_type -> ethereum.eth.v1.StateRootResponse - 21, // 35: ethereum.eth.service.BeaconChain.GetStateFork:output_type -> ethereum.eth.v1.StateForkResponse - 22, // 36: ethereum.eth.service.BeaconChain.GetFinalityCheckpoints:output_type -> ethereum.eth.v1.StateFinalityCheckpointResponse - 23, // 37: ethereum.eth.service.BeaconChain.ListValidators:output_type -> ethereum.eth.v1.StateValidatorsResponse - 24, // 38: ethereum.eth.service.BeaconChain.GetValidator:output_type -> ethereum.eth.v1.StateValidatorResponse - 25, // 39: ethereum.eth.service.BeaconChain.ListValidatorBalances:output_type -> ethereum.eth.v1.ValidatorBalancesResponse - 26, // 40: ethereum.eth.service.BeaconChain.ListCommittees:output_type -> ethereum.eth.v1.StateCommitteesResponse - 27, // 41: ethereum.eth.service.BeaconChain.ListSyncCommittees:output_type -> ethereum.eth.v2.StateSyncCommitteesResponse - 28, // 42: ethereum.eth.service.BeaconChain.ListBlockHeaders:output_type -> ethereum.eth.v1.BlockHeadersResponse - 29, // 43: ethereum.eth.service.BeaconChain.GetBlockHeader:output_type -> ethereum.eth.v1.BlockHeaderResponse - 0, // 44: ethereum.eth.service.BeaconChain.SubmitBlock:output_type -> google.protobuf.Empty - 0, // 45: ethereum.eth.service.BeaconChain.SubmitBlindedBlock:output_type -> google.protobuf.Empty - 30, // 46: ethereum.eth.service.BeaconChain.GetBlockRoot:output_type -> ethereum.eth.v1.BlockRootResponse - 31, // 47: ethereum.eth.service.BeaconChain.GetBlock:output_type -> ethereum.eth.v1.BlockResponse - 32, // 48: ethereum.eth.service.BeaconChain.GetBlockSSZ:output_type -> ethereum.eth.v1.BlockSSZResponse - 33, // 49: ethereum.eth.service.BeaconChain.GetBlockV2:output_type -> ethereum.eth.v2.BlockResponseV2 - 34, // 50: ethereum.eth.service.BeaconChain.GetBlockSSZV2:output_type -> ethereum.eth.v2.BlockSSZResponseV2 - 35, // 51: ethereum.eth.service.BeaconChain.ListBlockAttestations:output_type -> ethereum.eth.v1.BlockAttestationsResponse - 36, // 52: ethereum.eth.service.BeaconChain.ListPoolAttestations:output_type -> ethereum.eth.v1.AttestationsPoolResponse - 0, // 53: ethereum.eth.service.BeaconChain.SubmitAttestations:output_type -> google.protobuf.Empty - 37, // 54: ethereum.eth.service.BeaconChain.ListPoolAttesterSlashings:output_type -> ethereum.eth.v1.AttesterSlashingsPoolResponse - 0, // 55: ethereum.eth.service.BeaconChain.SubmitAttesterSlashing:output_type -> google.protobuf.Empty - 38, // 56: ethereum.eth.service.BeaconChain.ListPoolProposerSlashings:output_type -> ethereum.eth.v1.ProposerSlashingPoolResponse - 0, // 57: ethereum.eth.service.BeaconChain.SubmitProposerSlashing:output_type -> google.protobuf.Empty - 39, // 58: ethereum.eth.service.BeaconChain.ListPoolVoluntaryExits:output_type -> ethereum.eth.v1.VoluntaryExitsPoolResponse - 0, // 59: ethereum.eth.service.BeaconChain.SubmitVoluntaryExit:output_type -> google.protobuf.Empty - 0, // 60: ethereum.eth.service.BeaconChain.SubmitPoolSyncCommitteeSignatures:output_type -> google.protobuf.Empty - 40, // 61: ethereum.eth.service.BeaconChain.GetForkSchedule:output_type -> ethereum.eth.v1.ForkScheduleResponse - 41, // 62: ethereum.eth.service.BeaconChain.GetSpec:output_type -> ethereum.eth.v1.SpecResponse - 42, // 63: ethereum.eth.service.BeaconChain.GetDepositContract:output_type -> ethereum.eth.v1.DepositContractResponse - 32, // [32:64] is the sub-list for method output_type - 0, // [0:32] is the sub-list for method input_type + 10, // 13: ethereum.eth.service.BeaconChain.SubmitBlockSSZ:input_type -> ethereum.eth.v2.SSZContainer + 11, // 14: ethereum.eth.service.BeaconChain.SubmitBlindedBlock:input_type -> ethereum.eth.v2.SignedBlindedBeaconBlockContainer + 10, // 15: ethereum.eth.service.BeaconChain.SubmitBlindedBlockSSZ:input_type -> ethereum.eth.v2.SSZContainer + 8, // 16: ethereum.eth.service.BeaconChain.GetBlockRoot:input_type -> ethereum.eth.v1.BlockRequest + 8, // 17: ethereum.eth.service.BeaconChain.GetBlock:input_type -> ethereum.eth.v1.BlockRequest + 8, // 18: ethereum.eth.service.BeaconChain.GetBlockSSZ:input_type -> ethereum.eth.v1.BlockRequest + 12, // 19: ethereum.eth.service.BeaconChain.GetBlockV2:input_type -> ethereum.eth.v2.BlockRequestV2 + 12, // 20: ethereum.eth.service.BeaconChain.GetBlockSSZV2:input_type -> ethereum.eth.v2.BlockRequestV2 + 8, // 21: ethereum.eth.service.BeaconChain.ListBlockAttestations:input_type -> ethereum.eth.v1.BlockRequest + 13, // 22: ethereum.eth.service.BeaconChain.ListPoolAttestations:input_type -> ethereum.eth.v1.AttestationsPoolRequest + 14, // 23: ethereum.eth.service.BeaconChain.SubmitAttestations:input_type -> ethereum.eth.v1.SubmitAttestationsRequest + 0, // 24: ethereum.eth.service.BeaconChain.ListPoolAttesterSlashings:input_type -> google.protobuf.Empty + 15, // 25: ethereum.eth.service.BeaconChain.SubmitAttesterSlashing:input_type -> ethereum.eth.v1.AttesterSlashing + 0, // 26: ethereum.eth.service.BeaconChain.ListPoolProposerSlashings:input_type -> google.protobuf.Empty + 16, // 27: ethereum.eth.service.BeaconChain.SubmitProposerSlashing:input_type -> ethereum.eth.v1.ProposerSlashing + 0, // 28: ethereum.eth.service.BeaconChain.ListPoolVoluntaryExits:input_type -> google.protobuf.Empty + 17, // 29: ethereum.eth.service.BeaconChain.SubmitVoluntaryExit:input_type -> ethereum.eth.v1.SignedVoluntaryExit + 18, // 30: ethereum.eth.service.BeaconChain.SubmitPoolSyncCommitteeSignatures:input_type -> ethereum.eth.v2.SubmitPoolSyncCommitteeSignatures + 0, // 31: ethereum.eth.service.BeaconChain.GetForkSchedule:input_type -> google.protobuf.Empty + 0, // 32: ethereum.eth.service.BeaconChain.GetSpec:input_type -> google.protobuf.Empty + 0, // 33: ethereum.eth.service.BeaconChain.GetDepositContract:input_type -> google.protobuf.Empty + 19, // 34: ethereum.eth.service.BeaconChain.GetGenesis:output_type -> ethereum.eth.v1.GenesisResponse + 20, // 35: ethereum.eth.service.BeaconChain.GetWeakSubjectivity:output_type -> ethereum.eth.v1.WeakSubjectivityResponse + 21, // 36: ethereum.eth.service.BeaconChain.GetStateRoot:output_type -> ethereum.eth.v1.StateRootResponse + 22, // 37: ethereum.eth.service.BeaconChain.GetStateFork:output_type -> ethereum.eth.v1.StateForkResponse + 23, // 38: ethereum.eth.service.BeaconChain.GetFinalityCheckpoints:output_type -> ethereum.eth.v1.StateFinalityCheckpointResponse + 24, // 39: ethereum.eth.service.BeaconChain.ListValidators:output_type -> ethereum.eth.v1.StateValidatorsResponse + 25, // 40: ethereum.eth.service.BeaconChain.GetValidator:output_type -> ethereum.eth.v1.StateValidatorResponse + 26, // 41: ethereum.eth.service.BeaconChain.ListValidatorBalances:output_type -> ethereum.eth.v1.ValidatorBalancesResponse + 27, // 42: ethereum.eth.service.BeaconChain.ListCommittees:output_type -> ethereum.eth.v1.StateCommitteesResponse + 28, // 43: ethereum.eth.service.BeaconChain.ListSyncCommittees:output_type -> ethereum.eth.v2.StateSyncCommitteesResponse + 29, // 44: ethereum.eth.service.BeaconChain.ListBlockHeaders:output_type -> ethereum.eth.v1.BlockHeadersResponse + 30, // 45: ethereum.eth.service.BeaconChain.GetBlockHeader:output_type -> ethereum.eth.v1.BlockHeaderResponse + 0, // 46: ethereum.eth.service.BeaconChain.SubmitBlock:output_type -> google.protobuf.Empty + 0, // 47: ethereum.eth.service.BeaconChain.SubmitBlockSSZ:output_type -> google.protobuf.Empty + 0, // 48: ethereum.eth.service.BeaconChain.SubmitBlindedBlock:output_type -> google.protobuf.Empty + 0, // 49: ethereum.eth.service.BeaconChain.SubmitBlindedBlockSSZ:output_type -> google.protobuf.Empty + 31, // 50: ethereum.eth.service.BeaconChain.GetBlockRoot:output_type -> ethereum.eth.v1.BlockRootResponse + 32, // 51: ethereum.eth.service.BeaconChain.GetBlock:output_type -> ethereum.eth.v1.BlockResponse + 33, // 52: ethereum.eth.service.BeaconChain.GetBlockSSZ:output_type -> ethereum.eth.v1.BlockSSZResponse + 34, // 53: ethereum.eth.service.BeaconChain.GetBlockV2:output_type -> ethereum.eth.v2.BlockResponseV2 + 10, // 54: ethereum.eth.service.BeaconChain.GetBlockSSZV2:output_type -> ethereum.eth.v2.SSZContainer + 35, // 55: ethereum.eth.service.BeaconChain.ListBlockAttestations:output_type -> ethereum.eth.v1.BlockAttestationsResponse + 36, // 56: ethereum.eth.service.BeaconChain.ListPoolAttestations:output_type -> ethereum.eth.v1.AttestationsPoolResponse + 0, // 57: ethereum.eth.service.BeaconChain.SubmitAttestations:output_type -> google.protobuf.Empty + 37, // 58: ethereum.eth.service.BeaconChain.ListPoolAttesterSlashings:output_type -> ethereum.eth.v1.AttesterSlashingsPoolResponse + 0, // 59: ethereum.eth.service.BeaconChain.SubmitAttesterSlashing:output_type -> google.protobuf.Empty + 38, // 60: ethereum.eth.service.BeaconChain.ListPoolProposerSlashings:output_type -> ethereum.eth.v1.ProposerSlashingPoolResponse + 0, // 61: ethereum.eth.service.BeaconChain.SubmitProposerSlashing:output_type -> google.protobuf.Empty + 39, // 62: ethereum.eth.service.BeaconChain.ListPoolVoluntaryExits:output_type -> ethereum.eth.v1.VoluntaryExitsPoolResponse + 0, // 63: ethereum.eth.service.BeaconChain.SubmitVoluntaryExit:output_type -> google.protobuf.Empty + 0, // 64: ethereum.eth.service.BeaconChain.SubmitPoolSyncCommitteeSignatures:output_type -> google.protobuf.Empty + 40, // 65: ethereum.eth.service.BeaconChain.GetForkSchedule:output_type -> ethereum.eth.v1.ForkScheduleResponse + 41, // 66: ethereum.eth.service.BeaconChain.GetSpec:output_type -> ethereum.eth.v1.SpecResponse + 42, // 67: ethereum.eth.service.BeaconChain.GetDepositContract:output_type -> ethereum.eth.v1.DepositContractResponse + 34, // [34:68] is the sub-list for method output_type + 0, // [0:34] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name @@ -526,12 +547,14 @@ type BeaconChainClient interface { ListBlockHeaders(ctx context.Context, in *v1.BlockHeadersRequest, opts ...grpc.CallOption) (*v1.BlockHeadersResponse, error) GetBlockHeader(ctx context.Context, in *v1.BlockRequest, opts ...grpc.CallOption) (*v1.BlockHeaderResponse, error) SubmitBlock(ctx context.Context, in *v2.SignedBeaconBlockContainerV2, opts ...grpc.CallOption) (*empty.Empty, error) + SubmitBlockSSZ(ctx context.Context, in *v2.SSZContainer, opts ...grpc.CallOption) (*empty.Empty, error) SubmitBlindedBlock(ctx context.Context, in *v2.SignedBlindedBeaconBlockContainer, opts ...grpc.CallOption) (*empty.Empty, error) + SubmitBlindedBlockSSZ(ctx context.Context, in *v2.SSZContainer, opts ...grpc.CallOption) (*empty.Empty, error) GetBlockRoot(ctx context.Context, in *v1.BlockRequest, opts ...grpc.CallOption) (*v1.BlockRootResponse, error) GetBlock(ctx context.Context, in *v1.BlockRequest, opts ...grpc.CallOption) (*v1.BlockResponse, error) GetBlockSSZ(ctx context.Context, in *v1.BlockRequest, opts ...grpc.CallOption) (*v1.BlockSSZResponse, error) GetBlockV2(ctx context.Context, in *v2.BlockRequestV2, opts ...grpc.CallOption) (*v2.BlockResponseV2, error) - GetBlockSSZV2(ctx context.Context, in *v2.BlockRequestV2, opts ...grpc.CallOption) (*v2.BlockSSZResponseV2, error) + GetBlockSSZV2(ctx context.Context, in *v2.BlockRequestV2, opts ...grpc.CallOption) (*v2.SSZContainer, error) ListBlockAttestations(ctx context.Context, in *v1.BlockRequest, opts ...grpc.CallOption) (*v1.BlockAttestationsResponse, error) ListPoolAttestations(ctx context.Context, in *v1.AttestationsPoolRequest, opts ...grpc.CallOption) (*v1.AttestationsPoolResponse, error) SubmitAttestations(ctx context.Context, in *v1.SubmitAttestationsRequest, opts ...grpc.CallOption) (*empty.Empty, error) @@ -672,6 +695,15 @@ func (c *beaconChainClient) SubmitBlock(ctx context.Context, in *v2.SignedBeacon return out, nil } +func (c *beaconChainClient) SubmitBlockSSZ(ctx context.Context, in *v2.SSZContainer, opts ...grpc.CallOption) (*empty.Empty, error) { + out := new(empty.Empty) + err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconChain/SubmitBlockSSZ", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *beaconChainClient) SubmitBlindedBlock(ctx context.Context, in *v2.SignedBlindedBeaconBlockContainer, opts ...grpc.CallOption) (*empty.Empty, error) { out := new(empty.Empty) err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconChain/SubmitBlindedBlock", in, out, opts...) @@ -681,6 +713,15 @@ func (c *beaconChainClient) SubmitBlindedBlock(ctx context.Context, in *v2.Signe return out, nil } +func (c *beaconChainClient) SubmitBlindedBlockSSZ(ctx context.Context, in *v2.SSZContainer, opts ...grpc.CallOption) (*empty.Empty, error) { + out := new(empty.Empty) + err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconChain/SubmitBlindedBlockSSZ", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *beaconChainClient) GetBlockRoot(ctx context.Context, in *v1.BlockRequest, opts ...grpc.CallOption) (*v1.BlockRootResponse, error) { out := new(v1.BlockRootResponse) err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconChain/GetBlockRoot", in, out, opts...) @@ -717,8 +758,8 @@ func (c *beaconChainClient) GetBlockV2(ctx context.Context, in *v2.BlockRequestV return out, nil } -func (c *beaconChainClient) GetBlockSSZV2(ctx context.Context, in *v2.BlockRequestV2, opts ...grpc.CallOption) (*v2.BlockSSZResponseV2, error) { - out := new(v2.BlockSSZResponseV2) +func (c *beaconChainClient) GetBlockSSZV2(ctx context.Context, in *v2.BlockRequestV2, opts ...grpc.CallOption) (*v2.SSZContainer, error) { + out := new(v2.SSZContainer) err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconChain/GetBlockSSZV2", in, out, opts...) if err != nil { return nil, err @@ -858,12 +899,14 @@ type BeaconChainServer interface { ListBlockHeaders(context.Context, *v1.BlockHeadersRequest) (*v1.BlockHeadersResponse, error) GetBlockHeader(context.Context, *v1.BlockRequest) (*v1.BlockHeaderResponse, error) SubmitBlock(context.Context, *v2.SignedBeaconBlockContainerV2) (*empty.Empty, error) + SubmitBlockSSZ(context.Context, *v2.SSZContainer) (*empty.Empty, error) SubmitBlindedBlock(context.Context, *v2.SignedBlindedBeaconBlockContainer) (*empty.Empty, error) + SubmitBlindedBlockSSZ(context.Context, *v2.SSZContainer) (*empty.Empty, error) GetBlockRoot(context.Context, *v1.BlockRequest) (*v1.BlockRootResponse, error) GetBlock(context.Context, *v1.BlockRequest) (*v1.BlockResponse, error) GetBlockSSZ(context.Context, *v1.BlockRequest) (*v1.BlockSSZResponse, error) GetBlockV2(context.Context, *v2.BlockRequestV2) (*v2.BlockResponseV2, error) - GetBlockSSZV2(context.Context, *v2.BlockRequestV2) (*v2.BlockSSZResponseV2, error) + GetBlockSSZV2(context.Context, *v2.BlockRequestV2) (*v2.SSZContainer, error) ListBlockAttestations(context.Context, *v1.BlockRequest) (*v1.BlockAttestationsResponse, error) ListPoolAttestations(context.Context, *v1.AttestationsPoolRequest) (*v1.AttestationsPoolResponse, error) SubmitAttestations(context.Context, *v1.SubmitAttestationsRequest) (*empty.Empty, error) @@ -922,9 +965,15 @@ func (*UnimplementedBeaconChainServer) GetBlockHeader(context.Context, *v1.Block func (*UnimplementedBeaconChainServer) SubmitBlock(context.Context, *v2.SignedBeaconBlockContainerV2) (*empty.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method SubmitBlock not implemented") } +func (*UnimplementedBeaconChainServer) SubmitBlockSSZ(context.Context, *v2.SSZContainer) (*empty.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method SubmitBlockSSZ not implemented") +} func (*UnimplementedBeaconChainServer) SubmitBlindedBlock(context.Context, *v2.SignedBlindedBeaconBlockContainer) (*empty.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method SubmitBlindedBlock not implemented") } +func (*UnimplementedBeaconChainServer) SubmitBlindedBlockSSZ(context.Context, *v2.SSZContainer) (*empty.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method SubmitBlindedBlockSSZ not implemented") +} func (*UnimplementedBeaconChainServer) GetBlockRoot(context.Context, *v1.BlockRequest) (*v1.BlockRootResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBlockRoot not implemented") } @@ -937,7 +986,7 @@ func (*UnimplementedBeaconChainServer) GetBlockSSZ(context.Context, *v1.BlockReq func (*UnimplementedBeaconChainServer) GetBlockV2(context.Context, *v2.BlockRequestV2) (*v2.BlockResponseV2, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBlockV2 not implemented") } -func (*UnimplementedBeaconChainServer) GetBlockSSZV2(context.Context, *v2.BlockRequestV2) (*v2.BlockSSZResponseV2, error) { +func (*UnimplementedBeaconChainServer) GetBlockSSZV2(context.Context, *v2.BlockRequestV2) (*v2.SSZContainer, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBlockSSZV2 not implemented") } func (*UnimplementedBeaconChainServer) ListBlockAttestations(context.Context, *v1.BlockRequest) (*v1.BlockAttestationsResponse, error) { @@ -1218,6 +1267,24 @@ func _BeaconChain_SubmitBlock_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _BeaconChain_SubmitBlockSSZ_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v2.SSZContainer) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BeaconChainServer).SubmitBlockSSZ(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ethereum.eth.service.BeaconChain/SubmitBlockSSZ", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BeaconChainServer).SubmitBlockSSZ(ctx, req.(*v2.SSZContainer)) + } + return interceptor(ctx, in, info, handler) +} + func _BeaconChain_SubmitBlindedBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(v2.SignedBlindedBeaconBlockContainer) if err := dec(in); err != nil { @@ -1236,6 +1303,24 @@ func _BeaconChain_SubmitBlindedBlock_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _BeaconChain_SubmitBlindedBlockSSZ_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v2.SSZContainer) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BeaconChainServer).SubmitBlindedBlockSSZ(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ethereum.eth.service.BeaconChain/SubmitBlindedBlockSSZ", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BeaconChainServer).SubmitBlindedBlockSSZ(ctx, req.(*v2.SSZContainer)) + } + return interceptor(ctx, in, info, handler) +} + func _BeaconChain_GetBlockRoot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(v1.BlockRequest) if err := dec(in); err != nil { @@ -1616,10 +1701,18 @@ var _BeaconChain_serviceDesc = grpc.ServiceDesc{ MethodName: "SubmitBlock", Handler: _BeaconChain_SubmitBlock_Handler, }, + { + MethodName: "SubmitBlockSSZ", + Handler: _BeaconChain_SubmitBlockSSZ_Handler, + }, { MethodName: "SubmitBlindedBlock", Handler: _BeaconChain_SubmitBlindedBlock_Handler, }, + { + MethodName: "SubmitBlindedBlockSSZ", + Handler: _BeaconChain_SubmitBlindedBlockSSZ_Handler, + }, { MethodName: "GetBlockRoot", Handler: _BeaconChain_GetBlockRoot_Handler, diff --git a/proto/eth/service/beacon_chain_service.pb.gw.go b/proto/eth/service/beacon_chain_service.pb.gw.go index 06bc256d0a1c..26a9f919d735 100755 --- a/proto/eth/service/beacon_chain_service.pb.gw.go +++ b/proto/eth/service/beacon_chain_service.pb.gw.go @@ -725,6 +725,40 @@ func local_request_BeaconChain_SubmitBlock_0(ctx context.Context, marshaler runt } +func request_BeaconChain_SubmitBlockSSZ_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq eth.SSZContainer + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.SubmitBlockSSZ(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_BeaconChain_SubmitBlockSSZ_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq eth.SSZContainer + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.SubmitBlockSSZ(ctx, &protoReq) + return msg, metadata, err + +} + func request_BeaconChain_SubmitBlindedBlock_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq eth.SignedBlindedBeaconBlockContainer var metadata runtime.ServerMetadata @@ -759,6 +793,40 @@ func local_request_BeaconChain_SubmitBlindedBlock_0(ctx context.Context, marshal } +func request_BeaconChain_SubmitBlindedBlockSSZ_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq eth.SSZContainer + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.SubmitBlindedBlockSSZ(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_BeaconChain_SubmitBlindedBlockSSZ_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq eth.SSZContainer + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.SubmitBlindedBlockSSZ(ctx, &protoReq) + return msg, metadata, err + +} + func request_BeaconChain_GetBlockRoot_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq v1.BlockRequest var metadata runtime.ServerMetadata @@ -1702,6 +1770,29 @@ func RegisterBeaconChainHandlerServer(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_BeaconChain_SubmitBlockSSZ_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.BeaconChain/SubmitBlockSSZ") + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_BeaconChain_SubmitBlockSSZ_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_BeaconChain_SubmitBlockSSZ_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_BeaconChain_SubmitBlindedBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1725,6 +1816,29 @@ func RegisterBeaconChainHandlerServer(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_BeaconChain_SubmitBlindedBlockSSZ_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.BeaconChain/SubmitBlindedBlockSSZ") + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_BeaconChain_SubmitBlindedBlockSSZ_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_BeaconChain_SubmitBlindedBlockSSZ_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_BeaconChain_GetBlockRoot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2440,6 +2554,26 @@ func RegisterBeaconChainHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_BeaconChain_SubmitBlockSSZ_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.BeaconChain/SubmitBlockSSZ") + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_BeaconChain_SubmitBlockSSZ_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_BeaconChain_SubmitBlockSSZ_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_BeaconChain_SubmitBlindedBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2460,6 +2594,26 @@ func RegisterBeaconChainHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_BeaconChain_SubmitBlindedBlockSSZ_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.BeaconChain/SubmitBlindedBlockSSZ") + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_BeaconChain_SubmitBlindedBlockSSZ_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_BeaconChain_SubmitBlindedBlockSSZ_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_BeaconChain_GetBlockRoot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2850,8 +3004,12 @@ var ( pattern_BeaconChain_SubmitBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"internal", "eth", "v1", "beacon", "blocks"}, "")) + pattern_BeaconChain_SubmitBlockSSZ_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"internal", "eth", "v1", "beacon", "blocks", "ssz"}, "")) + pattern_BeaconChain_SubmitBlindedBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"internal", "eth", "v1", "beacon", "blinded_blocks"}, "")) + pattern_BeaconChain_SubmitBlindedBlockSSZ_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"internal", "eth", "v1", "beacon", "blinded_blocks", "ssz"}, "")) + pattern_BeaconChain_GetBlockRoot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"internal", "eth", "v1", "beacon", "blocks", "block_id", "root"}, "")) pattern_BeaconChain_GetBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"internal", "eth", "v1", "beacon", "blocks", "block_id"}, "")) @@ -2916,8 +3074,12 @@ var ( forward_BeaconChain_SubmitBlock_0 = runtime.ForwardResponseMessage + forward_BeaconChain_SubmitBlockSSZ_0 = runtime.ForwardResponseMessage + forward_BeaconChain_SubmitBlindedBlock_0 = runtime.ForwardResponseMessage + forward_BeaconChain_SubmitBlindedBlockSSZ_0 = runtime.ForwardResponseMessage + forward_BeaconChain_GetBlockRoot_0 = runtime.ForwardResponseMessage forward_BeaconChain_GetBlock_0 = runtime.ForwardResponseMessage diff --git a/proto/eth/service/beacon_chain_service.proto b/proto/eth/service/beacon_chain_service.proto index 72a8aad28b9c..32f06eeda80e 100644 --- a/proto/eth/service/beacon_chain_service.proto +++ b/proto/eth/service/beacon_chain_service.proto @@ -22,6 +22,7 @@ import "google/protobuf/empty.proto"; import "proto/eth/v1/beacon_block.proto"; import "proto/eth/v1/beacon_chain.proto"; import "proto/eth/v2/beacon_block.proto"; +import "proto/eth/v2/ssz.proto"; import "proto/eth/v2/sync_committee.proto"; option csharp_namespace = "Ethereum.Eth.Service"; @@ -136,6 +137,20 @@ service BeaconChain { }; } + // SubmitBlock instructs the beacon node to broadcast a newly signed beacon block to the beacon network, to be + // included in the beacon chain. The beacon node is not required to validate the signed BeaconBlock, and a successful + // response (20X) only indicates that the broadcast has been successful. The beacon node is expected to integrate the + // new block into its state, and therefore validate the block internally, however blocks which fail the validation are + // still broadcast but a different status code is returned (202). + // + // The provided block must be SSZ-serialized. + rpc SubmitBlockSSZ(v2.SSZContainer) returns (google.protobuf.Empty) { + option (google.api.http) = { + post: "/internal/eth/v1/beacon/blocks/ssz" + body: "*" + }; + } + // SubmitBlindedBlock instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct // and publish a `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`. // The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network, @@ -151,6 +166,23 @@ service BeaconChain { }; } + // SubmitBlindedBlock instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct + // and publish a `SignedBeaconBlock` by swapping out the `transactions_root` for the corresponding full list of `transactions`. + // The beacon node should broadcast a newly constructed `SignedBeaconBlock` to the beacon network, + // to be included in the beacon chain. The beacon node is not required to validate the signed + // `BeaconBlock`, and a successful response (20X) only indicates that the broadcast has been + // successful. The beacon node is expected to integrate the new block into its state, and + // therefore validate the block internally, however blocks which fail the validation are still + // broadcast but a different status code is returned (202). + // + // The provided block must be SSZ-serialized. + rpc SubmitBlindedBlockSSZ(v2.SSZContainer) returns (google.protobuf.Empty) { + option (google.api.http) = { + post: "/internal/eth/v1/beacon/blinded_blocks/ssz" + body: "*" + }; + } + // GetBlockRoot retrieves hashTreeRoot of BeaconBlock/BeaconBlockHeader. rpc GetBlockRoot(v1.BlockRequest) returns (v1.BlockRootResponse) { option (google.api.http) = { @@ -180,7 +212,7 @@ service BeaconChain { } // GetBlockSSZV2 returns the SSZ-serialized version of block details for given block id. - rpc GetBlockSSZV2(v2.BlockRequestV2) returns (v2.BlockSSZResponseV2) { + rpc GetBlockSSZV2(v2.BlockRequestV2) returns (v2.SSZContainer) { option (google.api.http) = { get: "/internal/eth/v2/beacon/blocks/{block_id}/ssz" }; diff --git a/proto/eth/service/beacon_debug_service.pb.go b/proto/eth/service/beacon_debug_service.pb.go index 41cfb7494c9d..5118cd16046f 100755 --- a/proto/eth/service/beacon_debug_service.pb.go +++ b/proto/eth/service/beacon_debug_service.pb.go @@ -48,85 +48,84 @@ var file_proto_eth_service_beacon_debug_service_proto_rawDesc = []byte{ 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x81, 0x07, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x44, - 0x65, 0x62, 0x75, 0x67, 0x12, 0x8e, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, + 0x76, 0x32, 0x2f, 0x73, 0x73, 0x7a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xeb, 0x06, 0x0a, + 0x0b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x12, 0x8e, 0x01, 0x0a, + 0x0e, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x64, + 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x8e, 0x01, + 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x53, 0x53, 0x5a, 0x12, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x53, 0x5a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x12, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x62, 0x75, + 0x67, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, + 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0x94, + 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x56, 0x32, 0x12, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x56, 0x32, 0x1a, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x32, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, - 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, 0x61, + 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x98, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x53, 0x5a, 0x12, 0x1d, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x53, 0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x12, 0x33, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, - 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, - 0x12, 0x94, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x56, 0x32, 0x12, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x1a, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x32, 0x22, 0x37, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x53, 0x5a, 0x56, 0x32, 0x12, - 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, - 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x53, - 0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x32, 0x22, 0x3b, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x35, 0x12, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0x84, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, - 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x73, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x43, - 0x68, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x62, - 0x75, 0x67, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x12, - 0x86, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x68, 0x6f, 0x69, - 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x73, 0x56, 0x32, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x65, - 0x61, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x42, 0x95, 0x01, 0x0a, 0x18, 0x6f, 0x72, 0x67, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x17, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x44, 0x65, 0x62, - 0x75, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, - 0x68, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x92, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x53, 0x5a, 0x56, 0x32, 0x12, 0x1f, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x1a, 0x1d, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, + 0x2e, 0x53, 0x53, 0x5a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, 0x3b, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x12, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0x84, 0x01, 0x0a, 0x13, 0x4c, + 0x69, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, + 0x64, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, + 0x6b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x64, + 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, + 0x73, 0x12, 0x86, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x68, + 0x6f, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x73, 0x56, 0x32, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, + 0x48, 0x65, 0x61, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x62, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x42, 0x95, 0x01, 0x0a, 0x18, 0x6f, + 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x17, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x44, + 0x65, 0x62, 0x75, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x45, 0x74, 0x68, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x14, 0x45, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_proto_eth_service_beacon_debug_service_proto_goTypes = []interface{}{ - (*v1.StateRequest)(nil), // 0: ethereum.eth.v1.StateRequest - (*v2.StateRequestV2)(nil), // 1: ethereum.eth.v2.StateRequestV2 - (*empty.Empty)(nil), // 2: google.protobuf.Empty - (*v1.BeaconStateResponse)(nil), // 3: ethereum.eth.v1.BeaconStateResponse - (*v1.BeaconStateSSZResponse)(nil), // 4: ethereum.eth.v1.BeaconStateSSZResponse - (*v2.BeaconStateResponseV2)(nil), // 5: ethereum.eth.v2.BeaconStateResponseV2 - (*v2.BeaconStateSSZResponseV2)(nil), // 6: ethereum.eth.v2.BeaconStateSSZResponseV2 - (*v1.ForkChoiceHeadsResponse)(nil), // 7: ethereum.eth.v1.ForkChoiceHeadsResponse - (*v2.ForkChoiceHeadsResponse)(nil), // 8: ethereum.eth.v2.ForkChoiceHeadsResponse + (*v1.StateRequest)(nil), // 0: ethereum.eth.v1.StateRequest + (*v2.StateRequestV2)(nil), // 1: ethereum.eth.v2.StateRequestV2 + (*empty.Empty)(nil), // 2: google.protobuf.Empty + (*v1.BeaconStateResponse)(nil), // 3: ethereum.eth.v1.BeaconStateResponse + (*v2.SSZContainer)(nil), // 4: ethereum.eth.v2.SSZContainer + (*v2.BeaconStateResponseV2)(nil), // 5: ethereum.eth.v2.BeaconStateResponseV2 + (*v1.ForkChoiceHeadsResponse)(nil), // 6: ethereum.eth.v1.ForkChoiceHeadsResponse + (*v2.ForkChoiceHeadsResponse)(nil), // 7: ethereum.eth.v2.ForkChoiceHeadsResponse } var file_proto_eth_service_beacon_debug_service_proto_depIdxs = []int32{ 0, // 0: ethereum.eth.service.BeaconDebug.GetBeaconState:input_type -> ethereum.eth.v1.StateRequest @@ -136,11 +135,11 @@ var file_proto_eth_service_beacon_debug_service_proto_depIdxs = []int32{ 2, // 4: ethereum.eth.service.BeaconDebug.ListForkChoiceHeads:input_type -> google.protobuf.Empty 2, // 5: ethereum.eth.service.BeaconDebug.ListForkChoiceHeadsV2:input_type -> google.protobuf.Empty 3, // 6: ethereum.eth.service.BeaconDebug.GetBeaconState:output_type -> ethereum.eth.v1.BeaconStateResponse - 4, // 7: ethereum.eth.service.BeaconDebug.GetBeaconStateSSZ:output_type -> ethereum.eth.v1.BeaconStateSSZResponse + 4, // 7: ethereum.eth.service.BeaconDebug.GetBeaconStateSSZ:output_type -> ethereum.eth.v2.SSZContainer 5, // 8: ethereum.eth.service.BeaconDebug.GetBeaconStateV2:output_type -> ethereum.eth.v2.BeaconStateResponseV2 - 6, // 9: ethereum.eth.service.BeaconDebug.GetBeaconStateSSZV2:output_type -> ethereum.eth.v2.BeaconStateSSZResponseV2 - 7, // 10: ethereum.eth.service.BeaconDebug.ListForkChoiceHeads:output_type -> ethereum.eth.v1.ForkChoiceHeadsResponse - 8, // 11: ethereum.eth.service.BeaconDebug.ListForkChoiceHeadsV2:output_type -> ethereum.eth.v2.ForkChoiceHeadsResponse + 4, // 9: ethereum.eth.service.BeaconDebug.GetBeaconStateSSZV2:output_type -> ethereum.eth.v2.SSZContainer + 6, // 10: ethereum.eth.service.BeaconDebug.ListForkChoiceHeads:output_type -> ethereum.eth.v1.ForkChoiceHeadsResponse + 7, // 11: ethereum.eth.service.BeaconDebug.ListForkChoiceHeadsV2:output_type -> ethereum.eth.v2.ForkChoiceHeadsResponse 6, // [6:12] is the sub-list for method output_type 0, // [0:6] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -185,9 +184,9 @@ const _ = grpc.SupportPackageIsVersion6 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type BeaconDebugClient interface { GetBeaconState(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v1.BeaconStateResponse, error) - GetBeaconStateSSZ(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v1.BeaconStateSSZResponse, error) + GetBeaconStateSSZ(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v2.SSZContainer, error) GetBeaconStateV2(ctx context.Context, in *v2.StateRequestV2, opts ...grpc.CallOption) (*v2.BeaconStateResponseV2, error) - GetBeaconStateSSZV2(ctx context.Context, in *v2.StateRequestV2, opts ...grpc.CallOption) (*v2.BeaconStateSSZResponseV2, error) + GetBeaconStateSSZV2(ctx context.Context, in *v2.StateRequestV2, opts ...grpc.CallOption) (*v2.SSZContainer, error) ListForkChoiceHeads(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*v1.ForkChoiceHeadsResponse, error) ListForkChoiceHeadsV2(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*v2.ForkChoiceHeadsResponse, error) } @@ -209,8 +208,8 @@ func (c *beaconDebugClient) GetBeaconState(ctx context.Context, in *v1.StateRequ return out, nil } -func (c *beaconDebugClient) GetBeaconStateSSZ(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v1.BeaconStateSSZResponse, error) { - out := new(v1.BeaconStateSSZResponse) +func (c *beaconDebugClient) GetBeaconStateSSZ(ctx context.Context, in *v1.StateRequest, opts ...grpc.CallOption) (*v2.SSZContainer, error) { + out := new(v2.SSZContainer) err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconDebug/GetBeaconStateSSZ", in, out, opts...) if err != nil { return nil, err @@ -227,8 +226,8 @@ func (c *beaconDebugClient) GetBeaconStateV2(ctx context.Context, in *v2.StateRe return out, nil } -func (c *beaconDebugClient) GetBeaconStateSSZV2(ctx context.Context, in *v2.StateRequestV2, opts ...grpc.CallOption) (*v2.BeaconStateSSZResponseV2, error) { - out := new(v2.BeaconStateSSZResponseV2) +func (c *beaconDebugClient) GetBeaconStateSSZV2(ctx context.Context, in *v2.StateRequestV2, opts ...grpc.CallOption) (*v2.SSZContainer, error) { + out := new(v2.SSZContainer) err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconDebug/GetBeaconStateSSZV2", in, out, opts...) if err != nil { return nil, err @@ -257,9 +256,9 @@ func (c *beaconDebugClient) ListForkChoiceHeadsV2(ctx context.Context, in *empty // BeaconDebugServer is the server API for BeaconDebug service. type BeaconDebugServer interface { GetBeaconState(context.Context, *v1.StateRequest) (*v1.BeaconStateResponse, error) - GetBeaconStateSSZ(context.Context, *v1.StateRequest) (*v1.BeaconStateSSZResponse, error) + GetBeaconStateSSZ(context.Context, *v1.StateRequest) (*v2.SSZContainer, error) GetBeaconStateV2(context.Context, *v2.StateRequestV2) (*v2.BeaconStateResponseV2, error) - GetBeaconStateSSZV2(context.Context, *v2.StateRequestV2) (*v2.BeaconStateSSZResponseV2, error) + GetBeaconStateSSZV2(context.Context, *v2.StateRequestV2) (*v2.SSZContainer, error) ListForkChoiceHeads(context.Context, *empty.Empty) (*v1.ForkChoiceHeadsResponse, error) ListForkChoiceHeadsV2(context.Context, *empty.Empty) (*v2.ForkChoiceHeadsResponse, error) } @@ -271,13 +270,13 @@ type UnimplementedBeaconDebugServer struct { func (*UnimplementedBeaconDebugServer) GetBeaconState(context.Context, *v1.StateRequest) (*v1.BeaconStateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBeaconState not implemented") } -func (*UnimplementedBeaconDebugServer) GetBeaconStateSSZ(context.Context, *v1.StateRequest) (*v1.BeaconStateSSZResponse, error) { +func (*UnimplementedBeaconDebugServer) GetBeaconStateSSZ(context.Context, *v1.StateRequest) (*v2.SSZContainer, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBeaconStateSSZ not implemented") } func (*UnimplementedBeaconDebugServer) GetBeaconStateV2(context.Context, *v2.StateRequestV2) (*v2.BeaconStateResponseV2, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBeaconStateV2 not implemented") } -func (*UnimplementedBeaconDebugServer) GetBeaconStateSSZV2(context.Context, *v2.StateRequestV2) (*v2.BeaconStateSSZResponseV2, error) { +func (*UnimplementedBeaconDebugServer) GetBeaconStateSSZV2(context.Context, *v2.StateRequestV2) (*v2.SSZContainer, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBeaconStateSSZV2 not implemented") } func (*UnimplementedBeaconDebugServer) ListForkChoiceHeads(context.Context, *empty.Empty) (*v1.ForkChoiceHeadsResponse, error) { diff --git a/proto/eth/service/beacon_debug_service.proto b/proto/eth/service/beacon_debug_service.proto index a7e0ed7fafce..a8f735c80432 100644 --- a/proto/eth/service/beacon_debug_service.proto +++ b/proto/eth/service/beacon_debug_service.proto @@ -22,6 +22,7 @@ import "google/protobuf/empty.proto"; import "proto/eth/v1/beacon_chain.proto"; import "proto/eth/v1/beacon_state.proto"; import "proto/eth/v2/beacon_state.proto"; +import "proto/eth/v2/ssz.proto"; option csharp_namespace = "Ethereum.Eth.Service"; option go_package = "github.com/prysmaticlabs/prysm/proto/eth/service"; @@ -44,7 +45,7 @@ service BeaconDebug { } // GetBeaconStateSSZ returns the SSZ-serialized version of the full BeaconState object for given stateId. - rpc GetBeaconStateSSZ(v1.StateRequest) returns (v1.BeaconStateSSZResponse) { + rpc GetBeaconStateSSZ(v1.StateRequest) returns (v2.SSZContainer) { option (google.api.http) = { get: "/internal/eth/v1/debug/beacon/states/{state_id}/ssz" }; @@ -58,7 +59,7 @@ service BeaconDebug { } // GetBeaconStateSSZV2 returns the SSZ-serialized version of the full BeaconState object for given stateId. - rpc GetBeaconStateSSZV2(v2.StateRequestV2) returns (v2.BeaconStateSSZResponseV2) { + rpc GetBeaconStateSSZV2(v2.StateRequestV2) returns (v2.SSZContainer) { option (google.api.http) = { get: "/internal/eth/v2/debug/beacon/states/{state_id}/ssz" }; diff --git a/proto/eth/service/validator_service.pb.go b/proto/eth/service/validator_service.pb.go index 70cdc06ac413..6dba1ab87988 100755 --- a/proto/eth/service/validator_service.pb.go +++ b/proto/eth/service/validator_service.pb.go @@ -43,171 +43,191 @@ var file_proto_eth_service_validator_service_proto_rawDesc = []byte{ 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xfc, 0x12, 0x0a, 0x0f, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0xa3, - 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, - 0x74, 0x69, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, - 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x16, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x73, 0x7a, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, + 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x32, 0xab, 0x15, 0x0a, 0x0f, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0xa3, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x22, 0x32, 0x2f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, - 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x7b, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0xa0, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, - 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x34, 0x12, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, - 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x2f, - 0x7b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x7d, 0x12, 0xae, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, - 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x44, 0x75, 0x74, 0x69, - 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x65, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x32, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x44, - 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x22, 0x2e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, + 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3d, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x22, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x2f, 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x2f, 0x7b, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0x8d, 0x01, 0x0a, 0x0c, 0x50, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, - 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, - 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, - 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x73, 0x2f, 0x7b, 0x73, 0x6c, 0x6f, 0x74, 0x7d, 0x12, 0x91, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x32, 0x12, 0x24, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x32, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x73, 0x6c, 0x6f, 0x74, 0x7d, 0x12, 0xa3, 0x01, 0x0a, - 0x13, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, - 0x12, 0x30, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x69, - 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x73, 0x6c, 0x6f, - 0x74, 0x7d, 0x12, 0x9d, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x12, 0x2d, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x22, 0x32, 0x2f, 0x69, 0x6e, + 0x72, 0x2f, 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x2f, 0x7b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0xa0, 0x01, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, 0x69, + 0x65, 0x73, 0x12, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x12, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, - 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x3a, - 0x01, 0x2a, 0x12, 0xae, 0x01, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x12, 0x2b, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x2f, 0x7b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x7d, 0x12, + 0xae, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x22, 0x2e, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, + 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x2f, 0x7b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x7d, 0x3a, 0x01, 0x2a, + 0x12, 0x8d, 0x01, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, - 0x61, 0x74, 0x61, 0x12, 0xb0, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, + 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x73, 0x6c, 0x6f, 0x74, 0x7d, + 0x12, 0x91, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x56, 0x32, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x56, 0x32, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x73, + 0x6c, 0x6f, 0x74, 0x7d, 0x12, 0x8e, 0x01, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x32, 0x53, 0x53, 0x5a, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x32, 0x2e, 0x53, 0x53, 0x5a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, + 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x73, 0x6c, 0x6f, 0x74, + 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0xa3, 0x01, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x65, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, - 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xa0, 0x01, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x73, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x2f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xbd, 0x01, 0x0a, 0x21, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x22, 0x39, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xb7, 0x01, 0x0a, 0x1f, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, - 0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x22, 0x37, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x3a, 0x01, 0x2a, 0x12, 0xd7, 0x01, 0x0a, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x53, - 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, - 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3e, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xa9, 0x01, - 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x33, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x69, + 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, 0x73, 0x6c, 0x6f, 0x74, 0x7d, 0x12, 0x9b, 0x01, 0x0a, 0x16, + 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, + 0x53, 0x5a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, 0x3c, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x36, 0x12, 0x34, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, + 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x7b, + 0x73, 0x6c, 0x6f, 0x74, 0x7d, 0x2f, 0x73, 0x73, 0x7a, 0x12, 0x9d, 0x01, 0x0a, 0x15, 0x50, 0x72, + 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, + 0x73, 0x65, 0x72, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x22, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x3a, 0x01, 0x2a, 0x42, 0x93, 0x01, 0x0a, 0x18, 0x6f, 0x72, - 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x15, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, + 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x70, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0xae, 0x01, 0x0a, 0x16, 0x50, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x12, 0x2b, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x12, 0xb0, 0x01, 0x0a, 0x17, 0x47, + 0x65, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xa0, 0x01, + 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, + 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x2f, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x3a, 0x01, 0x2a, + 0x12, 0xbd, 0x01, 0x0a, 0x21, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x3e, 0x22, 0x39, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x01, 0x2a, + 0x12, 0xb7, 0x01, 0x0a, 0x1f, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x79, 0x6e, + 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x22, 0x37, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xd7, 0x01, 0x0a, 0x20, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x38, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xa9, 0x01, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x22, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x3a, 0x01, 0x2a, + 0x42, 0x93, 0x01, 0x0a, 0x18, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x15, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, + 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_proto_eth_service_validator_service_proto_goTypes = []interface{}{ @@ -228,11 +248,12 @@ var file_proto_eth_service_validator_service_proto_goTypes = []interface{}{ (*v2.SyncCommitteeDutiesResponse)(nil), // 14: ethereum.eth.v2.SyncCommitteeDutiesResponse (*v1.ProduceBlockResponse)(nil), // 15: ethereum.eth.v1.ProduceBlockResponse (*v2.ProduceBlockResponseV2)(nil), // 16: ethereum.eth.v2.ProduceBlockResponseV2 - (*v2.ProduceBlindedBlockResponse)(nil), // 17: ethereum.eth.v2.ProduceBlindedBlockResponse - (*empty.Empty)(nil), // 18: google.protobuf.Empty - (*v1.ProduceAttestationDataResponse)(nil), // 19: ethereum.eth.v1.ProduceAttestationDataResponse - (*v1.AggregateAttestationResponse)(nil), // 20: ethereum.eth.v1.AggregateAttestationResponse - (*v2.ProduceSyncCommitteeContributionResponse)(nil), // 21: ethereum.eth.v2.ProduceSyncCommitteeContributionResponse + (*v2.SSZContainer)(nil), // 17: ethereum.eth.v2.SSZContainer + (*v2.ProduceBlindedBlockResponse)(nil), // 18: ethereum.eth.v2.ProduceBlindedBlockResponse + (*empty.Empty)(nil), // 19: google.protobuf.Empty + (*v1.ProduceAttestationDataResponse)(nil), // 20: ethereum.eth.v1.ProduceAttestationDataResponse + (*v1.AggregateAttestationResponse)(nil), // 21: ethereum.eth.v1.AggregateAttestationResponse + (*v2.ProduceSyncCommitteeContributionResponse)(nil), // 22: ethereum.eth.v2.ProduceSyncCommitteeContributionResponse } var file_proto_eth_service_validator_service_proto_depIdxs = []int32{ 0, // 0: ethereum.eth.service.BeaconValidator.GetAttesterDuties:input_type -> ethereum.eth.v1.AttesterDutiesRequest @@ -240,31 +261,35 @@ var file_proto_eth_service_validator_service_proto_depIdxs = []int32{ 2, // 2: ethereum.eth.service.BeaconValidator.GetSyncCommitteeDuties:input_type -> ethereum.eth.v2.SyncCommitteeDutiesRequest 3, // 3: ethereum.eth.service.BeaconValidator.ProduceBlock:input_type -> ethereum.eth.v1.ProduceBlockRequest 3, // 4: ethereum.eth.service.BeaconValidator.ProduceBlockV2:input_type -> ethereum.eth.v1.ProduceBlockRequest - 3, // 5: ethereum.eth.service.BeaconValidator.ProduceBlindedBlock:input_type -> ethereum.eth.v1.ProduceBlockRequest - 4, // 6: ethereum.eth.service.BeaconValidator.PrepareBeaconProposer:input_type -> ethereum.eth.v1.PrepareBeaconProposerRequest - 5, // 7: ethereum.eth.service.BeaconValidator.ProduceAttestationData:input_type -> ethereum.eth.v1.ProduceAttestationDataRequest - 6, // 8: ethereum.eth.service.BeaconValidator.GetAggregateAttestation:input_type -> ethereum.eth.v1.AggregateAttestationRequest - 7, // 9: ethereum.eth.service.BeaconValidator.SubmitAggregateAndProofs:input_type -> ethereum.eth.v1.SubmitAggregateAndProofsRequest - 8, // 10: ethereum.eth.service.BeaconValidator.SubmitBeaconCommitteeSubscription:input_type -> ethereum.eth.v1.SubmitBeaconCommitteeSubscriptionsRequest - 9, // 11: ethereum.eth.service.BeaconValidator.SubmitSyncCommitteeSubscription:input_type -> ethereum.eth.v2.SubmitSyncCommitteeSubscriptionsRequest - 10, // 12: ethereum.eth.service.BeaconValidator.ProduceSyncCommitteeContribution:input_type -> ethereum.eth.v2.ProduceSyncCommitteeContributionRequest - 11, // 13: ethereum.eth.service.BeaconValidator.SubmitContributionAndProofs:input_type -> ethereum.eth.v2.SubmitContributionAndProofsRequest - 12, // 14: ethereum.eth.service.BeaconValidator.GetAttesterDuties:output_type -> ethereum.eth.v1.AttesterDutiesResponse - 13, // 15: ethereum.eth.service.BeaconValidator.GetProposerDuties:output_type -> ethereum.eth.v1.ProposerDutiesResponse - 14, // 16: ethereum.eth.service.BeaconValidator.GetSyncCommitteeDuties:output_type -> ethereum.eth.v2.SyncCommitteeDutiesResponse - 15, // 17: ethereum.eth.service.BeaconValidator.ProduceBlock:output_type -> ethereum.eth.v1.ProduceBlockResponse - 16, // 18: ethereum.eth.service.BeaconValidator.ProduceBlockV2:output_type -> ethereum.eth.v2.ProduceBlockResponseV2 - 17, // 19: ethereum.eth.service.BeaconValidator.ProduceBlindedBlock:output_type -> ethereum.eth.v2.ProduceBlindedBlockResponse - 18, // 20: ethereum.eth.service.BeaconValidator.PrepareBeaconProposer:output_type -> google.protobuf.Empty - 19, // 21: ethereum.eth.service.BeaconValidator.ProduceAttestationData:output_type -> ethereum.eth.v1.ProduceAttestationDataResponse - 20, // 22: ethereum.eth.service.BeaconValidator.GetAggregateAttestation:output_type -> ethereum.eth.v1.AggregateAttestationResponse - 18, // 23: ethereum.eth.service.BeaconValidator.SubmitAggregateAndProofs:output_type -> google.protobuf.Empty - 18, // 24: ethereum.eth.service.BeaconValidator.SubmitBeaconCommitteeSubscription:output_type -> google.protobuf.Empty - 18, // 25: ethereum.eth.service.BeaconValidator.SubmitSyncCommitteeSubscription:output_type -> google.protobuf.Empty - 21, // 26: ethereum.eth.service.BeaconValidator.ProduceSyncCommitteeContribution:output_type -> ethereum.eth.v2.ProduceSyncCommitteeContributionResponse - 18, // 27: ethereum.eth.service.BeaconValidator.SubmitContributionAndProofs:output_type -> google.protobuf.Empty - 14, // [14:28] is the sub-list for method output_type - 0, // [0:14] is the sub-list for method input_type + 3, // 5: ethereum.eth.service.BeaconValidator.ProduceBlockV2SSZ:input_type -> ethereum.eth.v1.ProduceBlockRequest + 3, // 6: ethereum.eth.service.BeaconValidator.ProduceBlindedBlock:input_type -> ethereum.eth.v1.ProduceBlockRequest + 3, // 7: ethereum.eth.service.BeaconValidator.ProduceBlindedBlockSSZ:input_type -> ethereum.eth.v1.ProduceBlockRequest + 4, // 8: ethereum.eth.service.BeaconValidator.PrepareBeaconProposer:input_type -> ethereum.eth.v1.PrepareBeaconProposerRequest + 5, // 9: ethereum.eth.service.BeaconValidator.ProduceAttestationData:input_type -> ethereum.eth.v1.ProduceAttestationDataRequest + 6, // 10: ethereum.eth.service.BeaconValidator.GetAggregateAttestation:input_type -> ethereum.eth.v1.AggregateAttestationRequest + 7, // 11: ethereum.eth.service.BeaconValidator.SubmitAggregateAndProofs:input_type -> ethereum.eth.v1.SubmitAggregateAndProofsRequest + 8, // 12: ethereum.eth.service.BeaconValidator.SubmitBeaconCommitteeSubscription:input_type -> ethereum.eth.v1.SubmitBeaconCommitteeSubscriptionsRequest + 9, // 13: ethereum.eth.service.BeaconValidator.SubmitSyncCommitteeSubscription:input_type -> ethereum.eth.v2.SubmitSyncCommitteeSubscriptionsRequest + 10, // 14: ethereum.eth.service.BeaconValidator.ProduceSyncCommitteeContribution:input_type -> ethereum.eth.v2.ProduceSyncCommitteeContributionRequest + 11, // 15: ethereum.eth.service.BeaconValidator.SubmitContributionAndProofs:input_type -> ethereum.eth.v2.SubmitContributionAndProofsRequest + 12, // 16: ethereum.eth.service.BeaconValidator.GetAttesterDuties:output_type -> ethereum.eth.v1.AttesterDutiesResponse + 13, // 17: ethereum.eth.service.BeaconValidator.GetProposerDuties:output_type -> ethereum.eth.v1.ProposerDutiesResponse + 14, // 18: ethereum.eth.service.BeaconValidator.GetSyncCommitteeDuties:output_type -> ethereum.eth.v2.SyncCommitteeDutiesResponse + 15, // 19: ethereum.eth.service.BeaconValidator.ProduceBlock:output_type -> ethereum.eth.v1.ProduceBlockResponse + 16, // 20: ethereum.eth.service.BeaconValidator.ProduceBlockV2:output_type -> ethereum.eth.v2.ProduceBlockResponseV2 + 17, // 21: ethereum.eth.service.BeaconValidator.ProduceBlockV2SSZ:output_type -> ethereum.eth.v2.SSZContainer + 18, // 22: ethereum.eth.service.BeaconValidator.ProduceBlindedBlock:output_type -> ethereum.eth.v2.ProduceBlindedBlockResponse + 17, // 23: ethereum.eth.service.BeaconValidator.ProduceBlindedBlockSSZ:output_type -> ethereum.eth.v2.SSZContainer + 19, // 24: ethereum.eth.service.BeaconValidator.PrepareBeaconProposer:output_type -> google.protobuf.Empty + 20, // 25: ethereum.eth.service.BeaconValidator.ProduceAttestationData:output_type -> ethereum.eth.v1.ProduceAttestationDataResponse + 21, // 26: ethereum.eth.service.BeaconValidator.GetAggregateAttestation:output_type -> ethereum.eth.v1.AggregateAttestationResponse + 19, // 27: ethereum.eth.service.BeaconValidator.SubmitAggregateAndProofs:output_type -> google.protobuf.Empty + 19, // 28: ethereum.eth.service.BeaconValidator.SubmitBeaconCommitteeSubscription:output_type -> google.protobuf.Empty + 19, // 29: ethereum.eth.service.BeaconValidator.SubmitSyncCommitteeSubscription:output_type -> google.protobuf.Empty + 22, // 30: ethereum.eth.service.BeaconValidator.ProduceSyncCommitteeContribution:output_type -> ethereum.eth.v2.ProduceSyncCommitteeContributionResponse + 19, // 31: ethereum.eth.service.BeaconValidator.SubmitContributionAndProofs:output_type -> google.protobuf.Empty + 16, // [16:32] is the sub-list for method output_type + 0, // [0:16] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name @@ -311,7 +336,9 @@ type BeaconValidatorClient interface { GetSyncCommitteeDuties(ctx context.Context, in *v2.SyncCommitteeDutiesRequest, opts ...grpc.CallOption) (*v2.SyncCommitteeDutiesResponse, error) ProduceBlock(ctx context.Context, in *v1.ProduceBlockRequest, opts ...grpc.CallOption) (*v1.ProduceBlockResponse, error) ProduceBlockV2(ctx context.Context, in *v1.ProduceBlockRequest, opts ...grpc.CallOption) (*v2.ProduceBlockResponseV2, error) + ProduceBlockV2SSZ(ctx context.Context, in *v1.ProduceBlockRequest, opts ...grpc.CallOption) (*v2.SSZContainer, error) ProduceBlindedBlock(ctx context.Context, in *v1.ProduceBlockRequest, opts ...grpc.CallOption) (*v2.ProduceBlindedBlockResponse, error) + ProduceBlindedBlockSSZ(ctx context.Context, in *v1.ProduceBlockRequest, opts ...grpc.CallOption) (*v2.SSZContainer, error) PrepareBeaconProposer(ctx context.Context, in *v1.PrepareBeaconProposerRequest, opts ...grpc.CallOption) (*empty.Empty, error) ProduceAttestationData(ctx context.Context, in *v1.ProduceAttestationDataRequest, opts ...grpc.CallOption) (*v1.ProduceAttestationDataResponse, error) GetAggregateAttestation(ctx context.Context, in *v1.AggregateAttestationRequest, opts ...grpc.CallOption) (*v1.AggregateAttestationResponse, error) @@ -375,6 +402,15 @@ func (c *beaconValidatorClient) ProduceBlockV2(ctx context.Context, in *v1.Produ return out, nil } +func (c *beaconValidatorClient) ProduceBlockV2SSZ(ctx context.Context, in *v1.ProduceBlockRequest, opts ...grpc.CallOption) (*v2.SSZContainer, error) { + out := new(v2.SSZContainer) + err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconValidator/ProduceBlockV2SSZ", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *beaconValidatorClient) ProduceBlindedBlock(ctx context.Context, in *v1.ProduceBlockRequest, opts ...grpc.CallOption) (*v2.ProduceBlindedBlockResponse, error) { out := new(v2.ProduceBlindedBlockResponse) err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconValidator/ProduceBlindedBlock", in, out, opts...) @@ -384,6 +420,15 @@ func (c *beaconValidatorClient) ProduceBlindedBlock(ctx context.Context, in *v1. return out, nil } +func (c *beaconValidatorClient) ProduceBlindedBlockSSZ(ctx context.Context, in *v1.ProduceBlockRequest, opts ...grpc.CallOption) (*v2.SSZContainer, error) { + out := new(v2.SSZContainer) + err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconValidator/ProduceBlindedBlockSSZ", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *beaconValidatorClient) PrepareBeaconProposer(ctx context.Context, in *v1.PrepareBeaconProposerRequest, opts ...grpc.CallOption) (*empty.Empty, error) { out := new(empty.Empty) err := c.cc.Invoke(ctx, "/ethereum.eth.service.BeaconValidator/PrepareBeaconProposer", in, out, opts...) @@ -463,7 +508,9 @@ type BeaconValidatorServer interface { GetSyncCommitteeDuties(context.Context, *v2.SyncCommitteeDutiesRequest) (*v2.SyncCommitteeDutiesResponse, error) ProduceBlock(context.Context, *v1.ProduceBlockRequest) (*v1.ProduceBlockResponse, error) ProduceBlockV2(context.Context, *v1.ProduceBlockRequest) (*v2.ProduceBlockResponseV2, error) + ProduceBlockV2SSZ(context.Context, *v1.ProduceBlockRequest) (*v2.SSZContainer, error) ProduceBlindedBlock(context.Context, *v1.ProduceBlockRequest) (*v2.ProduceBlindedBlockResponse, error) + ProduceBlindedBlockSSZ(context.Context, *v1.ProduceBlockRequest) (*v2.SSZContainer, error) PrepareBeaconProposer(context.Context, *v1.PrepareBeaconProposerRequest) (*empty.Empty, error) ProduceAttestationData(context.Context, *v1.ProduceAttestationDataRequest) (*v1.ProduceAttestationDataResponse, error) GetAggregateAttestation(context.Context, *v1.AggregateAttestationRequest) (*v1.AggregateAttestationResponse, error) @@ -493,9 +540,15 @@ func (*UnimplementedBeaconValidatorServer) ProduceBlock(context.Context, *v1.Pro func (*UnimplementedBeaconValidatorServer) ProduceBlockV2(context.Context, *v1.ProduceBlockRequest) (*v2.ProduceBlockResponseV2, error) { return nil, status.Errorf(codes.Unimplemented, "method ProduceBlockV2 not implemented") } +func (*UnimplementedBeaconValidatorServer) ProduceBlockV2SSZ(context.Context, *v1.ProduceBlockRequest) (*v2.SSZContainer, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProduceBlockV2SSZ not implemented") +} func (*UnimplementedBeaconValidatorServer) ProduceBlindedBlock(context.Context, *v1.ProduceBlockRequest) (*v2.ProduceBlindedBlockResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProduceBlindedBlock not implemented") } +func (*UnimplementedBeaconValidatorServer) ProduceBlindedBlockSSZ(context.Context, *v1.ProduceBlockRequest) (*v2.SSZContainer, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProduceBlindedBlockSSZ not implemented") +} func (*UnimplementedBeaconValidatorServer) PrepareBeaconProposer(context.Context, *v1.PrepareBeaconProposerRequest) (*empty.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method PrepareBeaconProposer not implemented") } @@ -615,6 +668,24 @@ func _BeaconValidator_ProduceBlockV2_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _BeaconValidator_ProduceBlockV2SSZ_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1.ProduceBlockRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BeaconValidatorServer).ProduceBlockV2SSZ(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ethereum.eth.service.BeaconValidator/ProduceBlockV2SSZ", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BeaconValidatorServer).ProduceBlockV2SSZ(ctx, req.(*v1.ProduceBlockRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _BeaconValidator_ProduceBlindedBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(v1.ProduceBlockRequest) if err := dec(in); err != nil { @@ -633,6 +704,24 @@ func _BeaconValidator_ProduceBlindedBlock_Handler(srv interface{}, ctx context.C return interceptor(ctx, in, info, handler) } +func _BeaconValidator_ProduceBlindedBlockSSZ_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1.ProduceBlockRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BeaconValidatorServer).ProduceBlindedBlockSSZ(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ethereum.eth.service.BeaconValidator/ProduceBlindedBlockSSZ", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BeaconValidatorServer).ProduceBlindedBlockSSZ(ctx, req.(*v1.ProduceBlockRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _BeaconValidator_PrepareBeaconProposer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(v1.PrepareBeaconProposerRequest) if err := dec(in); err != nil { @@ -801,10 +890,18 @@ var _BeaconValidator_serviceDesc = grpc.ServiceDesc{ MethodName: "ProduceBlockV2", Handler: _BeaconValidator_ProduceBlockV2_Handler, }, + { + MethodName: "ProduceBlockV2SSZ", + Handler: _BeaconValidator_ProduceBlockV2SSZ_Handler, + }, { MethodName: "ProduceBlindedBlock", Handler: _BeaconValidator_ProduceBlindedBlock_Handler, }, + { + MethodName: "ProduceBlindedBlockSSZ", + Handler: _BeaconValidator_ProduceBlindedBlockSSZ_Handler, + }, { MethodName: "PrepareBeaconProposer", Handler: _BeaconValidator_PrepareBeaconProposer_Handler, diff --git a/proto/eth/service/validator_service.pb.gw.go b/proto/eth/service/validator_service.pb.gw.go index fdbb33caa473..f787c7dd34ef 100755 --- a/proto/eth/service/validator_service.pb.gw.go +++ b/proto/eth/service/validator_service.pb.gw.go @@ -377,6 +377,78 @@ func local_request_BeaconValidator_ProduceBlockV2_0(ctx context.Context, marshal } +var ( + filter_BeaconValidator_ProduceBlockV2SSZ_0 = &utilities.DoubleArray{Encoding: map[string]int{"slot": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_BeaconValidator_ProduceBlockV2SSZ_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq v1.ProduceBlockRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["slot"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "slot") + } + + slot, err := runtime.Uint64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "slot", err) + } + protoReq.Slot = github_com_prysmaticlabs_prysm_consensus_types_primitives.Slot(slot) + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconValidator_ProduceBlockV2SSZ_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ProduceBlockV2SSZ(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_BeaconValidator_ProduceBlockV2SSZ_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq v1.ProduceBlockRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["slot"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "slot") + } + + slot, err := runtime.Uint64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "slot", err) + } + protoReq.Slot = github_com_prysmaticlabs_prysm_consensus_types_primitives.Slot(slot) + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconValidator_ProduceBlockV2SSZ_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ProduceBlockV2SSZ(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_BeaconValidator_ProduceBlindedBlock_0 = &utilities.DoubleArray{Encoding: map[string]int{"slot": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -449,6 +521,78 @@ func local_request_BeaconValidator_ProduceBlindedBlock_0(ctx context.Context, ma } +var ( + filter_BeaconValidator_ProduceBlindedBlockSSZ_0 = &utilities.DoubleArray{Encoding: map[string]int{"slot": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_BeaconValidator_ProduceBlindedBlockSSZ_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq v1.ProduceBlockRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["slot"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "slot") + } + + slot, err := runtime.Uint64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "slot", err) + } + protoReq.Slot = github_com_prysmaticlabs_prysm_consensus_types_primitives.Slot(slot) + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconValidator_ProduceBlindedBlockSSZ_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ProduceBlindedBlockSSZ(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_BeaconValidator_ProduceBlindedBlockSSZ_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq v1.ProduceBlockRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["slot"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "slot") + } + + slot, err := runtime.Uint64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "slot", err) + } + protoReq.Slot = github_com_prysmaticlabs_prysm_consensus_types_primitives.Slot(slot) + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconValidator_ProduceBlindedBlockSSZ_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ProduceBlindedBlockSSZ(ctx, &protoReq) + return msg, metadata, err + +} + func request_BeaconValidator_PrepareBeaconProposer_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq v1.PrepareBeaconProposerRequest var metadata runtime.ServerMetadata @@ -848,6 +992,29 @@ func RegisterBeaconValidatorHandlerServer(ctx context.Context, mux *runtime.Serv }) + mux.Handle("GET", pattern_BeaconValidator_ProduceBlockV2SSZ_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.BeaconValidator/ProduceBlockV2SSZ") + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_BeaconValidator_ProduceBlockV2SSZ_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_BeaconValidator_ProduceBlockV2SSZ_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_BeaconValidator_ProduceBlindedBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -871,6 +1038,29 @@ func RegisterBeaconValidatorHandlerServer(ctx context.Context, mux *runtime.Serv }) + mux.Handle("GET", pattern_BeaconValidator_ProduceBlindedBlockSSZ_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.BeaconValidator/ProduceBlindedBlockSSZ") + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_BeaconValidator_ProduceBlindedBlockSSZ_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_BeaconValidator_ProduceBlindedBlockSSZ_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_BeaconValidator_PrepareBeaconProposer_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1196,6 +1386,26 @@ func RegisterBeaconValidatorHandlerClient(ctx context.Context, mux *runtime.Serv }) + mux.Handle("GET", pattern_BeaconValidator_ProduceBlockV2SSZ_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.BeaconValidator/ProduceBlockV2SSZ") + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_BeaconValidator_ProduceBlockV2SSZ_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_BeaconValidator_ProduceBlockV2SSZ_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_BeaconValidator_ProduceBlindedBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1216,6 +1426,26 @@ func RegisterBeaconValidatorHandlerClient(ctx context.Context, mux *runtime.Serv }) + mux.Handle("GET", pattern_BeaconValidator_ProduceBlindedBlockSSZ_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.BeaconValidator/ProduceBlindedBlockSSZ") + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_BeaconValidator_ProduceBlindedBlockSSZ_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_BeaconValidator_ProduceBlindedBlockSSZ_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_BeaconValidator_PrepareBeaconProposer_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1390,8 +1620,12 @@ var ( pattern_BeaconValidator_ProduceBlockV2_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"internal", "eth", "v2", "validator", "blocks", "slot"}, "")) + pattern_BeaconValidator_ProduceBlockV2SSZ_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"internal", "eth", "v2", "validator", "blocks", "slot", "ssz"}, "")) + pattern_BeaconValidator_ProduceBlindedBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"internal", "eth", "v1", "validator", "blinded_blocks", "slot"}, "")) + pattern_BeaconValidator_ProduceBlindedBlockSSZ_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"internal", "eth", "v1", "validator", "blinded_blocks", "slot", "ssz"}, "")) + pattern_BeaconValidator_PrepareBeaconProposer_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"internal", "eth", "v1", "validator", "prepare_beacon_proposer"}, "")) pattern_BeaconValidator_ProduceAttestationData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"internal", "eth", "v1", "validator", "attestation_data"}, "")) @@ -1420,8 +1654,12 @@ var ( forward_BeaconValidator_ProduceBlockV2_0 = runtime.ForwardResponseMessage + forward_BeaconValidator_ProduceBlockV2SSZ_0 = runtime.ForwardResponseMessage + forward_BeaconValidator_ProduceBlindedBlock_0 = runtime.ForwardResponseMessage + forward_BeaconValidator_ProduceBlindedBlockSSZ_0 = runtime.ForwardResponseMessage + forward_BeaconValidator_PrepareBeaconProposer_0 = runtime.ForwardResponseMessage forward_BeaconValidator_ProduceAttestationData_0 = runtime.ForwardResponseMessage diff --git a/proto/eth/service/validator_service.proto b/proto/eth/service/validator_service.proto index 4a39c69cf7bd..4ab66e07d913 100644 --- a/proto/eth/service/validator_service.proto +++ b/proto/eth/service/validator_service.proto @@ -20,6 +20,7 @@ import "google/protobuf/descriptor.proto"; import "google/protobuf/empty.proto"; import "proto/eth/v1/validator.proto"; +import "proto/eth/v2/ssz.proto"; import "proto/eth/v2/validator.proto"; option csharp_namespace = "Ethereum.Eth.Service"; @@ -101,6 +102,20 @@ service BeaconValidator { option (google.api.http) = { get: "/internal/eth/v2/validator/blocks/{slot}" }; } + // ProduceBlockV2 requests the beacon node to produce a valid unsigned beacon block, + // which can then be signed by a proposer and submitted. + // + // The produced block is in SSZ form. + // + // HTTP response usage: + // - 200: Successful response + // - 400: Invalid block production request + // - 500: Beacon node internal error + // - 503: Beacon node is currently syncing, try again later + rpc ProduceBlockV2SSZ(v1.ProduceBlockRequest) returns (v2.SSZContainer) { + option (google.api.http) = { get: "/internal/eth/v2/validator/blocks/{slot}/ssz" }; + } + // ProduceBlindedBlock requests the beacon node to produce a valid unsigned blinded beacon block, // which can then be signed by a proposer and submitted. // @@ -117,6 +132,24 @@ service BeaconValidator { option (google.api.http) = { get: "/internal/eth/v1/validator/blinded_blocks/{slot}" }; } + // ProduceBlindedBlock requests the beacon node to produce a valid unsigned blinded beacon block, + // which can then be signed by a proposer and submitted. + // + // The produced block is in SSZ form. + // + // Metadata in the response indicates the type of block produced, and the supported types of block + // will be added to as forks progress. + // + // Pre-Bellatrix, this endpoint will return a regular block. + // HTTP response usage: + // - 200: Successful response + // - 400: Invalid block production request + // - 500: Beacon node internal error + // - 503: Beacon node is currently syncing, try again later + rpc ProduceBlindedBlockSSZ(v1.ProduceBlockRequest) returns (v2.SSZContainer) { + option (google.api.http) = { get: "/internal/eth/v1/validator/blinded_blocks/{slot}/ssz" }; + } + // PrepareBeaconProposer submits fee recipient information to be used when preparing block // proposal execution payloads. // diff --git a/proto/eth/v1/beacon_state.pb.go b/proto/eth/v1/beacon_state.pb.go index 21dde4ff2185..7974b58ad433 100755 --- a/proto/eth/v1/beacon_state.pb.go +++ b/proto/eth/v1/beacon_state.pb.go @@ -578,53 +578,6 @@ func (x *BeaconStateResponse) GetData() *BeaconState { return nil } -type BeaconStateSSZResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` -} - -func (x *BeaconStateSSZResponse) Reset() { - *x = BeaconStateSSZResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconStateSSZResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconStateSSZResponse) ProtoMessage() {} - -func (x *BeaconStateSSZResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v1_beacon_state_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconStateSSZResponse.ProtoReflect.Descriptor instead. -func (*BeaconStateSSZResponse) Descriptor() ([]byte, []int) { - return file_proto_eth_v1_beacon_state_proto_rawDescGZIP(), []int{7} -} - -func (x *BeaconStateSSZResponse) GetData() []byte { - if x != nil { - return x.Data - } - return nil -} - var File_proto_eth_v1_beacon_state_proto protoreflect.FileDescriptor var file_proto_eth_v1_beacon_state_proto_rawDesc = []byte{ @@ -809,18 +762,16 @@ var file_proto_eth_v1_beacon_state_proto_rawDesc = []byte{ 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x2c, 0x0a, - 0x16, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x53, 0x5a, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x7a, 0x0a, 0x13, 0x6f, - 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, - 0x2f, 0x76, 0x31, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, - 0x74, 0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x7a, 0x0a, + 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -835,7 +786,7 @@ func file_proto_eth_v1_beacon_state_proto_rawDescGZIP() []byte { return file_proto_eth_v1_beacon_state_proto_rawDescData } -var file_proto_eth_v1_beacon_state_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_proto_eth_v1_beacon_state_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_proto_eth_v1_beacon_state_proto_goTypes = []interface{}{ (*BeaconState)(nil), // 0: ethereum.eth.v1.BeaconState (*PendingAttestation)(nil), // 1: ethereum.eth.v1.PendingAttestation @@ -844,25 +795,24 @@ var file_proto_eth_v1_beacon_state_proto_goTypes = []interface{}{ (*ForkChoiceHeadsResponse)(nil), // 4: ethereum.eth.v1.ForkChoiceHeadsResponse (*ForkChoiceHead)(nil), // 5: ethereum.eth.v1.ForkChoiceHead (*BeaconStateResponse)(nil), // 6: ethereum.eth.v1.BeaconStateResponse - (*BeaconStateSSZResponse)(nil), // 7: ethereum.eth.v1.BeaconStateSSZResponse - (*BeaconBlockHeader)(nil), // 8: ethereum.eth.v1.BeaconBlockHeader - (*Eth1Data)(nil), // 9: ethereum.eth.v1.Eth1Data - (*Validator)(nil), // 10: ethereum.eth.v1.Validator - (*Checkpoint)(nil), // 11: ethereum.eth.v1.Checkpoint - (*AttestationData)(nil), // 12: ethereum.eth.v1.AttestationData + (*BeaconBlockHeader)(nil), // 7: ethereum.eth.v1.BeaconBlockHeader + (*Eth1Data)(nil), // 8: ethereum.eth.v1.Eth1Data + (*Validator)(nil), // 9: ethereum.eth.v1.Validator + (*Checkpoint)(nil), // 10: ethereum.eth.v1.Checkpoint + (*AttestationData)(nil), // 11: ethereum.eth.v1.AttestationData } var file_proto_eth_v1_beacon_state_proto_depIdxs = []int32{ 3, // 0: ethereum.eth.v1.BeaconState.fork:type_name -> ethereum.eth.v1.Fork - 8, // 1: ethereum.eth.v1.BeaconState.latest_block_header:type_name -> ethereum.eth.v1.BeaconBlockHeader - 9, // 2: ethereum.eth.v1.BeaconState.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 9, // 3: ethereum.eth.v1.BeaconState.eth1_data_votes:type_name -> ethereum.eth.v1.Eth1Data - 10, // 4: ethereum.eth.v1.BeaconState.validators:type_name -> ethereum.eth.v1.Validator + 7, // 1: ethereum.eth.v1.BeaconState.latest_block_header:type_name -> ethereum.eth.v1.BeaconBlockHeader + 8, // 2: ethereum.eth.v1.BeaconState.eth1_data:type_name -> ethereum.eth.v1.Eth1Data + 8, // 3: ethereum.eth.v1.BeaconState.eth1_data_votes:type_name -> ethereum.eth.v1.Eth1Data + 9, // 4: ethereum.eth.v1.BeaconState.validators:type_name -> ethereum.eth.v1.Validator 1, // 5: ethereum.eth.v1.BeaconState.previous_epoch_attestations:type_name -> ethereum.eth.v1.PendingAttestation 1, // 6: ethereum.eth.v1.BeaconState.current_epoch_attestations:type_name -> ethereum.eth.v1.PendingAttestation - 11, // 7: ethereum.eth.v1.BeaconState.previous_justified_checkpoint:type_name -> ethereum.eth.v1.Checkpoint - 11, // 8: ethereum.eth.v1.BeaconState.current_justified_checkpoint:type_name -> ethereum.eth.v1.Checkpoint - 11, // 9: ethereum.eth.v1.BeaconState.finalized_checkpoint:type_name -> ethereum.eth.v1.Checkpoint - 12, // 10: ethereum.eth.v1.PendingAttestation.data:type_name -> ethereum.eth.v1.AttestationData + 10, // 7: ethereum.eth.v1.BeaconState.previous_justified_checkpoint:type_name -> ethereum.eth.v1.Checkpoint + 10, // 8: ethereum.eth.v1.BeaconState.current_justified_checkpoint:type_name -> ethereum.eth.v1.Checkpoint + 10, // 9: ethereum.eth.v1.BeaconState.finalized_checkpoint:type_name -> ethereum.eth.v1.Checkpoint + 11, // 10: ethereum.eth.v1.PendingAttestation.data:type_name -> ethereum.eth.v1.AttestationData 5, // 11: ethereum.eth.v1.ForkChoiceHeadsResponse.data:type_name -> ethereum.eth.v1.ForkChoiceHead 0, // 12: ethereum.eth.v1.BeaconStateResponse.data:type_name -> ethereum.eth.v1.BeaconState 13, // [13:13] is the sub-list for method output_type @@ -965,18 +915,6 @@ func file_proto_eth_v1_beacon_state_proto_init() { return nil } } - file_proto_eth_v1_beacon_state_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconStateSSZResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } type x struct{} out := protoimpl.TypeBuilder{ @@ -984,7 +922,7 @@ func file_proto_eth_v1_beacon_state_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_eth_v1_beacon_state_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/eth/v1/beacon_state.proto b/proto/eth/v1/beacon_state.proto index 62b000bc7f75..b48355da49d6 100644 --- a/proto/eth/v1/beacon_state.proto +++ b/proto/eth/v1/beacon_state.proto @@ -105,7 +105,3 @@ message ForkChoiceHead { message BeaconStateResponse { BeaconState data = 1; } - -message BeaconStateSSZResponse { - bytes data = 1; -} diff --git a/proto/eth/v2/BUILD.bazel b/proto/eth/v2/BUILD.bazel index 395c46399e86..d07a434dbcf2 100644 --- a/proto/eth/v2/BUILD.bazel +++ b/proto/eth/v2/BUILD.bazel @@ -9,6 +9,7 @@ proto_library( name = "proto", srcs = [ "beacon_block.proto", + "ssz.proto", "version.proto", ":ssz_proto_files", ], diff --git a/proto/eth/v2/beacon_block.pb.go b/proto/eth/v2/beacon_block.pb.go index 379206ec8630..064610645fd5 100755 --- a/proto/eth/v2/beacon_block.pb.go +++ b/proto/eth/v2/beacon_block.pb.go @@ -135,61 +135,6 @@ func (x *BlockResponseV2) GetExecutionOptimistic() bool { return false } -type BlockSSZResponseV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=ethereum.eth.v2.Version" json:"version,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` -} - -func (x *BlockSSZResponseV2) Reset() { - *x = BlockSSZResponseV2{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlockSSZResponseV2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockSSZResponseV2) ProtoMessage() {} - -func (x *BlockSSZResponseV2) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlockSSZResponseV2.ProtoReflect.Descriptor instead. -func (*BlockSSZResponseV2) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{2} -} - -func (x *BlockSSZResponseV2) GetVersion() Version { - if x != nil { - return x.Version - } - return Version_PHASE0 -} - -func (x *BlockSSZResponseV2) GetData() []byte { - if x != nil { - return x.Data - } - return nil -} - type BeaconBlockContainerV2 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -205,7 +150,7 @@ type BeaconBlockContainerV2 struct { func (x *BeaconBlockContainerV2) Reset() { *x = BeaconBlockContainerV2{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[3] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -218,7 +163,7 @@ func (x *BeaconBlockContainerV2) String() string { func (*BeaconBlockContainerV2) ProtoMessage() {} func (x *BeaconBlockContainerV2) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[3] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -231,7 +176,7 @@ func (x *BeaconBlockContainerV2) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconBlockContainerV2.ProtoReflect.Descriptor instead. func (*BeaconBlockContainerV2) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{3} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{2} } func (m *BeaconBlockContainerV2) GetBlock() isBeaconBlockContainerV2_Block { @@ -300,7 +245,7 @@ type SignedBeaconBlockContainerV2 struct { func (x *SignedBeaconBlockContainerV2) Reset() { *x = SignedBeaconBlockContainerV2{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[4] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -313,7 +258,7 @@ func (x *SignedBeaconBlockContainerV2) String() string { func (*SignedBeaconBlockContainerV2) ProtoMessage() {} func (x *SignedBeaconBlockContainerV2) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[4] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -326,7 +271,7 @@ func (x *SignedBeaconBlockContainerV2) ProtoReflect() protoreflect.Message { // Deprecated: Use SignedBeaconBlockContainerV2.ProtoReflect.Descriptor instead. func (*SignedBeaconBlockContainerV2) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{4} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{3} } func (m *SignedBeaconBlockContainerV2) GetMessage() isSignedBeaconBlockContainerV2_Message { @@ -401,7 +346,7 @@ type BlindedBeaconBlockContainer struct { func (x *BlindedBeaconBlockContainer) Reset() { *x = BlindedBeaconBlockContainer{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[5] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -414,7 +359,7 @@ func (x *BlindedBeaconBlockContainer) String() string { func (*BlindedBeaconBlockContainer) ProtoMessage() {} func (x *BlindedBeaconBlockContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[5] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -427,7 +372,7 @@ func (x *BlindedBeaconBlockContainer) ProtoReflect() protoreflect.Message { // Deprecated: Use BlindedBeaconBlockContainer.ProtoReflect.Descriptor instead. func (*BlindedBeaconBlockContainer) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{5} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{4} } func (m *BlindedBeaconBlockContainer) GetBlock() isBlindedBeaconBlockContainer_Block { @@ -496,7 +441,7 @@ type SignedBlindedBeaconBlockContainer struct { func (x *SignedBlindedBeaconBlockContainer) Reset() { *x = SignedBlindedBeaconBlockContainer{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[6] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -509,7 +454,7 @@ func (x *SignedBlindedBeaconBlockContainer) String() string { func (*SignedBlindedBeaconBlockContainer) ProtoMessage() {} func (x *SignedBlindedBeaconBlockContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[6] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -522,7 +467,7 @@ func (x *SignedBlindedBeaconBlockContainer) ProtoReflect() protoreflect.Message // Deprecated: Use SignedBlindedBeaconBlockContainer.ProtoReflect.Descriptor instead. func (*SignedBlindedBeaconBlockContainer) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{6} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{5} } func (m *SignedBlindedBeaconBlockContainer) GetMessage() isSignedBlindedBeaconBlockContainer_Message { @@ -595,7 +540,7 @@ type SignedBeaconBlockBellatrix struct { func (x *SignedBeaconBlockBellatrix) Reset() { *x = SignedBeaconBlockBellatrix{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[7] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -608,7 +553,7 @@ func (x *SignedBeaconBlockBellatrix) String() string { func (*SignedBeaconBlockBellatrix) ProtoMessage() {} func (x *SignedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[7] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -621,7 +566,7 @@ func (x *SignedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { // Deprecated: Use SignedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. func (*SignedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{7} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{6} } func (x *SignedBeaconBlockBellatrix) GetMessage() *BeaconBlockBellatrix { @@ -650,7 +595,7 @@ type SignedBlindedBeaconBlockBellatrix struct { func (x *SignedBlindedBeaconBlockBellatrix) Reset() { *x = SignedBlindedBeaconBlockBellatrix{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[8] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -663,7 +608,7 @@ func (x *SignedBlindedBeaconBlockBellatrix) String() string { func (*SignedBlindedBeaconBlockBellatrix) ProtoMessage() {} func (x *SignedBlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[8] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -676,7 +621,7 @@ func (x *SignedBlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message // Deprecated: Use SignedBlindedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. func (*SignedBlindedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{8} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{7} } func (x *SignedBlindedBeaconBlockBellatrix) GetMessage() *BlindedBeaconBlockBellatrix { @@ -705,7 +650,7 @@ type SignedBeaconBlockAltair struct { func (x *SignedBeaconBlockAltair) Reset() { *x = SignedBeaconBlockAltair{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[9] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -718,7 +663,7 @@ func (x *SignedBeaconBlockAltair) String() string { func (*SignedBeaconBlockAltair) ProtoMessage() {} func (x *SignedBeaconBlockAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[9] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -731,7 +676,7 @@ func (x *SignedBeaconBlockAltair) ProtoReflect() protoreflect.Message { // Deprecated: Use SignedBeaconBlockAltair.ProtoReflect.Descriptor instead. func (*SignedBeaconBlockAltair) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{9} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{8} } func (x *SignedBeaconBlockAltair) GetMessage() *BeaconBlockAltair { @@ -763,7 +708,7 @@ type BeaconBlockBellatrix struct { func (x *BeaconBlockBellatrix) Reset() { *x = BeaconBlockBellatrix{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[10] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -776,7 +721,7 @@ func (x *BeaconBlockBellatrix) String() string { func (*BeaconBlockBellatrix) ProtoMessage() {} func (x *BeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[10] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -789,7 +734,7 @@ func (x *BeaconBlockBellatrix) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconBlockBellatrix.ProtoReflect.Descriptor instead. func (*BeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{10} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{9} } func (x *BeaconBlockBellatrix) GetSlot() github_com_prysmaticlabs_prysm_consensus_types_primitives.Slot { @@ -842,7 +787,7 @@ type BlindedBeaconBlockBellatrix struct { func (x *BlindedBeaconBlockBellatrix) Reset() { *x = BlindedBeaconBlockBellatrix{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[11] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -855,7 +800,7 @@ func (x *BlindedBeaconBlockBellatrix) String() string { func (*BlindedBeaconBlockBellatrix) ProtoMessage() {} func (x *BlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[11] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -868,7 +813,7 @@ func (x *BlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { // Deprecated: Use BlindedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. func (*BlindedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{11} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{10} } func (x *BlindedBeaconBlockBellatrix) GetSlot() github_com_prysmaticlabs_prysm_consensus_types_primitives.Slot { @@ -921,7 +866,7 @@ type BeaconBlockAltair struct { func (x *BeaconBlockAltair) Reset() { *x = BeaconBlockAltair{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[12] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -934,7 +879,7 @@ func (x *BeaconBlockAltair) String() string { func (*BeaconBlockAltair) ProtoMessage() {} func (x *BeaconBlockAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[12] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -947,7 +892,7 @@ func (x *BeaconBlockAltair) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconBlockAltair.ProtoReflect.Descriptor instead. func (*BeaconBlockAltair) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{12} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{11} } func (x *BeaconBlockAltair) GetSlot() github_com_prysmaticlabs_prysm_consensus_types_primitives.Slot { @@ -1005,7 +950,7 @@ type BeaconBlockBodyBellatrix struct { func (x *BeaconBlockBodyBellatrix) Reset() { *x = BeaconBlockBodyBellatrix{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[13] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1018,7 +963,7 @@ func (x *BeaconBlockBodyBellatrix) String() string { func (*BeaconBlockBodyBellatrix) ProtoMessage() {} func (x *BeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[13] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1031,7 +976,7 @@ func (x *BeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconBlockBodyBellatrix.ProtoReflect.Descriptor instead. func (*BeaconBlockBodyBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{13} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{12} } func (x *BeaconBlockBodyBellatrix) GetRandaoReveal() []byte { @@ -1124,7 +1069,7 @@ type BlindedBeaconBlockBodyBellatrix struct { func (x *BlindedBeaconBlockBodyBellatrix) Reset() { *x = BlindedBeaconBlockBodyBellatrix{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[14] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1137,7 +1082,7 @@ func (x *BlindedBeaconBlockBodyBellatrix) String() string { func (*BlindedBeaconBlockBodyBellatrix) ProtoMessage() {} func (x *BlindedBeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[14] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1150,7 +1095,7 @@ func (x *BlindedBeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { // Deprecated: Use BlindedBeaconBlockBodyBellatrix.ProtoReflect.Descriptor instead. func (*BlindedBeaconBlockBodyBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{14} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{13} } func (x *BlindedBeaconBlockBodyBellatrix) GetRandaoReveal() []byte { @@ -1242,7 +1187,7 @@ type BeaconBlockBodyAltair struct { func (x *BeaconBlockBodyAltair) Reset() { *x = BeaconBlockBodyAltair{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[15] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1255,7 +1200,7 @@ func (x *BeaconBlockBodyAltair) String() string { func (*BeaconBlockBodyAltair) ProtoMessage() {} func (x *BeaconBlockBodyAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[15] + mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1268,7 +1213,7 @@ func (x *BeaconBlockBodyAltair) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconBlockBodyAltair.ProtoReflect.Descriptor instead. func (*BeaconBlockBodyAltair) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{15} + return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{14} } func (x *BeaconBlockBodyAltair) GetRandaoReveal() []byte { @@ -1365,321 +1310,315 @@ var file_proto_eth_v2_beacon_block_proto_rawDesc = []byte{ 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x22, - 0x5c, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x53, 0x5a, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x56, 0x32, 0x12, 0x32, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xff, 0x01, - 0x0a, 0x16, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, 0x32, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, - 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, - 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, - 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, - 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x50, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, + 0xff, 0x01, 0x0a, 0x16, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, 0x32, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, + 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, + 0x52, 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, + 0x0c, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, + 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x50, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, + 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x22, 0xad, 0x02, 0x0a, 0x1c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x56, 0x32, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, + 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x50, + 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, + 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x8b, 0x02, 0x0a, 0x1b, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, + 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x57, 0x0a, + 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, - 0xad, 0x02, 0x0a, 0x1c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, 0x32, - 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, - 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x50, 0x0a, 0x0f, - 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, - 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x8b, 0x02, 0x0a, 0x1b, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, - 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, - 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x57, 0x0a, 0x0f, 0x62, - 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, + 0xb9, 0x02, 0x0a, 0x21, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, + 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, 0x61, + 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, 0x6c, 0x74, 0x61, + 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, + 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, + 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x57, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, + 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, + 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, + 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x1a, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x3f, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, - 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0xb9, 0x02, - 0x0a, 0x21, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, - 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, - 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, - 0x57, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x69, 0x78, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x91, 0x01, 0x0a, 0x21, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, + 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, + 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x46, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, - 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, - 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x09, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x1a, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, - 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x3f, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, - 0x91, 0x01, 0x0a, 0x21, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, - 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x46, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, - 0x74, 0x72, 0x69, 0x78, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x22, 0x7d, 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x3c, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, - 0x61, 0x69, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x22, 0xf2, 0x02, 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x56, 0x0a, 0x04, 0x73, - 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x42, 0x82, 0xb5, 0x18, 0x3e, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, - 0x6c, 0x6f, 0x74, 0x12, 0x73, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4c, 0x82, 0xb5, 0x18, - 0x48, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x7d, 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, + 0x12, 0x3c, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, + 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x22, 0xf2, 0x02, 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x56, 0x0a, + 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x42, 0x82, 0xb5, 0x18, + 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, - 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x80, 0x03, 0x0a, 0x1b, 0x42, 0x6c, 0x69, 0x6e, - 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, - 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x56, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x42, 0x82, 0xb5, 0x18, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, - 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, - 0x73, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4c, 0x82, 0xb5, 0x18, 0x48, 0x67, 0x69, 0x74, + 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, + 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x73, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4c, 0x82, + 0xb5, 0x18, 0x48, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, + 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, + 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, + 0x72, 0x69, 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x80, 0x03, 0x0a, 0x1b, 0x42, 0x6c, + 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x56, 0x0a, 0x04, 0x73, 0x6c, 0x6f, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x42, 0x82, 0xb5, 0x18, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, - 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x44, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, - 0x74, 0x72, 0x69, 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xec, 0x02, 0x0a, 0x11, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, - 0x12, 0x56, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x42, - 0x82, 0xb5, 0x18, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, - 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x73, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x42, 0x4c, 0x82, 0xb5, 0x18, 0x48, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, + 0x74, 0x12, 0x73, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4c, 0x82, 0xb5, 0x18, 0x48, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, + 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, + 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x44, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, + 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xec, 0x02, 0x0a, + 0x11, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, + 0x69, 0x72, 0x12, 0x56, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x42, 0x82, 0xb5, 0x18, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, - 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, - 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x3a, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x41, 0x6c, 0x74, - 0x61, 0x69, 0x72, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xd0, 0x05, 0x0a, 0x18, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, - 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, - 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, - 0x65, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, - 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, - 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, - 0x58, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, - 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, - 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, - 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, - 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x49, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, - 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, - 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, - 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, - 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, - 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, - 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, - 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, - 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x11, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xea, 0x05, 0x0a, - 0x1f, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, - 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x36, 0x0a, - 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, - 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, - 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, 0x12, 0x70, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, - 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, - 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, - 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, - 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, - 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x0c, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, - 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, + 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x73, 0x0a, 0x0e, 0x70, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x4c, 0x82, 0xb5, 0x18, 0x48, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, + 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, + 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, + 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, + 0x3a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x41, + 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xd0, 0x05, 0x0a, 0x18, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, + 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, + 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, + 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, + 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, + 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, + 0x69, 0x12, 0x58, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, + 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, + 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, + 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, + 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x3c, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, + 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, + 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, + 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, + 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, + 0x78, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, + 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x11, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xea, + 0x05, 0x0a, 0x1f, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, + 0x69, 0x78, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, + 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, + 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, + 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, + 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, + 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, + 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, 0x12, 0x70, + 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, + 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, + 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x49, + 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, + 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, + 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, + 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x45, + 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0xfa, 0x04, 0x0a, 0x15, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x41, + 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, + 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, + 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, + 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, + 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, + 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, + 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x73, 0x12, 0x49, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, + 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, - 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, - 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, - 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0xfa, 0x04, 0x0a, 0x15, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x41, 0x6c, 0x74, - 0x61, 0x69, 0x72, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, - 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, - 0x12, 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, - 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, - 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, 0x12, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, - 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, - 0x49, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, - 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, - 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, - 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, - 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, - 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x42, 0x80, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x12, - 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, - 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, + 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, + 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, + 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, + 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, + 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x42, 0x80, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, + 0x42, 0x12, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, + 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1694,86 +1633,84 @@ func file_proto_eth_v2_beacon_block_proto_rawDescGZIP() []byte { return file_proto_eth_v2_beacon_block_proto_rawDescData } -var file_proto_eth_v2_beacon_block_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_proto_eth_v2_beacon_block_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_proto_eth_v2_beacon_block_proto_goTypes = []interface{}{ (*BlockRequestV2)(nil), // 0: ethereum.eth.v2.BlockRequestV2 (*BlockResponseV2)(nil), // 1: ethereum.eth.v2.BlockResponseV2 - (*BlockSSZResponseV2)(nil), // 2: ethereum.eth.v2.BlockSSZResponseV2 - (*BeaconBlockContainerV2)(nil), // 3: ethereum.eth.v2.BeaconBlockContainerV2 - (*SignedBeaconBlockContainerV2)(nil), // 4: ethereum.eth.v2.SignedBeaconBlockContainerV2 - (*BlindedBeaconBlockContainer)(nil), // 5: ethereum.eth.v2.BlindedBeaconBlockContainer - (*SignedBlindedBeaconBlockContainer)(nil), // 6: ethereum.eth.v2.SignedBlindedBeaconBlockContainer - (*SignedBeaconBlockBellatrix)(nil), // 7: ethereum.eth.v2.SignedBeaconBlockBellatrix - (*SignedBlindedBeaconBlockBellatrix)(nil), // 8: ethereum.eth.v2.SignedBlindedBeaconBlockBellatrix - (*SignedBeaconBlockAltair)(nil), // 9: ethereum.eth.v2.SignedBeaconBlockAltair - (*BeaconBlockBellatrix)(nil), // 10: ethereum.eth.v2.BeaconBlockBellatrix - (*BlindedBeaconBlockBellatrix)(nil), // 11: ethereum.eth.v2.BlindedBeaconBlockBellatrix - (*BeaconBlockAltair)(nil), // 12: ethereum.eth.v2.BeaconBlockAltair - (*BeaconBlockBodyBellatrix)(nil), // 13: ethereum.eth.v2.BeaconBlockBodyBellatrix - (*BlindedBeaconBlockBodyBellatrix)(nil), // 14: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix - (*BeaconBlockBodyAltair)(nil), // 15: ethereum.eth.v2.BeaconBlockBodyAltair - (Version)(0), // 16: ethereum.eth.v2.Version - (*v1.BeaconBlock)(nil), // 17: ethereum.eth.v1.BeaconBlock - (*v1.Eth1Data)(nil), // 18: ethereum.eth.v1.Eth1Data - (*v1.ProposerSlashing)(nil), // 19: ethereum.eth.v1.ProposerSlashing - (*v1.AttesterSlashing)(nil), // 20: ethereum.eth.v1.AttesterSlashing - (*v1.Attestation)(nil), // 21: ethereum.eth.v1.Attestation - (*v1.Deposit)(nil), // 22: ethereum.eth.v1.Deposit - (*v1.SignedVoluntaryExit)(nil), // 23: ethereum.eth.v1.SignedVoluntaryExit - (*v1.SyncAggregate)(nil), // 24: ethereum.eth.v1.SyncAggregate - (*v11.ExecutionPayload)(nil), // 25: ethereum.engine.v1.ExecutionPayload - (*v11.ExecutionPayloadHeader)(nil), // 26: ethereum.engine.v1.ExecutionPayloadHeader + (*BeaconBlockContainerV2)(nil), // 2: ethereum.eth.v2.BeaconBlockContainerV2 + (*SignedBeaconBlockContainerV2)(nil), // 3: ethereum.eth.v2.SignedBeaconBlockContainerV2 + (*BlindedBeaconBlockContainer)(nil), // 4: ethereum.eth.v2.BlindedBeaconBlockContainer + (*SignedBlindedBeaconBlockContainer)(nil), // 5: ethereum.eth.v2.SignedBlindedBeaconBlockContainer + (*SignedBeaconBlockBellatrix)(nil), // 6: ethereum.eth.v2.SignedBeaconBlockBellatrix + (*SignedBlindedBeaconBlockBellatrix)(nil), // 7: ethereum.eth.v2.SignedBlindedBeaconBlockBellatrix + (*SignedBeaconBlockAltair)(nil), // 8: ethereum.eth.v2.SignedBeaconBlockAltair + (*BeaconBlockBellatrix)(nil), // 9: ethereum.eth.v2.BeaconBlockBellatrix + (*BlindedBeaconBlockBellatrix)(nil), // 10: ethereum.eth.v2.BlindedBeaconBlockBellatrix + (*BeaconBlockAltair)(nil), // 11: ethereum.eth.v2.BeaconBlockAltair + (*BeaconBlockBodyBellatrix)(nil), // 12: ethereum.eth.v2.BeaconBlockBodyBellatrix + (*BlindedBeaconBlockBodyBellatrix)(nil), // 13: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix + (*BeaconBlockBodyAltair)(nil), // 14: ethereum.eth.v2.BeaconBlockBodyAltair + (Version)(0), // 15: ethereum.eth.v2.Version + (*v1.BeaconBlock)(nil), // 16: ethereum.eth.v1.BeaconBlock + (*v1.Eth1Data)(nil), // 17: ethereum.eth.v1.Eth1Data + (*v1.ProposerSlashing)(nil), // 18: ethereum.eth.v1.ProposerSlashing + (*v1.AttesterSlashing)(nil), // 19: ethereum.eth.v1.AttesterSlashing + (*v1.Attestation)(nil), // 20: ethereum.eth.v1.Attestation + (*v1.Deposit)(nil), // 21: ethereum.eth.v1.Deposit + (*v1.SignedVoluntaryExit)(nil), // 22: ethereum.eth.v1.SignedVoluntaryExit + (*v1.SyncAggregate)(nil), // 23: ethereum.eth.v1.SyncAggregate + (*v11.ExecutionPayload)(nil), // 24: ethereum.engine.v1.ExecutionPayload + (*v11.ExecutionPayloadHeader)(nil), // 25: ethereum.engine.v1.ExecutionPayloadHeader } var file_proto_eth_v2_beacon_block_proto_depIdxs = []int32{ - 16, // 0: ethereum.eth.v2.BlockResponseV2.version:type_name -> ethereum.eth.v2.Version - 4, // 1: ethereum.eth.v2.BlockResponseV2.data:type_name -> ethereum.eth.v2.SignedBeaconBlockContainerV2 - 16, // 2: ethereum.eth.v2.BlockSSZResponseV2.version:type_name -> ethereum.eth.v2.Version - 17, // 3: ethereum.eth.v2.BeaconBlockContainerV2.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock - 12, // 4: ethereum.eth.v2.BeaconBlockContainerV2.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair - 10, // 5: ethereum.eth.v2.BeaconBlockContainerV2.bellatrix_block:type_name -> ethereum.eth.v2.BeaconBlockBellatrix - 17, // 6: ethereum.eth.v2.SignedBeaconBlockContainerV2.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock - 12, // 7: ethereum.eth.v2.SignedBeaconBlockContainerV2.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair - 10, // 8: ethereum.eth.v2.SignedBeaconBlockContainerV2.bellatrix_block:type_name -> ethereum.eth.v2.BeaconBlockBellatrix - 17, // 9: ethereum.eth.v2.BlindedBeaconBlockContainer.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock - 12, // 10: ethereum.eth.v2.BlindedBeaconBlockContainer.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair - 11, // 11: ethereum.eth.v2.BlindedBeaconBlockContainer.bellatrix_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix - 17, // 12: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock - 12, // 13: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair - 11, // 14: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.bellatrix_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix - 10, // 15: ethereum.eth.v2.SignedBeaconBlockBellatrix.message:type_name -> ethereum.eth.v2.BeaconBlockBellatrix - 11, // 16: ethereum.eth.v2.SignedBlindedBeaconBlockBellatrix.message:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix - 12, // 17: ethereum.eth.v2.SignedBeaconBlockAltair.message:type_name -> ethereum.eth.v2.BeaconBlockAltair - 13, // 18: ethereum.eth.v2.BeaconBlockBellatrix.body:type_name -> ethereum.eth.v2.BeaconBlockBodyBellatrix - 14, // 19: ethereum.eth.v2.BlindedBeaconBlockBellatrix.body:type_name -> ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix - 15, // 20: ethereum.eth.v2.BeaconBlockAltair.body:type_name -> ethereum.eth.v2.BeaconBlockBodyAltair - 18, // 21: ethereum.eth.v2.BeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 19, // 22: ethereum.eth.v2.BeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 20, // 23: ethereum.eth.v2.BeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 21, // 24: ethereum.eth.v2.BeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1.Attestation - 22, // 25: ethereum.eth.v2.BeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1.Deposit - 23, // 26: ethereum.eth.v2.BeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 24, // 27: ethereum.eth.v2.BeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 25, // 28: ethereum.eth.v2.BeaconBlockBodyBellatrix.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayload - 18, // 29: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 19, // 30: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 20, // 31: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 21, // 32: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1.Attestation - 22, // 33: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1.Deposit - 23, // 34: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 24, // 35: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 26, // 36: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeader - 18, // 37: ethereum.eth.v2.BeaconBlockBodyAltair.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 19, // 38: ethereum.eth.v2.BeaconBlockBodyAltair.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 20, // 39: ethereum.eth.v2.BeaconBlockBodyAltair.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 21, // 40: ethereum.eth.v2.BeaconBlockBodyAltair.attestations:type_name -> ethereum.eth.v1.Attestation - 22, // 41: ethereum.eth.v2.BeaconBlockBodyAltair.deposits:type_name -> ethereum.eth.v1.Deposit - 23, // 42: ethereum.eth.v2.BeaconBlockBodyAltair.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 24, // 43: ethereum.eth.v2.BeaconBlockBodyAltair.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 44, // [44:44] is the sub-list for method output_type - 44, // [44:44] is the sub-list for method input_type - 44, // [44:44] is the sub-list for extension type_name - 44, // [44:44] is the sub-list for extension extendee - 0, // [0:44] is the sub-list for field type_name + 15, // 0: ethereum.eth.v2.BlockResponseV2.version:type_name -> ethereum.eth.v2.Version + 3, // 1: ethereum.eth.v2.BlockResponseV2.data:type_name -> ethereum.eth.v2.SignedBeaconBlockContainerV2 + 16, // 2: ethereum.eth.v2.BeaconBlockContainerV2.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock + 11, // 3: ethereum.eth.v2.BeaconBlockContainerV2.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair + 9, // 4: ethereum.eth.v2.BeaconBlockContainerV2.bellatrix_block:type_name -> ethereum.eth.v2.BeaconBlockBellatrix + 16, // 5: ethereum.eth.v2.SignedBeaconBlockContainerV2.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock + 11, // 6: ethereum.eth.v2.SignedBeaconBlockContainerV2.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair + 9, // 7: ethereum.eth.v2.SignedBeaconBlockContainerV2.bellatrix_block:type_name -> ethereum.eth.v2.BeaconBlockBellatrix + 16, // 8: ethereum.eth.v2.BlindedBeaconBlockContainer.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock + 11, // 9: ethereum.eth.v2.BlindedBeaconBlockContainer.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair + 10, // 10: ethereum.eth.v2.BlindedBeaconBlockContainer.bellatrix_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix + 16, // 11: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock + 11, // 12: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair + 10, // 13: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.bellatrix_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix + 9, // 14: ethereum.eth.v2.SignedBeaconBlockBellatrix.message:type_name -> ethereum.eth.v2.BeaconBlockBellatrix + 10, // 15: ethereum.eth.v2.SignedBlindedBeaconBlockBellatrix.message:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix + 11, // 16: ethereum.eth.v2.SignedBeaconBlockAltair.message:type_name -> ethereum.eth.v2.BeaconBlockAltair + 12, // 17: ethereum.eth.v2.BeaconBlockBellatrix.body:type_name -> ethereum.eth.v2.BeaconBlockBodyBellatrix + 13, // 18: ethereum.eth.v2.BlindedBeaconBlockBellatrix.body:type_name -> ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix + 14, // 19: ethereum.eth.v2.BeaconBlockAltair.body:type_name -> ethereum.eth.v2.BeaconBlockBodyAltair + 17, // 20: ethereum.eth.v2.BeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1.Eth1Data + 18, // 21: ethereum.eth.v2.BeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing + 19, // 22: ethereum.eth.v2.BeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing + 20, // 23: ethereum.eth.v2.BeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1.Attestation + 21, // 24: ethereum.eth.v2.BeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1.Deposit + 22, // 25: ethereum.eth.v2.BeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit + 23, // 26: ethereum.eth.v2.BeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate + 24, // 27: ethereum.eth.v2.BeaconBlockBodyBellatrix.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayload + 17, // 28: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1.Eth1Data + 18, // 29: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing + 19, // 30: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing + 20, // 31: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1.Attestation + 21, // 32: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1.Deposit + 22, // 33: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit + 23, // 34: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate + 25, // 35: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeader + 17, // 36: ethereum.eth.v2.BeaconBlockBodyAltair.eth1_data:type_name -> ethereum.eth.v1.Eth1Data + 18, // 37: ethereum.eth.v2.BeaconBlockBodyAltair.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing + 19, // 38: ethereum.eth.v2.BeaconBlockBodyAltair.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing + 20, // 39: ethereum.eth.v2.BeaconBlockBodyAltair.attestations:type_name -> ethereum.eth.v1.Attestation + 21, // 40: ethereum.eth.v2.BeaconBlockBodyAltair.deposits:type_name -> ethereum.eth.v1.Deposit + 22, // 41: ethereum.eth.v2.BeaconBlockBodyAltair.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit + 23, // 42: ethereum.eth.v2.BeaconBlockBodyAltair.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate + 43, // [43:43] is the sub-list for method output_type + 43, // [43:43] is the sub-list for method input_type + 43, // [43:43] is the sub-list for extension type_name + 43, // [43:43] is the sub-list for extension extendee + 0, // [0:43] is the sub-list for field type_name } func init() { file_proto_eth_v2_beacon_block_proto_init() } @@ -1808,18 +1745,6 @@ func file_proto_eth_v2_beacon_block_proto_init() { } } file_proto_eth_v2_beacon_block_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlockSSZResponseV2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BeaconBlockContainerV2); i { case 0: return &v.state @@ -1831,7 +1756,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SignedBeaconBlockContainerV2); i { case 0: return &v.state @@ -1843,7 +1768,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlindedBeaconBlockContainer); i { case 0: return &v.state @@ -1855,7 +1780,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SignedBlindedBeaconBlockContainer); i { case 0: return &v.state @@ -1867,7 +1792,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SignedBeaconBlockBellatrix); i { case 0: return &v.state @@ -1879,7 +1804,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SignedBlindedBeaconBlockBellatrix); i { case 0: return &v.state @@ -1891,7 +1816,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SignedBeaconBlockAltair); i { case 0: return &v.state @@ -1903,7 +1828,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BeaconBlockBellatrix); i { case 0: return &v.state @@ -1915,7 +1840,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlindedBeaconBlockBellatrix); i { case 0: return &v.state @@ -1927,7 +1852,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BeaconBlockAltair); i { case 0: return &v.state @@ -1939,7 +1864,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BeaconBlockBodyBellatrix); i { case 0: return &v.state @@ -1951,7 +1876,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlindedBeaconBlockBodyBellatrix); i { case 0: return &v.state @@ -1963,7 +1888,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { return nil } } - file_proto_eth_v2_beacon_block_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_v2_beacon_block_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BeaconBlockBodyAltair); i { case 0: return &v.state @@ -1976,22 +1901,22 @@ func file_proto_eth_v2_beacon_block_proto_init() { } } } - file_proto_eth_v2_beacon_block_proto_msgTypes[3].OneofWrappers = []interface{}{ + file_proto_eth_v2_beacon_block_proto_msgTypes[2].OneofWrappers = []interface{}{ (*BeaconBlockContainerV2_Phase0Block)(nil), (*BeaconBlockContainerV2_AltairBlock)(nil), (*BeaconBlockContainerV2_BellatrixBlock)(nil), } - file_proto_eth_v2_beacon_block_proto_msgTypes[4].OneofWrappers = []interface{}{ + file_proto_eth_v2_beacon_block_proto_msgTypes[3].OneofWrappers = []interface{}{ (*SignedBeaconBlockContainerV2_Phase0Block)(nil), (*SignedBeaconBlockContainerV2_AltairBlock)(nil), (*SignedBeaconBlockContainerV2_BellatrixBlock)(nil), } - file_proto_eth_v2_beacon_block_proto_msgTypes[5].OneofWrappers = []interface{}{ + file_proto_eth_v2_beacon_block_proto_msgTypes[4].OneofWrappers = []interface{}{ (*BlindedBeaconBlockContainer_Phase0Block)(nil), (*BlindedBeaconBlockContainer_AltairBlock)(nil), (*BlindedBeaconBlockContainer_BellatrixBlock)(nil), } - file_proto_eth_v2_beacon_block_proto_msgTypes[6].OneofWrappers = []interface{}{ + file_proto_eth_v2_beacon_block_proto_msgTypes[5].OneofWrappers = []interface{}{ (*SignedBlindedBeaconBlockContainer_Phase0Block)(nil), (*SignedBlindedBeaconBlockContainer_AltairBlock)(nil), (*SignedBlindedBeaconBlockContainer_BellatrixBlock)(nil), @@ -2002,7 +1927,7 @@ func file_proto_eth_v2_beacon_block_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_eth_v2_beacon_block_proto_rawDesc, NumEnums: 0, - NumMessages: 16, + NumMessages: 15, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/eth/v2/beacon_block.proto b/proto/eth/v2/beacon_block.proto index 1b0e79fcdc1b..7434e7ebc174 100644 --- a/proto/eth/v2/beacon_block.proto +++ b/proto/eth/v2/beacon_block.proto @@ -40,11 +40,6 @@ message BlockResponseV2 { bool execution_optimistic = 3; } -message BlockSSZResponseV2 { - v2.Version version = 1; - bytes data = 2; -} - message BeaconBlockContainerV2 { oneof block { v1.BeaconBlock phase0_block = 1; diff --git a/proto/eth/v2/ssz.pb.go b/proto/eth/v2/ssz.pb.go new file mode 100755 index 000000000000..388ae783915c --- /dev/null +++ b/proto/eth/v2/ssz.pb.go @@ -0,0 +1,166 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.15.8 +// source: proto/eth/v2/ssz.proto + +package eth + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type SSZContainer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=ethereum.eth.v2.Version" json:"version,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *SSZContainer) Reset() { + *x = SSZContainer{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_eth_v2_ssz_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SSZContainer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SSZContainer) ProtoMessage() {} + +func (x *SSZContainer) ProtoReflect() protoreflect.Message { + mi := &file_proto_eth_v2_ssz_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SSZContainer.ProtoReflect.Descriptor instead. +func (*SSZContainer) Descriptor() ([]byte, []int) { + return file_proto_eth_v2_ssz_proto_rawDescGZIP(), []int{0} +} + +func (x *SSZContainer) GetVersion() Version { + if x != nil { + return x.Version + } + return Version_PHASE0 +} + +func (x *SSZContainer) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +var File_proto_eth_v2_ssz_proto protoreflect.FileDescriptor + +var file_proto_eth_v2_ssz_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x73, + 0x73, 0x7a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x1a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x0c, 0x53, 0x53, 0x5a, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x76, 0x0a, + 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x32, 0x42, 0x08, 0x53, 0x73, 0x7a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, + 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, + 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, + 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_eth_v2_ssz_proto_rawDescOnce sync.Once + file_proto_eth_v2_ssz_proto_rawDescData = file_proto_eth_v2_ssz_proto_rawDesc +) + +func file_proto_eth_v2_ssz_proto_rawDescGZIP() []byte { + file_proto_eth_v2_ssz_proto_rawDescOnce.Do(func() { + file_proto_eth_v2_ssz_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_ssz_proto_rawDescData) + }) + return file_proto_eth_v2_ssz_proto_rawDescData +} + +var file_proto_eth_v2_ssz_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_proto_eth_v2_ssz_proto_goTypes = []interface{}{ + (*SSZContainer)(nil), // 0: ethereum.eth.v2.SSZContainer + (Version)(0), // 1: ethereum.eth.v2.Version +} +var file_proto_eth_v2_ssz_proto_depIdxs = []int32{ + 1, // 0: ethereum.eth.v2.SSZContainer.version:type_name -> ethereum.eth.v2.Version + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_proto_eth_v2_ssz_proto_init() } +func file_proto_eth_v2_ssz_proto_init() { + if File_proto_eth_v2_ssz_proto != nil { + return + } + file_proto_eth_v2_version_proto_init() + if !protoimpl.UnsafeEnabled { + file_proto_eth_v2_ssz_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SSZContainer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_eth_v2_ssz_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_eth_v2_ssz_proto_goTypes, + DependencyIndexes: file_proto_eth_v2_ssz_proto_depIdxs, + MessageInfos: file_proto_eth_v2_ssz_proto_msgTypes, + }.Build() + File_proto_eth_v2_ssz_proto = out.File + file_proto_eth_v2_ssz_proto_rawDesc = nil + file_proto_eth_v2_ssz_proto_goTypes = nil + file_proto_eth_v2_ssz_proto_depIdxs = nil +} diff --git a/proto/eth/v2/ssz.pb.gw.go b/proto/eth/v2/ssz.pb.gw.go new file mode 100755 index 000000000000..cdd03643f0c7 --- /dev/null +++ b/proto/eth/v2/ssz.pb.gw.go @@ -0,0 +1,4 @@ +//go:build ignore +// +build ignore + +package ignore diff --git a/proto/eth/v2/ssz.proto b/proto/eth/v2/ssz.proto new file mode 100644 index 000000000000..be78b311a95c --- /dev/null +++ b/proto/eth/v2/ssz.proto @@ -0,0 +1,30 @@ +// Copyright 2022 Prysmatic Labs. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; + +package ethereum.eth.v2; + +option csharp_namespace = "Ethereum.Eth.V2"; +option go_package = "github.com/prysmaticlabs/prysm/proto/eth/v2;eth"; +option java_multiple_files = true; +option java_outer_classname = "SszProto"; +option java_package = "org.ethereum.eth.v2"; +option php_namespace = "Ethereum\\Eth\\v2"; + +import "proto/eth/v2/version.proto"; + +message SSZContainer { + Version version = 1; + bytes data = 2; +} \ No newline at end of file diff --git a/proto/migration/v1alpha1_to_v2_test.go b/proto/migration/v1alpha1_to_v2_test.go index e6a14c5cc006..77aed5b5d7dd 100644 --- a/proto/migration/v1alpha1_to_v2_test.go +++ b/proto/migration/v1alpha1_to_v2_test.go @@ -45,6 +45,7 @@ func TestV1Alpha1SignedContributionAndProofToV2(t *testing.T) { assert.DeepEqual(t, bitfield.NewBitvector128(), contrib.AggregationBits) assert.DeepEqual(t, signature, contrib.Signature) } + func Test_V1Alpha1BeaconBlockAltairToV2(t *testing.T) { alphaBlock := util.HydrateBeaconBlockAltair(ðpbalpha.BeaconBlockAltair{}) alphaBlock.Slot = slot diff --git a/testing/endtoend/README.md b/testing/endtoend/README.md index 4532176fa8b6..9ff572c26fa3 100644 --- a/testing/endtoend/README.md +++ b/testing/endtoend/README.md @@ -1,27 +1,8 @@ # End-to-end Testing Package This is the main project folder of the end-to-end testing suite for Prysm. This performs a full end-to-end test for Prysm, including spinning up an ETH1 dev chain, sending deposits to the deposit contract, and making sure the beacon node and its validators are running and performing properly for a few epochs. -It also performs a test on a syncing node, and supports featureflags to allow easy E2E testing of experimental features. +It also performs a test on a syncing node, and supports feature flags to allow easy E2E testing of experimental features. ## How it works -Through the `end2EndConfig` struct, you can declare several options such as how many epochs the test should run for, and what `BeaconConfig` the test should use. You can also declare how many beacon nodes and validator clients are run, the E2E will automatically divide the validators evently among the beacon nodes. - -In order to "evaluate" the state of the beacon chain while the E2E is running, there are `Evaluators` that use the beacon chain node API to determine if the network is performing as it should. This can evaluate for conditions like validator activation, finalization, validator participation and more. - -Evaluators have 3 parts, the name for it's test name, a `policy` which declares which epoch(s) the evaluator should run, and then the `evaluation` which uses the beacon chain API to determine if the beacon chain passes certain conditions like finality. - -## Current end-to-end tests - -* Minimal Config - 2 beacon nodes, 256 validators, running for 8 epochs -* Minimal Config Slashing Test - 2 beacon nodes, 256 validators, tests attester and proposer slashing - -## Instructions - -Note: Java 11 or greater is required to run web3signer. - -If you wish to run all the minimal spec E2E tests, you can run them through bazel with: - -``` -bazel test //testing/endtoend:go_default_test --test_output=streamed -``` +Please see our docs page, https://docs.prylabs.network/docs/devtools/end-to-end, to read more about the feature. diff --git a/testing/endtoend/components/lighthouse_beacon.go b/testing/endtoend/components/lighthouse_beacon.go index 9422e1a20409..c9f2593cb2da 100644 --- a/testing/endtoend/components/lighthouse_beacon.go +++ b/testing/endtoend/components/lighthouse_beacon.go @@ -78,7 +78,7 @@ type LighthouseBeaconNode struct { enr string } -// NewBeaconNode creates and returns a beacon node. +// NewLighthouseBeaconNode creates and returns a lighthouse beacon node. func NewLighthouseBeaconNode(config *e2etypes.E2EConfig, index int, enr string) *LighthouseBeaconNode { return &LighthouseBeaconNode{ config: config, diff --git a/testing/endtoend/components/validator.go b/testing/endtoend/components/validator.go index cbad7a410868..8c832720c5cf 100644 --- a/testing/endtoend/components/validator.go +++ b/testing/endtoend/components/validator.go @@ -3,7 +3,6 @@ package components import ( "bytes" "context" - "encoding/hex" "fmt" "math/big" "os" @@ -14,6 +13,7 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" @@ -61,7 +61,6 @@ func (s *ValidatorNodeSet) Start(ctx context.Context) error { return errors.New("validator count is not easily divisible by beacon node count") } validatorsPerNode := validatorNum / beaconNodeNum - // Create validator nodes. nodes := make([]e2etypes.ComponentRunner, prysmBeaconNodeNum) for i := 0; i < prysmBeaconNodeNum; i++ { @@ -159,7 +158,7 @@ func (v *ValidatorNode) Start(ctx context.Context) error { } var hexPubs []string for _, pub := range pubs { - hexPubs = append(hexPubs, "0x"+hex.EncodeToString(pub.Marshal())) + hexPubs = append(hexPubs, hexutil.Encode(pub.Marshal())) } args = append(args, fmt.Sprintf("--%s=%s", flags.Web3SignerPublicValidatorKeysFlag.Name, strings.Join(hexPubs, ","))) } else { diff --git a/testing/endtoend/components/web3remotesigner.go b/testing/endtoend/components/web3remotesigner.go index 6c3248e2fe6d..fe5e4b4cb62c 100644 --- a/testing/endtoend/components/web3remotesigner.go +++ b/testing/endtoend/components/web3remotesigner.go @@ -216,6 +216,9 @@ func writeKeystoreKeys(ctx context.Context, keystorePath string, numKeys uint64) if err != nil { return err } + for i, p := range pub { + log.Infof("web3signer file added %s, key index %v", hexutil.Encode(p.Marshal()), i) + } for i, pk := range priv { if ctx.Err() != nil { return ctx.Err() diff --git a/testing/endtoend/deps.bzl b/testing/endtoend/deps.bzl index f940d0ce1a59..646ff879d0cd 100644 --- a/testing/endtoend/deps.bzl +++ b/testing/endtoend/deps.bzl @@ -6,11 +6,10 @@ lighthouse_archive_name = "lighthouse-%s-x86_64-unknown-linux-gnu-portable.tar.g def e2e_deps(): http_archive( name = "web3signer", - # Built from commit 17d253b which has important unreleased changes. - urls = ["https://prysmaticlabs.com/uploads/web3signer-17d253b.tar.gz"], - sha256 = "bf450a59a0845c1ce8100b3192c7fec021b565efe8b1ab46bed9f71cb994a6d7", + urls = ["https://artifacts.consensys.net/public/web3signer/raw/names/web3signer.tar.gz/versions/22.5.0/web3signer-22.5.0.tar.gz"], + sha256 = "3a954f5302e424b34acb4bb024f275caf722d8b116c639617f7a2e0f9c9ddc78", build_file = "@prysm//testing/endtoend:web3signer.BUILD", - strip_prefix = "web3signer-develop", + strip_prefix = "web3signer-22.5.0", ) http_archive( diff --git a/testing/endtoend/endtoend_test.go b/testing/endtoend/endtoend_test.go index 9aefa32d1ca3..878d0e862e34 100644 --- a/testing/endtoend/endtoend_test.go +++ b/testing/endtoend/endtoend_test.go @@ -178,7 +178,7 @@ func (r *testRunner) run() { comps = append(comps, web3RemoteSigner) } if err := helpers.ComponentsStarted(ctx, comps); err != nil { - return errors.Wrap(err, "validator nodes require beacon nodes to run") + return errors.Wrap(err, "validator nodes require components to run") } if err := validatorNodes.Start(ctx); err != nil { return errors.Wrap(err, "failed to start validator nodes") @@ -272,9 +272,7 @@ func (r *testRunner) run() { } if config.ExtraEpochs > 0 { - secondsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot)) - dl := time.Now().Add(time.Second * time.Duration(config.ExtraEpochs*secondsPerEpoch)) - if err := r.waitUntilEpoch(ctx, types.Epoch(config.EpochsToRun+config.ExtraEpochs), conns[0], dl); err != nil { + if err := r.waitExtra(ctx, types.Epoch(config.EpochsToRun+config.ExtraEpochs), conns[0], types.Epoch(config.ExtraEpochs)); err != nil { return errors.Wrap(err, "error while waiting for ExtraEpochs") } syncEvaluators := []e2etypes.Evaluator{ev.FinishedSyncing, ev.AllNodesHaveSameHead} @@ -297,9 +295,12 @@ func (r *testRunner) run() { } } -func (r *testRunner) waitUntilEpoch(ctx context.Context, e types.Epoch, conn *grpc.ClientConn, deadline time.Time) error { +func (r *testRunner) waitExtra(ctx context.Context, e types.Epoch, conn *grpc.ClientConn, extra types.Epoch) error { + spe := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot)) + dl := time.Now().Add(time.Second * time.Duration(uint64(extra)*spe)) + beaconClient := eth.NewBeaconChainClient(conn) - ctx, cancel := context.WithDeadline(ctx, deadline) + ctx, cancel := context.WithDeadline(ctx, dl) defer cancel() for { select { @@ -308,9 +309,15 @@ func (r *testRunner) waitUntilEpoch(ctx context.Context, e types.Epoch, conn *gr default: chainHead, err := beaconClient.GetChainHead(ctx, &emptypb.Empty{}) if err != nil { - return err + log.Warnf("while querying connection %s for chain head got error=%s", conn.Target(), err.Error()) + } + if chainHead.HeadEpoch > e { + // no need to wait, other nodes should be caught up + return nil } - if chainHead.HeadEpoch >= e { + if chainHead.HeadEpoch == e { + // wait until halfway into the epoch to give other nodes time to catch up + time.Sleep(time.Second * time.Duration(spe/2)) return nil } } @@ -368,6 +375,8 @@ func (r *testRunner) runEvaluators(conns []*grpc.ClientConn, tickingStartTime ti func (r *testRunner) testDepositsAndTx(ctx context.Context, g *errgroup.Group, keystorePath string, requiredNodes []e2etypes.ComponentRunner) { minGenesisActiveCount := int(params.BeaconConfig().MinGenesisActiveValidatorCount) + // prysm web3signer doesn't support deposits + r.config.UseWeb3RemoteSigner = false depositCheckValidator := components.NewValidatorNode(r.config, int(e2e.DepositCount), e2e.TestParams.BeaconNodeCount, minGenesisActiveCount) g.Go(func() error { if err := helpers.ComponentsStarted(ctx, requiredNodes); err != nil { diff --git a/testing/endtoend/evaluators/validator.go b/testing/endtoend/evaluators/validator.go index f6412a445352..d6ec1ec7e079 100644 --- a/testing/endtoend/evaluators/validator.go +++ b/testing/endtoend/evaluators/validator.go @@ -125,9 +125,9 @@ func validatorsParticipating(conns ...*grpc.ClientConn) error { if err != nil { return errors.Wrap(err, "failed to get beacon state") } - missSrcVals := []uint64{} - missTgtVals := []uint64{} - missHeadVals := []uint64{} + var missSrcVals []uint64 + var missTgtVals []uint64 + var missHeadVals []uint64 switch obj := st.Data.State.(type) { case *eth.BeaconStateContainer_Phase0State: // Do Nothing @@ -188,18 +188,19 @@ func validatorsSyncParticipation(conns ...*grpc.ClientConn) error { if b.IsNil() { return errors.New("nil block provided") } - forkSlot, err := slots.EpochStart(helpers.AltairE2EForkEpoch) - if err != nil { - return err - } - nexForkSlot, err := slots.EpochStart(helpers.BellatrixE2EForkEpoch) + forkStartSlot, err := slots.EpochStart(helpers.AltairE2EForkEpoch) if err != nil { return err } - switch b.Block().Slot() { - case forkSlot, forkSlot + 1, nexForkSlot: - // Skip evaluation of the slot. + if forkStartSlot == b.Block().Slot() { + // Skip fork slot. continue + } + expectedParticipation := expectedSyncParticipation + switch slots.ToEpoch(b.Block().Slot()) { + case helpers.AltairE2EForkEpoch: + // Drop expected sync participation figure. + expectedParticipation = 0.90 default: // no-op } @@ -207,7 +208,7 @@ func validatorsSyncParticipation(conns ...*grpc.ClientConn) error { if err != nil { return err } - threshold := uint64(float64(syncAgg.SyncCommitteeBits.Len()) * expectedSyncParticipation) + threshold := uint64(float64(syncAgg.SyncCommitteeBits.Len()) * expectedParticipation) if syncAgg.SyncCommitteeBits.Count() < threshold { return errors.Errorf("In block of slot %d ,the aggregate bitvector with length of %d only got a count of %d", b.Block().Slot(), threshold, syncAgg.SyncCommitteeBits.Count()) } @@ -273,9 +274,9 @@ func findMissingValidators(participation []byte) ([]uint64, []uint64, []uint64, sourceFlagIndex := cfg.TimelySourceFlagIndex targetFlagIndex := cfg.TimelyTargetFlagIndex headFlagIndex := cfg.TimelyHeadFlagIndex - missingSourceValidators := []uint64{} - missingHeadValidators := []uint64{} - missingTargetValidators := []uint64{} + var missingSourceValidators []uint64 + var missingHeadValidators []uint64 + var missingTargetValidators []uint64 for i, b := range participation { hasSource, err := altair.HasValidatorFlag(b, sourceFlagIndex) if err != nil { diff --git a/testing/endtoend/minimal_e2e_test.go b/testing/endtoend/minimal_e2e_test.go index 65ae221967cd..35f0e8462b13 100644 --- a/testing/endtoend/minimal_e2e_test.go +++ b/testing/endtoend/minimal_e2e_test.go @@ -8,7 +8,6 @@ import ( "github.com/prysmaticlabs/prysm/config/params" ev "github.com/prysmaticlabs/prysm/testing/endtoend/evaluators" - "github.com/prysmaticlabs/prysm/testing/endtoend/helpers" e2eParams "github.com/prysmaticlabs/prysm/testing/endtoend/params" "github.com/prysmaticlabs/prysm/testing/endtoend/types" "github.com/prysmaticlabs/prysm/testing/require" @@ -34,10 +33,6 @@ func e2eMinimal(t *testing.T, useWeb3RemoteSigner bool, extraEpochs uint64) { epochsToRun, err = strconv.Atoi(epochStr) require.NoError(t, err) } - // TODO(#10053): Web3signer does not support bellatrix yet. - if useWeb3RemoteSigner { - epochsToRun = helpers.BellatrixE2EForkEpoch - 1 - } seed := 0 seedStr, isValid := os.LookupEnv("E2E_SEED") if isValid { @@ -53,13 +48,13 @@ func e2eMinimal(t *testing.T, useWeb3RemoteSigner bool, extraEpochs uint64) { ev.ValidatorsAreActive, ev.ValidatorsParticipatingAtEpoch(2), ev.FinalizationOccurs(3), + ev.VerifyBlockGraffiti, ev.PeersCheck, + ev.ProposeVoluntaryExit, + ev.ValidatorHasExited, ev.ProcessesDepositsInBlocks, - ev.VerifyBlockGraffiti, ev.ActivatesDepositedValidators, ev.DepositedValidatorsAreActive, - ev.ProposeVoluntaryExit, - ev.ValidatorHasExited, ev.ValidatorsVoteWithTheMajority, ev.ColdStateCheckpoint, ev.AltairForkTransition, diff --git a/testing/util/attestation.go b/testing/util/attestation.go index 216592d58c2f..c34de8971d3e 100644 --- a/testing/util/attestation.go +++ b/testing/util/attestation.go @@ -78,7 +78,7 @@ func GenerateAttestations( if err != nil { return nil, err } - headState = state.BeaconState(genState) + headState = genState case version.Altair: pbState, err := v2.ProtobufBeaconState(bState.CloneInnerState()) if err != nil { @@ -88,7 +88,7 @@ func GenerateAttestations( if err != nil { return nil, err } - headState = state.BeaconState(genState) + headState = genState default: return nil, errors.New("state type isn't supported") } diff --git a/validator/accounts/BUILD.bazel b/validator/accounts/BUILD.bazel index 370b0694a72c..b191acae740f 100644 --- a/validator/accounts/BUILD.bazel +++ b/validator/accounts/BUILD.bazel @@ -66,7 +66,6 @@ go_test( name = "go_default_test", srcs = [ "accounts_backup_test.go", - "accounts_delete_test.go", "accounts_exit_test.go", "accounts_import_test.go", "accounts_list_test.go", diff --git a/validator/accounts/accounts_backup.go b/validator/accounts/accounts_backup.go index ff8ba160538b..8e1cb876b3c8 100644 --- a/validator/accounts/accounts_backup.go +++ b/validator/accounts/accounts_backup.go @@ -69,7 +69,7 @@ func BackupAccountsCli(cliCtx *cli.Context) error { // Allow the user to interactively select the accounts to backup or optionally // provide them via cli flags as a string of comma-separated, hex strings. - filteredPubKeys, err := filterPublicKeysFromUserInput( + filteredPubKeys, err := FilterPublicKeysFromUserInput( cliCtx, flags.BackupPublicKeysFlag, pubKeys, diff --git a/validator/accounts/accounts_delete.go b/validator/accounts/accounts_delete.go index 48c87cb8c044..16acb43cc978 100644 --- a/validator/accounts/accounts_delete.go +++ b/validator/accounts/accounts_delete.go @@ -7,64 +7,23 @@ import ( "strings" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/cmd/validator/flags" "github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/io/prompt" ethpbservice "github.com/prysmaticlabs/prysm/proto/eth/service" - "github.com/prysmaticlabs/prysm/validator/accounts/iface" - "github.com/prysmaticlabs/prysm/validator/accounts/userprompt" - "github.com/prysmaticlabs/prysm/validator/accounts/wallet" - "github.com/prysmaticlabs/prysm/validator/keymanager" - "github.com/urfave/cli/v2" ) -// DeleteAccountCli deletes the accounts that the user requests to be deleted from the wallet. -// This function uses the CLI to extract necessary values. -func DeleteAccountCli(cliCtx *cli.Context) error { - w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) { - return nil, wallet.ErrNoWalletFound - }) - if err != nil { - return errors.Wrap(err, "could not open wallet") - } - // TODO(#9883) - Remove this when we have a better way to handle this. - if w.KeymanagerKind() == keymanager.Remote || w.KeymanagerKind() == keymanager.Web3Signer { - return errors.New( - "remote and web3signer wallets cannot delete accounts locally. please delete the account on the remote signer node", - ) - } - kManager, err := w.InitializeKeymanager(cliCtx.Context, iface.InitKeymanagerConfig{ListenForChanges: false}) - if err != nil { - return errors.Wrap(err, ErrCouldNotInitializeKeymanager) - } - validatingPublicKeys, err := kManager.FetchValidatingPublicKeys(cliCtx.Context) - if err != nil { - return err - } - if len(validatingPublicKeys) == 0 { - return errors.New("wallet is empty, no accounts to delete") - } - // Allow the user to interactively select the accounts to delete or optionally - // provide them via cli flags as a string of comma-separated, hex strings. - filteredPubKeys, err := filterPublicKeysFromUserInput( - cliCtx, - flags.DeletePublicKeysFlag, - validatingPublicKeys, - userprompt.SelectAccountsDeletePromptText, - ) - if err != nil { - return errors.Wrap(err, "could not filter public keys for deletion") - } - rawPublicKeys := make([][]byte, len(filteredPubKeys)) - formattedPubKeys := make([]string, len(filteredPubKeys)) - for i, pk := range filteredPubKeys { +// Delete the accounts that the user requests to be deleted from the wallet. +func (acm *AccountsCLIManager) Delete(ctx context.Context) error { + rawPublicKeys := make([][]byte, len(acm.filteredPubKeys)) + formattedPubKeys := make([]string, len(acm.filteredPubKeys)) + for i, pk := range acm.filteredPubKeys { pubKeyBytes := pk.Marshal() rawPublicKeys[i] = pubKeyBytes formattedPubKeys[i] = fmt.Sprintf("%#x", bytesutil.Trunc(pubKeyBytes)) } allAccountStr := strings.Join(formattedPubKeys, ", ") - if !cliCtx.IsSet(flags.DeletePublicKeysFlag.Name) { - if len(filteredPubKeys) == 1 { + if !acm.deletePublicKeys { + if len(acm.filteredPubKeys) == 1 { promptText := "Are you sure you want to delete 1 account? (%s) Y/N" resp, err := prompt.ValidatePrompt( os.Stdin, fmt.Sprintf(promptText, au.BrightGreen(formattedPubKeys[0])), prompt.ValidateYesOrNo, @@ -77,10 +36,10 @@ func DeleteAccountCli(cliCtx *cli.Context) error { } } else { promptText := "Are you sure you want to delete %d accounts? (%s) Y/N" - if len(filteredPubKeys) == len(validatingPublicKeys) { + if len(acm.filteredPubKeys) == acm.walletKeyCount { promptText = fmt.Sprintf("Are you sure you want to delete all accounts? Y/N (%s)", au.BrightGreen(allAccountStr)) } else { - promptText = fmt.Sprintf(promptText, len(filteredPubKeys), au.BrightGreen(allAccountStr)) + promptText = fmt.Sprintf(promptText, len(acm.filteredPubKeys), au.BrightGreen(allAccountStr)) } resp, err := prompt.ValidatePrompt(os.Stdin, promptText, prompt.ValidateYesOrNo) if err != nil { @@ -91,8 +50,8 @@ func DeleteAccountCli(cliCtx *cli.Context) error { } } } - if err := DeleteAccount(cliCtx.Context, &DeleteConfig{ - Keymanager: kManager, + if err := DeleteAccount(ctx, &DeleteConfig{ + Keymanager: acm.keymanager, DeletePublicKeys: rawPublicKeys, }); err != nil { return err @@ -104,7 +63,7 @@ func DeleteAccountCli(cliCtx *cli.Context) error { return nil } -// DeleteAccount deletes the accounts that the user requests to be deleted from the wallet. +// DeleteAccount permforms the deletion on the Keymanager. func DeleteAccount(ctx context.Context, cfg *DeleteConfig) error { if len(cfg.DeletePublicKeys) == 1 { log.Info("Deleting account...") diff --git a/validator/accounts/accounts_delete_test.go b/validator/accounts/accounts_delete_test.go deleted file mode 100644 index 498fa08d0d2a..000000000000 --- a/validator/accounts/accounts_delete_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package accounts - -import ( - "encoding/hex" - "os" - "path/filepath" - "strings" - "testing" - "time" - - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" - "github.com/prysmaticlabs/prysm/validator/accounts/wallet" - "github.com/prysmaticlabs/prysm/validator/keymanager" - "github.com/prysmaticlabs/prysm/validator/keymanager/local" -) - -func TestDeleteAccounts_Noninteractive(t *testing.T) { - walletDir, _, passwordFilePath := setupWalletAndPasswordsDir(t) - // Write a directory where we will import keys from. - keysDir := filepath.Join(t.TempDir(), "keysDir") - require.NoError(t, os.MkdirAll(keysDir, os.ModePerm)) - - // Create 3 keystore files in the keys directory we can then - // import from in our wallet. - k1, _ := createKeystore(t, keysDir) - time.Sleep(time.Second) - k2, _ := createKeystore(t, keysDir) - time.Sleep(time.Second) - k3, _ := createKeystore(t, keysDir) - generatedPubKeys := []string{k1.Pubkey, k2.Pubkey, k3.Pubkey} - // Only delete keys 0 and 1. - deletePublicKeys := strings.Join(generatedPubKeys[0:2], ",") - - // We initialize a wallet with a local keymanager. - cliCtx := setupWalletCtx(t, &testWalletConfig{ - // Wallet configuration flags. - walletDir: walletDir, - keymanagerKind: keymanager.Local, - walletPasswordFile: passwordFilePath, - accountPasswordFile: passwordFilePath, - // Flags required for ImportAccounts to work. - keysDir: keysDir, - // Flags required for DeleteAccounts to work. - deletePublicKeys: deletePublicKeys, - }) - w, err := CreateWalletWithKeymanager(cliCtx.Context, &CreateWalletConfig{ - WalletCfg: &wallet.Config{ - WalletDir: walletDir, - KeymanagerKind: keymanager.Local, - WalletPassword: password, - }, - }) - require.NoError(t, err) - - // We attempt to import accounts. - require.NoError(t, ImportAccountsCli(cliCtx)) - - // We attempt to delete the accounts specified. - require.NoError(t, DeleteAccountCli(cliCtx)) - - keymanager, err := local.NewKeymanager( - cliCtx.Context, - &local.SetupConfig{ - Wallet: w, - ListenForChanges: false, - }, - ) - require.NoError(t, err) - remainingAccounts, err := keymanager.FetchValidatingPublicKeys(cliCtx.Context) - require.NoError(t, err) - require.Equal(t, len(remainingAccounts), 1) - remainingPublicKey, err := hex.DecodeString(k3.Pubkey) - require.NoError(t, err) - assert.DeepEqual(t, remainingAccounts[0], bytesutil.ToBytes48(remainingPublicKey)) -} diff --git a/validator/accounts/accounts_exit.go b/validator/accounts/accounts_exit.go index 17fb94556b8e..833196603442 100644 --- a/validator/accounts/accounts_exit.go +++ b/validator/accounts/accounts_exit.go @@ -164,7 +164,7 @@ func interact( if !cliCtx.IsSet(flags.ExitAllFlag.Name) { // Allow the user to interactively select the accounts to exit or optionally // provide them via cli flags as a string of comma-separated, hex strings. - filteredPubKeys, err := filterPublicKeysFromUserInput( + filteredPubKeys, err := FilterPublicKeysFromUserInput( cliCtx, flags.VoluntaryExitPublicKeysFlag, validatingPublicKeys, diff --git a/validator/accounts/accounts_helper.go b/validator/accounts/accounts_helper.go index 2f431d4f3285..6a74f4eaf460 100644 --- a/validator/accounts/accounts_helper.go +++ b/validator/accounts/accounts_helper.go @@ -11,13 +11,14 @@ import ( "github.com/urfave/cli/v2" ) -func filterPublicKeysFromUserInput( +// FilterPublicKeysFromUserInput collects the set of public keys from the +// command line or an interactive session. +func FilterPublicKeysFromUserInput( cliCtx *cli.Context, publicKeysFlag *cli.StringFlag, validatingPublicKeys [][fieldparams.BLSPubkeyLength]byte, selectionPrompt string, ) ([]bls.PublicKey, error) { - var filteredPubKeys []bls.PublicKey if cliCtx.IsSet(publicKeysFlag.Name) { pubKeyStrings := strings.Split(cliCtx.String(publicKeysFlag.Name), ",") if len(pubKeyStrings) == 0 { @@ -26,22 +27,27 @@ func filterPublicKeysFromUserInput( publicKeysFlag.Name, ) } - for _, str := range pubKeyStrings { - pkString := str - if strings.Contains(pkString, "0x") { - pkString = pkString[2:] - } - pubKeyBytes, err := hex.DecodeString(pkString) - if err != nil { - return nil, errors.Wrapf(err, "could not decode string %s as hex", pkString) - } - blsPublicKey, err := bls.PublicKeyFromBytes(pubKeyBytes) - if err != nil { - return nil, errors.Wrapf(err, "%#x is not a valid BLS public key", pubKeyBytes) - } - filteredPubKeys = append(filteredPubKeys, blsPublicKey) - } - return filteredPubKeys, nil + return filterPublicKeys(pubKeyStrings) } return selectAccounts(selectionPrompt, validatingPublicKeys) } + +func filterPublicKeys(pubKeyStrings []string) ([]bls.PublicKey, error) { + var filteredPubKeys []bls.PublicKey + for _, str := range pubKeyStrings { + pkString := str + if strings.Contains(pkString, "0x") { + pkString = pkString[2:] + } + pubKeyBytes, err := hex.DecodeString(pkString) + if err != nil { + return nil, errors.Wrapf(err, "could not decode string %s as hex", pkString) + } + blsPublicKey, err := bls.PublicKeyFromBytes(pubKeyBytes) + if err != nil { + return nil, errors.Wrapf(err, "%#x is not a valid BLS public key", pubKeyBytes) + } + filteredPubKeys = append(filteredPubKeys, blsPublicKey) + } + return filteredPubKeys, nil +} diff --git a/validator/accounts/cli_manager.go b/validator/accounts/cli_manager.go index 87d00883adb9..1ef118d4e652 100644 --- a/validator/accounts/cli_manager.go +++ b/validator/accounts/cli_manager.go @@ -5,6 +5,7 @@ import ( "github.com/pkg/errors" grpcutil "github.com/prysmaticlabs/prysm/api/grpc" + "github.com/prysmaticlabs/prysm/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/validator/accounts/wallet" "github.com/prysmaticlabs/prysm/validator/keymanager" @@ -30,9 +31,12 @@ type AccountsCLIManager struct { showDepositData bool showPrivateKeys bool listValidatorIndices bool + deletePublicKeys bool dialOpts []grpc.DialOption grpcHeaders []string beaconRPCProvider string + filteredPubKeys []bls.PublicKey + walletKeyCount int } func (acm *AccountsCLIManager) prepareBeaconClients(ctx context.Context) (*ethpb.BeaconNodeValidatorClient, *ethpb.NodeClient, error) { diff --git a/validator/accounts/cli_options.go b/validator/accounts/cli_options.go index 14c09782298c..211d7e6526a4 100644 --- a/validator/accounts/cli_options.go +++ b/validator/accounts/cli_options.go @@ -1,6 +1,7 @@ package accounts import ( + "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/validator/accounts/wallet" "github.com/prysmaticlabs/prysm/validator/keymanager" "google.golang.org/grpc" @@ -72,3 +73,26 @@ func WithBeaconRPCProvider(provider string) Option { return nil } } + +// WithFilteredPubKeys adds public key strings parsed from CLI. +func WithFilteredPubKeys(filteredPubKeys []bls.PublicKey) Option { + return func(acc *AccountsCLIManager) error { + acc.filteredPubKeys = filteredPubKeys + return nil + } +} + +// WithWalletKeyCount tracks the number of keys in a wallet. +func WithWalletKeyCount(walletKeyCount int) Option { + return func(acc *AccountsCLIManager) error { + acc.walletKeyCount = walletKeyCount + return nil + } +} + +func WithDeletePublicKeys(deletePublicKeys bool) Option { + return func(acc *AccountsCLIManager) error { + acc.deletePublicKeys = deletePublicKeys + return nil + } +} diff --git a/validator/accounts/petnames/BUILD.bazel b/validator/accounts/petnames/BUILD.bazel index 5ee3621344c6..d282de844f49 100644 --- a/validator/accounts/petnames/BUILD.bazel +++ b/validator/accounts/petnames/BUILD.bazel @@ -4,7 +4,10 @@ go_library( name = "go_default_library", srcs = ["names.go"], importpath = "github.com/prysmaticlabs/prysm/validator/accounts/petnames", - visibility = ["//validator:__subpackages__"], + visibility = [ + "//cmd/validator:__subpackages__", + "//validator:__subpackages__", + ], deps = [ "//crypto/hash:go_default_library", "//crypto/rand:go_default_library", diff --git a/validator/client/metrics_test.go b/validator/client/metrics_test.go index 2125db55f6ef..fc1c0c3589c2 100644 --- a/validator/client/metrics_test.go +++ b/validator/client/metrics_test.go @@ -82,7 +82,7 @@ func TestUpdateLogAggregateStats(t *testing.T) { if i == len(responses)-1 { // Handle last log. hook = logTest.NewGlobal() } - v.UpdateLogAggregateStats(val, types.Slot(params.BeaconConfig().SlotsPerEpoch*types.Slot(i+1))) + v.UpdateLogAggregateStats(val, params.BeaconConfig().SlotsPerEpoch*types.Slot(i+1)) } require.LogsContain(t, hook, "msg=\"Previous epoch aggregated voting summary\" attestationInclusionPct=\"67%\" "+ diff --git a/validator/client/service.go b/validator/client/service.go index 65b177d3985b..6d2af7ad79b1 100644 --- a/validator/client/service.go +++ b/validator/client/service.go @@ -241,7 +241,7 @@ func (v *ValidatorService) Status() error { return nil } -// UseInteropKeys returns the useInteropKeys flag. +// InteropKeysConfig returns the useInteropKeys flag. func (v *ValidatorService) InteropKeysConfig() *local.InteropKeymanagerConfig { return v.interopKeysConfig } diff --git a/validator/client/testutil/mock_validator.go b/validator/client/testutil/mock_validator.go index a5f42ebe9888..643e67d5b5ca 100644 --- a/validator/client/testutil/mock_validator.go +++ b/validator/client/testutil/mock_validator.go @@ -62,7 +62,7 @@ func (fv *FakeValidator) Done() { fv.DoneCalled = true } -// WaitForWalletInitialization for mocking. +// WaitForKeymanagerInitialization for mocking. func (fv *FakeValidator) WaitForKeymanagerInitialization(_ context.Context) error { fv.WaitForWalletInitializationCalled = true return nil diff --git a/validator/keymanager/derived/BUILD.bazel b/validator/keymanager/derived/BUILD.bazel index 8680f1a5d026..c3396e55f628 100644 --- a/validator/keymanager/derived/BUILD.bazel +++ b/validator/keymanager/derived/BUILD.bazel @@ -9,6 +9,7 @@ go_library( ], importpath = "github.com/prysmaticlabs/prysm/validator/keymanager/derived", visibility = [ + "//cmd/validator:__subpackages__", "//tools:__subpackages__", "//validator:__subpackages__", ], diff --git a/validator/keymanager/local/BUILD.bazel b/validator/keymanager/local/BUILD.bazel index de2d13f866cd..422f4bd9b709 100644 --- a/validator/keymanager/local/BUILD.bazel +++ b/validator/keymanager/local/BUILD.bazel @@ -14,6 +14,7 @@ go_library( ], importpath = "github.com/prysmaticlabs/prysm/validator/keymanager/local", visibility = [ + "//cmd/validator:__subpackages__", "//tools:__subpackages__", "//validator:__pkg__", "//validator:__subpackages__", diff --git a/validator/keymanager/remote-web3signer/keymanager.go b/validator/keymanager/remote-web3signer/keymanager.go index c989d74b8a09..44a160043c87 100644 --- a/validator/keymanager/remote-web3signer/keymanager.go +++ b/validator/keymanager/remote-web3signer/keymanager.go @@ -20,7 +20,7 @@ import ( "github.com/prysmaticlabs/prysm/validator/keymanager" remote_utils "github.com/prysmaticlabs/prysm/validator/keymanager/remote-utils" "github.com/prysmaticlabs/prysm/validator/keymanager/remote-web3signer/internal" - v1 "github.com/prysmaticlabs/prysm/validator/keymanager/remote-web3signer/v1" + web3signerv1 "github.com/prysmaticlabs/prysm/validator/keymanager/remote-web3signer/v1" log "github.com/sirupsen/logrus" ) @@ -113,7 +113,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ } switch request.Object.(type) { case *validatorpb.SignRequest_Block: - bockSignRequest, err := v1.GetBlockSignRequest(request, genesisValidatorsRoot) + bockSignRequest, err := web3signerv1.GetBlockSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -123,7 +123,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ blockSignRequestsTotal.Inc() return json.Marshal(bockSignRequest) case *validatorpb.SignRequest_AttestationData: - attestationSignRequest, err := v1.GetAttestationSignRequest(request, genesisValidatorsRoot) + attestationSignRequest, err := web3signerv1.GetAttestationSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -133,7 +133,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ attestationSignRequestsTotal.Inc() return json.Marshal(attestationSignRequest) case *validatorpb.SignRequest_AggregateAttestationAndProof: - aggregateAndProofSignRequest, err := v1.GetAggregateAndProofSignRequest(request, genesisValidatorsRoot) + aggregateAndProofSignRequest, err := web3signerv1.GetAggregateAndProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -143,7 +143,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ aggregateAndProofSignRequestsTotal.Inc() return json.Marshal(aggregateAndProofSignRequest) case *validatorpb.SignRequest_Slot: - aggregationSlotSignRequest, err := v1.GetAggregationSlotSignRequest(request, genesisValidatorsRoot) + aggregationSlotSignRequest, err := web3signerv1.GetAggregationSlotSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -153,22 +153,35 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ aggregationSlotSignRequestsTotal.Inc() return json.Marshal(aggregationSlotSignRequest) case *validatorpb.SignRequest_BlockV2: - blocv2AltairSignRequest, err := v1.GetBlockV2AltairSignRequest(request, genesisValidatorsRoot) + blockv2AltairSignRequest, err := web3signerv1.GetBlockV2AltairSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } - if err = validator.StructCtx(ctx, blocv2AltairSignRequest); err != nil { + if err = validator.StructCtx(ctx, blockv2AltairSignRequest); err != nil { return nil, err } blockV2SignRequestsTotal.Inc() - return json.Marshal(blocv2AltairSignRequest) - // TODO(#10053): Need to add support for merge blocks. - - /* - case *validatorpb.SignRequest_BlockV3: - return "BLOCK_V3", nil - */ - + return json.Marshal(blockv2AltairSignRequest) + case *validatorpb.SignRequest_BlockV3: + blockv2BellatrixSignRequest, err := web3signerv1.GetBlockV2BellatrixSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blockv2BellatrixSignRequest); err != nil { + return nil, err + } + blockV3SignRequestsTotal.Inc() + return json.Marshal(blockv2BellatrixSignRequest) + case *validatorpb.SignRequest_BlindedBlockV3: + blindedBlockv2SignRequest, err := web3signerv1.GetBlockV2BellatrixSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blindedBlockv2SignRequest); err != nil { + return nil, err + } + blindedblockV3SignRequestsTotal.Inc() + return json.Marshal(blindedBlockv2SignRequest) // We do not support "DEPOSIT" type. /* case *validatorpb.: @@ -176,7 +189,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ */ case *validatorpb.SignRequest_Epoch: - randaoRevealSignRequest, err := v1.GetRandaoRevealSignRequest(request, genesisValidatorsRoot) + randaoRevealSignRequest, err := web3signerv1.GetRandaoRevealSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -186,7 +199,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ randaoRevealSignRequestsTotal.Inc() return json.Marshal(randaoRevealSignRequest) case *validatorpb.SignRequest_Exit: - voluntaryExitRequest, err := v1.GetVoluntaryExitSignRequest(request, genesisValidatorsRoot) + voluntaryExitRequest, err := web3signerv1.GetVoluntaryExitSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -196,7 +209,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ voluntaryExitSignRequestsTotal.Inc() return json.Marshal(voluntaryExitRequest) case *validatorpb.SignRequest_SyncMessageBlockRoot: - syncCommitteeMessageRequest, err := v1.GetSyncCommitteeMessageSignRequest(request, genesisValidatorsRoot) + syncCommitteeMessageRequest, err := web3signerv1.GetSyncCommitteeMessageSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -206,7 +219,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ syncCommitteeMessageSignRequestsTotal.Inc() return json.Marshal(syncCommitteeMessageRequest) case *validatorpb.SignRequest_SyncAggregatorSelectionData: - syncCommitteeSelectionProofRequest, err := v1.GetSyncCommitteeSelectionProofSignRequest(request, genesisValidatorsRoot) + syncCommitteeSelectionProofRequest, err := web3signerv1.GetSyncCommitteeSelectionProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -216,7 +229,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ syncCommitteeSelectionProofSignRequestsTotal.Inc() return json.Marshal(syncCommitteeSelectionProofRequest) case *validatorpb.SignRequest_ContributionAndProof: - contributionAndProofRequest, err := v1.GetSyncCommitteeContributionAndProofSignRequest(request, genesisValidatorsRoot) + contributionAndProofRequest, err := web3signerv1.GetSyncCommitteeContributionAndProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } diff --git a/validator/keymanager/remote-web3signer/metrics.go b/validator/keymanager/remote-web3signer/metrics.go index b9b9716ec9d8..83710ad463eb 100644 --- a/validator/keymanager/remote-web3signer/metrics.go +++ b/validator/keymanager/remote-web3signer/metrics.go @@ -34,6 +34,14 @@ var ( Name: "remote_web3signer_block_v2_sign_requests_total", Help: "Total number of block v2 sign requests", }) + blockV3SignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_block_v3_sign_requests_total", + Help: "Total number of block v3 sign requests", + }) + blindedblockV3SignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_blinded_block_v3_sign_requests_total", + Help: "Total number of blinded block v3 sign requests", + }) randaoRevealSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ Name: "remote_web3signer_randao_reveal_sign_requests_total", Help: "Total number of randao reveal sign requests", diff --git a/validator/keymanager/remote-web3signer/v1/BUILD.bazel b/validator/keymanager/remote-web3signer/v1/BUILD.bazel index 731ef6e2529e..56804d31bd36 100644 --- a/validator/keymanager/remote-web3signer/v1/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/v1/BUILD.bazel @@ -10,7 +10,9 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/validator/keymanager/remote-web3signer/v1", visibility = ["//visibility:public"], deps = [ + "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", + "//consensus-types/wrapper:go_default_library", "//network/forks:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", diff --git a/validator/keymanager/remote-web3signer/v1/custom_mappers.go b/validator/keymanager/remote-web3signer/v1/custom_mappers.go index 82100f899ee9..25b7c2900024 100644 --- a/validator/keymanager/remote-web3signer/v1/custom_mappers.go +++ b/validator/keymanager/remote-web3signer/v1/custom_mappers.go @@ -170,12 +170,12 @@ func MapProposerSlashing(slashing *ethpb.ProposerSlashing) (*ProposerSlashing, e return nil, errors.Wrap(err, "could not map signed header 2") } return &ProposerSlashing{ - SignedHeader_1: signedHeader1, - SignedHeader_2: signedHeader2, + Signedheader1: signedHeader1, + Signedheader2: signedHeader2, }, nil } -// MapAttesterSlashing maps the eth2.AttesterSlashing proto to the Web3Signer spec. +// MapSignedBeaconBlockHeader maps the eth2.AttesterSlashing proto to the Web3Signer spec. func MapSignedBeaconBlockHeader(signedHeader *ethpb.SignedBeaconBlockHeader) (*SignedBeaconBlockHeader, error) { if signedHeader == nil { return nil, fmt.Errorf("signed beacon block header is nil") @@ -217,8 +217,8 @@ func MapAttesterSlashing(slashing *ethpb.AttesterSlashing) (*AttesterSlashing, e return nil, errors.Wrap(err, "could not map attestation 2") } return &AttesterSlashing{ - Attestation_1: attestation1, - Attestation_2: attestation2, + Attestation1: attestation1, + Attestation2: attestation2, }, nil } diff --git a/validator/keymanager/remote-web3signer/v1/custom_mappers_test.go b/validator/keymanager/remote-web3signer/v1/custom_mappers_test.go index 4bcd727bad81..aca1b904e9a7 100644 --- a/validator/keymanager/remote-web3signer/v1/custom_mappers_test.go +++ b/validator/keymanager/remote-web3signer/v1/custom_mappers_test.go @@ -195,8 +195,8 @@ func TestMapAttesterSlashing(t *testing.T) { }, }, want: &v1.AttesterSlashing{ - Attestation_1: mock.MockIndexedAttestation(), - Attestation_2: mock.MockIndexedAttestation(), + Attestation1: mock.MockIndexedAttestation(), + Attestation2: mock.MockIndexedAttestation(), }, wantErr: false, }, @@ -208,8 +208,8 @@ func TestMapAttesterSlashing(t *testing.T) { t.Errorf("MapAttesterSlashing() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(got.Attestation_1, tt.want.Attestation_1) { - t.Errorf("MapAttesterSlashing() got = %v, want %v", got.Attestation_1, tt.want.Attestation_1) + if !reflect.DeepEqual(got.Attestation1, tt.want.Attestation1) { + t.Errorf("MapAttesterSlashing() got = %v, want %v", got.Attestation1, tt.want.Attestation1) } }) } diff --git a/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel b/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel index e227bdb8a172..34a6de456396 100644 --- a/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel @@ -10,6 +10,7 @@ go_library( "//config/fieldparams:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", + "//testing/util:go_default_library", "//validator/keymanager/remote-web3signer/v1:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", diff --git a/validator/keymanager/remote-web3signer/v1/mock/mocks.go b/validator/keymanager/remote-web3signer/v1/mock/mocks.go index 64b4fed958d0..18738c036654 100644 --- a/validator/keymanager/remote-web3signer/v1/mock/mocks.go +++ b/validator/keymanager/remote-web3signer/v1/mock/mocks.go @@ -8,6 +8,7 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/validator-client" + "github.com/prysmaticlabs/prysm/testing/util" v1 "github.com/prysmaticlabs/prysm/validator/keymanager/remote-web3signer/v1" ) @@ -326,6 +327,24 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { }, SigningSlot: 0, } + case "BLOCK_V2_BELLATRIX": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlockV3{ + BlockV3: util.HydrateBeaconBlockBellatrix(ð.BeaconBlockBellatrix{}), + }, + } + case "BLOCK_V2_BLINDED_BELLATRIX": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlindedBlockV3{ + BlindedBlockV3: util.HydrateBlindedBeaconBlockBellatrix(ð.BlindedBeaconBlockBellatrix{}), + }, + } case "RANDAO_REVEAL": return &validatorpb.SignRequest{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), @@ -461,6 +480,24 @@ func MockBlockV2AltairSignRequest() *v1.BlockV2AltairSignRequest { } } +func MockBlockV2BellatrixSignRequest(bodyRoot string) *v1.BlockV2BellatrixSignRequest { + return &v1.BlockV2BellatrixSignRequest{ + Type: "BLOCK_V2", + ForkInfo: MockForkInfo(), + SigningRoot: hexutil.Encode(make([]byte, fieldparams.RootLength)), + BeaconBlock: &v1.BeaconBlockBellatrixBlockV2{ + Version: "BELLATRIX", + BlockHeader: &v1.BeaconBlockHeader{ + Slot: "0", + ProposerIndex: "0", + ParentRoot: hexutil.Encode(make([]byte, fieldparams.RootLength)), + StateRoot: hexutil.Encode(make([]byte, fieldparams.RootLength)), + BodyRoot: bodyRoot, + }, + }, + } +} + // MockRandaoRevealSignRequest is a mock implementation of the RandaoRevealSignRequest. func MockRandaoRevealSignRequest() *v1.RandaoRevealSignRequest { return &v1.RandaoRevealSignRequest{ @@ -596,7 +633,7 @@ func MockBeaconBlockAltair() *v1.BeaconBlockAltair { Graffiti: hexutil.Encode(make([]byte, 32)), ProposerSlashings: []*v1.ProposerSlashing{ { - SignedHeader_1: &v1.SignedBeaconBlockHeader{ + Signedheader1: &v1.SignedBeaconBlockHeader{ Message: &v1.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", @@ -606,7 +643,7 @@ func MockBeaconBlockAltair() *v1.BeaconBlockAltair { }, Signature: hexutil.Encode(make([]byte, fieldparams.BLSSignatureLength)), }, - SignedHeader_2: &v1.SignedBeaconBlockHeader{ + Signedheader2: &v1.SignedBeaconBlockHeader{ Message: &v1.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", @@ -620,8 +657,8 @@ func MockBeaconBlockAltair() *v1.BeaconBlockAltair { }, AttesterSlashings: []*v1.AttesterSlashing{ { - Attestation_1: MockIndexedAttestation(), - Attestation_2: MockIndexedAttestation(), + Attestation1: MockIndexedAttestation(), + Attestation2: MockIndexedAttestation(), }, }, Attestations: []*v1.Attestation{ @@ -666,7 +703,7 @@ func MockBeaconBlockBody() *v1.BeaconBlockBody { Graffiti: hexutil.Encode(make([]byte, 32)), ProposerSlashings: []*v1.ProposerSlashing{ { - SignedHeader_1: &v1.SignedBeaconBlockHeader{ + Signedheader1: &v1.SignedBeaconBlockHeader{ Message: &v1.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", @@ -676,7 +713,7 @@ func MockBeaconBlockBody() *v1.BeaconBlockBody { }, Signature: hexutil.Encode(make([]byte, fieldparams.BLSSignatureLength)), }, - SignedHeader_2: &v1.SignedBeaconBlockHeader{ + Signedheader2: &v1.SignedBeaconBlockHeader{ Message: &v1.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", @@ -690,8 +727,8 @@ func MockBeaconBlockBody() *v1.BeaconBlockBody { }, AttesterSlashings: []*v1.AttesterSlashing{ { - Attestation_1: MockIndexedAttestation(), - Attestation_2: MockIndexedAttestation(), + Attestation1: MockIndexedAttestation(), + Attestation2: MockIndexedAttestation(), }, }, Attestations: []*v1.Attestation{ diff --git a/validator/keymanager/remote-web3signer/v1/requests.go b/validator/keymanager/remote-web3signer/v1/requests.go index be13f5e8982a..fdca1a6894c3 100644 --- a/validator/keymanager/remote-web3signer/v1/requests.go +++ b/validator/keymanager/remote-web3signer/v1/requests.go @@ -5,6 +5,8 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/consensus-types/wrapper" validatorpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/validator-client" ) @@ -216,6 +218,9 @@ func GetSyncCommitteeMessageSignRequest(request *validatorpb.SignRequest, genesi // GetSyncCommitteeSelectionProofSignRequest maps the request for signing type SYNC_COMMITTEE_SELECTION_PROOF. func GetSyncCommitteeSelectionProofSignRequest(request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*SyncCommitteeSelectionProofSignRequest, error) { + if request == nil { + return nil, errors.New("nil sign request provided") + } syncCommitteeSelectionProof, ok := request.Object.(*validatorpb.SignRequest_SyncAggregatorSelectionData) if !ok { return nil, errors.New("failed to cast request object to sync committee selection proof") @@ -241,6 +246,9 @@ func GetSyncCommitteeSelectionProofSignRequest(request *validatorpb.SignRequest, // GetSyncCommitteeContributionAndProofSignRequest maps the request for signing type SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF. func GetSyncCommitteeContributionAndProofSignRequest(request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*SyncCommitteeContributionAndProofSignRequest, error) { + if request == nil { + return nil, errors.New("nil sign request provided") + } syncCommitteeContributionAndProof, ok := request.Object.(*validatorpb.SignRequest_ContributionAndProof) if !ok { return nil, errors.New("failed to cast request object to sync committee contribution and proof") @@ -263,3 +271,66 @@ func GetSyncCommitteeContributionAndProofSignRequest(request *validatorpb.SignRe ContributionAndProof: contribution, }, nil } + +// GetBlockV2BellatrixSignRequest maps the request for signing type BLOCK_V2_BELLATRIX. +// note: web3signer uses blockv2 instead of block v3 for signing type +func GetBlockV2BellatrixSignRequest(request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*BlockV2BellatrixSignRequest, error) { + if request == nil { + return nil, errors.New("nil sign request provided") + } + var b interfaces.BeaconBlock + switch request.Object.(type) { + case *validatorpb.SignRequest_BlindedBlockV3: + blindedBlockV3, ok := request.Object.(*validatorpb.SignRequest_BlindedBlockV3) + if !ok { + return nil, errors.New("failed to cast request object to blinded block v3") + } + if blindedBlockV3 == nil { + return nil, errors.New("invalid sign request - blindedBlockV3 is nil") + } + beaconBlock, err := wrapper.WrappedBeaconBlock(blindedBlockV3.BlindedBlockV3) + if err != nil { + return nil, err + } + b = beaconBlock + case *validatorpb.SignRequest_BlockV3: + blockV3Bellatrix, ok := request.Object.(*validatorpb.SignRequest_BlockV3) + if !ok { + return nil, errors.New("failed to cast request object to block v3 bellatrix") + } + + if blockV3Bellatrix == nil { + return nil, errors.New("invalid sign request: blockV3Bellatrix is nil") + } + beaconBlock, err := wrapper.WrappedBeaconBlock(blockV3Bellatrix.BlockV3) + if err != nil { + return nil, err + } + b = beaconBlock + default: + return nil, errors.New("invalid sign request - invalid object type") + } + fork, err := MapForkInfo(request.SigningSlot, genesisValidatorsRoot) + if err != nil { + return nil, err + } + beaconBlockHeader, err := interfaces.BeaconBlockHeaderFromBlockInterface(b) + if err != nil { + return nil, err + } + return &BlockV2BellatrixSignRequest{ + Type: "BLOCK_V2", + ForkInfo: fork, + SigningRoot: hexutil.Encode(request.SigningRoot), + BeaconBlock: &BeaconBlockBellatrixBlockV2{ + Version: "BELLATRIX", + BlockHeader: &BeaconBlockHeader{ + Slot: fmt.Sprint(beaconBlockHeader.Slot), + ProposerIndex: fmt.Sprint(beaconBlockHeader.ProposerIndex), + ParentRoot: hexutil.Encode(beaconBlockHeader.ParentRoot), + StateRoot: hexutil.Encode(beaconBlockHeader.StateRoot), + BodyRoot: hexutil.Encode(beaconBlockHeader.BodyRoot), + }, + }, + }, nil +} diff --git a/validator/keymanager/remote-web3signer/v1/requests_test.go b/validator/keymanager/remote-web3signer/v1/requests_test.go index 4e91cf5cf894..f1218f250aa3 100644 --- a/validator/keymanager/remote-web3signer/v1/requests_test.go +++ b/validator/keymanager/remote-web3signer/v1/requests_test.go @@ -358,3 +358,47 @@ func TestGetVoluntaryExitSignRequest(t *testing.T) { }) } } + +func TestGetBlockV3BellatrixSignRequest(t *testing.T) { + type args struct { + request *validatorpb.SignRequest + genesisValidatorsRoot []byte + } + tests := []struct { + name string + args args + want *v1.BlockV2BellatrixSignRequest + wantErr bool + }{ + { + name: "Happy Path Test non blinded", + args: args{ + request: mock.GetMockSignRequest("BLOCK_V2_BELLATRIX"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.MockBlockV2BellatrixSignRequest("0xcd7c49966ebe72b1214e6d4733adf6bf06935c5fbc3b3ad08e84e3085428b82f"), + wantErr: false, + }, + { + name: "Happy Path Test blinded", + args: args{ + request: mock.GetMockSignRequest("BLOCK_V2_BLINDED_BELLATRIX"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.MockBlockV2BellatrixSignRequest("0xbabb9c2d10dd3f16dc50e31fd6eb270c9c5e95a6dcb5a1eb34389ef28194285b"), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := v1.GetBlockV2BellatrixSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + if (err != nil) != tt.wantErr { + t.Errorf("GetBlockV2BellatrixSignRequest() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetBlockV2AltairSignRequest() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/validator/keymanager/remote-web3signer/v1/web3signer_types.go b/validator/keymanager/remote-web3signer/v1/web3signer_types.go index e8991dc5b116..3f728bbb3a33 100644 --- a/validator/keymanager/remote-web3signer/v1/web3signer_types.go +++ b/validator/keymanager/remote-web3signer/v1/web3signer_types.go @@ -10,7 +10,7 @@ type AggregationSlotSignRequest struct { AggregationSlot *AggregationSlot `json:"aggregation_slot" validate:"required"` } -// AggregationSlotSignRequest is a request object for web3signer sign api. +// AggregateAndProofSignRequest is a request object for web3signer sign api. type AggregateAndProofSignRequest struct { Type string `json:"type" validate:"required"` ForkInfo *ForkInfo `json:"fork_info" validate:"required"` @@ -42,6 +42,14 @@ type BlockV2AltairSignRequest struct { BeaconBlock *BeaconBlockAltairBlockV2 `json:"beacon_block" validate:"required"` } +// BlockV2BellatrixSignRequest is a request object for web3signer sign api for supporting Bellatrix fork. +type BlockV2BellatrixSignRequest struct { + Type string `json:"type" validate:"required"` + ForkInfo *ForkInfo `json:"fork_info" validate:"required"` + SigningRoot string `json:"signingRoot"` + BeaconBlock *BeaconBlockBellatrixBlockV2 `json:"beacon_block" validate:"required"` +} + // BlockV2SignRequest is a request object for web3signer sign api. type BlockV2SignRequest struct { Type string `json:"type" validate:"required"` @@ -175,9 +183,9 @@ type Eth1Data struct { // ProposerSlashing a sub property of BeaconBlockBody. type ProposerSlashing struct { // Prysm uses Header_1 but web3signer uses signed_header_1. - SignedHeader_1 *SignedBeaconBlockHeader `json:"signed_header_1"` + Signedheader1 *SignedBeaconBlockHeader `json:"signed_header_1"` // Prysm uses Header_2 but web3signer uses signed_header_2. - SignedHeader_2 *SignedBeaconBlockHeader `json:"signed_header_2"` + Signedheader2 *SignedBeaconBlockHeader `json:"signed_header_2"` } // SignedBeaconBlockHeader is a sub property of ProposerSlashing. @@ -197,8 +205,8 @@ type BeaconBlockHeader struct { // AttesterSlashing a sub property of BeaconBlockBody. type AttesterSlashing struct { - Attestation_1 *IndexedAttestation `json:"attestation_1"` - Attestation_2 *IndexedAttestation `json:"attestation_2"` + Attestation1 *IndexedAttestation `json:"attestation_1"` + Attestation2 *IndexedAttestation `json:"attestation_2"` } // IndexedAttestation a sub property of AttesterSlashing. @@ -264,6 +272,12 @@ type BeaconBlockBodyAltair struct { SyncAggregate *SyncAggregate `json:"sync_aggregate"` } +// BeaconBlockBellatrixBlockV2 a field of BlockV2BellatrixSignRequest. +type BeaconBlockBellatrixBlockV2 struct { + Version string `json:"version"` + BlockHeader *BeaconBlockHeader `json:"block_header"` +} + // SyncAggregate is a sub property of BeaconBlockBodyAltair. type SyncAggregate struct { SyncCommitteeBits string `json:"sync_committee_bits"` /* SSZ hexadecimal string */ diff --git a/validator/keymanager/remote/BUILD.bazel b/validator/keymanager/remote/BUILD.bazel index 553d024171e4..a094470b1625 100644 --- a/validator/keymanager/remote/BUILD.bazel +++ b/validator/keymanager/remote/BUILD.bazel @@ -9,6 +9,7 @@ go_library( ], importpath = "github.com/prysmaticlabs/prysm/validator/keymanager/remote", visibility = [ + "//cmd/validator:__subpackages__", "//validator:__pkg__", "//validator:__subpackages__", ], diff --git a/validator/node/BUILD.bazel b/validator/node/BUILD.bazel index 9a05707c1582..04c67d689a24 100644 --- a/validator/node/BUILD.bazel +++ b/validator/node/BUILD.bazel @@ -11,6 +11,7 @@ go_test( "//config/fieldparams:go_default_library", "//config/validator/service:go_default_library", "//encoding/bytesutil:go_default_library", + "//testing/assert:go_default_library", "//testing/require:go_default_library", "//validator/accounts:go_default_library", "//validator/accounts/wallet:go_default_library", diff --git a/validator/node/node.go b/validator/node/node.go index 82ab2c15a896..edcf9ff52c32 100644 --- a/validator/node/node.go +++ b/validator/node/node.go @@ -539,8 +539,19 @@ func feeRecipientConfig(cliCtx *cli.Context) (*validatorServiceConfig.FeeRecipie if !common.IsHexAddress(option.FeeRecipient) { return nil, errors.New("fee recipient is not a valid eth1 address") } + mixedcaseAddress, err := common.NewMixedcaseAddressFromString(option.FeeRecipient) + if err != nil { + return nil, errors.Wrapf(err, "could not decode fee recipient %s", option.FeeRecipient) + } + checksumAddress := common.BytesToAddress(feebytes) + if !mixedcaseAddress.ValidChecksum() { + log.Warnf("Fee recipient %s is not a checksum Ethereum address. "+ + "The checksummed address is %s and will be used as the fee recipient. "+ + "We recommend using a mixed-case address (checksum) "+ + "to prevent spelling mistakes in your fee recipient Ethereum address", option.FeeRecipient, checksumAddress.Hex()) + } frConfig.ProposeConfig[bytesutil.ToBytes48(decodedKey)] = &validatorServiceConfig.FeeRecipientOptions{ - FeeRecipient: common.BytesToAddress(feebytes), + FeeRecipient: checksumAddress, } } } diff --git a/validator/node/node_test.go b/validator/node/node_test.go index c457b07cc908..5c7b048c5f9d 100644 --- a/validator/node/node_test.go +++ b/validator/node/node_test.go @@ -16,6 +16,7 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" validator_service_config "github.com/prysmaticlabs/prysm/config/validator/service" "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/validator/accounts" "github.com/prysmaticlabs/prysm/validator/accounts/wallet" @@ -312,6 +313,8 @@ func TestUnmarshalFromURL(t *testing.T) { } func TestFeeRecipientConfig(t *testing.T) { + hook := logTest.NewGlobal() + type feeRecipientFlag struct { dir string url string @@ -326,12 +329,13 @@ func TestFeeRecipientConfig(t *testing.T) { want func() *validator_service_config.FeeRecipientConfig urlResponse string wantErr string + wantLog string }{ { - name: "Happy Path Config file File", + name: "Happy Path Config file File, bad checksum", args: args{ feeRecipientFlagValues: &feeRecipientFlag{ - dir: "./testdata/good-prepare-beacon-proposer-config.json", + dir: "./testdata/good-prepare-beacon-proposer-config-badchecksum.json", url: "", defaultfee: "", }, @@ -342,15 +346,16 @@ func TestFeeRecipientConfig(t *testing.T) { return &validator_service_config.FeeRecipientConfig{ ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.FeeRecipientOptions{ bytesutil.ToBytes48(key1): { - FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"), + FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"), }, }, DefaultConfig: &validator_service_config.FeeRecipientOptions{ - FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"), + FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"), }, } }, wantErr: "", + wantLog: "is not a checksum Ethereum address", }, { name: "Happy Path Config file File multiple fee recipients", @@ -506,6 +511,11 @@ func TestFeeRecipientConfig(t *testing.T) { require.ErrorContains(t, tt.wantErr, err) return } + if tt.wantLog != "" { + assert.LogsContain(t, hook, + tt.wantLog, + ) + } w := tt.want() require.DeepEqual(t, w, got) }) diff --git a/validator/node/testdata/good-prepare-beacon-proposer-config-badchecksum.json b/validator/node/testdata/good-prepare-beacon-proposer-config-badchecksum.json new file mode 100644 index 000000000000..86965b4e1b4d --- /dev/null +++ b/validator/node/testdata/good-prepare-beacon-proposer-config-badchecksum.json @@ -0,0 +1,10 @@ +{ + "proposer_config": { + "0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a": { + "fee_recipient": "0xae967917c465db8578ca9024c205720b1a3651A9" + } + }, + "default_config": { + "fee_recipient": "0xae967917c465db8578ca9024c205720b1a3651A9" + } +}