mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-11 00:18:06 -05:00
Validator: propose Altair block (#9414)
* Validator can propose block * Gazelle * Preston's feedback * Rename * Fix deep source * Fix build Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
This commit is contained in:
@@ -43,6 +43,7 @@ go_library(
|
||||
"//shared/slotutil:go_default_library",
|
||||
"//shared/timeutils:go_default_library",
|
||||
"//shared/traceutil:go_default_library",
|
||||
"//shared/version:go_default_library",
|
||||
"//validator/accounts/iface:go_default_library",
|
||||
"//validator/accounts/wallet:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
|
||||
@@ -10,14 +10,16 @@ import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/validator-client"
|
||||
wrapperv1 "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
wrapper "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/mputil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/rand"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
"github.com/prysmaticlabs/prysm/shared/version"
|
||||
"github.com/prysmaticlabs/prysm/validator/client/iface"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -36,6 +38,16 @@ const signExitErr = "could not sign voluntary exit proposal"
|
||||
// the state root computation, and finally signed by the validator before being
|
||||
// sent back to the beacon node for broadcasting.
|
||||
func (v *validator) ProposeBlock(ctx context.Context, slot types.Slot, pubKey [48]byte) {
|
||||
currEpoch := helpers.SlotToEpoch(slot)
|
||||
switch {
|
||||
case currEpoch >= params.BeaconConfig().AltairForkEpoch:
|
||||
v.proposeBlockAltair(ctx, slot, pubKey)
|
||||
default:
|
||||
v.proposeBlockPhase0(ctx, slot, pubKey)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *validator) proposeBlockPhase0(ctx context.Context, slot types.Slot, pubKey [48]byte) {
|
||||
if slot == 0 {
|
||||
log.Debug("Assigned to genesis slot, skipping proposal")
|
||||
return
|
||||
@@ -43,7 +55,7 @@ func (v *validator) ProposeBlock(ctx context.Context, slot types.Slot, pubKey [4
|
||||
lock := mputil.NewMultilock(fmt.Sprint(iface.RoleProposer), string(pubKey[:]))
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
ctx, span := trace.StartSpan(ctx, "validator.ProposeBlock")
|
||||
ctx, span := trace.StartSpan(ctx, "validator.proposeBlockPhase0")
|
||||
defer span.End()
|
||||
fmtKey := fmt.Sprintf("%#x", pubKey[:])
|
||||
|
||||
@@ -84,7 +96,7 @@ func (v *validator) ProposeBlock(ctx context.Context, slot types.Slot, pubKey [4
|
||||
}
|
||||
|
||||
// Sign returned block from beacon node
|
||||
sig, domain, err := v.signBlock(ctx, pubKey, epoch, b)
|
||||
sig, domain, err := v.signBlock(ctx, pubKey, epoch, wrapper.WrappedPhase0BeaconBlock(b))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to sign block")
|
||||
if v.emitAccountMetrics {
|
||||
@@ -106,16 +118,16 @@ func (v *validator) ProposeBlock(ctx context.Context, slot types.Slot, pubKey [4
|
||||
return
|
||||
}
|
||||
|
||||
if err := v.preBlockSignValidations(ctx, pubKey, wrapperv1.WrappedPhase0BeaconBlock(b), signingRoot); err != nil {
|
||||
if err := v.preBlockSignValidations(ctx, pubKey, wrapper.WrappedPhase0BeaconBlock(b), signingRoot); err != nil {
|
||||
log.WithFields(
|
||||
blockLogFields(pubKey, wrapperv1.WrappedPhase0BeaconBlock(b), nil),
|
||||
blockLogFields(pubKey, wrapper.WrappedPhase0BeaconBlock(b), nil),
|
||||
).WithError(err).Error("Failed block slashing protection check")
|
||||
return
|
||||
}
|
||||
|
||||
if err := v.postBlockSignUpdate(ctx, pubKey, wrapperv1.WrappedPhase0SignedBeaconBlock(blk), signingRoot); err != nil {
|
||||
if err := v.postBlockSignUpdate(ctx, pubKey, wrapper.WrappedPhase0SignedBeaconBlock(blk), signingRoot); err != nil {
|
||||
log.WithFields(
|
||||
blockLogFields(pubKey, wrapperv1.WrappedPhase0BeaconBlock(b), sig),
|
||||
blockLogFields(pubKey, wrapper.WrappedPhase0BeaconBlock(b), sig),
|
||||
).WithError(err).Error("Failed block slashing protection check")
|
||||
return
|
||||
}
|
||||
@@ -150,6 +162,146 @@ func (v *validator) ProposeBlock(ctx context.Context, slot types.Slot, pubKey [4
|
||||
}
|
||||
}
|
||||
|
||||
// This is a routine to propose altair compatible beacon blocks.
|
||||
func (v *validator) proposeBlockAltair(ctx context.Context, slot types.Slot, pubKey [48]byte) {
|
||||
if slot == 0 {
|
||||
log.Debug("Assigned to genesis slot, skipping proposal")
|
||||
return
|
||||
}
|
||||
ctx, span := trace.StartSpan(ctx, "validator.proposeBlockAltair")
|
||||
defer span.End()
|
||||
|
||||
lock := mputil.NewMultilock(fmt.Sprint(iface.RoleProposer), string(pubKey[:]))
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
fmtKey := fmt.Sprintf("%#x", pubKey[:])
|
||||
span.AddAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey)))
|
||||
log := log.WithField("pubKey", fmt.Sprintf("%#x", bytesutil.Trunc(pubKey[:])))
|
||||
|
||||
// Sign randao reveal, it's used to request block from beacon node
|
||||
epoch := types.Epoch(slot / params.BeaconConfig().SlotsPerEpoch)
|
||||
randaoReveal, err := v.signRandaoReveal(ctx, pubKey, epoch)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to sign randao reveal")
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
g, err := v.getGraffiti(ctx, pubKey)
|
||||
if err != nil {
|
||||
// Graffiti is not a critical enough to fail block production and cause
|
||||
// validator to miss block reward. When failed, validator should continue
|
||||
// to produce the block.
|
||||
log.WithError(err).Warn("Could not get graffiti")
|
||||
}
|
||||
|
||||
// Request block from beacon node
|
||||
b, err := v.validatorClient.GetBlockAltair(ctx, ðpb.BlockRequest{
|
||||
Slot: slot,
|
||||
RandaoReveal: randaoReveal,
|
||||
Graffiti: g,
|
||||
})
|
||||
if err != nil {
|
||||
log.WithField("blockSlot", slot).WithError(err).Error("Failed to request block from beacon node")
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Sign returned block from beacon node
|
||||
wb, err := wrapper.WrappedAltairBeaconBlock(b)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to wrap block")
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return
|
||||
}
|
||||
sig, domain, err := v.signBlock(ctx, pubKey, epoch, wb)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to sign block")
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return
|
||||
}
|
||||
blk := ðpb.SignedBeaconBlockAltair{
|
||||
Block: b,
|
||||
Signature: sig,
|
||||
}
|
||||
|
||||
signingRoot, err := helpers.ComputeSigningRoot(b, domain.SignatureDomain)
|
||||
if err != nil {
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
log.WithError(err).Error("Failed to compute signing root for block")
|
||||
return
|
||||
}
|
||||
|
||||
if err := v.preBlockSignValidations(ctx, pubKey, wb, signingRoot); err != nil {
|
||||
log.WithFields(
|
||||
blockLogFields(pubKey, wb, nil),
|
||||
).WithError(err).Error("Failed block slashing protection check")
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(blk)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to wrap signed block")
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return
|
||||
}
|
||||
if err := v.postBlockSignUpdate(ctx, pubKey, wsb, signingRoot); err != nil {
|
||||
log.WithFields(
|
||||
blockLogFields(pubKey, wb, sig),
|
||||
).WithError(err).Error("Failed block slashing protection check")
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Propose and broadcast block via beacon node
|
||||
blkResp, err := v.validatorClient.ProposeBlockAltair(ctx, blk)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to propose block")
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
span.AddAttributes(
|
||||
trace.StringAttribute("blockRoot", fmt.Sprintf("%#x", blkResp.BlockRoot)),
|
||||
trace.Int64Attribute("numDeposits", int64(len(b.Body.Deposits))),
|
||||
trace.Int64Attribute("numAttestations", int64(len(b.Body.Attestations))),
|
||||
)
|
||||
|
||||
blkRoot := fmt.Sprintf("%#x", bytesutil.Trunc(blkResp.BlockRoot))
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": b.Slot,
|
||||
"blockRoot": blkRoot,
|
||||
"numAttestations": len(b.Body.Attestations),
|
||||
"numDeposits": len(b.Body.Deposits),
|
||||
"graffiti": string(b.Body.Graffiti),
|
||||
"fork": "altair",
|
||||
}).Info("Submitted new block")
|
||||
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeSuccessVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
}
|
||||
|
||||
// ProposeExit performs a voluntary exit on a validator.
|
||||
// The exit is signed by the validator before being sent to the beacon node for broadcasting.
|
||||
func ProposeExit(
|
||||
@@ -221,7 +373,7 @@ func (v *validator) signRandaoReveal(ctx context.Context, pubKey [48]byte, epoch
|
||||
}
|
||||
|
||||
// Sign block with proposer domain and private key.
|
||||
func (v *validator) signBlock(ctx context.Context, pubKey [48]byte, epoch types.Epoch, b *ethpb.BeaconBlock) ([]byte, *ethpb.DomainResponse, error) {
|
||||
func (v *validator) signBlock(ctx context.Context, pubKey [48]byte, epoch types.Epoch, b block.BeaconBlock) ([]byte, *ethpb.DomainResponse, error) {
|
||||
domain, err := v.domainData(ctx, epoch, params.BeaconConfig().DomainBeaconProposer[:])
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, domainDataErr)
|
||||
@@ -231,20 +383,48 @@ func (v *validator) signBlock(ctx context.Context, pubKey [48]byte, epoch types.
|
||||
}
|
||||
|
||||
var sig bls.Signature
|
||||
blockRoot, err := helpers.ComputeSigningRoot(b, domain.SignatureDomain)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, signingRootErr)
|
||||
switch b.Version() {
|
||||
case version.Altair:
|
||||
block, ok := b.Proto().(*ethpb.BeaconBlockAltair)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("could not convert obj to beacon block altair")
|
||||
}
|
||||
blockRoot, err := helpers.ComputeSigningRoot(block, domain.SignatureDomain)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, signingRootErr)
|
||||
}
|
||||
sig, err = v.keyManager.Sign(ctx, &validatorpb.SignRequest{
|
||||
PublicKey: pubKey[:],
|
||||
SigningRoot: blockRoot[:],
|
||||
SignatureDomain: domain.SignatureDomain,
|
||||
Object: &validatorpb.SignRequest_BlockV2{BlockV2: block},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not sign block proposal")
|
||||
}
|
||||
return sig.Marshal(), domain, nil
|
||||
case version.Phase0:
|
||||
block, ok := b.Proto().(*ethpb.BeaconBlock)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("could not convert obj to beacon block phase 0")
|
||||
}
|
||||
blockRoot, err := helpers.ComputeSigningRoot(block, domain.SignatureDomain)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, signingRootErr)
|
||||
}
|
||||
sig, err = v.keyManager.Sign(ctx, &validatorpb.SignRequest{
|
||||
PublicKey: pubKey[:],
|
||||
SigningRoot: blockRoot[:],
|
||||
SignatureDomain: domain.SignatureDomain,
|
||||
Object: &validatorpb.SignRequest_Block{Block: block},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not sign block proposal")
|
||||
}
|
||||
return sig.Marshal(), domain, nil
|
||||
default:
|
||||
return nil, nil, errors.New("unknown block type")
|
||||
}
|
||||
sig, err = v.keyManager.Sign(ctx, &validatorpb.SignRequest{
|
||||
PublicKey: pubKey[:],
|
||||
SigningRoot: blockRoot[:],
|
||||
SignatureDomain: domain.SignatureDomain,
|
||||
Object: &validatorpb.SignRequest_Block{Block: b},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not sign block proposal")
|
||||
}
|
||||
return sig.Marshal(), domain, nil
|
||||
}
|
||||
|
||||
// Sign voluntary exit with proposer domain and private key.
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/validator-client"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
lruwrpr "github.com/prysmaticlabs/prysm/shared/lru"
|
||||
@@ -156,6 +157,31 @@ func TestProposeBlock_RequestBlockFailed(t *testing.T) {
|
||||
require.LogsContain(t, hook, "Failed to request block from beacon node")
|
||||
}
|
||||
|
||||
func TestProposeBlockAltair_RequestBlockFailed(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.AltairForkEpoch = 2
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
validator, m, validatorKey, finish := setup(t)
|
||||
defer finish()
|
||||
pubKey := [48]byte{}
|
||||
copy(pubKey[:], validatorKey.PublicKey().Marshal())
|
||||
|
||||
m.validatorClient.EXPECT().DomainData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // epoch
|
||||
).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
|
||||
|
||||
m.validatorClient.EXPECT().GetBlockAltair(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // block request
|
||||
).Return(nil /*response*/, errors.New("uh oh"))
|
||||
|
||||
validator.ProposeBlock(context.Background(), 2*params.BeaconConfig().SlotsPerEpoch, pubKey)
|
||||
require.LogsContain(t, hook, "Failed to request block from beacon node")
|
||||
}
|
||||
|
||||
func TestProposeBlock_ProposeBlockFailed(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
validator, m, validatorKey, finish := setup(t)
|
||||
@@ -187,6 +213,41 @@ func TestProposeBlock_ProposeBlockFailed(t *testing.T) {
|
||||
require.LogsContain(t, hook, "Failed to propose block")
|
||||
}
|
||||
|
||||
func TestProposeBlockAltair_ProposeBlockFailed(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.AltairForkEpoch = 2
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
validator, m, validatorKey, finish := setup(t)
|
||||
defer finish()
|
||||
pubKey := [48]byte{}
|
||||
copy(pubKey[:], validatorKey.PublicKey().Marshal())
|
||||
|
||||
m.validatorClient.EXPECT().DomainData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // epoch
|
||||
).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
|
||||
|
||||
m.validatorClient.EXPECT().GetBlockAltair(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(),
|
||||
).Return(testutil.NewBeaconBlockAltair().Block, nil /*err*/)
|
||||
|
||||
m.validatorClient.EXPECT().DomainData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // epoch
|
||||
).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
|
||||
|
||||
m.validatorClient.EXPECT().ProposeBlockAltair(
|
||||
gomock.Any(), // ctx
|
||||
gomock.AssignableToTypeOf(ðpb.SignedBeaconBlockAltair{}),
|
||||
).Return(nil /*response*/, errors.New("uh oh"))
|
||||
|
||||
validator.ProposeBlock(context.Background(), 2*params.BeaconConfig().SlotsPerEpoch, pubKey)
|
||||
require.LogsContain(t, hook, "Failed to propose block")
|
||||
}
|
||||
|
||||
func TestProposeBlock_BlocksDoubleProposal(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
validator, m, validatorKey, finish := setup(t)
|
||||
@@ -239,6 +300,62 @@ func TestProposeBlock_BlocksDoubleProposal(t *testing.T) {
|
||||
require.LogsContain(t, hook, failedPreBlockSignLocalErr)
|
||||
}
|
||||
|
||||
func TestProposeBlockAltair_BlocksDoubleProposal(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.AltairForkEpoch = 2
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
validator, m, validatorKey, finish := setup(t)
|
||||
defer finish()
|
||||
pubKey := [48]byte{}
|
||||
copy(pubKey[:], validatorKey.PublicKey().Marshal())
|
||||
|
||||
dummyRoot := [32]byte{}
|
||||
// Save a dummy proposal history at slot 0.
|
||||
err := validator.db.SaveProposalHistoryForSlot(context.Background(), pubKey, 0, dummyRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
m.validatorClient.EXPECT().DomainData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // epoch
|
||||
).Times(1).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
|
||||
|
||||
testBlock := testutil.NewBeaconBlockAltair()
|
||||
slot := params.BeaconConfig().SlotsPerEpoch*5 + 2
|
||||
testBlock.Block.Slot = slot
|
||||
m.validatorClient.EXPECT().GetBlockAltair(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(),
|
||||
).Return(testBlock.Block, nil /*err*/)
|
||||
|
||||
secondTestBlock := testutil.NewBeaconBlockAltair()
|
||||
secondTestBlock.Block.Slot = slot
|
||||
graffiti := [32]byte{}
|
||||
copy(graffiti[:], "someothergraffiti")
|
||||
secondTestBlock.Block.Body.Graffiti = graffiti[:]
|
||||
m.validatorClient.EXPECT().GetBlockAltair(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(),
|
||||
).Return(secondTestBlock.Block, nil /*err*/)
|
||||
|
||||
m.validatorClient.EXPECT().DomainData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // epoch
|
||||
).Times(3).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
|
||||
|
||||
m.validatorClient.EXPECT().ProposeBlockAltair(
|
||||
gomock.Any(), // ctx
|
||||
gomock.AssignableToTypeOf(ðpb.SignedBeaconBlockAltair{}),
|
||||
).Return(ðpb.ProposeResponse{BlockRoot: make([]byte, 32)}, nil /*error*/)
|
||||
|
||||
validator.ProposeBlock(context.Background(), slot, pubKey)
|
||||
require.LogsDoNotContain(t, hook, failedPreBlockSignLocalErr)
|
||||
|
||||
validator.ProposeBlock(context.Background(), slot, pubKey)
|
||||
require.LogsContain(t, hook, failedPreBlockSignLocalErr)
|
||||
}
|
||||
|
||||
func TestProposeBlock_BlocksDoubleProposal_After54KEpochs(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
validator, m, validatorKey, finish := setup(t)
|
||||
@@ -455,6 +572,49 @@ func TestProposeBlock_BroadcastsBlock_WithGraffiti(t *testing.T) {
|
||||
assert.Equal(t, string(validator.graffiti), string(sentBlock.Block.Body.Graffiti))
|
||||
}
|
||||
|
||||
func TestProposeBlockAltair_BroadcastsBlock_WithGraffiti(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.AltairForkEpoch = 2
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
validator, m, validatorKey, finish := setup(t)
|
||||
defer finish()
|
||||
pubKey := [48]byte{}
|
||||
copy(pubKey[:], validatorKey.PublicKey().Marshal())
|
||||
|
||||
validator.graffiti = []byte("12345678901234567890123456789012")
|
||||
|
||||
m.validatorClient.EXPECT().DomainData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // epoch
|
||||
).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
|
||||
|
||||
blk := testutil.NewBeaconBlockAltair()
|
||||
blk.Block.Body.Graffiti = validator.graffiti
|
||||
m.validatorClient.EXPECT().GetBlockAltair(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(),
|
||||
).Return(blk.Block, nil /*err*/)
|
||||
|
||||
m.validatorClient.EXPECT().DomainData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // epoch
|
||||
).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
|
||||
|
||||
var sentBlock *ethpb.SignedBeaconBlockAltair
|
||||
|
||||
m.validatorClient.EXPECT().ProposeBlockAltair(
|
||||
gomock.Any(), // ctx
|
||||
gomock.AssignableToTypeOf(ðpb.SignedBeaconBlockAltair{}),
|
||||
).DoAndReturn(func(ctx context.Context, block *ethpb.SignedBeaconBlockAltair, opts ...grpc.CallOption) (*ethpb.ProposeResponse, error) {
|
||||
sentBlock = block
|
||||
return ðpb.ProposeResponse{BlockRoot: make([]byte, 32)}, nil
|
||||
})
|
||||
|
||||
validator.ProposeBlock(context.Background(), 2*params.BeaconConfig().SlotsPerEpoch, pubKey)
|
||||
assert.Equal(t, string(validator.graffiti), string(sentBlock.Block.Body.Graffiti))
|
||||
}
|
||||
|
||||
func TestProposeExit_ValidatorIndexFailed(t *testing.T) {
|
||||
_, m, validatorKey, finish := setup(t)
|
||||
defer finish()
|
||||
@@ -661,7 +821,7 @@ func TestSignBlock(t *testing.T) {
|
||||
},
|
||||
}
|
||||
validator.keyManager = km
|
||||
sig, domain, err := validator.signBlock(ctx, pubKey, 0, blk.Block)
|
||||
sig, domain, err := validator.signBlock(ctx, pubKey, 0, wrapper.WrappedPhase0BeaconBlock(blk.Block))
|
||||
require.NoError(t, err, "%x,%x,%v", sig, domain.SignatureDomain, err)
|
||||
require.Equal(t, "a049e1dc723e5a8b5bd14f292973572dffd53785ddb337"+
|
||||
"82f20bf762cbe10ee7b9b4f5ae1ad6ff2089d352403750bed402b94b58469c072536"+
|
||||
@@ -671,6 +831,36 @@ func TestSignBlock(t *testing.T) {
|
||||
require.DeepEqual(t, proposerDomain, domain.SignatureDomain)
|
||||
}
|
||||
|
||||
func TestSignAltairBlock(t *testing.T) {
|
||||
validator, m, _, finish := setup(t)
|
||||
defer finish()
|
||||
|
||||
secretKey, err := bls.SecretKeyFromBytes(bytesutil.PadTo([]byte{1}, 32))
|
||||
require.NoError(t, err, "Failed to generate key from bytes")
|
||||
publicKey := secretKey.PublicKey()
|
||||
proposerDomain := make([]byte, 32)
|
||||
m.validatorClient.EXPECT().
|
||||
DomainData(gomock.Any(), gomock.Any()).
|
||||
Return(ðpb.DomainResponse{SignatureDomain: proposerDomain}, nil)
|
||||
ctx := context.Background()
|
||||
blk := testutil.NewBeaconBlockAltair()
|
||||
blk.Block.Slot = 1
|
||||
blk.Block.ProposerIndex = 100
|
||||
var pubKey [48]byte
|
||||
copy(pubKey[:], publicKey.Marshal())
|
||||
km := &mockKeymanager{
|
||||
keysMap: map[[48]byte]bls.SecretKey{
|
||||
pubKey: secretKey,
|
||||
},
|
||||
}
|
||||
validator.keyManager = km
|
||||
wb, err := wrapper.WrappedAltairBeaconBlock(blk.Block)
|
||||
require.NoError(t, err)
|
||||
sig, domain, err := validator.signBlock(ctx, pubKey, 0, wb)
|
||||
require.NoError(t, err, "%x,%x,%v", sig, domain.SignatureDomain, err)
|
||||
require.DeepEqual(t, proposerDomain, domain.SignatureDomain)
|
||||
}
|
||||
|
||||
func TestGetGraffiti_Ok(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
m := &mocks{
|
||||
|
||||
Reference in New Issue
Block a user