mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 22:07:59 -05:00
Compare commits
9 Commits
builder-1
...
v2.1.3-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76b941b310 | ||
|
|
d099c2790b | ||
|
|
2fc3d41ffa | ||
|
|
2e4174bdd6 | ||
|
|
a170fd4bd6 | ||
|
|
3e36eacd1e | ||
|
|
0e9dfe04a1 | ||
|
|
302a5cf00b | ||
|
|
c72f1af951 |
@@ -1,7 +0,0 @@
|
||||
package builder
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
var (
|
||||
ErrNotRunning = errors.New("builder is not running")
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
)
|
||||
|
||||
var (
|
||||
submitBlindedBlockLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "submit_blinded_block_latency_milliseconds",
|
||||
Help: "Captures RPC latency for submitting blinded block in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
getHeaderLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "get_header_latency_milliseconds",
|
||||
Help: "Captures RPC latency for get header in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
registerValidatorLatency = promauto.NewHistogram(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "register_validator_latency_milliseconds",
|
||||
Help: "Captures RPC latency for register validator in milliseconds",
|
||||
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000},
|
||||
},
|
||||
)
|
||||
)
|
||||
@@ -1,58 +0,0 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/network"
|
||||
"github.com/prysmaticlabs/prysm/network/authorization"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type Option func(s *Service) error
|
||||
|
||||
// FlagOptions for builder service flag configurations.
|
||||
func FlagOptions(c *cli.Context) ([]Option, error) {
|
||||
endpoints := parseBuilderEndpoints(c)
|
||||
opts := []Option{
|
||||
WithBuilderEndpoints(endpoints),
|
||||
}
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func WithBuilderEndpoints(endpoints []string) Option {
|
||||
return func(s *Service) error {
|
||||
stringEndpoints := dedupEndpoints(endpoints)
|
||||
endpoints := make([]network.Endpoint, len(stringEndpoints))
|
||||
for i, e := range stringEndpoints {
|
||||
endpoints[i] = covertEndPoint(e)
|
||||
}
|
||||
s.cfg.builderEndpoint = endpoints[0] // Use the first one as the default.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func covertEndPoint(ep string) network.Endpoint {
|
||||
return network.Endpoint{
|
||||
Url: ep,
|
||||
Auth: network.AuthorizationData{ // Not sure about authorization for now.
|
||||
Method: authorization.None,
|
||||
Value: "",
|
||||
}}
|
||||
}
|
||||
|
||||
func parseBuilderEndpoints(c *cli.Context) []string {
|
||||
// Goal is to support multiple end points later.
|
||||
return []string{c.String(flags.MevBuilderFlag.Name)}
|
||||
}
|
||||
|
||||
func dedupEndpoints(endpoints []string) []string {
|
||||
selectionMap := make(map[string]bool)
|
||||
newEndpoints := make([]string, 0, len(endpoints))
|
||||
for _, point := range endpoints {
|
||||
if selectionMap[point] {
|
||||
continue
|
||||
}
|
||||
newEndpoints = append(newEndpoints, point)
|
||||
selectionMap[point] = true
|
||||
}
|
||||
return newEndpoints
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/signing"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
func VerifyRegistrationSignature(
|
||||
slot types.Slot,
|
||||
fork *ethpb.Fork,
|
||||
signed *ethpb.SignedValidatorRegistrationV1,
|
||||
genesisRoot []byte,
|
||||
) error {
|
||||
if signed == nil || signed.Message == nil {
|
||||
return errors.New("nil signed registration")
|
||||
}
|
||||
domain, err := signing.Domain(fork, slots.ToEpoch(slot), [4]byte{} /*TODO: Use registration signing domain */, genesisRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := signing.VerifySigningRoot(signed, signed.Message.Pubkey, signed.Signature, domain); err != nil {
|
||||
return signing.ErrSigFailedToVerify
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -410,23 +410,23 @@ func (s *Store) HighestSlotBlocksBelow(ctx context.Context, slot types.Slot) ([]
|
||||
c := bkt.Cursor()
|
||||
// The documentation for Seek says:
|
||||
// "If the key does not exist then the next key is used. If no keys follow, a nil key is returned."
|
||||
sl, r := c.Seek(sk)
|
||||
// So if there are slots in the index higher than the requested slot, sl will be equal to the key that is
|
||||
// one higher than the value we want. If the slot argument is higher than the highest value in the index,
|
||||
// we'll get a nil value for `sl`. In that case we'll go backwards from Cursor.Last().
|
||||
if sl == nil {
|
||||
sl, r = c.Last()
|
||||
seekPast := func(ic *bolt.Cursor, k []byte) ([]byte, []byte) {
|
||||
ik, iv := ic.Seek(k)
|
||||
// So if there are slots in the index higher than the requested slot, sl will be equal to the key that is
|
||||
// one higher than the value we want. If the slot argument is higher than the highest value in the index,
|
||||
// we'll get a nil value for `sl`. In that case we'll go backwards from Cursor.Last().
|
||||
if ik == nil {
|
||||
return ic.Last()
|
||||
}
|
||||
return ik, iv
|
||||
}
|
||||
for {
|
||||
// re loop condition: when .Prev() rewinds past the beginning off the collection, the loop will terminate,
|
||||
// because `sl` will be nil. If we don't find a value for `root` before iteration ends,
|
||||
// `root` will be the zero value, in which case this function will return the genesis block.
|
||||
for sl, r := seekPast(c, sk); sl != nil; sl, r = c.Prev() {
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
// termination condition: when .Prev() rewinds past the beginning off the collection, key will be nil.
|
||||
// breaking without setting `root` means `root` will be the zero value, so this function will return
|
||||
// the genesis block.
|
||||
if sl == nil {
|
||||
break
|
||||
}
|
||||
if r == nil {
|
||||
continue
|
||||
}
|
||||
@@ -437,7 +437,6 @@ func (s *Store) HighestSlotBlocksBelow(ctx context.Context, slot types.Slot) ([]
|
||||
root = bytesutil.ToBytes32(r)
|
||||
break
|
||||
}
|
||||
sl, r = c.Prev()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -470,8 +469,20 @@ func (s *Store) FeeRecipientByValidatorID(ctx context.Context, id types.Validato
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(feeRecipientBucket)
|
||||
addr = bkt.Get(bytesutil.Uint64ToBytesBigEndian(uint64(id)))
|
||||
// IF the fee recipient is not found in the standard fee recipient bucket, then
|
||||
// check the registration bucket. The fee recipient may be there.
|
||||
// This is to resolve imcompatility until we fully migrate to the registration bucket.
|
||||
if addr == nil {
|
||||
return errors.Wrapf(ErrNotFoundFeeRecipient, "validator id %d", id)
|
||||
bkt = tx.Bucket(registrationBucket)
|
||||
enc := bkt.Get(bytesutil.Uint64ToBytesBigEndian(uint64(id)))
|
||||
if enc == nil {
|
||||
return errors.Wrapf(ErrNotFoundFeeRecipient, "validator id %d", id)
|
||||
}
|
||||
reg := ðpb.ValidatorRegistrationV1{}
|
||||
if err := decode(ctx, enc, reg); err != nil {
|
||||
return err
|
||||
}
|
||||
addr = reg.FeeRecipient
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -499,6 +510,48 @@ func (s *Store) SaveFeeRecipientsByValidatorIDs(ctx context.Context, ids []types
|
||||
})
|
||||
}
|
||||
|
||||
// RegistrationByValidatorID returns the validator registration object for a validator id.
|
||||
// `ErrNotFoundFeeRecipient` is returned if the validator id is not found.
|
||||
func (s *Store) RegistrationByValidatorID(ctx context.Context, id types.ValidatorIndex) (*ethpb.ValidatorRegistrationV1, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.RegistrationByValidatorID")
|
||||
defer span.End()
|
||||
reg := ðpb.ValidatorRegistrationV1{}
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(registrationBucket)
|
||||
enc := bkt.Get(bytesutil.Uint64ToBytesBigEndian(uint64(id)))
|
||||
if enc == nil {
|
||||
return errors.Wrapf(ErrNotFoundFeeRecipient, "validator id %d", id)
|
||||
}
|
||||
return decode(ctx, enc, reg)
|
||||
})
|
||||
return reg, err
|
||||
}
|
||||
|
||||
// SaveRegistrationsByValidatorIDs saves the validator registrations for validator ids.
|
||||
// Error is returned if `ids` and `registrations` are not the same length.
|
||||
func (s *Store) SaveRegistrationsByValidatorIDs(ctx context.Context, ids []types.ValidatorIndex, regs []*ethpb.ValidatorRegistrationV1) error {
|
||||
_, span := trace.StartSpan(ctx, "BeaconDB.SaveRegistrationsByValidatorIDs")
|
||||
defer span.End()
|
||||
|
||||
if len(ids) != len(regs) {
|
||||
return errors.New("ids and registrations must be the same length")
|
||||
}
|
||||
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(registrationBucket)
|
||||
for i, id := range ids {
|
||||
enc, err := encode(ctx, regs[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bkt.Put(bytesutil.Uint64ToBytesBigEndian(uint64(id)), enc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// blockRootsByFilter retrieves the block roots given the filter criteria.
|
||||
func blockRootsByFilter(ctx context.Context, tx *bolt.Tx, f *filters.QueryFilter) ([][]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.blockRootsByFilter")
|
||||
|
||||
@@ -693,4 +693,78 @@ func TestStore_FeeRecipientByValidatorID(t *testing.T) {
|
||||
_, err = db.FeeRecipientByValidatorID(ctx, 3)
|
||||
want := errors.Wrap(ErrNotFoundFeeRecipient, "validator id 3")
|
||||
require.Equal(t, want.Error(), err.Error())
|
||||
|
||||
regs := []*ethpb.ValidatorRegistrationV1{
|
||||
{
|
||||
FeeRecipient: bytesutil.PadTo([]byte("a"), 20),
|
||||
GasLimit: 1,
|
||||
Timestamp: 2,
|
||||
Pubkey: bytesutil.PadTo([]byte("b"), 48),
|
||||
}}
|
||||
require.NoError(t, db.SaveRegistrationsByValidatorIDs(ctx, []types.ValidatorIndex{3}, regs))
|
||||
f, err = db.FeeRecipientByValidatorID(ctx, 3)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, common.Address{'a'}, f)
|
||||
|
||||
_, err = db.FeeRecipientByValidatorID(ctx, 4)
|
||||
want = errors.Wrap(ErrNotFoundFeeRecipient, "validator id 4")
|
||||
require.Equal(t, want.Error(), err.Error())
|
||||
}
|
||||
|
||||
func TestStore_RegistrationsByValidatorID(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
ids := []types.ValidatorIndex{0, 0, 0}
|
||||
regs := []*ethpb.ValidatorRegistrationV1{{}, {}, {}, {}}
|
||||
require.ErrorContains(t, "ids and registrations must be the same length", db.SaveRegistrationsByValidatorIDs(ctx, ids, regs))
|
||||
|
||||
ids = []types.ValidatorIndex{0, 1, 2}
|
||||
regs = []*ethpb.ValidatorRegistrationV1{
|
||||
{
|
||||
FeeRecipient: bytesutil.PadTo([]byte("a"), 20),
|
||||
GasLimit: 1,
|
||||
Timestamp: 2,
|
||||
Pubkey: bytesutil.PadTo([]byte("b"), 48),
|
||||
},
|
||||
{
|
||||
FeeRecipient: bytesutil.PadTo([]byte("c"), 20),
|
||||
GasLimit: 3,
|
||||
Timestamp: 4,
|
||||
Pubkey: bytesutil.PadTo([]byte("d"), 48),
|
||||
},
|
||||
{
|
||||
FeeRecipient: bytesutil.PadTo([]byte("e"), 20),
|
||||
GasLimit: 5,
|
||||
Timestamp: 6,
|
||||
Pubkey: bytesutil.PadTo([]byte("f"), 48),
|
||||
},
|
||||
}
|
||||
require.NoError(t, db.SaveRegistrationsByValidatorIDs(ctx, ids, regs))
|
||||
f, err := db.RegistrationByValidatorID(ctx, 0)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, ðpb.ValidatorRegistrationV1{
|
||||
FeeRecipient: bytesutil.PadTo([]byte("a"), 20),
|
||||
GasLimit: 1,
|
||||
Timestamp: 2,
|
||||
Pubkey: bytesutil.PadTo([]byte("b"), 48),
|
||||
}, f)
|
||||
f, err = db.RegistrationByValidatorID(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, ðpb.ValidatorRegistrationV1{
|
||||
FeeRecipient: bytesutil.PadTo([]byte("c"), 20),
|
||||
GasLimit: 3,
|
||||
Timestamp: 4,
|
||||
Pubkey: bytesutil.PadTo([]byte("d"), 48),
|
||||
}, f)
|
||||
f, err = db.RegistrationByValidatorID(ctx, 2)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, ðpb.ValidatorRegistrationV1{
|
||||
FeeRecipient: bytesutil.PadTo([]byte("e"), 20),
|
||||
GasLimit: 5,
|
||||
Timestamp: 6,
|
||||
Pubkey: bytesutil.PadTo([]byte("f"), 48),
|
||||
}, f)
|
||||
_, err = db.RegistrationByValidatorID(ctx, 3)
|
||||
want := errors.Wrap(ErrNotFoundFeeRecipient, "validator id 3")
|
||||
require.Equal(t, want.Error(), err.Error())
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ func isSSZStorageFormat(obj interface{}) bool {
|
||||
return true
|
||||
case *ethpb.VoluntaryExit:
|
||||
return true
|
||||
case *ethpb.ValidatorRegistrationV1:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -192,6 +192,7 @@ func NewKVStore(ctx context.Context, dirPath string, config *Config) (*Store, er
|
||||
migrationsBucket,
|
||||
|
||||
feeRecipientBucket,
|
||||
registrationBucket,
|
||||
)
|
||||
}); err != nil {
|
||||
log.WithField("elapsed", time.Since(start)).Error("Failed to update db and create buckets")
|
||||
|
||||
@@ -19,6 +19,7 @@ var (
|
||||
powchainBucket = []byte("powchain")
|
||||
stateValidatorsBucket = []byte("state-validators")
|
||||
feeRecipientBucket = []byte("fee-recipient")
|
||||
registrationBucket = []byte("registration")
|
||||
|
||||
// Deprecated: This bucket was migrated in PR 6461. Do not use, except for migrations.
|
||||
slotsHasObjectBucket = []byte("slots-has-objects")
|
||||
|
||||
@@ -228,11 +228,6 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
|
||||
log.Debugln("Starting Fork Choice")
|
||||
beacon.startForkChoice()
|
||||
|
||||
log.Debugln("Registering builder service")
|
||||
if err := beacon.registerBuilderService(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugln("Registering Blockchain Service")
|
||||
if err := beacon.registerBlockchainService(); err != nil {
|
||||
return nil, err
|
||||
@@ -573,14 +568,6 @@ func (b *BeaconNode) fetchP2P() p2p.P2P {
|
||||
return p
|
||||
}
|
||||
|
||||
func (b *BeaconNode) fetchBuilderService() *builder.Service {
|
||||
var s *builder.Service
|
||||
if err := b.services.FetchService(&s); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (b *BeaconNode) registerAttestationPool() error {
|
||||
s, err := attestations.NewService(b.ctx, &attestations.Config{
|
||||
Pool: b.attestationPool,
|
||||
@@ -819,7 +806,6 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
AttestationReceiver: chainService,
|
||||
GenesisTimeFetcher: chainService,
|
||||
GenesisFetcher: chainService,
|
||||
BlockBuilder: b.fetchBuilderService(),
|
||||
OptimisticModeFetcher: chainService,
|
||||
AttestationsPool: b.attestationPool,
|
||||
ExitPool: b.exitPool,
|
||||
@@ -984,12 +970,3 @@ func (b *BeaconNode) registerValidatorMonitorService() error {
|
||||
}
|
||||
return b.services.RegisterService(svc)
|
||||
}
|
||||
|
||||
func (b *BeaconNode) registerBuilderService() error {
|
||||
options := b.serviceFlagOpts.builderOpts
|
||||
svc, err := builder.NewService(b.ctx, options...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.services.RegisterService(svc)
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ func (s *Service) retrieveHeaderInfo(ctx context.Context, bNum uint64) (*types.H
|
||||
return nil, err
|
||||
}
|
||||
if blk == nil {
|
||||
return nil, errors.New("header with the provided number does not exist")
|
||||
return nil, errors.Errorf("header with the number %d does not exist", bNum)
|
||||
}
|
||||
if err := s.headerCache.AddHeader(blk); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -369,12 +369,17 @@ func (s *Service) ETH1ConnectionErrors() []error {
|
||||
|
||||
// refers to the latest eth1 block which follows the condition: eth1_timestamp +
|
||||
// SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE <= current_unix_time
|
||||
func (s *Service) followedBlockHeight(_ context.Context) (uint64, error) {
|
||||
latestValidBlock := uint64(0)
|
||||
if s.latestEth1Data.BlockHeight > params.BeaconConfig().Eth1FollowDistance {
|
||||
latestValidBlock = s.latestEth1Data.BlockHeight - params.BeaconConfig().Eth1FollowDistance
|
||||
func (s *Service) followedBlockHeight(ctx context.Context) (uint64, error) {
|
||||
followTime := params.BeaconConfig().Eth1FollowDistance * params.BeaconConfig().SecondsPerETH1Block
|
||||
latestBlockTime := uint64(0)
|
||||
if s.latestEth1Data.BlockTime > followTime {
|
||||
latestBlockTime = s.latestEth1Data.BlockTime - followTime
|
||||
}
|
||||
return latestValidBlock, nil
|
||||
blk, err := s.BlockByTimestamp(ctx, latestBlockTime)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return blk.Number.Uint64(), nil
|
||||
}
|
||||
|
||||
func (s *Service) initDepositCaches(ctx context.Context, ctrs []*ethpb.DepositContainer) error {
|
||||
|
||||
@@ -81,7 +81,8 @@ func (g *goodNotifier) StateFeed() *event.Feed {
|
||||
}
|
||||
|
||||
type goodFetcher struct {
|
||||
backend *backends.SimulatedBackend
|
||||
backend *backends.SimulatedBackend
|
||||
blockNumMap map[uint64]*gethTypes.Header
|
||||
}
|
||||
|
||||
func (_ *goodFetcher) Close() {}
|
||||
@@ -104,12 +105,15 @@ func (g *goodFetcher) HeaderByHash(_ context.Context, hash common.Hash) (*gethTy
|
||||
}
|
||||
|
||||
func (g *goodFetcher) HeaderByNumber(_ context.Context, number *big.Int) (*gethTypes.Header, error) {
|
||||
if g.backend == nil {
|
||||
if g.backend == nil && g.blockNumMap == nil {
|
||||
return &gethTypes.Header{
|
||||
Number: big.NewInt(15),
|
||||
Time: 150,
|
||||
}, nil
|
||||
}
|
||||
if g.blockNumMap != nil {
|
||||
return g.blockNumMap[number.Uint64()], nil
|
||||
}
|
||||
var header *gethTypes.Header
|
||||
if number == nil {
|
||||
header = g.backend.Blockchain().CurrentHeader()
|
||||
@@ -864,6 +868,28 @@ func TestService_CacheBlockHeaders(t *testing.T) {
|
||||
assert.Equal(t, 5, rClient.numOfCalls)
|
||||
}
|
||||
|
||||
func TestService_FollowBlock(t *testing.T) {
|
||||
followTime := params.BeaconConfig().Eth1FollowDistance * params.BeaconConfig().SecondsPerETH1Block
|
||||
followTime += 10000
|
||||
bMap := make(map[uint64]*gethTypes.Header)
|
||||
for i := uint64(3000); i > 0; i-- {
|
||||
bMap[i] = &gethTypes.Header{
|
||||
Number: big.NewInt(int64(i)),
|
||||
Time: followTime + (i * 40),
|
||||
}
|
||||
}
|
||||
s := &Service{
|
||||
cfg: &config{eth1HeaderReqLimit: 1000},
|
||||
eth1DataFetcher: &goodFetcher{blockNumMap: bMap},
|
||||
headerCache: newHeaderCache(),
|
||||
latestEth1Data: ðpb.LatestETH1Data{BlockTime: (3000 * 40) + followTime, BlockHeight: 3000},
|
||||
}
|
||||
h, err := s.followedBlockHeight(context.Background())
|
||||
assert.NoError(t, err)
|
||||
// With a much higher blocktime, the follow height is respectively shortened.
|
||||
assert.Equal(t, uint64(2283), h)
|
||||
}
|
||||
|
||||
type slowRPCClient struct {
|
||||
limit int
|
||||
numOfCalls int
|
||||
|
||||
@@ -10,7 +10,6 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/builder:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
"//beacon-chain/core/feed/block:go_default_library",
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -17,10 +18,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
versionHeader = "Eth-Consensus-Version"
|
||||
grpcVersionHeader = "Grpc-metadata-Eth-Consensus-Version"
|
||||
versionHeader = "Eth-Consensus-Version"
|
||||
grpcVersionHeader = "Grpc-metadata-Eth-Consensus-Version"
|
||||
jsonMediaType = "application/json"
|
||||
octetStreamMediaType = "application/octet-stream"
|
||||
)
|
||||
|
||||
// match a number with optional decimals
|
||||
var priorityRegex = regexp.MustCompile(`q=(\d+(?:\.\d+)?)`)
|
||||
|
||||
type sszConfig struct {
|
||||
fileName string
|
||||
responseJson sszResponse
|
||||
@@ -99,7 +105,12 @@ func handleGetSSZ(
|
||||
req *http.Request,
|
||||
config sszConfig,
|
||||
) (handled bool) {
|
||||
if !sszRequested(req) {
|
||||
ssz, err := sszRequested(req)
|
||||
if err != nil {
|
||||
apimiddleware.WriteError(w, apimiddleware.InternalServerError(err), nil)
|
||||
return true
|
||||
}
|
||||
if !ssz {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -193,17 +204,42 @@ func handlePostSSZ(
|
||||
return true
|
||||
}
|
||||
|
||||
func sszRequested(req *http.Request) bool {
|
||||
accept, ok := req.Header["Accept"]
|
||||
if !ok {
|
||||
return false
|
||||
func sszRequested(req *http.Request) (bool, error) {
|
||||
accept := req.Header.Values("Accept")
|
||||
if len(accept) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
for _, v := range accept {
|
||||
if v == "application/octet-stream" {
|
||||
return true
|
||||
types := strings.Split(accept[0], ",")
|
||||
currentType, currentPriority := "", 0.0
|
||||
for _, t := range types {
|
||||
values := strings.Split(t, ";")
|
||||
name := values[0]
|
||||
if name != jsonMediaType && name != octetStreamMediaType {
|
||||
continue
|
||||
}
|
||||
// no params specified
|
||||
if len(values) == 1 {
|
||||
priority := 1.0
|
||||
if priority > currentPriority {
|
||||
currentType, currentPriority = name, priority
|
||||
}
|
||||
continue
|
||||
}
|
||||
params := values[1]
|
||||
match := priorityRegex.FindAllStringSubmatch(params, 1)
|
||||
if len(match) != 1 {
|
||||
continue
|
||||
}
|
||||
priority, err := strconv.ParseFloat(match[0][1], 32)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if priority > currentPriority {
|
||||
currentType, currentPriority = name, priority
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
return currentType == octetStreamMediaType, nil
|
||||
}
|
||||
|
||||
func sszPosted(req *http.Request) bool {
|
||||
@@ -214,7 +250,7 @@ func sszPosted(req *http.Request) bool {
|
||||
if len(ct) != 1 {
|
||||
return false
|
||||
}
|
||||
return ct[0] == "application/octet-stream"
|
||||
return ct[0] == octetStreamMediaType
|
||||
}
|
||||
|
||||
func prepareSSZRequestForProxying(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, req *http.Request) apimiddleware.ErrorJson {
|
||||
@@ -252,7 +288,7 @@ func preparePostedSSZData(req *http.Request) apimiddleware.ErrorJson {
|
||||
}
|
||||
req.Body = io.NopCloser(bytes.NewBuffer(data))
|
||||
req.ContentLength = int64(len(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Content-Type", jsonMediaType)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -280,7 +316,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-Type", octetStreamMediaType)
|
||||
w.Header().Set("Content-Disposition", "attachment; filename="+fileName)
|
||||
w.Header().Set(versionHeader, respVersion)
|
||||
if statusCodeHeader != "" {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
@@ -34,28 +35,88 @@ func (t testSSZResponseJson) SSZData() string {
|
||||
func TestSSZRequested(t *testing.T) {
|
||||
t.Run("ssz_requested", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{"application/octet-stream"}
|
||||
result := sszRequested(request)
|
||||
request.Header["Accept"] = []string{octetStreamMediaType}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, result)
|
||||
})
|
||||
|
||||
t.Run("multiple_content_types", func(t *testing.T) {
|
||||
t.Run("ssz_content_type_first", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{"application/json", "application/octet-stream"}
|
||||
result := sszRequested(request)
|
||||
request.Header["Accept"] = []string{fmt.Sprintf("%s,%s", octetStreamMediaType, jsonMediaType)}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, result)
|
||||
})
|
||||
|
||||
t.Run("ssz_content_type_preferred_1", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.9,%s", jsonMediaType, octetStreamMediaType)}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, result)
|
||||
})
|
||||
|
||||
t.Run("ssz_content_type_preferred_2", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{fmt.Sprintf("%s;q=0.95,%s;q=0.9", octetStreamMediaType, jsonMediaType)}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, result)
|
||||
})
|
||||
|
||||
t.Run("other_content_type_preferred", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9", jsonMediaType, octetStreamMediaType)}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, result)
|
||||
})
|
||||
|
||||
t.Run("other_params", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{fmt.Sprintf("%s,%s;q=0.9,otherparam=xyz", jsonMediaType, octetStreamMediaType)}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, result)
|
||||
})
|
||||
|
||||
t.Run("no_header", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
result := sszRequested(request)
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, result)
|
||||
})
|
||||
|
||||
t.Run("empty_header", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, result)
|
||||
})
|
||||
|
||||
t.Run("empty_header_value", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{""}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, result)
|
||||
})
|
||||
|
||||
t.Run("other_content_type", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{"application/json"}
|
||||
result := sszRequested(request)
|
||||
request.Header["Accept"] = []string{"application/other"}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, result)
|
||||
})
|
||||
|
||||
t.Run("garbage", func(t *testing.T) {
|
||||
request := httptest.NewRequest("GET", "http://foo.example", nil)
|
||||
request.Header["Accept"] = []string{"This is Sparta!!!"}
|
||||
result, err := sszRequested(request)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, result)
|
||||
})
|
||||
}
|
||||
@@ -82,7 +143,7 @@ func TestPreparePostedSszData(t *testing.T) {
|
||||
|
||||
preparePostedSSZData(request)
|
||||
assert.Equal(t, int64(19), request.ContentLength)
|
||||
assert.Equal(t, "application/json", request.Header.Get("Content-Type"))
|
||||
assert.Equal(t, jsonMediaType, request.Header.Get("Content-Type"))
|
||||
}
|
||||
|
||||
func TestSerializeMiddlewareResponseIntoSSZ(t *testing.T) {
|
||||
@@ -138,7 +199,7 @@ func TestWriteSSZResponseHeaderAndBody(t *testing.T) {
|
||||
v, ok = writer.Header()["Content-Type"]
|
||||
require.Equal(t, true, ok, "header not found")
|
||||
require.Equal(t, 1, len(v), "wrong number of header values")
|
||||
assert.Equal(t, "application/octet-stream", v[0])
|
||||
assert.Equal(t, octetStreamMediaType, v[0])
|
||||
v, ok = writer.Header()["Content-Disposition"]
|
||||
require.Equal(t, true, ok, "header not found")
|
||||
require.Equal(t, 1, len(v), "wrong number of header values")
|
||||
|
||||
@@ -550,7 +550,7 @@ type indexedAttestationJson struct {
|
||||
}
|
||||
|
||||
type feeRecipientJson struct {
|
||||
ValidatorIndex uint64 `json:"validator_index"`
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
FeeRecipient string `json:"fee_recipient" hex:"true"`
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ go_library(
|
||||
deps = [
|
||||
"//async/event:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/builder:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
"//beacon-chain/core/altair:go_default_library",
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -58,7 +57,12 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vs.getBellatrixBeaconBlock(ctx, req)
|
||||
blk, err := vs.getBellatrixBeaconBlock(ctx, req)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not fetch Bellatrix beacon block: %v", err)
|
||||
}
|
||||
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: blk}}, nil
|
||||
}
|
||||
|
||||
// GetBlock is called by a proposer during its assigned slot to request a block to sign
|
||||
@@ -129,20 +133,9 @@ func (vs *Server) PrepareBeaconProposer(
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// SubmitValidatorRegistration submits validator registration.
|
||||
func (vs *Server) SubmitValidatorRegistration(context.Context, *ethpb.SignedValidatorRegistrationV1) (*emptypb.Empty, error) {
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk interfaces.SignedBeaconBlock) (*ethpb.ProposeResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.proposeGenericBeaconBlock")
|
||||
defer span.End()
|
||||
|
||||
blk, err := vs.getBuilderBlock(ctx, blk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not tree hash block: %v", err)
|
||||
@@ -175,75 +168,6 @@ func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk interfaces.
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) getBuilderBlock(ctx context.Context, b interfaces.SignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
|
||||
if b.Version() != version.BellatrixBlind {
|
||||
return b, nil
|
||||
}
|
||||
if vs.BlockBuilder.Status() != nil {
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "Block builder is not running")
|
||||
}
|
||||
agg, err := b.Block().Body().SyncAggregate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, err := b.Block().Body().ExecutionPayloadHeader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sb := ðpb.SignedBlindedBeaconBlockBellatrix{
|
||||
Block: ðpb.BlindedBeaconBlockBellatrix{
|
||||
Slot: b.Block().Slot(),
|
||||
ProposerIndex: b.Block().ProposerIndex(),
|
||||
ParentRoot: b.Block().ParentRoot(),
|
||||
StateRoot: b.Block().StateRoot(),
|
||||
Body: ðpb.BlindedBeaconBlockBodyBellatrix{
|
||||
RandaoReveal: b.Block().Body().RandaoReveal(),
|
||||
Eth1Data: b.Block().Body().Eth1Data(),
|
||||
Graffiti: b.Block().Body().Graffiti(),
|
||||
ProposerSlashings: b.Block().Body().ProposerSlashings(),
|
||||
AttesterSlashings: b.Block().Body().AttesterSlashings(),
|
||||
Attestations: b.Block().Body().Attestations(),
|
||||
Deposits: b.Block().Body().Deposits(),
|
||||
VoluntaryExits: b.Block().Body().VoluntaryExits(),
|
||||
SyncAggregate: agg,
|
||||
ExecutionPayloadHeader: h,
|
||||
},
|
||||
},
|
||||
Signature: nil,
|
||||
}
|
||||
|
||||
payload, err := vs.BlockBuilder.SubmitBlindedBlock(ctx, sb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bb := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Slot: sb.Block.Slot,
|
||||
ProposerIndex: sb.Block.ProposerIndex,
|
||||
ParentRoot: sb.Block.ParentRoot,
|
||||
StateRoot: sb.Block.StateRoot,
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
RandaoReveal: sb.Block.Body.RandaoReveal,
|
||||
Eth1Data: sb.Block.Body.Eth1Data,
|
||||
Graffiti: sb.Block.Body.Graffiti,
|
||||
ProposerSlashings: sb.Block.Body.ProposerSlashings,
|
||||
AttesterSlashings: sb.Block.Body.AttesterSlashings,
|
||||
Attestations: sb.Block.Body.Attestations,
|
||||
Deposits: sb.Block.Body.Deposits,
|
||||
VoluntaryExits: sb.Block.Body.VoluntaryExits,
|
||||
SyncAggregate: agg,
|
||||
ExecutionPayload: payload,
|
||||
},
|
||||
},
|
||||
Signature: nil,
|
||||
}
|
||||
wb, err := wrapper.WrappedSignedBeaconBlock(bb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return wb, nil
|
||||
}
|
||||
|
||||
// computeStateRoot computes the state root after a block has been processed through a state transition and
|
||||
// returns it to the validator client.
|
||||
func (vs *Server) computeStateRoot(ctx context.Context, block interfaces.SignedBeaconBlock) ([]byte, error) {
|
||||
|
||||
@@ -4,59 +4,18 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition/interop"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
|
||||
func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockBellatrix, error) {
|
||||
altairBlk, err := vs.buildAltairBeaconBlock(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h, exists, err := vs.getBuilderHeader(ctx, req.Slot, altairBlk.ProposerIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
blk := ðpb.BlindedBeaconBlockBellatrix{
|
||||
Slot: altairBlk.Slot,
|
||||
ProposerIndex: altairBlk.ProposerIndex,
|
||||
ParentRoot: altairBlk.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
Body: ðpb.BlindedBeaconBlockBodyBellatrix{
|
||||
RandaoReveal: altairBlk.Body.RandaoReveal,
|
||||
Eth1Data: altairBlk.Body.Eth1Data,
|
||||
Graffiti: altairBlk.Body.Graffiti,
|
||||
ProposerSlashings: altairBlk.Body.ProposerSlashings,
|
||||
AttesterSlashings: altairBlk.Body.AttesterSlashings,
|
||||
Attestations: altairBlk.Body.Attestations,
|
||||
Deposits: altairBlk.Body.Deposits,
|
||||
VoluntaryExits: altairBlk.Body.VoluntaryExits,
|
||||
SyncAggregate: altairBlk.Body.SyncAggregate,
|
||||
ExecutionPayloadHeader: h,
|
||||
},
|
||||
}
|
||||
wsb, err := wrapper.WrappedSignedBeaconBlock(
|
||||
ðpb.SignedBlindedBeaconBlockBellatrix{Block: blk, Signature: make([]byte, 96)},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stateRoot, err := vs.computeStateRoot(ctx, wsb)
|
||||
if err != nil {
|
||||
interop.WriteBlockToDisk(wsb, true /*failed*/)
|
||||
return nil, fmt.Errorf("could not compute state root: %v", err)
|
||||
}
|
||||
blk.StateRoot = stateRoot
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: blk}}, nil
|
||||
}
|
||||
|
||||
payload, err := vs.getExecutionPayload(ctx, req.Slot, altairBlk.ProposerIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -93,33 +52,5 @@ func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockR
|
||||
return nil, fmt.Errorf("could not compute state root: %v", err)
|
||||
}
|
||||
blk.StateRoot = stateRoot
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: blk}}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) getBuilderHeader(ctx context.Context, slot types.Slot, idx types.ValidatorIndex) (*ethpb.ExecutionPayloadHeader, bool, error) {
|
||||
if vs.BlockBuilder.Status() != nil {
|
||||
log.WithError(vs.BlockBuilder.Status()).Error("Could not get builder status")
|
||||
return nil, false, nil
|
||||
}
|
||||
b, err := vs.HeadFetcher.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if blocks.IsPreBellatrixVersion(b.Version()) {
|
||||
return nil, false, nil
|
||||
}
|
||||
h, err := b.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
pk, err := vs.HeadFetcher.HeadValidatorIndexToPublicKey(ctx, idx)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
bid, err := vs.BlockBuilder.GetHeader(ctx, slot, bytesutil.ToBytes32(h.BlockHash), pk)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get builder header")
|
||||
return nil, false, nil
|
||||
}
|
||||
return bid.Message.Header, true, nil
|
||||
return blk, nil
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/builder"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
@@ -70,7 +69,6 @@ type Server struct {
|
||||
ReplayerBuilder stategen.ReplayerBuilder
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
ExecutionEngineCaller powchain.EngineCaller
|
||||
BlockBuilder builder.BlockBuilder
|
||||
}
|
||||
|
||||
// WaitForActivation checks if a validator public key exists in the active validator registry of the current
|
||||
|
||||
@@ -113,7 +113,7 @@ func (vs *Server) CheckDoppelGanger(ctx context.Context, req *ethpb.DoppelGanger
|
||||
|
||||
// Return early if we are in phase0.
|
||||
if headState.Version() == version.Phase0 {
|
||||
log.Info("Skipping goppelganger check for Phase 0")
|
||||
log.Info("Skipping doppelganger check for Phase 0")
|
||||
|
||||
resp := ðpb.DoppelGangerResponse{
|
||||
Responses: []*ethpb.DoppelGangerResponse_ValidatorResponse{},
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
|
||||
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/builder"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block"
|
||||
@@ -91,7 +90,6 @@ type Config struct {
|
||||
POWChainInfoFetcher powchain.ChainInfoFetcher
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
GenesisFetcher blockchain.GenesisFetcher
|
||||
BlockBuilder builder.BlockBuilder
|
||||
EnableDebugRPCEndpoints bool
|
||||
MockEth1Votes bool
|
||||
AttestationsPool attestations.Pool
|
||||
@@ -218,7 +216,6 @@ func (s *Service) Start() {
|
||||
ExecutionEngineCaller: s.cfg.ExecutionEngineCaller,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ProposerSlotIndexCache: s.cfg.ProposerIdsCache,
|
||||
BlockBuilder: s.cfg.BlockBuilder,
|
||||
}
|
||||
validatorServerV1 := &validator.Server{
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
|
||||
@@ -32,7 +32,7 @@ func RopstenConfig() *BeaconChainConfig {
|
||||
cfg.AltairForkVersion = []byte{0x80, 0x00, 0x00, 0x70}
|
||||
cfg.BellatrixForkEpoch = 750
|
||||
cfg.BellatrixForkVersion = []byte{0x80, 0x00, 0x00, 0x71}
|
||||
cfg.TerminalTotalDifficulty = "100000000000000000000000"
|
||||
cfg.TerminalTotalDifficulty = "50000000000000000"
|
||||
cfg.DepositContractAddress = "0x6f22fFbC56eFF051aECF839396DD1eD9aD6BBA9D"
|
||||
cfg.InitializeForkSchedule()
|
||||
return cfg
|
||||
|
||||
@@ -108,6 +108,7 @@ ssz_gen_marshal(
|
||||
"BlindedBeaconBlockBellatrix",
|
||||
"BlindedBeaconBlockBodyBellatrix",
|
||||
"SignedValidatorRegistrationV1",
|
||||
"ValidatorRegistrationV1",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/validator-client"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// SubmitBuilderValidatorRegistration submits builder validator registration
|
||||
func SubmitBuilderValidatorRegistration(
|
||||
ctx context.Context,
|
||||
validatorClient ethpb.BeaconNodeValidatorClient,
|
||||
nodeClient ethpb.NodeClient,
|
||||
signer signingFunc,
|
||||
reg *ethpb.ValidatorRegistrationV1,
|
||||
) error {
|
||||
ctx, span := trace.StartSpan(ctx, "validator.ProposeBuilderValidatorRegistration")
|
||||
defer span.End()
|
||||
|
||||
genesisResponse, err := nodeClient.GetGenesis(ctx, &emptypb.Empty{})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "gRPC call to get genesis time failed")
|
||||
}
|
||||
ts := time.Unix(int64(reg.Timestamp), 0)
|
||||
secs := int64(ts.Second()) - genesisResponse.GenesisTime.Seconds
|
||||
currentSlot := types.Slot(uint64(secs) / params.BeaconConfig().SecondsPerSlot)
|
||||
|
||||
sig, err := signBuilderValidatorRegistration(ctx, currentSlot, validatorClient, signer, reg)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to sign builder validator registration obj")
|
||||
}
|
||||
|
||||
signedReg := ðpb.SignedValidatorRegistrationV1{
|
||||
Message: reg,
|
||||
Signature: sig,
|
||||
}
|
||||
if _, err := validatorClient.SubmitValidatorRegistration(ctx, signedReg); err != nil {
|
||||
return errors.Wrap(err, "could not submit signed registration to beacon node")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sings validator registration obj with proposer domain and private key.
|
||||
func signBuilderValidatorRegistration(
|
||||
ctx context.Context,
|
||||
slot types.Slot,
|
||||
validatorClient ethpb.BeaconNodeValidatorClient,
|
||||
signer signingFunc,
|
||||
reg *ethpb.ValidatorRegistrationV1,
|
||||
) ([]byte, error) {
|
||||
req := ðpb.DomainRequest{
|
||||
Epoch: slots.ToEpoch(slot),
|
||||
Domain: []byte{},
|
||||
}
|
||||
|
||||
domain, err := validatorClient.DomainData(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, domainDataErr)
|
||||
}
|
||||
if domain == nil {
|
||||
return nil, errors.New(domainDataErr)
|
||||
}
|
||||
|
||||
exitRoot, err := signing.ComputeSigningRoot(reg, domain.SignatureDomain)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, signingRootErr)
|
||||
}
|
||||
|
||||
sig, err := signer(ctx, &validatorpb.SignRequest{
|
||||
PublicKey: reg.Pubkey,
|
||||
SigningRoot: exitRoot[:],
|
||||
SignatureDomain: domain.SignatureDomain,
|
||||
Object: &validatorpb.SignRequest_Registration{Registration: reg},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, signExitErr)
|
||||
}
|
||||
return sig.Marshal(), nil
|
||||
}
|
||||
Reference in New Issue
Block a user